]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD/mapillary-js/mapillary.unminified.js
Update to iD v2.22.0
[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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
27         return extendStatics(d, b);
28     };
29
30     function __extends(d, b) {
31         if (typeof b !== "function" && b !== null)
32             throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
33         extendStatics(d, b);
34         function __() { this.constructor = d; }
35         d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
36     }
37
38     function __awaiter(thisArg, _arguments, P, generator) {
39         function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
40         return new (P || (P = Promise))(function (resolve, reject) {
41             function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
42             function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
43             function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
44             step((generator = generator.apply(thisArg, _arguments || [])).next());
45         });
46     }
47
48     function __generator(thisArg, body) {
49         var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
50         return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
51         function verb(n) { return function (v) { return step([n, v]); }; }
52         function step(op) {
53             if (f) throw new TypeError("Generator is already executing.");
54             while (_) try {
55                 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
56                 if (y = 0, t) op = [op[0] & 2, t.value];
57                 switch (op[0]) {
58                     case 0: case 1: t = op; break;
59                     case 4: _.label++; return { value: op[1], done: false };
60                     case 5: _.label++; y = op[1]; op = [0]; continue;
61                     case 7: op = _.ops.pop(); _.trys.pop(); continue;
62                     default:
63                         if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
64                         if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
65                         if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
66                         if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
67                         if (t[2]) _.ops.pop();
68                         _.trys.pop(); continue;
69                 }
70                 op = body.call(thisArg, _);
71             } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
72             if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
73         }
74     }
75
76     function __values(o) {
77         var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
78         if (m) return m.call(o);
79         if (o && typeof o.length === "number") return {
80             next: function () {
81                 if (o && i >= o.length) o = void 0;
82                 return { value: o && o[i++], done: !o };
83             }
84         };
85         throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
86     }
87
88     function __read(o, n) {
89         var m = typeof Symbol === "function" && o[Symbol.iterator];
90         if (!m) return o;
91         var i = m.call(o), r, ar = [], e;
92         try {
93             while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
94         }
95         catch (error) { e = { error: error }; }
96         finally {
97             try {
98                 if (r && !r.done && (m = i["return"])) m.call(i);
99             }
100             finally { if (e) throw e.error; }
101         }
102         return ar;
103     }
104
105     function __spreadArray(to, from) {
106         for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
107             to[j] = from[i];
108         return to;
109     }
110
111     function __await(v) {
112         return this instanceof __await ? (this.v = v, this) : new __await(v);
113     }
114
115     function __asyncGenerator(thisArg, _arguments, generator) {
116         if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
117         var g = generator.apply(thisArg, _arguments || []), i, q = [];
118         return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
119         function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
120         function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
121         function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
122         function fulfill(value) { resume("next", value); }
123         function reject(value) { resume("throw", value); }
124         function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
125     }
126
127     function __asyncValues(o) {
128         if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
129         var m = o[Symbol.asyncIterator], i;
130         return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
131         function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
132         function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
133     }
134
135     function isFunction(value) {
136         return typeof value === 'function';
137     }
138
139     function createErrorClass(createImpl) {
140         var _super = function (instance) {
141             Error.call(instance);
142             instance.stack = new Error().stack;
143         };
144         var ctorFunc = createImpl(_super);
145         ctorFunc.prototype = Object.create(Error.prototype);
146         ctorFunc.prototype.constructor = ctorFunc;
147         return ctorFunc;
148     }
149
150     var UnsubscriptionError = createErrorClass(function (_super) {
151         return function UnsubscriptionErrorImpl(errors) {
152             _super(this);
153             this.message = errors
154                 ? errors.length + " errors occurred during unsubscription:\n" + errors.map(function (err, i) { return i + 1 + ") " + err.toString(); }).join('\n  ')
155                 : '';
156             this.name = 'UnsubscriptionError';
157             this.errors = errors;
158         };
159     });
160
161     function arrRemove(arr, item) {
162         if (arr) {
163             var index = arr.indexOf(item);
164             0 <= index && arr.splice(index, 1);
165         }
166     }
167
168     var Subscription = (function () {
169         function Subscription(initialTeardown) {
170             this.initialTeardown = initialTeardown;
171             this.closed = false;
172             this._parentage = null;
173             this._teardowns = null;
174         }
175         Subscription.prototype.unsubscribe = function () {
176             var e_1, _a, e_2, _b;
177             var errors;
178             if (!this.closed) {
179                 this.closed = true;
180                 var _parentage = this._parentage;
181                 if (_parentage) {
182                     this._parentage = null;
183                     if (Array.isArray(_parentage)) {
184                         try {
185                             for (var _parentage_1 = __values(_parentage), _parentage_1_1 = _parentage_1.next(); !_parentage_1_1.done; _parentage_1_1 = _parentage_1.next()) {
186                                 var parent_1 = _parentage_1_1.value;
187                                 parent_1.remove(this);
188                             }
189                         }
190                         catch (e_1_1) { e_1 = { error: e_1_1 }; }
191                         finally {
192                             try {
193                                 if (_parentage_1_1 && !_parentage_1_1.done && (_a = _parentage_1.return)) _a.call(_parentage_1);
194                             }
195                             finally { if (e_1) throw e_1.error; }
196                         }
197                     }
198                     else {
199                         _parentage.remove(this);
200                     }
201                 }
202                 var initialTeardown = this.initialTeardown;
203                 if (isFunction(initialTeardown)) {
204                     try {
205                         initialTeardown();
206                     }
207                     catch (e) {
208                         errors = e instanceof UnsubscriptionError ? e.errors : [e];
209                     }
210                 }
211                 var _teardowns = this._teardowns;
212                 if (_teardowns) {
213                     this._teardowns = null;
214                     try {
215                         for (var _teardowns_1 = __values(_teardowns), _teardowns_1_1 = _teardowns_1.next(); !_teardowns_1_1.done; _teardowns_1_1 = _teardowns_1.next()) {
216                             var teardown_1 = _teardowns_1_1.value;
217                             try {
218                                 execTeardown(teardown_1);
219                             }
220                             catch (err) {
221                                 errors = errors !== null && errors !== void 0 ? errors : [];
222                                 if (err instanceof UnsubscriptionError) {
223                                     errors = __spreadArray(__spreadArray([], __read(errors)), __read(err.errors));
224                                 }
225                                 else {
226                                     errors.push(err);
227                                 }
228                             }
229                         }
230                     }
231                     catch (e_2_1) { e_2 = { error: e_2_1 }; }
232                     finally {
233                         try {
234                             if (_teardowns_1_1 && !_teardowns_1_1.done && (_b = _teardowns_1.return)) _b.call(_teardowns_1);
235                         }
236                         finally { if (e_2) throw e_2.error; }
237                     }
238                 }
239                 if (errors) {
240                     throw new UnsubscriptionError(errors);
241                 }
242             }
243         };
244         Subscription.prototype.add = function (teardown) {
245             var _a;
246             if (teardown && teardown !== this) {
247                 if (this.closed) {
248                     execTeardown(teardown);
249                 }
250                 else {
251                     if (teardown instanceof Subscription) {
252                         if (teardown.closed || teardown._hasParent(this)) {
253                             return;
254                         }
255                         teardown._addParent(this);
256                     }
257                     (this._teardowns = (_a = this._teardowns) !== null && _a !== void 0 ? _a : []).push(teardown);
258                 }
259             }
260         };
261         Subscription.prototype._hasParent = function (parent) {
262             var _parentage = this._parentage;
263             return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));
264         };
265         Subscription.prototype._addParent = function (parent) {
266             var _parentage = this._parentage;
267             this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;
268         };
269         Subscription.prototype._removeParent = function (parent) {
270             var _parentage = this._parentage;
271             if (_parentage === parent) {
272                 this._parentage = null;
273             }
274             else if (Array.isArray(_parentage)) {
275                 arrRemove(_parentage, parent);
276             }
277         };
278         Subscription.prototype.remove = function (teardown) {
279             var _teardowns = this._teardowns;
280             _teardowns && arrRemove(_teardowns, teardown);
281             if (teardown instanceof Subscription) {
282                 teardown._removeParent(this);
283             }
284         };
285         Subscription.EMPTY = (function () {
286             var empty = new Subscription();
287             empty.closed = true;
288             return empty;
289         })();
290         return Subscription;
291     }());
292     var EMPTY_SUBSCRIPTION = Subscription.EMPTY;
293     function isSubscription(value) {
294         return (value instanceof Subscription ||
295             (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe)));
296     }
297     function execTeardown(teardown) {
298         if (isFunction(teardown)) {
299             teardown();
300         }
301         else {
302             teardown.unsubscribe();
303         }
304     }
305
306     var config = {
307         onUnhandledError: null,
308         onStoppedNotification: null,
309         Promise: undefined,
310         useDeprecatedSynchronousErrorHandling: false,
311         useDeprecatedNextContext: false,
312     };
313
314     var timeoutProvider = {
315         setTimeout: function () {
316             var args = [];
317             for (var _i = 0; _i < arguments.length; _i++) {
318                 args[_i] = arguments[_i];
319             }
320             var delegate = timeoutProvider.delegate;
321             return ((delegate === null || delegate === void 0 ? void 0 : delegate.setTimeout) || setTimeout).apply(void 0, __spreadArray([], __read(args)));
322         },
323         clearTimeout: function (handle) {
324             var delegate = timeoutProvider.delegate;
325             return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearTimeout) || clearTimeout)(handle);
326         },
327         delegate: undefined,
328     };
329
330     function reportUnhandledError(err) {
331         timeoutProvider.setTimeout(function () {
332             {
333                 throw err;
334             }
335         });
336     }
337
338     function noop() { }
339
340     var COMPLETE_NOTIFICATION = (function () { return createNotification('C', undefined, undefined); })();
341     function errorNotification(error) {
342         return createNotification('E', undefined, error);
343     }
344     function nextNotification(value) {
345         return createNotification('N', value, undefined);
346     }
347     function createNotification(kind, value, error) {
348         return {
349             kind: kind,
350             value: value,
351             error: error,
352         };
353     }
354
355     var context = null;
356     function errorContext(cb) {
357         if (config.useDeprecatedSynchronousErrorHandling) {
358             var isRoot = !context;
359             if (isRoot) {
360                 context = { errorThrown: false, error: null };
361             }
362             cb();
363             if (isRoot) {
364                 var _a = context, errorThrown = _a.errorThrown, error = _a.error;
365                 context = null;
366                 if (errorThrown) {
367                     throw error;
368                 }
369             }
370         }
371         else {
372             cb();
373         }
374     }
375
376     var Subscriber = (function (_super) {
377         __extends(Subscriber, _super);
378         function Subscriber(destination) {
379             var _this = _super.call(this) || this;
380             _this.isStopped = false;
381             if (destination) {
382                 _this.destination = destination;
383                 if (isSubscription(destination)) {
384                     destination.add(_this);
385                 }
386             }
387             else {
388                 _this.destination = EMPTY_OBSERVER;
389             }
390             return _this;
391         }
392         Subscriber.create = function (next, error, complete) {
393             return new SafeSubscriber(next, error, complete);
394         };
395         Subscriber.prototype.next = function (value) {
396             if (this.isStopped) {
397                 handleStoppedNotification(nextNotification(value), this);
398             }
399             else {
400                 this._next(value);
401             }
402         };
403         Subscriber.prototype.error = function (err) {
404             if (this.isStopped) {
405                 handleStoppedNotification(errorNotification(err), this);
406             }
407             else {
408                 this.isStopped = true;
409                 this._error(err);
410             }
411         };
412         Subscriber.prototype.complete = function () {
413             if (this.isStopped) {
414                 handleStoppedNotification(COMPLETE_NOTIFICATION, this);
415             }
416             else {
417                 this.isStopped = true;
418                 this._complete();
419             }
420         };
421         Subscriber.prototype.unsubscribe = function () {
422             if (!this.closed) {
423                 this.isStopped = true;
424                 _super.prototype.unsubscribe.call(this);
425                 this.destination = null;
426             }
427         };
428         Subscriber.prototype._next = function (value) {
429             this.destination.next(value);
430         };
431         Subscriber.prototype._error = function (err) {
432             try {
433                 this.destination.error(err);
434             }
435             finally {
436                 this.unsubscribe();
437             }
438         };
439         Subscriber.prototype._complete = function () {
440             try {
441                 this.destination.complete();
442             }
443             finally {
444                 this.unsubscribe();
445             }
446         };
447         return Subscriber;
448     }(Subscription));
449     var SafeSubscriber = (function (_super) {
450         __extends(SafeSubscriber, _super);
451         function SafeSubscriber(observerOrNext, error, complete) {
452             var _this = _super.call(this) || this;
453             var next;
454             if (isFunction(observerOrNext)) {
455                 next = observerOrNext;
456             }
457             else if (observerOrNext) {
458                 (next = observerOrNext.next, error = observerOrNext.error, complete = observerOrNext.complete);
459                 var context_1;
460                 if (_this && config.useDeprecatedNextContext) {
461                     context_1 = Object.create(observerOrNext);
462                     context_1.unsubscribe = function () { return _this.unsubscribe(); };
463                 }
464                 else {
465                     context_1 = observerOrNext;
466                 }
467                 next = next === null || next === void 0 ? void 0 : next.bind(context_1);
468                 error = error === null || error === void 0 ? void 0 : error.bind(context_1);
469                 complete = complete === null || complete === void 0 ? void 0 : complete.bind(context_1);
470             }
471             _this.destination = {
472                 next: next ? wrapForErrorHandling(next) : noop,
473                 error: wrapForErrorHandling(error !== null && error !== void 0 ? error : defaultErrorHandler),
474                 complete: complete ? wrapForErrorHandling(complete) : noop,
475             };
476             return _this;
477         }
478         return SafeSubscriber;
479     }(Subscriber));
480     function wrapForErrorHandling(handler, instance) {
481         return function () {
482             var args = [];
483             for (var _i = 0; _i < arguments.length; _i++) {
484                 args[_i] = arguments[_i];
485             }
486             try {
487                 handler.apply(void 0, __spreadArray([], __read(args)));
488             }
489             catch (err) {
490                 {
491                     reportUnhandledError(err);
492                 }
493             }
494         };
495     }
496     function defaultErrorHandler(err) {
497         throw err;
498     }
499     function handleStoppedNotification(notification, subscriber) {
500         var onStoppedNotification = config.onStoppedNotification;
501         onStoppedNotification && timeoutProvider.setTimeout(function () { return onStoppedNotification(notification, subscriber); });
502     }
503     var EMPTY_OBSERVER = {
504         closed: true,
505         next: noop,
506         error: defaultErrorHandler,
507         complete: noop,
508     };
509
510     var observable = (function () { return (typeof Symbol === 'function' && Symbol.observable) || '@@observable'; })();
511
512     function identity(x) {
513         return x;
514     }
515
516     function pipeFromArray(fns) {
517         if (fns.length === 0) {
518             return identity;
519         }
520         if (fns.length === 1) {
521             return fns[0];
522         }
523         return function piped(input) {
524             return fns.reduce(function (prev, fn) { return fn(prev); }, input);
525         };
526     }
527
528     var Observable = (function () {
529         function Observable(subscribe) {
530             if (subscribe) {
531                 this._subscribe = subscribe;
532             }
533         }
534         Observable.prototype.lift = function (operator) {
535             var observable = new Observable();
536             observable.source = this;
537             observable.operator = operator;
538             return observable;
539         };
540         Observable.prototype.subscribe = function (observerOrNext, error, complete) {
541             var _this = this;
542             var subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);
543             errorContext(function () {
544                 var _a = _this, operator = _a.operator, source = _a.source;
545                 subscriber.add(operator
546                     ?
547                         operator.call(subscriber, source)
548                     : source
549                         ?
550                             _this._subscribe(subscriber)
551                         :
552                             _this._trySubscribe(subscriber));
553             });
554             return subscriber;
555         };
556         Observable.prototype._trySubscribe = function (sink) {
557             try {
558                 return this._subscribe(sink);
559             }
560             catch (err) {
561                 sink.error(err);
562             }
563         };
564         Observable.prototype.forEach = function (next, promiseCtor) {
565             var _this = this;
566             promiseCtor = getPromiseCtor(promiseCtor);
567             return new promiseCtor(function (resolve, reject) {
568                 var subscription;
569                 subscription = _this.subscribe(function (value) {
570                     try {
571                         next(value);
572                     }
573                     catch (err) {
574                         reject(err);
575                         subscription === null || subscription === void 0 ? void 0 : subscription.unsubscribe();
576                     }
577                 }, reject, resolve);
578             });
579         };
580         Observable.prototype._subscribe = function (subscriber) {
581             var _a;
582             return (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber);
583         };
584         Observable.prototype[observable] = function () {
585             return this;
586         };
587         Observable.prototype.pipe = function () {
588             var operations = [];
589             for (var _i = 0; _i < arguments.length; _i++) {
590                 operations[_i] = arguments[_i];
591             }
592             return pipeFromArray(operations)(this);
593         };
594         Observable.prototype.toPromise = function (promiseCtor) {
595             var _this = this;
596             promiseCtor = getPromiseCtor(promiseCtor);
597             return new promiseCtor(function (resolve, reject) {
598                 var value;
599                 _this.subscribe(function (x) { return (value = x); }, function (err) { return reject(err); }, function () { return resolve(value); });
600             });
601         };
602         Observable.create = function (subscribe) {
603             return new Observable(subscribe);
604         };
605         return Observable;
606     }());
607     function getPromiseCtor(promiseCtor) {
608         var _a;
609         return (_a = promiseCtor !== null && promiseCtor !== void 0 ? promiseCtor : config.Promise) !== null && _a !== void 0 ? _a : Promise;
610     }
611     function isObserver(value) {
612         return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);
613     }
614     function isSubscriber(value) {
615         return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));
616     }
617
618     function hasLift(source) {
619         return isFunction(source === null || source === void 0 ? void 0 : source.lift);
620     }
621     function operate(init) {
622         return function (source) {
623             if (hasLift(source)) {
624                 return source.lift(function (liftedSource) {
625                     try {
626                         return init(liftedSource, this);
627                     }
628                     catch (err) {
629                         this.error(err);
630                     }
631                 });
632             }
633             throw new TypeError('Unable to lift unknown Observable type');
634         };
635     }
636
637     var OperatorSubscriber = (function (_super) {
638         __extends(OperatorSubscriber, _super);
639         function OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize) {
640             var _this = _super.call(this, destination) || this;
641             _this.onFinalize = onFinalize;
642             _this._next = onNext
643                 ? function (value) {
644                     try {
645                         onNext(value);
646                     }
647                     catch (err) {
648                         destination.error(err);
649                     }
650                 }
651                 : _super.prototype._next;
652             _this._error = onError
653                 ? function (err) {
654                     try {
655                         onError(err);
656                     }
657                     catch (err) {
658                         destination.error(err);
659                     }
660                     finally {
661                         this.unsubscribe();
662                     }
663                 }
664                 : _super.prototype._error;
665             _this._complete = onComplete
666                 ? function () {
667                     try {
668                         onComplete();
669                     }
670                     catch (err) {
671                         destination.error(err);
672                     }
673                     finally {
674                         this.unsubscribe();
675                     }
676                 }
677                 : _super.prototype._complete;
678             return _this;
679         }
680         OperatorSubscriber.prototype.unsubscribe = function () {
681             var _a;
682             var closed = this.closed;
683             _super.prototype.unsubscribe.call(this);
684             !closed && ((_a = this.onFinalize) === null || _a === void 0 ? void 0 : _a.call(this));
685         };
686         return OperatorSubscriber;
687     }(Subscriber));
688
689     function refCount() {
690         return operate(function (source, subscriber) {
691             var connection = null;
692             source._refCount++;
693             var refCounter = new OperatorSubscriber(subscriber, undefined, undefined, undefined, function () {
694                 if (!source || source._refCount <= 0 || 0 < --source._refCount) {
695                     connection = null;
696                     return;
697                 }
698                 var sharedConnection = source._connection;
699                 var conn = connection;
700                 connection = null;
701                 if (sharedConnection && (!conn || sharedConnection === conn)) {
702                     sharedConnection.unsubscribe();
703                 }
704                 subscriber.unsubscribe();
705             });
706             source.subscribe(refCounter);
707             if (!refCounter.closed) {
708                 connection = source.connect();
709             }
710         });
711     }
712
713     var ConnectableObservable = (function (_super) {
714         __extends(ConnectableObservable, _super);
715         function ConnectableObservable(source, subjectFactory) {
716             var _this = _super.call(this) || this;
717             _this.source = source;
718             _this.subjectFactory = subjectFactory;
719             _this._subject = null;
720             _this._refCount = 0;
721             _this._connection = null;
722             if (hasLift(source)) {
723                 _this.lift = source.lift;
724             }
725             return _this;
726         }
727         ConnectableObservable.prototype._subscribe = function (subscriber) {
728             return this.getSubject().subscribe(subscriber);
729         };
730         ConnectableObservable.prototype.getSubject = function () {
731             var subject = this._subject;
732             if (!subject || subject.isStopped) {
733                 this._subject = this.subjectFactory();
734             }
735             return this._subject;
736         };
737         ConnectableObservable.prototype._teardown = function () {
738             this._refCount = 0;
739             var _connection = this._connection;
740             this._subject = this._connection = null;
741             _connection === null || _connection === void 0 ? void 0 : _connection.unsubscribe();
742         };
743         ConnectableObservable.prototype.connect = function () {
744             var _this = this;
745             var connection = this._connection;
746             if (!connection) {
747                 connection = this._connection = new Subscription();
748                 var subject_1 = this.getSubject();
749                 connection.add(this.source.subscribe(new OperatorSubscriber(subject_1, undefined, function () {
750                     _this._teardown();
751                     subject_1.complete();
752                 }, function (err) {
753                     _this._teardown();
754                     subject_1.error(err);
755                 }, function () { return _this._teardown(); })));
756                 if (connection.closed) {
757                     this._connection = null;
758                     connection = Subscription.EMPTY;
759                 }
760             }
761             return connection;
762         };
763         ConnectableObservable.prototype.refCount = function () {
764             return refCount()(this);
765         };
766         return ConnectableObservable;
767     }(Observable));
768
769     var ObjectUnsubscribedError = createErrorClass(function (_super) {
770         return function ObjectUnsubscribedErrorImpl() {
771             _super(this);
772             this.name = 'ObjectUnsubscribedError';
773             this.message = 'object unsubscribed';
774         };
775     });
776
777     var Subject = (function (_super) {
778         __extends(Subject, _super);
779         function Subject() {
780             var _this = _super.call(this) || this;
781             _this.closed = false;
782             _this.observers = [];
783             _this.isStopped = false;
784             _this.hasError = false;
785             _this.thrownError = null;
786             return _this;
787         }
788         Subject.prototype.lift = function (operator) {
789             var subject = new AnonymousSubject(this, this);
790             subject.operator = operator;
791             return subject;
792         };
793         Subject.prototype._throwIfClosed = function () {
794             if (this.closed) {
795                 throw new ObjectUnsubscribedError();
796             }
797         };
798         Subject.prototype.next = function (value) {
799             var _this = this;
800             errorContext(function () {
801                 var e_1, _a;
802                 _this._throwIfClosed();
803                 if (!_this.isStopped) {
804                     var copy = _this.observers.slice();
805                     try {
806                         for (var copy_1 = __values(copy), copy_1_1 = copy_1.next(); !copy_1_1.done; copy_1_1 = copy_1.next()) {
807                             var observer = copy_1_1.value;
808                             observer.next(value);
809                         }
810                     }
811                     catch (e_1_1) { e_1 = { error: e_1_1 }; }
812                     finally {
813                         try {
814                             if (copy_1_1 && !copy_1_1.done && (_a = copy_1.return)) _a.call(copy_1);
815                         }
816                         finally { if (e_1) throw e_1.error; }
817                     }
818                 }
819             });
820         };
821         Subject.prototype.error = function (err) {
822             var _this = this;
823             errorContext(function () {
824                 _this._throwIfClosed();
825                 if (!_this.isStopped) {
826                     _this.hasError = _this.isStopped = true;
827                     _this.thrownError = err;
828                     var observers = _this.observers;
829                     while (observers.length) {
830                         observers.shift().error(err);
831                     }
832                 }
833             });
834         };
835         Subject.prototype.complete = function () {
836             var _this = this;
837             errorContext(function () {
838                 _this._throwIfClosed();
839                 if (!_this.isStopped) {
840                     _this.isStopped = true;
841                     var observers = _this.observers;
842                     while (observers.length) {
843                         observers.shift().complete();
844                     }
845                 }
846             });
847         };
848         Subject.prototype.unsubscribe = function () {
849             this.isStopped = this.closed = true;
850             this.observers = null;
851         };
852         Object.defineProperty(Subject.prototype, "observed", {
853             get: function () {
854                 var _a;
855                 return ((_a = this.observers) === null || _a === void 0 ? void 0 : _a.length) > 0;
856             },
857             enumerable: false,
858             configurable: true
859         });
860         Subject.prototype._trySubscribe = function (subscriber) {
861             this._throwIfClosed();
862             return _super.prototype._trySubscribe.call(this, subscriber);
863         };
864         Subject.prototype._subscribe = function (subscriber) {
865             this._throwIfClosed();
866             this._checkFinalizedStatuses(subscriber);
867             return this._innerSubscribe(subscriber);
868         };
869         Subject.prototype._innerSubscribe = function (subscriber) {
870             var _a = this, hasError = _a.hasError, isStopped = _a.isStopped, observers = _a.observers;
871             return hasError || isStopped
872                 ? EMPTY_SUBSCRIPTION
873                 : (observers.push(subscriber), new Subscription(function () { return arrRemove(observers, subscriber); }));
874         };
875         Subject.prototype._checkFinalizedStatuses = function (subscriber) {
876             var _a = this, hasError = _a.hasError, thrownError = _a.thrownError, isStopped = _a.isStopped;
877             if (hasError) {
878                 subscriber.error(thrownError);
879             }
880             else if (isStopped) {
881                 subscriber.complete();
882             }
883         };
884         Subject.prototype.asObservable = function () {
885             var observable = new Observable();
886             observable.source = this;
887             return observable;
888         };
889         Subject.create = function (destination, source) {
890             return new AnonymousSubject(destination, source);
891         };
892         return Subject;
893     }(Observable));
894     var AnonymousSubject = (function (_super) {
895         __extends(AnonymousSubject, _super);
896         function AnonymousSubject(destination, source) {
897             var _this = _super.call(this) || this;
898             _this.destination = destination;
899             _this.source = source;
900             return _this;
901         }
902         AnonymousSubject.prototype.next = function (value) {
903             var _a, _b;
904             (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.next) === null || _b === void 0 ? void 0 : _b.call(_a, value);
905         };
906         AnonymousSubject.prototype.error = function (err) {
907             var _a, _b;
908             (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.call(_a, err);
909         };
910         AnonymousSubject.prototype.complete = function () {
911             var _a, _b;
912             (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.complete) === null || _b === void 0 ? void 0 : _b.call(_a);
913         };
914         AnonymousSubject.prototype._subscribe = function (subscriber) {
915             var _a, _b;
916             return (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber)) !== null && _b !== void 0 ? _b : EMPTY_SUBSCRIPTION;
917         };
918         return AnonymousSubject;
919     }(Subject));
920
921     var BehaviorSubject = (function (_super) {
922         __extends(BehaviorSubject, _super);
923         function BehaviorSubject(_value) {
924             var _this = _super.call(this) || this;
925             _this._value = _value;
926             return _this;
927         }
928         Object.defineProperty(BehaviorSubject.prototype, "value", {
929             get: function () {
930                 return this.getValue();
931             },
932             enumerable: false,
933             configurable: true
934         });
935         BehaviorSubject.prototype._subscribe = function (subscriber) {
936             var subscription = _super.prototype._subscribe.call(this, subscriber);
937             !subscription.closed && subscriber.next(this._value);
938             return subscription;
939         };
940         BehaviorSubject.prototype.getValue = function () {
941             var _a = this, hasError = _a.hasError, thrownError = _a.thrownError, _value = _a._value;
942             if (hasError) {
943                 throw thrownError;
944             }
945             this._throwIfClosed();
946             return _value;
947         };
948         BehaviorSubject.prototype.next = function (value) {
949             _super.prototype.next.call(this, (this._value = value));
950         };
951         return BehaviorSubject;
952     }(Subject));
953
954     var dateTimestampProvider = {
955         now: function () {
956             return (dateTimestampProvider.delegate || Date).now();
957         },
958         delegate: undefined,
959     };
960
961     var ReplaySubject = (function (_super) {
962         __extends(ReplaySubject, _super);
963         function ReplaySubject(_bufferSize, _windowTime, _timestampProvider) {
964             if (_bufferSize === void 0) { _bufferSize = Infinity; }
965             if (_windowTime === void 0) { _windowTime = Infinity; }
966             if (_timestampProvider === void 0) { _timestampProvider = dateTimestampProvider; }
967             var _this = _super.call(this) || this;
968             _this._bufferSize = _bufferSize;
969             _this._windowTime = _windowTime;
970             _this._timestampProvider = _timestampProvider;
971             _this._buffer = [];
972             _this._infiniteTimeWindow = true;
973             _this._infiniteTimeWindow = _windowTime === Infinity;
974             _this._bufferSize = Math.max(1, _bufferSize);
975             _this._windowTime = Math.max(1, _windowTime);
976             return _this;
977         }
978         ReplaySubject.prototype.next = function (value) {
979             var _a = this, isStopped = _a.isStopped, _buffer = _a._buffer, _infiniteTimeWindow = _a._infiniteTimeWindow, _timestampProvider = _a._timestampProvider, _windowTime = _a._windowTime;
980             if (!isStopped) {
981                 _buffer.push(value);
982                 !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);
983             }
984             this._trimBuffer();
985             _super.prototype.next.call(this, value);
986         };
987         ReplaySubject.prototype._subscribe = function (subscriber) {
988             this._throwIfClosed();
989             this._trimBuffer();
990             var subscription = this._innerSubscribe(subscriber);
991             var _a = this, _infiniteTimeWindow = _a._infiniteTimeWindow, _buffer = _a._buffer;
992             var copy = _buffer.slice();
993             for (var i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {
994                 subscriber.next(copy[i]);
995             }
996             this._checkFinalizedStatuses(subscriber);
997             return subscription;
998         };
999         ReplaySubject.prototype._trimBuffer = function () {
1000             var _a = this, _bufferSize = _a._bufferSize, _timestampProvider = _a._timestampProvider, _buffer = _a._buffer, _infiniteTimeWindow = _a._infiniteTimeWindow;
1001             var adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;
1002             _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);
1003             if (!_infiniteTimeWindow) {
1004                 var now = _timestampProvider.now();
1005                 var last = 0;
1006                 for (var i = 1; i < _buffer.length && _buffer[i] <= now; i += 2) {
1007                     last = i;
1008                 }
1009                 last && _buffer.splice(0, last + 1);
1010             }
1011         };
1012         return ReplaySubject;
1013     }(Subject));
1014
1015     var Action = (function (_super) {
1016         __extends(Action, _super);
1017         function Action(scheduler, work) {
1018             return _super.call(this) || this;
1019         }
1020         Action.prototype.schedule = function (state, delay) {
1021             return this;
1022         };
1023         return Action;
1024     }(Subscription));
1025
1026     var intervalProvider = {
1027         setInterval: function () {
1028             var args = [];
1029             for (var _i = 0; _i < arguments.length; _i++) {
1030                 args[_i] = arguments[_i];
1031             }
1032             var delegate = intervalProvider.delegate;
1033             return ((delegate === null || delegate === void 0 ? void 0 : delegate.setInterval) || setInterval).apply(void 0, __spreadArray([], __read(args)));
1034         },
1035         clearInterval: function (handle) {
1036             var delegate = intervalProvider.delegate;
1037             return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearInterval) || clearInterval)(handle);
1038         },
1039         delegate: undefined,
1040     };
1041
1042     var AsyncAction = (function (_super) {
1043         __extends(AsyncAction, _super);
1044         function AsyncAction(scheduler, work) {
1045             var _this = _super.call(this, scheduler, work) || this;
1046             _this.scheduler = scheduler;
1047             _this.work = work;
1048             _this.pending = false;
1049             return _this;
1050         }
1051         AsyncAction.prototype.schedule = function (state, delay) {
1052             if (delay === void 0) { delay = 0; }
1053             if (this.closed) {
1054                 return this;
1055             }
1056             this.state = state;
1057             var id = this.id;
1058             var scheduler = this.scheduler;
1059             if (id != null) {
1060                 this.id = this.recycleAsyncId(scheduler, id, delay);
1061             }
1062             this.pending = true;
1063             this.delay = delay;
1064             this.id = this.id || this.requestAsyncId(scheduler, this.id, delay);
1065             return this;
1066         };
1067         AsyncAction.prototype.requestAsyncId = function (scheduler, _id, delay) {
1068             if (delay === void 0) { delay = 0; }
1069             return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);
1070         };
1071         AsyncAction.prototype.recycleAsyncId = function (_scheduler, id, delay) {
1072             if (delay === void 0) { delay = 0; }
1073             if (delay != null && this.delay === delay && this.pending === false) {
1074                 return id;
1075             }
1076             intervalProvider.clearInterval(id);
1077             return undefined;
1078         };
1079         AsyncAction.prototype.execute = function (state, delay) {
1080             if (this.closed) {
1081                 return new Error('executing a cancelled action');
1082             }
1083             this.pending = false;
1084             var error = this._execute(state, delay);
1085             if (error) {
1086                 return error;
1087             }
1088             else if (this.pending === false && this.id != null) {
1089                 this.id = this.recycleAsyncId(this.scheduler, this.id, null);
1090             }
1091         };
1092         AsyncAction.prototype._execute = function (state, _delay) {
1093             var errored = false;
1094             var errorValue;
1095             try {
1096                 this.work(state);
1097             }
1098             catch (e) {
1099                 errored = true;
1100                 errorValue = (!!e && e) || new Error(e);
1101             }
1102             if (errored) {
1103                 this.unsubscribe();
1104                 return errorValue;
1105             }
1106         };
1107         AsyncAction.prototype.unsubscribe = function () {
1108             if (!this.closed) {
1109                 var _a = this, id = _a.id, scheduler = _a.scheduler;
1110                 var actions = scheduler.actions;
1111                 this.work = this.state = this.scheduler = null;
1112                 this.pending = false;
1113                 arrRemove(actions, this);
1114                 if (id != null) {
1115                     this.id = this.recycleAsyncId(scheduler, id, null);
1116                 }
1117                 this.delay = null;
1118                 _super.prototype.unsubscribe.call(this);
1119             }
1120         };
1121         return AsyncAction;
1122     }(Action));
1123
1124     var Scheduler = (function () {
1125         function Scheduler(schedulerActionCtor, now) {
1126             if (now === void 0) { now = Scheduler.now; }
1127             this.schedulerActionCtor = schedulerActionCtor;
1128             this.now = now;
1129         }
1130         Scheduler.prototype.schedule = function (work, delay, state) {
1131             if (delay === void 0) { delay = 0; }
1132             return new this.schedulerActionCtor(this, work).schedule(state, delay);
1133         };
1134         Scheduler.now = dateTimestampProvider.now;
1135         return Scheduler;
1136     }());
1137
1138     var AsyncScheduler = (function (_super) {
1139         __extends(AsyncScheduler, _super);
1140         function AsyncScheduler(SchedulerAction, now) {
1141             if (now === void 0) { now = Scheduler.now; }
1142             var _this = _super.call(this, SchedulerAction, now) || this;
1143             _this.actions = [];
1144             _this._active = false;
1145             _this._scheduled = undefined;
1146             return _this;
1147         }
1148         AsyncScheduler.prototype.flush = function (action) {
1149             var actions = this.actions;
1150             if (this._active) {
1151                 actions.push(action);
1152                 return;
1153             }
1154             var error;
1155             this._active = true;
1156             do {
1157                 if ((error = action.execute(action.state, action.delay))) {
1158                     break;
1159                 }
1160             } while ((action = actions.shift()));
1161             this._active = false;
1162             if (error) {
1163                 while ((action = actions.shift())) {
1164                     action.unsubscribe();
1165                 }
1166                 throw error;
1167             }
1168         };
1169         return AsyncScheduler;
1170     }(Scheduler));
1171
1172     var asyncScheduler = new AsyncScheduler(AsyncAction);
1173     var async = asyncScheduler;
1174
1175     var EMPTY$1 = new Observable(function (subscriber) { return subscriber.complete(); });
1176     function empty(scheduler) {
1177         return scheduler ? emptyScheduled(scheduler) : EMPTY$1;
1178     }
1179     function emptyScheduled(scheduler) {
1180         return new Observable(function (subscriber) { return scheduler.schedule(function () { return subscriber.complete(); }); });
1181     }
1182
1183     function scheduleArray(input, scheduler) {
1184         return new Observable(function (subscriber) {
1185             var i = 0;
1186             return scheduler.schedule(function () {
1187                 if (i === input.length) {
1188                     subscriber.complete();
1189                 }
1190                 else {
1191                     subscriber.next(input[i++]);
1192                     if (!subscriber.closed) {
1193                         this.schedule();
1194                     }
1195                 }
1196             });
1197         });
1198     }
1199
1200     var isArrayLike = (function (x) { return x && typeof x.length === 'number' && typeof x !== 'function'; });
1201
1202     function isPromise(value) {
1203         return isFunction(value === null || value === void 0 ? void 0 : value.then);
1204     }
1205
1206     function scheduleObservable(input, scheduler) {
1207         return new Observable(function (subscriber) {
1208             var sub = new Subscription();
1209             sub.add(scheduler.schedule(function () {
1210                 var observable$1 = input[observable]();
1211                 sub.add(observable$1.subscribe({
1212                     next: function (value) { sub.add(scheduler.schedule(function () { return subscriber.next(value); })); },
1213                     error: function (err) { sub.add(scheduler.schedule(function () { return subscriber.error(err); })); },
1214                     complete: function () { sub.add(scheduler.schedule(function () { return subscriber.complete(); })); },
1215                 }));
1216             }));
1217             return sub;
1218         });
1219     }
1220
1221     function schedulePromise(input, scheduler) {
1222         return new Observable(function (subscriber) {
1223             return scheduler.schedule(function () {
1224                 return input.then(function (value) {
1225                     subscriber.add(scheduler.schedule(function () {
1226                         subscriber.next(value);
1227                         subscriber.add(scheduler.schedule(function () { return subscriber.complete(); }));
1228                     }));
1229                 }, function (err) {
1230                     subscriber.add(scheduler.schedule(function () { return subscriber.error(err); }));
1231                 });
1232             });
1233         });
1234     }
1235
1236     function getSymbolIterator() {
1237         if (typeof Symbol !== 'function' || !Symbol.iterator) {
1238             return '@@iterator';
1239         }
1240         return Symbol.iterator;
1241     }
1242     var iterator = getSymbolIterator();
1243
1244     function caughtSchedule(subscriber, scheduler, execute, delay) {
1245         if (delay === void 0) { delay = 0; }
1246         var subscription = scheduler.schedule(function () {
1247             try {
1248                 execute.call(this);
1249             }
1250             catch (err) {
1251                 subscriber.error(err);
1252             }
1253         }, delay);
1254         subscriber.add(subscription);
1255         return subscription;
1256     }
1257
1258     function scheduleIterable(input, scheduler) {
1259         return new Observable(function (subscriber) {
1260             var iterator$1;
1261             subscriber.add(scheduler.schedule(function () {
1262                 iterator$1 = input[iterator]();
1263                 caughtSchedule(subscriber, scheduler, function () {
1264                     var _a = iterator$1.next(), value = _a.value, done = _a.done;
1265                     if (done) {
1266                         subscriber.complete();
1267                     }
1268                     else {
1269                         subscriber.next(value);
1270                         this.schedule();
1271                     }
1272                 });
1273             }));
1274             return function () { return isFunction(iterator$1 === null || iterator$1 === void 0 ? void 0 : iterator$1.return) && iterator$1.return(); };
1275         });
1276     }
1277
1278     function scheduleAsyncIterable(input, scheduler) {
1279         if (!input) {
1280             throw new Error('Iterable cannot be null');
1281         }
1282         return new Observable(function (subscriber) {
1283             var sub = new Subscription();
1284             sub.add(scheduler.schedule(function () {
1285                 var iterator = input[Symbol.asyncIterator]();
1286                 sub.add(scheduler.schedule(function () {
1287                     var _this = this;
1288                     iterator.next().then(function (result) {
1289                         if (result.done) {
1290                             subscriber.complete();
1291                         }
1292                         else {
1293                             subscriber.next(result.value);
1294                             _this.schedule();
1295                         }
1296                     });
1297                 }));
1298             }));
1299             return sub;
1300         });
1301     }
1302
1303     function isInteropObservable(input) {
1304         return isFunction(input[observable]);
1305     }
1306
1307     function isIterable(input) {
1308         return isFunction(input === null || input === void 0 ? void 0 : input[iterator]);
1309     }
1310
1311     function isAsyncIterable(obj) {
1312         return Symbol.asyncIterator && isFunction(obj === null || obj === void 0 ? void 0 : obj[Symbol.asyncIterator]);
1313     }
1314
1315     function createInvalidObservableTypeError(input) {
1316         return new TypeError("You provided " + (input !== null && typeof input === 'object' ? 'an invalid object' : "'" + input + "'") + " where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.");
1317     }
1318
1319     function readableStreamLikeToAsyncGenerator(readableStream) {
1320         return __asyncGenerator(this, arguments, function readableStreamLikeToAsyncGenerator_1() {
1321             var reader, _a, value, done;
1322             return __generator(this, function (_b) {
1323                 switch (_b.label) {
1324                     case 0:
1325                         reader = readableStream.getReader();
1326                         _b.label = 1;
1327                     case 1:
1328                         _b.trys.push([1, , 9, 10]);
1329                         _b.label = 2;
1330                     case 2:
1331                         return [4, __await(reader.read())];
1332                     case 3:
1333                         _a = _b.sent(), value = _a.value, done = _a.done;
1334                         if (!done) return [3, 5];
1335                         return [4, __await(void 0)];
1336                     case 4: return [2, _b.sent()];
1337                     case 5: return [4, __await(value)];
1338                     case 6: return [4, _b.sent()];
1339                     case 7:
1340                         _b.sent();
1341                         return [3, 2];
1342                     case 8: return [3, 10];
1343                     case 9:
1344                         reader.releaseLock();
1345                         return [7];
1346                     case 10: return [2];
1347                 }
1348             });
1349         });
1350     }
1351     function isReadableStreamLike(obj) {
1352         return isFunction(obj === null || obj === void 0 ? void 0 : obj.getReader);
1353     }
1354
1355     function scheduleReadableStreamLike(input, scheduler) {
1356         return scheduleAsyncIterable(readableStreamLikeToAsyncGenerator(input), scheduler);
1357     }
1358
1359     function scheduled(input, scheduler) {
1360         if (input != null) {
1361             if (isInteropObservable(input)) {
1362                 return scheduleObservable(input, scheduler);
1363             }
1364             if (isArrayLike(input)) {
1365                 return scheduleArray(input, scheduler);
1366             }
1367             if (isPromise(input)) {
1368                 return schedulePromise(input, scheduler);
1369             }
1370             if (isAsyncIterable(input)) {
1371                 return scheduleAsyncIterable(input, scheduler);
1372             }
1373             if (isIterable(input)) {
1374                 return scheduleIterable(input, scheduler);
1375             }
1376             if (isReadableStreamLike(input)) {
1377                 return scheduleReadableStreamLike(input, scheduler);
1378             }
1379         }
1380         throw createInvalidObservableTypeError(input);
1381     }
1382
1383     function from(input, scheduler) {
1384         return scheduler ? scheduled(input, scheduler) : innerFrom(input);
1385     }
1386     function innerFrom(input) {
1387         if (input instanceof Observable) {
1388             return input;
1389         }
1390         if (input != null) {
1391             if (isInteropObservable(input)) {
1392                 return fromInteropObservable(input);
1393             }
1394             if (isArrayLike(input)) {
1395                 return fromArrayLike(input);
1396             }
1397             if (isPromise(input)) {
1398                 return fromPromise(input);
1399             }
1400             if (isAsyncIterable(input)) {
1401                 return fromAsyncIterable(input);
1402             }
1403             if (isIterable(input)) {
1404                 return fromIterable(input);
1405             }
1406             if (isReadableStreamLike(input)) {
1407                 return fromReadableStreamLike(input);
1408             }
1409         }
1410         throw createInvalidObservableTypeError(input);
1411     }
1412     function fromInteropObservable(obj) {
1413         return new Observable(function (subscriber) {
1414             var obs = obj[observable]();
1415             if (isFunction(obs.subscribe)) {
1416                 return obs.subscribe(subscriber);
1417             }
1418             throw new TypeError('Provided object does not correctly implement Symbol.observable');
1419         });
1420     }
1421     function fromArrayLike(array) {
1422         return new Observable(function (subscriber) {
1423             for (var i = 0; i < array.length && !subscriber.closed; i++) {
1424                 subscriber.next(array[i]);
1425             }
1426             subscriber.complete();
1427         });
1428     }
1429     function fromPromise(promise) {
1430         return new Observable(function (subscriber) {
1431             promise
1432                 .then(function (value) {
1433                 if (!subscriber.closed) {
1434                     subscriber.next(value);
1435                     subscriber.complete();
1436                 }
1437             }, function (err) { return subscriber.error(err); })
1438                 .then(null, reportUnhandledError);
1439         });
1440     }
1441     function fromIterable(iterable) {
1442         return new Observable(function (subscriber) {
1443             var e_1, _a;
1444             try {
1445                 for (var iterable_1 = __values(iterable), iterable_1_1 = iterable_1.next(); !iterable_1_1.done; iterable_1_1 = iterable_1.next()) {
1446                     var value = iterable_1_1.value;
1447                     subscriber.next(value);
1448                     if (subscriber.closed) {
1449                         return;
1450                     }
1451                 }
1452             }
1453             catch (e_1_1) { e_1 = { error: e_1_1 }; }
1454             finally {
1455                 try {
1456                     if (iterable_1_1 && !iterable_1_1.done && (_a = iterable_1.return)) _a.call(iterable_1);
1457                 }
1458                 finally { if (e_1) throw e_1.error; }
1459             }
1460             subscriber.complete();
1461         });
1462     }
1463     function fromAsyncIterable(asyncIterable) {
1464         return new Observable(function (subscriber) {
1465             process(asyncIterable, subscriber).catch(function (err) { return subscriber.error(err); });
1466         });
1467     }
1468     function fromReadableStreamLike(readableStream) {
1469         return fromAsyncIterable(readableStreamLikeToAsyncGenerator(readableStream));
1470     }
1471     function process(asyncIterable, subscriber) {
1472         var asyncIterable_1, asyncIterable_1_1;
1473         var e_2, _a;
1474         return __awaiter(this, void 0, void 0, function () {
1475             var value, e_2_1;
1476             return __generator(this, function (_b) {
1477                 switch (_b.label) {
1478                     case 0:
1479                         _b.trys.push([0, 5, 6, 11]);
1480                         asyncIterable_1 = __asyncValues(asyncIterable);
1481                         _b.label = 1;
1482                     case 1: return [4, asyncIterable_1.next()];
1483                     case 2:
1484                         if (!(asyncIterable_1_1 = _b.sent(), !asyncIterable_1_1.done)) return [3, 4];
1485                         value = asyncIterable_1_1.value;
1486                         subscriber.next(value);
1487                         if (subscriber.closed) {
1488                             return [2];
1489                         }
1490                         _b.label = 3;
1491                     case 3: return [3, 1];
1492                     case 4: return [3, 11];
1493                     case 5:
1494                         e_2_1 = _b.sent();
1495                         e_2 = { error: e_2_1 };
1496                         return [3, 11];
1497                     case 6:
1498                         _b.trys.push([6, , 9, 10]);
1499                         if (!(asyncIterable_1_1 && !asyncIterable_1_1.done && (_a = asyncIterable_1.return))) return [3, 8];
1500                         return [4, _a.call(asyncIterable_1)];
1501                     case 7:
1502                         _b.sent();
1503                         _b.label = 8;
1504                     case 8: return [3, 10];
1505                     case 9:
1506                         if (e_2) throw e_2.error;
1507                         return [7];
1508                     case 10: return [7];
1509                     case 11:
1510                         subscriber.complete();
1511                         return [2];
1512                 }
1513             });
1514         });
1515     }
1516
1517     function internalFromArray(input, scheduler) {
1518         return scheduler ? scheduleArray(input, scheduler) : fromArrayLike(input);
1519     }
1520
1521     function isScheduler(value) {
1522         return value && isFunction(value.schedule);
1523     }
1524
1525     function last$1(arr) {
1526         return arr[arr.length - 1];
1527     }
1528     function popResultSelector(args) {
1529         return isFunction(last$1(args)) ? args.pop() : undefined;
1530     }
1531     function popScheduler(args) {
1532         return isScheduler(last$1(args)) ? args.pop() : undefined;
1533     }
1534     function popNumber(args, defaultValue) {
1535         return typeof last$1(args) === 'number' ? args.pop() : defaultValue;
1536     }
1537
1538     function of() {
1539         var args = [];
1540         for (var _i = 0; _i < arguments.length; _i++) {
1541             args[_i] = arguments[_i];
1542         }
1543         var scheduler = popScheduler(args);
1544         return scheduler ? scheduleArray(args, scheduler) : internalFromArray(args);
1545     }
1546
1547     function throwError(errorOrErrorFactory, scheduler) {
1548         var errorFactory = isFunction(errorOrErrorFactory) ? errorOrErrorFactory : function () { return errorOrErrorFactory; };
1549         var init = function (subscriber) { return subscriber.error(errorFactory()); };
1550         return new Observable(scheduler ? function (subscriber) { return scheduler.schedule(init, 0, subscriber); } : init);
1551     }
1552
1553     var EmptyError = createErrorClass(function (_super) { return function EmptyErrorImpl() {
1554         _super(this);
1555         this.name = 'EmptyError';
1556         this.message = 'no elements in sequence';
1557     }; });
1558
1559     function isValidDate(value) {
1560         return value instanceof Date && !isNaN(value);
1561     }
1562
1563     var TimeoutError = createErrorClass(function (_super) {
1564         return function TimeoutErrorImpl(info) {
1565             if (info === void 0) { info = null; }
1566             _super(this);
1567             this.message = 'Timeout has occurred';
1568             this.name = 'TimeoutError';
1569             this.info = info;
1570         };
1571     });
1572     function timeout(config, schedulerArg) {
1573         var _a = (isValidDate(config)
1574             ? { first: config }
1575             : typeof config === 'number'
1576                 ? { each: config }
1577                 : config), first = _a.first, each = _a.each, _b = _a.with, _with = _b === void 0 ? timeoutErrorFactory : _b, _c = _a.scheduler, scheduler = _c === void 0 ? schedulerArg !== null && schedulerArg !== void 0 ? schedulerArg : asyncScheduler : _c, _d = _a.meta, meta = _d === void 0 ? null : _d;
1578         if (first == null && each == null) {
1579             throw new TypeError('No timeout provided.');
1580         }
1581         return operate(function (source, subscriber) {
1582             var originalSourceSubscription;
1583             var timerSubscription;
1584             var lastValue = null;
1585             var seen = 0;
1586             var startTimer = function (delay) {
1587                 timerSubscription = caughtSchedule(subscriber, scheduler, function () {
1588                     originalSourceSubscription.unsubscribe();
1589                     innerFrom(_with({
1590                         meta: meta,
1591                         lastValue: lastValue,
1592                         seen: seen,
1593                     })).subscribe(subscriber);
1594                 }, delay);
1595             };
1596             originalSourceSubscription = source.subscribe(new OperatorSubscriber(subscriber, function (value) {
1597                 timerSubscription === null || timerSubscription === void 0 ? void 0 : timerSubscription.unsubscribe();
1598                 seen++;
1599                 subscriber.next((lastValue = value));
1600                 each > 0 && startTimer(each);
1601             }, undefined, undefined, function () {
1602                 if (!(timerSubscription === null || timerSubscription === void 0 ? void 0 : timerSubscription.closed)) {
1603                     timerSubscription === null || timerSubscription === void 0 ? void 0 : timerSubscription.unsubscribe();
1604                 }
1605                 lastValue = null;
1606             }));
1607             startTimer(first != null ? (typeof first === 'number' ? first : +first - scheduler.now()) : each);
1608         });
1609     }
1610     function timeoutErrorFactory(info) {
1611         throw new TimeoutError(info);
1612     }
1613
1614     function map(project, thisArg) {
1615         return operate(function (source, subscriber) {
1616             var index = 0;
1617             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
1618                 subscriber.next(project.call(thisArg, value, index++));
1619             }));
1620         });
1621     }
1622
1623     var isArray$6 = Array.isArray;
1624     function callOrApply(fn, args) {
1625         return isArray$6(args) ? fn.apply(void 0, __spreadArray([], __read(args))) : fn(args);
1626     }
1627     function mapOneOrManyArgs(fn) {
1628         return map(function (args) { return callOrApply(fn, args); });
1629     }
1630
1631     var isArray$5 = Array.isArray;
1632     var getPrototypeOf = Object.getPrototypeOf, objectProto = Object.prototype, getKeys = Object.keys;
1633     function argsArgArrayOrObject(args) {
1634         if (args.length === 1) {
1635             var first_1 = args[0];
1636             if (isArray$5(first_1)) {
1637                 return { args: first_1, keys: null };
1638             }
1639             if (isPOJO(first_1)) {
1640                 var keys = getKeys(first_1);
1641                 return {
1642                     args: keys.map(function (key) { return first_1[key]; }),
1643                     keys: keys,
1644                 };
1645             }
1646         }
1647         return { args: args, keys: null };
1648     }
1649     function isPOJO(obj) {
1650         return obj && typeof obj === 'object' && getPrototypeOf(obj) === objectProto;
1651     }
1652
1653     function createObject(keys, values) {
1654         return keys.reduce(function (result, key, i) { return ((result[key] = values[i]), result); }, {});
1655     }
1656
1657     function combineLatest() {
1658         var args = [];
1659         for (var _i = 0; _i < arguments.length; _i++) {
1660             args[_i] = arguments[_i];
1661         }
1662         var scheduler = popScheduler(args);
1663         var resultSelector = popResultSelector(args);
1664         var _a = argsArgArrayOrObject(args), observables = _a.args, keys = _a.keys;
1665         if (observables.length === 0) {
1666             return from([], scheduler);
1667         }
1668         var result = new Observable(combineLatestInit(observables, scheduler, keys
1669             ?
1670                 function (values) { return createObject(keys, values); }
1671             :
1672                 identity));
1673         return resultSelector ? result.pipe(mapOneOrManyArgs(resultSelector)) : result;
1674     }
1675     function combineLatestInit(observables, scheduler, valueTransform) {
1676         if (valueTransform === void 0) { valueTransform = identity; }
1677         return function (subscriber) {
1678             maybeSchedule(scheduler, function () {
1679                 var length = observables.length;
1680                 var values = new Array(length);
1681                 var active = length;
1682                 var remainingFirstValues = length;
1683                 var _loop_1 = function (i) {
1684                     maybeSchedule(scheduler, function () {
1685                         var source = from(observables[i], scheduler);
1686                         var hasFirstValue = false;
1687                         source.subscribe(new OperatorSubscriber(subscriber, function (value) {
1688                             values[i] = value;
1689                             if (!hasFirstValue) {
1690                                 hasFirstValue = true;
1691                                 remainingFirstValues--;
1692                             }
1693                             if (!remainingFirstValues) {
1694                                 subscriber.next(valueTransform(values.slice()));
1695                             }
1696                         }, function () {
1697                             if (!--active) {
1698                                 subscriber.complete();
1699                             }
1700                         }));
1701                     }, subscriber);
1702                 };
1703                 for (var i = 0; i < length; i++) {
1704                     _loop_1(i);
1705                 }
1706             }, subscriber);
1707         };
1708     }
1709     function maybeSchedule(scheduler, execute, subscription) {
1710         if (scheduler) {
1711             subscription.add(scheduler.schedule(execute));
1712         }
1713         else {
1714             execute();
1715         }
1716     }
1717
1718     function mergeInternals(source, subscriber, project, concurrent, onBeforeNext, expand, innerSubScheduler, additionalTeardown) {
1719         var buffer = [];
1720         var active = 0;
1721         var index = 0;
1722         var isComplete = false;
1723         var checkComplete = function () {
1724             if (isComplete && !buffer.length && !active) {
1725                 subscriber.complete();
1726             }
1727         };
1728         var outerNext = function (value) { return (active < concurrent ? doInnerSub(value) : buffer.push(value)); };
1729         var doInnerSub = function (value) {
1730             expand && subscriber.next(value);
1731             active++;
1732             var innerComplete = false;
1733             innerFrom(project(value, index++)).subscribe(new OperatorSubscriber(subscriber, function (innerValue) {
1734                 onBeforeNext === null || onBeforeNext === void 0 ? void 0 : onBeforeNext(innerValue);
1735                 if (expand) {
1736                     outerNext(innerValue);
1737                 }
1738                 else {
1739                     subscriber.next(innerValue);
1740                 }
1741             }, function () {
1742                 innerComplete = true;
1743             }, undefined, function () {
1744                 if (innerComplete) {
1745                     try {
1746                         active--;
1747                         var _loop_1 = function () {
1748                             var bufferedValue = buffer.shift();
1749                             innerSubScheduler ? subscriber.add(innerSubScheduler.schedule(function () { return doInnerSub(bufferedValue); })) : doInnerSub(bufferedValue);
1750                         };
1751                         while (buffer.length && active < concurrent) {
1752                             _loop_1();
1753                         }
1754                         checkComplete();
1755                     }
1756                     catch (err) {
1757                         subscriber.error(err);
1758                     }
1759                 }
1760             }));
1761         };
1762         source.subscribe(new OperatorSubscriber(subscriber, outerNext, function () {
1763             isComplete = true;
1764             checkComplete();
1765         }));
1766         return function () {
1767             additionalTeardown === null || additionalTeardown === void 0 ? void 0 : additionalTeardown();
1768         };
1769     }
1770
1771     function mergeMap(project, resultSelector, concurrent) {
1772         if (concurrent === void 0) { concurrent = Infinity; }
1773         if (isFunction(resultSelector)) {
1774             return mergeMap(function (a, i) { return map(function (b, ii) { return resultSelector(a, b, i, ii); })(innerFrom(project(a, i))); }, concurrent);
1775         }
1776         else if (typeof resultSelector === 'number') {
1777             concurrent = resultSelector;
1778         }
1779         return operate(function (source, subscriber) { return mergeInternals(source, subscriber, project, concurrent); });
1780     }
1781
1782     function mergeAll(concurrent) {
1783         if (concurrent === void 0) { concurrent = Infinity; }
1784         return mergeMap(identity, concurrent);
1785     }
1786
1787     function concatAll() {
1788         return mergeAll(1);
1789     }
1790
1791     function concat() {
1792         var args = [];
1793         for (var _i = 0; _i < arguments.length; _i++) {
1794             args[_i] = arguments[_i];
1795         }
1796         return concatAll()(internalFromArray(args, popScheduler(args)));
1797     }
1798
1799     var nodeEventEmitterMethods = ['addListener', 'removeListener'];
1800     var eventTargetMethods = ['addEventListener', 'removeEventListener'];
1801     var jqueryMethods = ['on', 'off'];
1802     function fromEvent(target, eventName, options, resultSelector) {
1803         if (isFunction(options)) {
1804             resultSelector = options;
1805             options = undefined;
1806         }
1807         if (resultSelector) {
1808             return fromEvent(target, eventName, options).pipe(mapOneOrManyArgs(resultSelector));
1809         }
1810         var _a = __read(isEventTarget(target)
1811             ? eventTargetMethods.map(function (methodName) { return function (handler) { return target[methodName](eventName, handler, options); }; })
1812             :
1813                 isNodeStyleEventEmitter(target)
1814                     ? nodeEventEmitterMethods.map(toCommonHandlerRegistry(target, eventName))
1815                     : isJQueryStyleEventEmitter(target)
1816                         ? jqueryMethods.map(toCommonHandlerRegistry(target, eventName))
1817                         : [], 2), add = _a[0], remove = _a[1];
1818         if (!add) {
1819             if (isArrayLike(target)) {
1820                 return mergeMap(function (subTarget) { return fromEvent(subTarget, eventName, options); })(internalFromArray(target));
1821             }
1822         }
1823         if (!add) {
1824             throw new TypeError('Invalid event target');
1825         }
1826         return new Observable(function (subscriber) {
1827             var handler = function () {
1828                 var args = [];
1829                 for (var _i = 0; _i < arguments.length; _i++) {
1830                     args[_i] = arguments[_i];
1831                 }
1832                 return subscriber.next(1 < args.length ? args : args[0]);
1833             };
1834             add(handler);
1835             return function () { return remove(handler); };
1836         });
1837     }
1838     function toCommonHandlerRegistry(target, eventName) {
1839         return function (methodName) { return function (handler) { return target[methodName](eventName, handler); }; };
1840     }
1841     function isNodeStyleEventEmitter(target) {
1842         return isFunction(target.addListener) && isFunction(target.removeListener);
1843     }
1844     function isJQueryStyleEventEmitter(target) {
1845         return isFunction(target.on) && isFunction(target.off);
1846     }
1847     function isEventTarget(target) {
1848         return isFunction(target.addEventListener) && isFunction(target.removeEventListener);
1849     }
1850
1851     function timer(dueTime, intervalOrScheduler, scheduler) {
1852         if (dueTime === void 0) { dueTime = 0; }
1853         if (scheduler === void 0) { scheduler = async; }
1854         var intervalDuration = -1;
1855         if (intervalOrScheduler != null) {
1856             if (isScheduler(intervalOrScheduler)) {
1857                 scheduler = intervalOrScheduler;
1858             }
1859             else {
1860                 intervalDuration = intervalOrScheduler;
1861             }
1862         }
1863         return new Observable(function (subscriber) {
1864             var due = isValidDate(dueTime) ? +dueTime - scheduler.now() : dueTime;
1865             if (due < 0) {
1866                 due = 0;
1867             }
1868             var n = 0;
1869             return scheduler.schedule(function () {
1870                 if (!subscriber.closed) {
1871                     subscriber.next(n++);
1872                     if (0 <= intervalDuration) {
1873                         this.schedule(undefined, intervalDuration);
1874                     }
1875                     else {
1876                         subscriber.complete();
1877                     }
1878                 }
1879             }, due);
1880         });
1881     }
1882
1883     function merge() {
1884         var args = [];
1885         for (var _i = 0; _i < arguments.length; _i++) {
1886             args[_i] = arguments[_i];
1887         }
1888         var scheduler = popScheduler(args);
1889         var concurrent = popNumber(args, Infinity);
1890         var sources = args;
1891         return !sources.length
1892             ?
1893                 EMPTY$1
1894             : sources.length === 1
1895                 ?
1896                     innerFrom(sources[0])
1897                 :
1898                     mergeAll(concurrent)(internalFromArray(sources, scheduler));
1899     }
1900
1901     var isArray$4 = Array.isArray;
1902     function argsOrArgArray(args) {
1903         return args.length === 1 && isArray$4(args[0]) ? args[0] : args;
1904     }
1905
1906     function filter(predicate, thisArg) {
1907         return operate(function (source, subscriber) {
1908             var index = 0;
1909             source.subscribe(new OperatorSubscriber(subscriber, function (value) { return predicate.call(thisArg, value, index++) && subscriber.next(value); }));
1910         });
1911     }
1912
1913     function zip() {
1914         var args = [];
1915         for (var _i = 0; _i < arguments.length; _i++) {
1916             args[_i] = arguments[_i];
1917         }
1918         var resultSelector = popResultSelector(args);
1919         var sources = argsOrArgArray(args);
1920         return sources.length
1921             ? new Observable(function (subscriber) {
1922                 var buffers = sources.map(function () { return []; });
1923                 var completed = sources.map(function () { return false; });
1924                 subscriber.add(function () {
1925                     buffers = completed = null;
1926                 });
1927                 var _loop_1 = function (sourceIndex) {
1928                     innerFrom(sources[sourceIndex]).subscribe(new OperatorSubscriber(subscriber, function (value) {
1929                         buffers[sourceIndex].push(value);
1930                         if (buffers.every(function (buffer) { return buffer.length; })) {
1931                             var result = buffers.map(function (buffer) { return buffer.shift(); });
1932                             subscriber.next(resultSelector ? resultSelector.apply(void 0, __spreadArray([], __read(result))) : result);
1933                             if (buffers.some(function (buffer, i) { return !buffer.length && completed[i]; })) {
1934                                 subscriber.complete();
1935                             }
1936                         }
1937                     }, function () {
1938                         completed[sourceIndex] = true;
1939                         !buffers[sourceIndex].length && subscriber.complete();
1940                     }));
1941                 };
1942                 for (var sourceIndex = 0; !subscriber.closed && sourceIndex < sources.length; sourceIndex++) {
1943                     _loop_1(sourceIndex);
1944                 }
1945                 return function () {
1946                     buffers = completed = null;
1947                 };
1948             })
1949             : EMPTY$1;
1950     }
1951
1952     function audit(durationSelector) {
1953         return operate(function (source, subscriber) {
1954             var hasValue = false;
1955             var lastValue = null;
1956             var durationSubscriber = null;
1957             var isComplete = false;
1958             var endDuration = function () {
1959                 durationSubscriber === null || durationSubscriber === void 0 ? void 0 : durationSubscriber.unsubscribe();
1960                 durationSubscriber = null;
1961                 if (hasValue) {
1962                     hasValue = false;
1963                     var value = lastValue;
1964                     lastValue = null;
1965                     subscriber.next(value);
1966                 }
1967                 isComplete && subscriber.complete();
1968             };
1969             var cleanupDuration = function () {
1970                 durationSubscriber = null;
1971                 isComplete && subscriber.complete();
1972             };
1973             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
1974                 hasValue = true;
1975                 lastValue = value;
1976                 if (!durationSubscriber) {
1977                     innerFrom(durationSelector(value)).subscribe((durationSubscriber = new OperatorSubscriber(subscriber, endDuration, cleanupDuration)));
1978                 }
1979             }, function () {
1980                 isComplete = true;
1981                 (!hasValue || !durationSubscriber || durationSubscriber.closed) && subscriber.complete();
1982             }));
1983         });
1984     }
1985
1986     function auditTime(duration, scheduler) {
1987         if (scheduler === void 0) { scheduler = async; }
1988         return audit(function () { return timer(duration, scheduler); });
1989     }
1990
1991     function bufferCount(bufferSize, startBufferEvery) {
1992         if (startBufferEvery === void 0) { startBufferEvery = null; }
1993         startBufferEvery = startBufferEvery !== null && startBufferEvery !== void 0 ? startBufferEvery : bufferSize;
1994         return operate(function (source, subscriber) {
1995             var buffers = [];
1996             var count = 0;
1997             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
1998                 var e_1, _a, e_2, _b;
1999                 var toEmit = null;
2000                 if (count++ % startBufferEvery === 0) {
2001                     buffers.push([]);
2002                 }
2003                 try {
2004                     for (var buffers_1 = __values(buffers), buffers_1_1 = buffers_1.next(); !buffers_1_1.done; buffers_1_1 = buffers_1.next()) {
2005                         var buffer = buffers_1_1.value;
2006                         buffer.push(value);
2007                         if (bufferSize <= buffer.length) {
2008                             toEmit = toEmit !== null && toEmit !== void 0 ? toEmit : [];
2009                             toEmit.push(buffer);
2010                         }
2011                     }
2012                 }
2013                 catch (e_1_1) { e_1 = { error: e_1_1 }; }
2014                 finally {
2015                     try {
2016                         if (buffers_1_1 && !buffers_1_1.done && (_a = buffers_1.return)) _a.call(buffers_1);
2017                     }
2018                     finally { if (e_1) throw e_1.error; }
2019                 }
2020                 if (toEmit) {
2021                     try {
2022                         for (var toEmit_1 = __values(toEmit), toEmit_1_1 = toEmit_1.next(); !toEmit_1_1.done; toEmit_1_1 = toEmit_1.next()) {
2023                             var buffer = toEmit_1_1.value;
2024                             arrRemove(buffers, buffer);
2025                             subscriber.next(buffer);
2026                         }
2027                     }
2028                     catch (e_2_1) { e_2 = { error: e_2_1 }; }
2029                     finally {
2030                         try {
2031                             if (toEmit_1_1 && !toEmit_1_1.done && (_b = toEmit_1.return)) _b.call(toEmit_1);
2032                         }
2033                         finally { if (e_2) throw e_2.error; }
2034                     }
2035                 }
2036             }, function () {
2037                 var e_3, _a;
2038                 try {
2039                     for (var buffers_2 = __values(buffers), buffers_2_1 = buffers_2.next(); !buffers_2_1.done; buffers_2_1 = buffers_2.next()) {
2040                         var buffer = buffers_2_1.value;
2041                         subscriber.next(buffer);
2042                     }
2043                 }
2044                 catch (e_3_1) { e_3 = { error: e_3_1 }; }
2045                 finally {
2046                     try {
2047                         if (buffers_2_1 && !buffers_2_1.done && (_a = buffers_2.return)) _a.call(buffers_2);
2048                     }
2049                     finally { if (e_3) throw e_3.error; }
2050                 }
2051                 subscriber.complete();
2052             }, undefined, function () {
2053                 buffers = null;
2054             }));
2055         });
2056     }
2057
2058     function bufferWhen(closingSelector) {
2059         return operate(function (source, subscriber) {
2060             var buffer = null;
2061             var closingSubscriber = null;
2062             var openBuffer = function () {
2063                 closingSubscriber === null || closingSubscriber === void 0 ? void 0 : closingSubscriber.unsubscribe();
2064                 var b = buffer;
2065                 buffer = [];
2066                 b && subscriber.next(b);
2067                 innerFrom(closingSelector()).subscribe((closingSubscriber = new OperatorSubscriber(subscriber, openBuffer, noop)));
2068             };
2069             openBuffer();
2070             source.subscribe(new OperatorSubscriber(subscriber, function (value) { return buffer === null || buffer === void 0 ? void 0 : buffer.push(value); }, function () {
2071                 buffer && subscriber.next(buffer);
2072                 subscriber.complete();
2073             }, undefined, function () { return (buffer = closingSubscriber = null); }));
2074         });
2075     }
2076
2077     function catchError(selector) {
2078         return operate(function (source, subscriber) {
2079             var innerSub = null;
2080             var syncUnsub = false;
2081             var handledResult;
2082             innerSub = source.subscribe(new OperatorSubscriber(subscriber, undefined, undefined, function (err) {
2083                 handledResult = innerFrom(selector(err, catchError(selector)(source)));
2084                 if (innerSub) {
2085                     innerSub.unsubscribe();
2086                     innerSub = null;
2087                     handledResult.subscribe(subscriber);
2088                 }
2089                 else {
2090                     syncUnsub = true;
2091                 }
2092             }));
2093             if (syncUnsub) {
2094                 innerSub.unsubscribe();
2095                 innerSub = null;
2096                 handledResult.subscribe(subscriber);
2097             }
2098         });
2099     }
2100
2101     function scanInternals(accumulator, seed, hasSeed, emitOnNext, emitBeforeComplete) {
2102         return function (source, subscriber) {
2103             var hasState = hasSeed;
2104             var state = seed;
2105             var index = 0;
2106             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2107                 var i = index++;
2108                 state = hasState
2109                     ?
2110                         accumulator(state, value, i)
2111                     :
2112                         ((hasState = true), value);
2113                 emitOnNext && subscriber.next(state);
2114             }, emitBeforeComplete &&
2115                 (function () {
2116                     hasState && subscriber.next(state);
2117                     subscriber.complete();
2118                 })));
2119         };
2120     }
2121
2122     function reduce(accumulator, seed) {
2123         return operate(scanInternals(accumulator, seed, arguments.length >= 2, false, true));
2124     }
2125
2126     function concatMap(project, resultSelector) {
2127         return isFunction(resultSelector) ? mergeMap(project, resultSelector, 1) : mergeMap(project, 1);
2128     }
2129
2130     function fromSubscribable(subscribable) {
2131         return new Observable(function (subscriber) { return subscribable.subscribe(subscriber); });
2132     }
2133
2134     var DEFAULT_CONFIG = {
2135         connector: function () { return new Subject(); },
2136     };
2137     function connect(selector, config) {
2138         if (config === void 0) { config = DEFAULT_CONFIG; }
2139         var connector = config.connector;
2140         return operate(function (source, subscriber) {
2141             var subject = connector();
2142             from(selector(fromSubscribable(subject))).subscribe(subscriber);
2143             subscriber.add(source.subscribe(subject));
2144         });
2145     }
2146
2147     function debounceTime(dueTime, scheduler) {
2148         if (scheduler === void 0) { scheduler = asyncScheduler; }
2149         return operate(function (source, subscriber) {
2150             var activeTask = null;
2151             var lastValue = null;
2152             var lastTime = null;
2153             var emit = function () {
2154                 if (activeTask) {
2155                     activeTask.unsubscribe();
2156                     activeTask = null;
2157                     var value = lastValue;
2158                     lastValue = null;
2159                     subscriber.next(value);
2160                 }
2161             };
2162             function emitWhenIdle() {
2163                 var targetTime = lastTime + dueTime;
2164                 var now = scheduler.now();
2165                 if (now < targetTime) {
2166                     activeTask = this.schedule(undefined, targetTime - now);
2167                     subscriber.add(activeTask);
2168                     return;
2169                 }
2170                 emit();
2171             }
2172             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2173                 lastValue = value;
2174                 lastTime = scheduler.now();
2175                 if (!activeTask) {
2176                     activeTask = scheduler.schedule(emitWhenIdle, dueTime);
2177                     subscriber.add(activeTask);
2178                 }
2179             }, function () {
2180                 emit();
2181                 subscriber.complete();
2182             }, undefined, function () {
2183                 lastValue = activeTask = null;
2184             }));
2185         });
2186     }
2187
2188     function defaultIfEmpty(defaultValue) {
2189         return operate(function (source, subscriber) {
2190             var hasValue = false;
2191             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2192                 hasValue = true;
2193                 subscriber.next(value);
2194             }, function () {
2195                 if (!hasValue) {
2196                     subscriber.next(defaultValue);
2197                 }
2198                 subscriber.complete();
2199             }));
2200         });
2201     }
2202
2203     function take(count) {
2204         return count <= 0
2205             ?
2206                 function () { return EMPTY$1; }
2207             : operate(function (source, subscriber) {
2208                 var seen = 0;
2209                 source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2210                     if (++seen <= count) {
2211                         subscriber.next(value);
2212                         if (count <= seen) {
2213                             subscriber.complete();
2214                         }
2215                     }
2216                 }));
2217             });
2218     }
2219
2220     function distinctUntilChanged(comparator, keySelector) {
2221         if (keySelector === void 0) { keySelector = identity; }
2222         comparator = comparator !== null && comparator !== void 0 ? comparator : defaultCompare$3;
2223         return operate(function (source, subscriber) {
2224             var previousKey;
2225             var first = true;
2226             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2227                 var currentKey = keySelector(value);
2228                 if (first || !comparator(previousKey, currentKey)) {
2229                     first = false;
2230                     previousKey = currentKey;
2231                     subscriber.next(value);
2232                 }
2233             }));
2234         });
2235     }
2236     function defaultCompare$3(a, b) {
2237         return a === b;
2238     }
2239
2240     function throwIfEmpty(errorFactory) {
2241         if (errorFactory === void 0) { errorFactory = defaultErrorFactory; }
2242         return operate(function (source, subscriber) {
2243             var hasValue = false;
2244             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2245                 hasValue = true;
2246                 subscriber.next(value);
2247             }, function () { return (hasValue ? subscriber.complete() : subscriber.error(errorFactory())); }));
2248         });
2249     }
2250     function defaultErrorFactory() {
2251         return new EmptyError();
2252     }
2253
2254     function expand(project, concurrent, scheduler) {
2255         if (concurrent === void 0) { concurrent = Infinity; }
2256         concurrent = (concurrent || 0) < 1 ? Infinity : concurrent;
2257         return operate(function (source, subscriber) {
2258             return mergeInternals(source, subscriber, project, concurrent, undefined, true, scheduler);
2259         });
2260     }
2261
2262     function finalize(callback) {
2263         return operate(function (source, subscriber) {
2264             try {
2265                 source.subscribe(subscriber);
2266             }
2267             finally {
2268                 subscriber.add(callback);
2269             }
2270         });
2271     }
2272
2273     function first(predicate, defaultValue) {
2274         var hasDefaultValue = arguments.length >= 2;
2275         return function (source) {
2276             return source.pipe(predicate ? filter(function (v, i) { return predicate(v, i, source); }) : identity, take(1), hasDefaultValue ? defaultIfEmpty(defaultValue) : throwIfEmpty(function () { return new EmptyError(); }));
2277         };
2278     }
2279
2280     function takeLast(count) {
2281         return count <= 0
2282             ? function () { return EMPTY$1; }
2283             : operate(function (source, subscriber) {
2284                 var buffer = [];
2285                 source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2286                     buffer.push(value);
2287                     count < buffer.length && buffer.shift();
2288                 }, function () {
2289                     var e_1, _a;
2290                     try {
2291                         for (var buffer_1 = __values(buffer), buffer_1_1 = buffer_1.next(); !buffer_1_1.done; buffer_1_1 = buffer_1.next()) {
2292                             var value = buffer_1_1.value;
2293                             subscriber.next(value);
2294                         }
2295                     }
2296                     catch (e_1_1) { e_1 = { error: e_1_1 }; }
2297                     finally {
2298                         try {
2299                             if (buffer_1_1 && !buffer_1_1.done && (_a = buffer_1.return)) _a.call(buffer_1);
2300                         }
2301                         finally { if (e_1) throw e_1.error; }
2302                     }
2303                     subscriber.complete();
2304                 }, undefined, function () {
2305                     buffer = null;
2306                 }));
2307             });
2308     }
2309
2310     function last(predicate, defaultValue) {
2311         var hasDefaultValue = arguments.length >= 2;
2312         return function (source) {
2313             return source.pipe(predicate ? filter(function (v, i) { return predicate(v, i, source); }) : identity, takeLast(1), hasDefaultValue ? defaultIfEmpty(defaultValue) : throwIfEmpty(function () { return new EmptyError(); }));
2314         };
2315     }
2316
2317     function multicast(subjectOrSubjectFactory, selector) {
2318         var subjectFactory = isFunction(subjectOrSubjectFactory) ? subjectOrSubjectFactory : function () { return subjectOrSubjectFactory; };
2319         if (isFunction(selector)) {
2320             return connect(selector, {
2321                 connector: subjectFactory,
2322             });
2323         }
2324         return function (source) { return new ConnectableObservable(source, subjectFactory); };
2325     }
2326
2327     function pairwise() {
2328         return operate(function (source, subscriber) {
2329             var prev;
2330             var hasPrev = false;
2331             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2332                 var p = prev;
2333                 prev = value;
2334                 hasPrev && subscriber.next([p, value]);
2335                 hasPrev = true;
2336             }));
2337         });
2338     }
2339
2340     function pluck() {
2341         var properties = [];
2342         for (var _i = 0; _i < arguments.length; _i++) {
2343             properties[_i] = arguments[_i];
2344         }
2345         var length = properties.length;
2346         if (length === 0) {
2347             throw new Error('list of properties cannot be empty.');
2348         }
2349         return map(function (x) {
2350             var currentProp = x;
2351             for (var i = 0; i < length; i++) {
2352                 var p = currentProp === null || currentProp === void 0 ? void 0 : currentProp[properties[i]];
2353                 if (typeof p !== 'undefined') {
2354                     currentProp = p;
2355                 }
2356                 else {
2357                     return undefined;
2358                 }
2359             }
2360             return currentProp;
2361         });
2362     }
2363
2364     function publish(selector) {
2365         return selector ? function (source) { return connect(selector)(source); } : function (source) { return multicast(new Subject())(source); };
2366     }
2367
2368     function publishReplay(bufferSize, windowTime, selectorOrScheduler, timestampProvider) {
2369         if (selectorOrScheduler && !isFunction(selectorOrScheduler)) {
2370             timestampProvider = selectorOrScheduler;
2371         }
2372         var selector = isFunction(selectorOrScheduler) ? selectorOrScheduler : undefined;
2373         return function (source) { return multicast(new ReplaySubject(bufferSize, windowTime, timestampProvider), selector)(source); };
2374     }
2375
2376     function retry(configOrCount) {
2377         if (configOrCount === void 0) { configOrCount = Infinity; }
2378         var config;
2379         if (configOrCount && typeof configOrCount === 'object') {
2380             config = configOrCount;
2381         }
2382         else {
2383             config = {
2384                 count: configOrCount,
2385             };
2386         }
2387         var _a = config.count, count = _a === void 0 ? Infinity : _a, delay = config.delay, _b = config.resetOnSuccess, resetOnSuccess = _b === void 0 ? false : _b;
2388         return count <= 0
2389             ? identity
2390             : operate(function (source, subscriber) {
2391                 var soFar = 0;
2392                 var innerSub;
2393                 var subscribeForRetry = function () {
2394                     var syncUnsub = false;
2395                     innerSub = source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2396                         if (resetOnSuccess) {
2397                             soFar = 0;
2398                         }
2399                         subscriber.next(value);
2400                     }, undefined, function (err) {
2401                         if (soFar++ < count) {
2402                             var resub_1 = function () {
2403                                 if (innerSub) {
2404                                     innerSub.unsubscribe();
2405                                     innerSub = null;
2406                                     subscribeForRetry();
2407                                 }
2408                                 else {
2409                                     syncUnsub = true;
2410                                 }
2411                             };
2412                             if (delay != null) {
2413                                 var notifier = typeof delay === 'number' ? timer(delay) : innerFrom(delay(err, soFar));
2414                                 var notifierSubscriber_1 = new OperatorSubscriber(subscriber, function () {
2415                                     notifierSubscriber_1.unsubscribe();
2416                                     resub_1();
2417                                 }, function () {
2418                                     subscriber.complete();
2419                                 });
2420                                 notifier.subscribe(notifierSubscriber_1);
2421                             }
2422                             else {
2423                                 resub_1();
2424                             }
2425                         }
2426                         else {
2427                             subscriber.error(err);
2428                         }
2429                     }));
2430                     if (syncUnsub) {
2431                         innerSub.unsubscribe();
2432                         innerSub = null;
2433                         subscribeForRetry();
2434                     }
2435                 };
2436                 subscribeForRetry();
2437             });
2438     }
2439
2440     function sample(notifier) {
2441         return operate(function (source, subscriber) {
2442             var hasValue = false;
2443             var lastValue = null;
2444             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2445                 hasValue = true;
2446                 lastValue = value;
2447             }));
2448             var emit = function () {
2449                 if (hasValue) {
2450                     hasValue = false;
2451                     var value = lastValue;
2452                     lastValue = null;
2453                     subscriber.next(value);
2454                 }
2455             };
2456             notifier.subscribe(new OperatorSubscriber(subscriber, emit, noop));
2457         });
2458     }
2459
2460     function scan(accumulator, seed) {
2461         return operate(scanInternals(accumulator, seed, arguments.length >= 2, true));
2462     }
2463
2464     function share(options) {
2465         if (options === void 0) { options = {}; }
2466         var _a = options.connector, connector = _a === void 0 ? function () { return new Subject(); } : _a, _b = options.resetOnError, resetOnError = _b === void 0 ? true : _b, _c = options.resetOnComplete, resetOnComplete = _c === void 0 ? true : _c, _d = options.resetOnRefCountZero, resetOnRefCountZero = _d === void 0 ? true : _d;
2467         return function (wrapperSource) {
2468             var connection = null;
2469             var resetConnection = null;
2470             var subject = null;
2471             var refCount = 0;
2472             var hasCompleted = false;
2473             var hasErrored = false;
2474             var cancelReset = function () {
2475                 resetConnection === null || resetConnection === void 0 ? void 0 : resetConnection.unsubscribe();
2476                 resetConnection = null;
2477             };
2478             var reset = function () {
2479                 cancelReset();
2480                 connection = subject = null;
2481                 hasCompleted = hasErrored = false;
2482             };
2483             var resetAndUnsubscribe = function () {
2484                 var conn = connection;
2485                 reset();
2486                 conn === null || conn === void 0 ? void 0 : conn.unsubscribe();
2487             };
2488             return operate(function (source, subscriber) {
2489                 refCount++;
2490                 if (!hasErrored && !hasCompleted) {
2491                     cancelReset();
2492                 }
2493                 var dest = (subject = subject !== null && subject !== void 0 ? subject : connector());
2494                 subscriber.add(function () {
2495                     refCount--;
2496                     if (refCount === 0 && !hasErrored && !hasCompleted) {
2497                         resetConnection = handleReset(resetAndUnsubscribe, resetOnRefCountZero);
2498                     }
2499                 });
2500                 dest.subscribe(subscriber);
2501                 if (!connection) {
2502                     connection = new SafeSubscriber({
2503                         next: function (value) { return dest.next(value); },
2504                         error: function (err) {
2505                             hasErrored = true;
2506                             cancelReset();
2507                             resetConnection = handleReset(reset, resetOnError, err);
2508                             dest.error(err);
2509                         },
2510                         complete: function () {
2511                             hasCompleted = true;
2512                             cancelReset();
2513                             resetConnection = handleReset(reset, resetOnComplete);
2514                             dest.complete();
2515                         },
2516                     });
2517                     from(source).subscribe(connection);
2518                 }
2519             })(wrapperSource);
2520         };
2521     }
2522     function handleReset(reset, on) {
2523         var args = [];
2524         for (var _i = 2; _i < arguments.length; _i++) {
2525             args[_i - 2] = arguments[_i];
2526         }
2527         if (on === true) {
2528             reset();
2529             return null;
2530         }
2531         if (on === false) {
2532             return null;
2533         }
2534         return on.apply(void 0, __spreadArray([], __read(args))).pipe(take(1))
2535             .subscribe(function () { return reset(); });
2536     }
2537
2538     function skip(count) {
2539         return filter(function (_, index) { return count <= index; });
2540     }
2541
2542     function skipWhile(predicate) {
2543         return operate(function (source, subscriber) {
2544             var taking = false;
2545             var index = 0;
2546             source.subscribe(new OperatorSubscriber(subscriber, function (value) { return (taking || (taking = !predicate(value, index++))) && subscriber.next(value); }));
2547         });
2548     }
2549
2550     function startWith() {
2551         var values = [];
2552         for (var _i = 0; _i < arguments.length; _i++) {
2553             values[_i] = arguments[_i];
2554         }
2555         var scheduler = popScheduler(values);
2556         return operate(function (source, subscriber) {
2557             (scheduler ? concat(values, source, scheduler) : concat(values, source)).subscribe(subscriber);
2558         });
2559     }
2560
2561     function switchMap(project, resultSelector) {
2562         return operate(function (source, subscriber) {
2563             var innerSubscriber = null;
2564             var index = 0;
2565             var isComplete = false;
2566             var checkComplete = function () { return isComplete && !innerSubscriber && subscriber.complete(); };
2567             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2568                 innerSubscriber === null || innerSubscriber === void 0 ? void 0 : innerSubscriber.unsubscribe();
2569                 var innerIndex = 0;
2570                 var outerIndex = index++;
2571                 innerFrom(project(value, outerIndex)).subscribe((innerSubscriber = new OperatorSubscriber(subscriber, function (innerValue) { return subscriber.next(resultSelector ? resultSelector(value, innerValue, outerIndex, innerIndex++) : innerValue); }, function () {
2572                     innerSubscriber = null;
2573                     checkComplete();
2574                 })));
2575             }, function () {
2576                 isComplete = true;
2577                 checkComplete();
2578             }));
2579         });
2580     }
2581
2582     function takeUntil(notifier) {
2583         return operate(function (source, subscriber) {
2584             innerFrom(notifier).subscribe(new OperatorSubscriber(subscriber, function () { return subscriber.complete(); }, noop));
2585             !subscriber.closed && source.subscribe(subscriber);
2586         });
2587     }
2588
2589     function takeWhile(predicate, inclusive) {
2590         if (inclusive === void 0) { inclusive = false; }
2591         return operate(function (source, subscriber) {
2592             var index = 0;
2593             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2594                 var result = predicate(value, index++);
2595                 (result || inclusive) && subscriber.next(value);
2596                 !result && subscriber.complete();
2597             }));
2598         });
2599     }
2600
2601     function tap(observerOrNext, error, complete) {
2602         var tapObserver = isFunction(observerOrNext) || error || complete
2603             ?
2604                 { next: observerOrNext, error: error, complete: complete }
2605             : observerOrNext;
2606         return tapObserver
2607             ? operate(function (source, subscriber) {
2608                 var _a;
2609                 (_a = tapObserver.subscribe) === null || _a === void 0 ? void 0 : _a.call(tapObserver);
2610                 var isUnsub = true;
2611                 source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2612                     var _a;
2613                     (_a = tapObserver.next) === null || _a === void 0 ? void 0 : _a.call(tapObserver, value);
2614                     subscriber.next(value);
2615                 }, function () {
2616                     var _a;
2617                     isUnsub = false;
2618                     (_a = tapObserver.complete) === null || _a === void 0 ? void 0 : _a.call(tapObserver);
2619                     subscriber.complete();
2620                 }, function (err) {
2621                     var _a;
2622                     isUnsub = false;
2623                     (_a = tapObserver.error) === null || _a === void 0 ? void 0 : _a.call(tapObserver, err);
2624                     subscriber.error(err);
2625                 }, function () {
2626                     var _a, _b;
2627                     if (isUnsub) {
2628                         (_a = tapObserver.unsubscribe) === null || _a === void 0 ? void 0 : _a.call(tapObserver);
2629                     }
2630                     (_b = tapObserver.finalize) === null || _b === void 0 ? void 0 : _b.call(tapObserver);
2631                 }));
2632             })
2633             :
2634                 identity;
2635     }
2636
2637     function withLatestFrom() {
2638         var inputs = [];
2639         for (var _i = 0; _i < arguments.length; _i++) {
2640             inputs[_i] = arguments[_i];
2641         }
2642         var project = popResultSelector(inputs);
2643         return operate(function (source, subscriber) {
2644             var len = inputs.length;
2645             var otherValues = new Array(len);
2646             var hasValue = inputs.map(function () { return false; });
2647             var ready = false;
2648             var _loop_1 = function (i) {
2649                 innerFrom(inputs[i]).subscribe(new OperatorSubscriber(subscriber, function (value) {
2650                     otherValues[i] = value;
2651                     if (!ready && !hasValue[i]) {
2652                         hasValue[i] = true;
2653                         (ready = hasValue.every(identity)) && (hasValue = null);
2654                     }
2655                 }, noop));
2656             };
2657             for (var i = 0; i < len; i++) {
2658                 _loop_1(i);
2659             }
2660             source.subscribe(new OperatorSubscriber(subscriber, function (value) {
2661                 if (ready) {
2662                     var values = __spreadArray([value], __read(otherValues));
2663                     subscriber.next(project ? project.apply(void 0, __spreadArray([], __read(values))) : values);
2664                 }
2665             }));
2666         });
2667     }
2668
2669     /**
2670      * @class Filter
2671      *
2672      * @classdesc Represents a class for creating image filters. Implementation and
2673      * definitions based on https://github.com/mapbox/feature-filter.
2674      */
2675     class FilterCreator {
2676         /**
2677          * Create a filter from a filter expression.
2678          *
2679          * @description The following filters are supported:
2680          *
2681          * Comparison
2682          * `==`
2683          * `!=`
2684          * `<`
2685          * `<=`
2686          * `>`
2687          * `>=`
2688          *
2689          * Set membership
2690          * `in`
2691          * `!in`
2692          *
2693          * Combining
2694          * `all`
2695          *
2696          * @param {FilterExpression} filter - Comparison, set membership or combinding filter
2697          * expression.
2698          * @returns {FilterFunction} Function taking a image and returning a boolean that
2699          * indicates whether the image passed the test or not.
2700          */
2701         createFilter(filter) {
2702             return new Function("node", "return " + this._compile(filter) + ";");
2703         }
2704         _compile(filter) {
2705             if (filter == null || filter.length <= 1) {
2706                 return "true";
2707             }
2708             const operator = filter[0];
2709             const operation = operator === "==" ? this._compileComparisonOp("===", filter[1], filter[2], false) :
2710                 operator === "!=" ? this._compileComparisonOp("!==", filter[1], filter[2], false) :
2711                     operator === ">" ||
2712                         operator === ">=" ||
2713                         operator === "<" ||
2714                         operator === "<=" ? this._compileComparisonOp(operator, filter[1], filter[2], true) :
2715                         operator === "in" ?
2716                             this._compileInOp(filter[1], filter.slice(2)) :
2717                             operator === "!in" ?
2718                                 this._compileNegation(this._compileInOp(filter[1], filter.slice(2))) :
2719                                 operator === "all" ? this._compileLogicalOp(filter.slice(1), "&&") :
2720                                     "true";
2721             return "(" + operation + ")";
2722         }
2723         _compare(a, b) {
2724             return a < b ? -1 : a > b ? 1 : 0;
2725         }
2726         _compileComparisonOp(operator, property, value, checkType) {
2727             const left = this._compilePropertyReference(property);
2728             const right = JSON.stringify(value);
2729             return (checkType ? "typeof " + left + "===typeof " + right + "&&" : "") + left + operator + right;
2730         }
2731         _compileInOp(property, values) {
2732             const compare = this._compare;
2733             const left = JSON.stringify(values.sort(compare));
2734             const right = this._compilePropertyReference(property);
2735             return left + ".indexOf(" + right + ")!==-1";
2736         }
2737         _compileLogicalOp(filters, operator) {
2738             const compile = this._compile.bind(this);
2739             return filters.map(compile).join(operator);
2740         }
2741         _compileNegation(expression) {
2742             return "!(" + expression + ")";
2743         }
2744         _compilePropertyReference(property) {
2745             return "node[" + JSON.stringify(property) + "]";
2746         }
2747     }
2748
2749     /**
2750      * @license
2751      * Copyright 2010-2021 Three.js Authors
2752      * SPDX-License-Identifier: MIT
2753      */
2754     const REVISION = '134';
2755     const CullFaceNone = 0;
2756     const CullFaceBack = 1;
2757     const CullFaceFront = 2;
2758     const PCFShadowMap = 1;
2759     const PCFSoftShadowMap = 2;
2760     const VSMShadowMap = 3;
2761     const FrontSide = 0;
2762     const BackSide = 1;
2763     const DoubleSide = 2;
2764     const FlatShading = 1;
2765     const NoBlending = 0;
2766     const NormalBlending = 1;
2767     const AdditiveBlending = 2;
2768     const SubtractiveBlending = 3;
2769     const MultiplyBlending = 4;
2770     const CustomBlending = 5;
2771     const AddEquation = 100;
2772     const SubtractEquation = 101;
2773     const ReverseSubtractEquation = 102;
2774     const MinEquation = 103;
2775     const MaxEquation = 104;
2776     const ZeroFactor = 200;
2777     const OneFactor = 201;
2778     const SrcColorFactor = 202;
2779     const OneMinusSrcColorFactor = 203;
2780     const SrcAlphaFactor = 204;
2781     const OneMinusSrcAlphaFactor = 205;
2782     const DstAlphaFactor = 206;
2783     const OneMinusDstAlphaFactor = 207;
2784     const DstColorFactor = 208;
2785     const OneMinusDstColorFactor = 209;
2786     const SrcAlphaSaturateFactor = 210;
2787     const NeverDepth = 0;
2788     const AlwaysDepth = 1;
2789     const LessDepth = 2;
2790     const LessEqualDepth = 3;
2791     const EqualDepth = 4;
2792     const GreaterEqualDepth = 5;
2793     const GreaterDepth = 6;
2794     const NotEqualDepth = 7;
2795     const MultiplyOperation = 0;
2796     const MixOperation = 1;
2797     const AddOperation = 2;
2798     const NoToneMapping = 0;
2799     const LinearToneMapping = 1;
2800     const ReinhardToneMapping = 2;
2801     const CineonToneMapping = 3;
2802     const ACESFilmicToneMapping = 4;
2803     const CustomToneMapping = 5;
2804
2805     const UVMapping = 300;
2806     const CubeReflectionMapping = 301;
2807     const CubeRefractionMapping = 302;
2808     const EquirectangularReflectionMapping = 303;
2809     const EquirectangularRefractionMapping = 304;
2810     const CubeUVReflectionMapping = 306;
2811     const CubeUVRefractionMapping = 307;
2812     const RepeatWrapping = 1000;
2813     const ClampToEdgeWrapping = 1001;
2814     const MirroredRepeatWrapping = 1002;
2815     const NearestFilter = 1003;
2816     const NearestMipmapNearestFilter = 1004;
2817     const NearestMipmapLinearFilter = 1005;
2818     const LinearFilter = 1006;
2819     const LinearMipmapNearestFilter = 1007;
2820     const LinearMipmapLinearFilter = 1008;
2821     const UnsignedByteType = 1009;
2822     const ByteType = 1010;
2823     const ShortType = 1011;
2824     const UnsignedShortType = 1012;
2825     const IntType = 1013;
2826     const UnsignedIntType = 1014;
2827     const FloatType = 1015;
2828     const HalfFloatType = 1016;
2829     const UnsignedShort4444Type = 1017;
2830     const UnsignedShort5551Type = 1018;
2831     const UnsignedShort565Type = 1019;
2832     const UnsignedInt248Type = 1020;
2833     const AlphaFormat = 1021;
2834     const RGBFormat = 1022;
2835     const RGBAFormat = 1023;
2836     const LuminanceFormat = 1024;
2837     const LuminanceAlphaFormat = 1025;
2838     const RGBEFormat = RGBAFormat;
2839     const DepthFormat = 1026;
2840     const DepthStencilFormat = 1027;
2841     const RedFormat = 1028;
2842     const RedIntegerFormat = 1029;
2843     const RGFormat = 1030;
2844     const RGIntegerFormat = 1031;
2845     const RGBIntegerFormat = 1032;
2846     const RGBAIntegerFormat = 1033;
2847
2848     const RGB_S3TC_DXT1_Format = 33776;
2849     const RGBA_S3TC_DXT1_Format = 33777;
2850     const RGBA_S3TC_DXT3_Format = 33778;
2851     const RGBA_S3TC_DXT5_Format = 33779;
2852     const RGB_PVRTC_4BPPV1_Format = 35840;
2853     const RGB_PVRTC_2BPPV1_Format = 35841;
2854     const RGBA_PVRTC_4BPPV1_Format = 35842;
2855     const RGBA_PVRTC_2BPPV1_Format = 35843;
2856     const RGB_ETC1_Format = 36196;
2857     const RGB_ETC2_Format = 37492;
2858     const RGBA_ETC2_EAC_Format = 37496;
2859     const RGBA_ASTC_4x4_Format = 37808;
2860     const RGBA_ASTC_5x4_Format = 37809;
2861     const RGBA_ASTC_5x5_Format = 37810;
2862     const RGBA_ASTC_6x5_Format = 37811;
2863     const RGBA_ASTC_6x6_Format = 37812;
2864     const RGBA_ASTC_8x5_Format = 37813;
2865     const RGBA_ASTC_8x6_Format = 37814;
2866     const RGBA_ASTC_8x8_Format = 37815;
2867     const RGBA_ASTC_10x5_Format = 37816;
2868     const RGBA_ASTC_10x6_Format = 37817;
2869     const RGBA_ASTC_10x8_Format = 37818;
2870     const RGBA_ASTC_10x10_Format = 37819;
2871     const RGBA_ASTC_12x10_Format = 37820;
2872     const RGBA_ASTC_12x12_Format = 37821;
2873     const RGBA_BPTC_Format = 36492;
2874     const SRGB8_ALPHA8_ASTC_4x4_Format = 37840;
2875     const SRGB8_ALPHA8_ASTC_5x4_Format = 37841;
2876     const SRGB8_ALPHA8_ASTC_5x5_Format = 37842;
2877     const SRGB8_ALPHA8_ASTC_6x5_Format = 37843;
2878     const SRGB8_ALPHA8_ASTC_6x6_Format = 37844;
2879     const SRGB8_ALPHA8_ASTC_8x5_Format = 37845;
2880     const SRGB8_ALPHA8_ASTC_8x6_Format = 37846;
2881     const SRGB8_ALPHA8_ASTC_8x8_Format = 37847;
2882     const SRGB8_ALPHA8_ASTC_10x5_Format = 37848;
2883     const SRGB8_ALPHA8_ASTC_10x6_Format = 37849;
2884     const SRGB8_ALPHA8_ASTC_10x8_Format = 37850;
2885     const SRGB8_ALPHA8_ASTC_10x10_Format = 37851;
2886     const SRGB8_ALPHA8_ASTC_12x10_Format = 37852;
2887     const SRGB8_ALPHA8_ASTC_12x12_Format = 37853;
2888     const LoopOnce = 2200;
2889     const LoopRepeat = 2201;
2890     const LoopPingPong = 2202;
2891     const InterpolateDiscrete = 2300;
2892     const InterpolateLinear = 2301;
2893     const InterpolateSmooth = 2302;
2894     const ZeroCurvatureEnding = 2400;
2895     const ZeroSlopeEnding = 2401;
2896     const WrapAroundEnding = 2402;
2897     const NormalAnimationBlendMode = 2500;
2898     const AdditiveAnimationBlendMode = 2501;
2899     const TrianglesDrawMode = 0;
2900     const LinearEncoding = 3000;
2901     const sRGBEncoding = 3001;
2902     const GammaEncoding = 3007;
2903     const RGBEEncoding = 3002;
2904     const LogLuvEncoding = 3003;
2905     const RGBM7Encoding = 3004;
2906     const RGBM16Encoding = 3005;
2907     const RGBDEncoding = 3006;
2908     const BasicDepthPacking = 3200;
2909     const RGBADepthPacking = 3201;
2910     const TangentSpaceNormalMap = 0;
2911     const ObjectSpaceNormalMap = 1;
2912     const KeepStencilOp = 7680;
2913     const AlwaysStencilFunc = 519;
2914
2915     const StaticDrawUsage = 35044;
2916     const DynamicDrawUsage = 35048;
2917     const GLSL3 = '300 es';
2918
2919     /**
2920      * https://github.com/mrdoob/eventdispatcher.js/
2921      */
2922
2923     class EventDispatcher {
2924
2925         addEventListener( type, listener ) {
2926
2927                 if ( this._listeners === undefined ) this._listeners = {};
2928
2929                 const listeners = this._listeners;
2930
2931                 if ( listeners[ type ] === undefined ) {
2932
2933                         listeners[ type ] = [];
2934
2935                 }
2936
2937                 if ( listeners[ type ].indexOf( listener ) === - 1 ) {
2938
2939                         listeners[ type ].push( listener );
2940
2941                 }
2942
2943         }
2944
2945         hasEventListener( type, listener ) {
2946
2947                 if ( this._listeners === undefined ) return false;
2948
2949                 const listeners = this._listeners;
2950
2951                 return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
2952
2953         }
2954
2955         removeEventListener( type, listener ) {
2956
2957                 if ( this._listeners === undefined ) return;
2958
2959                 const listeners = this._listeners;
2960                 const listenerArray = listeners[ type ];
2961
2962                 if ( listenerArray !== undefined ) {
2963
2964                         const index = listenerArray.indexOf( listener );
2965
2966                         if ( index !== - 1 ) {
2967
2968                                 listenerArray.splice( index, 1 );
2969
2970                         }
2971
2972                 }
2973
2974         }
2975
2976         dispatchEvent( event ) {
2977
2978                 if ( this._listeners === undefined ) return;
2979
2980                 const listeners = this._listeners;
2981                 const listenerArray = listeners[ event.type ];
2982
2983                 if ( listenerArray !== undefined ) {
2984
2985                         event.target = this;
2986
2987                         // Make a copy, in case listeners are removed while iterating.
2988                         const array = listenerArray.slice( 0 );
2989
2990                         for ( let i = 0, l = array.length; i < l; i ++ ) {
2991
2992                                 array[ i ].call( this, event );
2993
2994                         }
2995
2996                         event.target = null;
2997
2998                 }
2999
3000         }
3001
3002     }
3003
3004     let _seed = 1234567;
3005
3006     const DEG2RAD$1 = Math.PI / 180;
3007     const RAD2DEG$1 = 180 / Math.PI;
3008
3009     //
3010
3011     const _lut = [];
3012
3013     for ( let i = 0; i < 256; i ++ ) {
3014
3015         _lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
3016
3017     }
3018
3019     const hasRandomUUID = typeof crypto !== 'undefined' && 'randomUUID' in crypto;
3020
3021     function generateUUID() {
3022
3023         if ( hasRandomUUID ) {
3024
3025                 return crypto.randomUUID().toUpperCase();
3026
3027         }
3028
3029         // TODO Remove this code when crypto.randomUUID() is available everywhere
3030         // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
3031
3032         const d0 = Math.random() * 0xffffffff | 0;
3033         const d1 = Math.random() * 0xffffffff | 0;
3034         const d2 = Math.random() * 0xffffffff | 0;
3035         const d3 = Math.random() * 0xffffffff | 0;
3036         const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
3037                         _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
3038                         _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
3039                         _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
3040
3041         // .toUpperCase() here flattens concatenated strings to save heap memory space.
3042         return uuid.toUpperCase();
3043
3044     }
3045
3046     function clamp$1( value, min, max ) {
3047
3048         return Math.max( min, Math.min( max, value ) );
3049
3050     }
3051
3052     // compute euclidian modulo of m % n
3053     // https://en.wikipedia.org/wiki/Modulo_operation
3054     function euclideanModulo( n, m ) {
3055
3056         return ( ( n % m ) + m ) % m;
3057
3058     }
3059
3060     // Linear mapping from range <a1, a2> to range <b1, b2>
3061     function mapLinear( x, a1, a2, b1, b2 ) {
3062
3063         return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
3064
3065     }
3066
3067     // https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
3068     function inverseLerp( x, y, value ) {
3069
3070         if ( x !== y ) {
3071
3072                 return ( value - x ) / ( y - x );
3073
3074         } else {
3075
3076                 return 0;
3077
3078         }
3079
3080     }
3081
3082     // https://en.wikipedia.org/wiki/Linear_interpolation
3083     function lerp( x, y, t ) {
3084
3085         return ( 1 - t ) * x + t * y;
3086
3087     }
3088
3089     // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
3090     function damp( x, y, lambda, dt ) {
3091
3092         return lerp( x, y, 1 - Math.exp( - lambda * dt ) );
3093
3094     }
3095
3096     // https://www.desmos.com/calculator/vcsjnyz7x4
3097     function pingpong( x, length = 1 ) {
3098
3099         return length - Math.abs( euclideanModulo( x, length * 2 ) - length );
3100
3101     }
3102
3103     // http://en.wikipedia.org/wiki/Smoothstep
3104     function smoothstep( x, min, max ) {
3105
3106         if ( x <= min ) return 0;
3107         if ( x >= max ) return 1;
3108
3109         x = ( x - min ) / ( max - min );
3110
3111         return x * x * ( 3 - 2 * x );
3112
3113     }
3114
3115     function smootherstep( x, min, max ) {
3116
3117         if ( x <= min ) return 0;
3118         if ( x >= max ) return 1;
3119
3120         x = ( x - min ) / ( max - min );
3121
3122         return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
3123
3124     }
3125
3126     // Random integer from <low, high> interval
3127     function randInt( low, high ) {
3128
3129         return low + Math.floor( Math.random() * ( high - low + 1 ) );
3130
3131     }
3132
3133     // Random float from <low, high> interval
3134     function randFloat( low, high ) {
3135
3136         return low + Math.random() * ( high - low );
3137
3138     }
3139
3140     // Random float from <-range/2, range/2> interval
3141     function randFloatSpread( range ) {
3142
3143         return range * ( 0.5 - Math.random() );
3144
3145     }
3146
3147     // Deterministic pseudo-random float in the interval [ 0, 1 ]
3148     function seededRandom( s ) {
3149
3150         if ( s !== undefined ) _seed = s % 2147483647;
3151
3152         // Park-Miller algorithm
3153
3154         _seed = _seed * 16807 % 2147483647;
3155
3156         return ( _seed - 1 ) / 2147483646;
3157
3158     }
3159
3160     function degToRad( degrees ) {
3161
3162         return degrees * DEG2RAD$1;
3163
3164     }
3165
3166     function radToDeg( radians ) {
3167
3168         return radians * RAD2DEG$1;
3169
3170     }
3171
3172     function isPowerOfTwo( value ) {
3173
3174         return ( value & ( value - 1 ) ) === 0 && value !== 0;
3175
3176     }
3177
3178     function ceilPowerOfTwo( value ) {
3179
3180         return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
3181
3182     }
3183
3184     function floorPowerOfTwo( value ) {
3185
3186         return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
3187
3188     }
3189
3190     function setQuaternionFromProperEuler( q, a, b, c, order ) {
3191
3192         // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
3193
3194         // rotations are applied to the axes in the order specified by 'order'
3195         // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
3196         // angles are in radians
3197
3198         const cos = Math.cos;
3199         const sin = Math.sin;
3200
3201         const c2 = cos( b / 2 );
3202         const s2 = sin( b / 2 );
3203
3204         const c13 = cos( ( a + c ) / 2 );
3205         const s13 = sin( ( a + c ) / 2 );
3206
3207         const c1_3 = cos( ( a - c ) / 2 );
3208         const s1_3 = sin( ( a - c ) / 2 );
3209
3210         const c3_1 = cos( ( c - a ) / 2 );
3211         const s3_1 = sin( ( c - a ) / 2 );
3212
3213         switch ( order ) {
3214
3215                 case 'XYX':
3216                         q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
3217                         break;
3218
3219                 case 'YZY':
3220                         q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
3221                         break;
3222
3223                 case 'ZXZ':
3224                         q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
3225                         break;
3226
3227                 case 'XZX':
3228                         q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
3229                         break;
3230
3231                 case 'YXY':
3232                         q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
3233                         break;
3234
3235                 case 'ZYZ':
3236                         q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
3237                         break;
3238
3239                 default:
3240                         console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
3241
3242         }
3243
3244     }
3245
3246     var MathUtils = /*#__PURE__*/Object.freeze({
3247         __proto__: null,
3248         DEG2RAD: DEG2RAD$1,
3249         RAD2DEG: RAD2DEG$1,
3250         generateUUID: generateUUID,
3251         clamp: clamp$1,
3252         euclideanModulo: euclideanModulo,
3253         mapLinear: mapLinear,
3254         inverseLerp: inverseLerp,
3255         lerp: lerp,
3256         damp: damp,
3257         pingpong: pingpong,
3258         smoothstep: smoothstep,
3259         smootherstep: smootherstep,
3260         randInt: randInt,
3261         randFloat: randFloat,
3262         randFloatSpread: randFloatSpread,
3263         seededRandom: seededRandom,
3264         degToRad: degToRad,
3265         radToDeg: radToDeg,
3266         isPowerOfTwo: isPowerOfTwo,
3267         ceilPowerOfTwo: ceilPowerOfTwo,
3268         floorPowerOfTwo: floorPowerOfTwo,
3269         setQuaternionFromProperEuler: setQuaternionFromProperEuler
3270     });
3271
3272     class Vector2 {
3273
3274         constructor( x = 0, y = 0 ) {
3275
3276                 this.x = x;
3277                 this.y = y;
3278
3279         }
3280
3281         get width() {
3282
3283                 return this.x;
3284
3285         }
3286
3287         set width( value ) {
3288
3289                 this.x = value;
3290
3291         }
3292
3293         get height() {
3294
3295                 return this.y;
3296
3297         }
3298
3299         set height( value ) {
3300
3301                 this.y = value;
3302
3303         }
3304
3305         set( x, y ) {
3306
3307                 this.x = x;
3308                 this.y = y;
3309
3310                 return this;
3311
3312         }
3313
3314         setScalar( scalar ) {
3315
3316                 this.x = scalar;
3317                 this.y = scalar;
3318
3319                 return this;
3320
3321         }
3322
3323         setX( x ) {
3324
3325                 this.x = x;
3326
3327                 return this;
3328
3329         }
3330
3331         setY( y ) {
3332
3333                 this.y = y;
3334
3335                 return this;
3336
3337         }
3338
3339         setComponent( index, value ) {
3340
3341                 switch ( index ) {
3342
3343                         case 0: this.x = value; break;
3344                         case 1: this.y = value; break;
3345                         default: throw new Error( 'index is out of range: ' + index );
3346
3347                 }
3348
3349                 return this;
3350
3351         }
3352
3353         getComponent( index ) {
3354
3355                 switch ( index ) {
3356
3357                         case 0: return this.x;
3358                         case 1: return this.y;
3359                         default: throw new Error( 'index is out of range: ' + index );
3360
3361                 }
3362
3363         }
3364
3365         clone() {
3366
3367                 return new this.constructor( this.x, this.y );
3368
3369         }
3370
3371         copy( v ) {
3372
3373                 this.x = v.x;
3374                 this.y = v.y;
3375
3376                 return this;
3377
3378         }
3379
3380         add( v, w ) {
3381
3382                 if ( w !== undefined ) {
3383
3384                         console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
3385                         return this.addVectors( v, w );
3386
3387                 }
3388
3389                 this.x += v.x;
3390                 this.y += v.y;
3391
3392                 return this;
3393
3394         }
3395
3396         addScalar( s ) {
3397
3398                 this.x += s;
3399                 this.y += s;
3400
3401                 return this;
3402
3403         }
3404
3405         addVectors( a, b ) {
3406
3407                 this.x = a.x + b.x;
3408                 this.y = a.y + b.y;
3409
3410                 return this;
3411
3412         }
3413
3414         addScaledVector( v, s ) {
3415
3416                 this.x += v.x * s;
3417                 this.y += v.y * s;
3418
3419                 return this;
3420
3421         }
3422
3423         sub( v, w ) {
3424
3425                 if ( w !== undefined ) {
3426
3427                         console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
3428                         return this.subVectors( v, w );
3429
3430                 }
3431
3432                 this.x -= v.x;
3433                 this.y -= v.y;
3434
3435                 return this;
3436
3437         }
3438
3439         subScalar( s ) {
3440
3441                 this.x -= s;
3442                 this.y -= s;
3443
3444                 return this;
3445
3446         }
3447
3448         subVectors( a, b ) {
3449
3450                 this.x = a.x - b.x;
3451                 this.y = a.y - b.y;
3452
3453                 return this;
3454
3455         }
3456
3457         multiply( v ) {
3458
3459                 this.x *= v.x;
3460                 this.y *= v.y;
3461
3462                 return this;
3463
3464         }
3465
3466         multiplyScalar( scalar ) {
3467
3468                 this.x *= scalar;
3469                 this.y *= scalar;
3470
3471                 return this;
3472
3473         }
3474
3475         divide( v ) {
3476
3477                 this.x /= v.x;
3478                 this.y /= v.y;
3479
3480                 return this;
3481
3482         }
3483
3484         divideScalar( scalar ) {
3485
3486                 return this.multiplyScalar( 1 / scalar );
3487
3488         }
3489
3490         applyMatrix3( m ) {
3491
3492                 const x = this.x, y = this.y;
3493                 const e = m.elements;
3494
3495                 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
3496                 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
3497
3498                 return this;
3499
3500         }
3501
3502         min( v ) {
3503
3504                 this.x = Math.min( this.x, v.x );
3505                 this.y = Math.min( this.y, v.y );
3506
3507                 return this;
3508
3509         }
3510
3511         max( v ) {
3512
3513                 this.x = Math.max( this.x, v.x );
3514                 this.y = Math.max( this.y, v.y );
3515
3516                 return this;
3517
3518         }
3519
3520         clamp( min, max ) {
3521
3522                 // assumes min < max, componentwise
3523
3524                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
3525                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
3526
3527                 return this;
3528
3529         }
3530
3531         clampScalar( minVal, maxVal ) {
3532
3533                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
3534                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
3535
3536                 return this;
3537
3538         }
3539
3540         clampLength( min, max ) {
3541
3542                 const length = this.length();
3543
3544                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
3545
3546         }
3547
3548         floor() {
3549
3550                 this.x = Math.floor( this.x );
3551                 this.y = Math.floor( this.y );
3552
3553                 return this;
3554
3555         }
3556
3557         ceil() {
3558
3559                 this.x = Math.ceil( this.x );
3560                 this.y = Math.ceil( this.y );
3561
3562                 return this;
3563
3564         }
3565
3566         round() {
3567
3568                 this.x = Math.round( this.x );
3569                 this.y = Math.round( this.y );
3570
3571                 return this;
3572
3573         }
3574
3575         roundToZero() {
3576
3577                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
3578                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
3579
3580                 return this;
3581
3582         }
3583
3584         negate() {
3585
3586                 this.x = - this.x;
3587                 this.y = - this.y;
3588
3589                 return this;
3590
3591         }
3592
3593         dot( v ) {
3594
3595                 return this.x * v.x + this.y * v.y;
3596
3597         }
3598
3599         cross( v ) {
3600
3601                 return this.x * v.y - this.y * v.x;
3602
3603         }
3604
3605         lengthSq() {
3606
3607                 return this.x * this.x + this.y * this.y;
3608
3609         }
3610
3611         length() {
3612
3613                 return Math.sqrt( this.x * this.x + this.y * this.y );
3614
3615         }
3616
3617         manhattanLength() {
3618
3619                 return Math.abs( this.x ) + Math.abs( this.y );
3620
3621         }
3622
3623         normalize() {
3624
3625                 return this.divideScalar( this.length() || 1 );
3626
3627         }
3628
3629         angle() {
3630
3631                 // computes the angle in radians with respect to the positive x-axis
3632
3633                 const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
3634
3635                 return angle;
3636
3637         }
3638
3639         distanceTo( v ) {
3640
3641                 return Math.sqrt( this.distanceToSquared( v ) );
3642
3643         }
3644
3645         distanceToSquared( v ) {
3646
3647                 const dx = this.x - v.x, dy = this.y - v.y;
3648                 return dx * dx + dy * dy;
3649
3650         }
3651
3652         manhattanDistanceTo( v ) {
3653
3654                 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
3655
3656         }
3657
3658         setLength( length ) {
3659
3660                 return this.normalize().multiplyScalar( length );
3661
3662         }
3663
3664         lerp( v, alpha ) {
3665
3666                 this.x += ( v.x - this.x ) * alpha;
3667                 this.y += ( v.y - this.y ) * alpha;
3668
3669                 return this;
3670
3671         }
3672
3673         lerpVectors( v1, v2, alpha ) {
3674
3675                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
3676                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
3677
3678                 return this;
3679
3680         }
3681
3682         equals( v ) {
3683
3684                 return ( ( v.x === this.x ) && ( v.y === this.y ) );
3685
3686         }
3687
3688         fromArray( array, offset = 0 ) {
3689
3690                 this.x = array[ offset ];
3691                 this.y = array[ offset + 1 ];
3692
3693                 return this;
3694
3695         }
3696
3697         toArray( array = [], offset = 0 ) {
3698
3699                 array[ offset ] = this.x;
3700                 array[ offset + 1 ] = this.y;
3701
3702                 return array;
3703
3704         }
3705
3706         fromBufferAttribute( attribute, index, offset ) {
3707
3708                 if ( offset !== undefined ) {
3709
3710                         console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
3711
3712                 }
3713
3714                 this.x = attribute.getX( index );
3715                 this.y = attribute.getY( index );
3716
3717                 return this;
3718
3719         }
3720
3721         rotateAround( center, angle ) {
3722
3723                 const c = Math.cos( angle ), s = Math.sin( angle );
3724
3725                 const x = this.x - center.x;
3726                 const y = this.y - center.y;
3727
3728                 this.x = x * c - y * s + center.x;
3729                 this.y = x * s + y * c + center.y;
3730
3731                 return this;
3732
3733         }
3734
3735         random() {
3736
3737                 this.x = Math.random();
3738                 this.y = Math.random();
3739
3740                 return this;
3741
3742         }
3743
3744         *[ Symbol.iterator ]() {
3745
3746                 yield this.x;
3747                 yield this.y;
3748
3749         }
3750
3751     }
3752
3753     Vector2.prototype.isVector2 = true;
3754
3755     class Matrix3 {
3756
3757         constructor() {
3758
3759                 this.elements = [
3760
3761                         1, 0, 0,
3762                         0, 1, 0,
3763                         0, 0, 1
3764
3765                 ];
3766
3767                 if ( arguments.length > 0 ) {
3768
3769                         console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
3770
3771                 }
3772
3773         }
3774
3775         set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
3776
3777                 const te = this.elements;
3778
3779                 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
3780                 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
3781                 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
3782
3783                 return this;
3784
3785         }
3786
3787         identity() {
3788
3789                 this.set(
3790
3791                         1, 0, 0,
3792                         0, 1, 0,
3793                         0, 0, 1
3794
3795                 );
3796
3797                 return this;
3798
3799         }
3800
3801         copy( m ) {
3802
3803                 const te = this.elements;
3804                 const me = m.elements;
3805
3806                 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
3807                 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
3808                 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
3809
3810                 return this;
3811
3812         }
3813
3814         extractBasis( xAxis, yAxis, zAxis ) {
3815
3816                 xAxis.setFromMatrix3Column( this, 0 );
3817                 yAxis.setFromMatrix3Column( this, 1 );
3818                 zAxis.setFromMatrix3Column( this, 2 );
3819
3820                 return this;
3821
3822         }
3823
3824         setFromMatrix4( m ) {
3825
3826                 const me = m.elements;
3827
3828                 this.set(
3829
3830                         me[ 0 ], me[ 4 ], me[ 8 ],
3831                         me[ 1 ], me[ 5 ], me[ 9 ],
3832                         me[ 2 ], me[ 6 ], me[ 10 ]
3833
3834                 );
3835
3836                 return this;
3837
3838         }
3839
3840         multiply( m ) {
3841
3842                 return this.multiplyMatrices( this, m );
3843
3844         }
3845
3846         premultiply( m ) {
3847
3848                 return this.multiplyMatrices( m, this );
3849
3850         }
3851
3852         multiplyMatrices( a, b ) {
3853
3854                 const ae = a.elements;
3855                 const be = b.elements;
3856                 const te = this.elements;
3857
3858                 const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
3859                 const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
3860                 const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
3861
3862                 const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
3863                 const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
3864                 const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
3865
3866                 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
3867                 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
3868                 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
3869
3870                 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
3871                 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
3872                 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
3873
3874                 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
3875                 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
3876                 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
3877
3878                 return this;
3879
3880         }
3881
3882         multiplyScalar( s ) {
3883
3884                 const te = this.elements;
3885
3886                 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
3887                 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
3888                 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
3889
3890                 return this;
3891
3892         }
3893
3894         determinant() {
3895
3896                 const te = this.elements;
3897
3898                 const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
3899                         d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
3900                         g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
3901
3902                 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
3903
3904         }
3905
3906         invert() {
3907
3908                 const te = this.elements,
3909
3910                         n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
3911                         n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
3912                         n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
3913
3914                         t11 = n33 * n22 - n32 * n23,
3915                         t12 = n32 * n13 - n33 * n12,
3916                         t13 = n23 * n12 - n22 * n13,
3917
3918                         det = n11 * t11 + n21 * t12 + n31 * t13;
3919
3920                 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
3921
3922                 const detInv = 1 / det;
3923
3924                 te[ 0 ] = t11 * detInv;
3925                 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
3926                 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
3927
3928                 te[ 3 ] = t12 * detInv;
3929                 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
3930                 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
3931
3932                 te[ 6 ] = t13 * detInv;
3933                 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
3934                 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
3935
3936                 return this;
3937
3938         }
3939
3940         transpose() {
3941
3942                 let tmp;
3943                 const m = this.elements;
3944
3945                 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
3946                 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
3947                 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
3948
3949                 return this;
3950
3951         }
3952
3953         getNormalMatrix( matrix4 ) {
3954
3955                 return this.setFromMatrix4( matrix4 ).invert().transpose();
3956
3957         }
3958
3959         transposeIntoArray( r ) {
3960
3961                 const m = this.elements;
3962
3963                 r[ 0 ] = m[ 0 ];
3964                 r[ 1 ] = m[ 3 ];
3965                 r[ 2 ] = m[ 6 ];
3966                 r[ 3 ] = m[ 1 ];
3967                 r[ 4 ] = m[ 4 ];
3968                 r[ 5 ] = m[ 7 ];
3969                 r[ 6 ] = m[ 2 ];
3970                 r[ 7 ] = m[ 5 ];
3971                 r[ 8 ] = m[ 8 ];
3972
3973                 return this;
3974
3975         }
3976
3977         setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
3978
3979                 const c = Math.cos( rotation );
3980                 const s = Math.sin( rotation );
3981
3982                 this.set(
3983                         sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
3984                         - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
3985                         0, 0, 1
3986                 );
3987
3988                 return this;
3989
3990         }
3991
3992         scale( sx, sy ) {
3993
3994                 const te = this.elements;
3995
3996                 te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
3997                 te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
3998
3999                 return this;
4000
4001         }
4002
4003         rotate( theta ) {
4004
4005                 const c = Math.cos( theta );
4006                 const s = Math.sin( theta );
4007
4008                 const te = this.elements;
4009
4010                 const a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
4011                 const a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
4012
4013                 te[ 0 ] = c * a11 + s * a21;
4014                 te[ 3 ] = c * a12 + s * a22;
4015                 te[ 6 ] = c * a13 + s * a23;
4016
4017                 te[ 1 ] = - s * a11 + c * a21;
4018                 te[ 4 ] = - s * a12 + c * a22;
4019                 te[ 7 ] = - s * a13 + c * a23;
4020
4021                 return this;
4022
4023         }
4024
4025         translate( tx, ty ) {
4026
4027                 const te = this.elements;
4028
4029                 te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
4030                 te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
4031
4032                 return this;
4033
4034         }
4035
4036         equals( matrix ) {
4037
4038                 const te = this.elements;
4039                 const me = matrix.elements;
4040
4041                 for ( let i = 0; i < 9; i ++ ) {
4042
4043                         if ( te[ i ] !== me[ i ] ) return false;
4044
4045                 }
4046
4047                 return true;
4048
4049         }
4050
4051         fromArray( array, offset = 0 ) {
4052
4053                 for ( let i = 0; i < 9; i ++ ) {
4054
4055                         this.elements[ i ] = array[ i + offset ];
4056
4057                 }
4058
4059                 return this;
4060
4061         }
4062
4063         toArray( array = [], offset = 0 ) {
4064
4065                 const te = this.elements;
4066
4067                 array[ offset ] = te[ 0 ];
4068                 array[ offset + 1 ] = te[ 1 ];
4069                 array[ offset + 2 ] = te[ 2 ];
4070
4071                 array[ offset + 3 ] = te[ 3 ];
4072                 array[ offset + 4 ] = te[ 4 ];
4073                 array[ offset + 5 ] = te[ 5 ];
4074
4075                 array[ offset + 6 ] = te[ 6 ];
4076                 array[ offset + 7 ] = te[ 7 ];
4077                 array[ offset + 8 ] = te[ 8 ];
4078
4079                 return array;
4080
4081         }
4082
4083         clone() {
4084
4085                 return new this.constructor().fromArray( this.elements );
4086
4087         }
4088
4089     }
4090
4091     Matrix3.prototype.isMatrix3 = true;
4092
4093     function arrayMax( array ) {
4094
4095         if ( array.length === 0 ) return - Infinity;
4096
4097         let max = array[ 0 ];
4098
4099         for ( let i = 1, l = array.length; i < l; ++ i ) {
4100
4101                 if ( array[ i ] > max ) max = array[ i ];
4102
4103         }
4104
4105         return max;
4106
4107     }
4108
4109     function createElementNS( name ) {
4110
4111         return document.createElementNS( 'http://www.w3.org/1999/xhtml', name );
4112
4113     }
4114
4115     /**
4116       * cyrb53 hash for string from: https://stackoverflow.com/a/52171480
4117       *
4118       * Public Domain, @bryc - https://stackoverflow.com/users/815680/bryc
4119       *
4120       * It is roughly similar to the well-known MurmurHash/xxHash algorithms. It uses a combination
4121       * of multiplication and Xorshift to generate the hash, but not as thorough. As a result it's
4122       * faster than either would be in JavaScript and significantly simpler to implement. Keep in
4123       * mind this is not a secure algorithm, if privacy/security is a concern, this is not for you.
4124       *
4125       * @param {string} str
4126       * @param {number} seed, default 0
4127       * @returns number
4128       */
4129     function hashString( str, seed = 0 ) {
4130
4131         let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
4132
4133         for ( let i = 0, ch; i < str.length; i ++ ) {
4134
4135                 ch = str.charCodeAt( i );
4136
4137                 h1 = Math.imul( h1 ^ ch, 2654435761 );
4138
4139                 h2 = Math.imul( h2 ^ ch, 1597334677 );
4140
4141         }
4142
4143         h1 = Math.imul( h1 ^ ( h1 >>> 16 ), 2246822507 ) ^ Math.imul( h2 ^ ( h2 >>> 13 ), 3266489909 );
4144
4145         h2 = Math.imul( h2 ^ ( h2 >>> 16 ), 2246822507 ) ^ Math.imul( h1 ^ ( h1 >>> 13 ), 3266489909 );
4146
4147         return 4294967296 * ( 2097151 & h2 ) + ( h1 >>> 0 );
4148
4149     }
4150
4151     let _canvas;
4152
4153     class ImageUtils {
4154
4155         static getDataURL( image ) {
4156
4157                 if ( /^data:/i.test( image.src ) ) {
4158
4159                         return image.src;
4160
4161                 }
4162
4163                 if ( typeof HTMLCanvasElement == 'undefined' ) {
4164
4165                         return image.src;
4166
4167                 }
4168
4169                 let canvas;
4170
4171                 if ( image instanceof HTMLCanvasElement ) {
4172
4173                         canvas = image;
4174
4175                 } else {
4176
4177                         if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' );
4178
4179                         _canvas.width = image.width;
4180                         _canvas.height = image.height;
4181
4182                         const context = _canvas.getContext( '2d' );
4183
4184                         if ( image instanceof ImageData ) {
4185
4186                                 context.putImageData( image, 0, 0 );
4187
4188                         } else {
4189
4190                                 context.drawImage( image, 0, 0, image.width, image.height );
4191
4192                         }
4193
4194                         canvas = _canvas;
4195
4196                 }
4197
4198                 if ( canvas.width > 2048 || canvas.height > 2048 ) {
4199
4200                         console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image );
4201
4202                         return canvas.toDataURL( 'image/jpeg', 0.6 );
4203
4204                 } else {
4205
4206                         return canvas.toDataURL( 'image/png' );
4207
4208                 }
4209
4210         }
4211
4212     }
4213
4214     let textureId = 0;
4215
4216     class Texture extends EventDispatcher {
4217
4218         constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding ) {
4219
4220                 super();
4221
4222                 Object.defineProperty( this, 'id', { value: textureId ++ } );
4223
4224                 this.uuid = generateUUID();
4225
4226                 this.name = '';
4227
4228                 this.image = image;
4229                 this.mipmaps = [];
4230
4231                 this.mapping = mapping;
4232
4233                 this.wrapS = wrapS;
4234                 this.wrapT = wrapT;
4235
4236                 this.magFilter = magFilter;
4237                 this.minFilter = minFilter;
4238
4239                 this.anisotropy = anisotropy;
4240
4241                 this.format = format;
4242                 this.internalFormat = null;
4243                 this.type = type;
4244
4245                 this.offset = new Vector2( 0, 0 );
4246                 this.repeat = new Vector2( 1, 1 );
4247                 this.center = new Vector2( 0, 0 );
4248                 this.rotation = 0;
4249
4250                 this.matrixAutoUpdate = true;
4251                 this.matrix = new Matrix3();
4252
4253                 this.generateMipmaps = true;
4254                 this.premultiplyAlpha = false;
4255                 this.flipY = true;
4256                 this.unpackAlignment = 4;       // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
4257
4258                 // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
4259                 //
4260                 // Also changing the encoding after already used by a Material will not automatically make the Material
4261                 // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
4262                 this.encoding = encoding;
4263
4264                 this.userData = {};
4265
4266                 this.version = 0;
4267                 this.onUpdate = null;
4268
4269                 this.isRenderTargetTexture = false;
4270
4271         }
4272
4273         updateMatrix() {
4274
4275                 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
4276
4277         }
4278
4279         clone() {
4280
4281                 return new this.constructor().copy( this );
4282
4283         }
4284
4285         copy( source ) {
4286
4287                 this.name = source.name;
4288
4289                 this.image = source.image;
4290                 this.mipmaps = source.mipmaps.slice( 0 );
4291
4292                 this.mapping = source.mapping;
4293
4294                 this.wrapS = source.wrapS;
4295                 this.wrapT = source.wrapT;
4296
4297                 this.magFilter = source.magFilter;
4298                 this.minFilter = source.minFilter;
4299
4300                 this.anisotropy = source.anisotropy;
4301
4302                 this.format = source.format;
4303                 this.internalFormat = source.internalFormat;
4304                 this.type = source.type;
4305
4306                 this.offset.copy( source.offset );
4307                 this.repeat.copy( source.repeat );
4308                 this.center.copy( source.center );
4309                 this.rotation = source.rotation;
4310
4311                 this.matrixAutoUpdate = source.matrixAutoUpdate;
4312                 this.matrix.copy( source.matrix );
4313
4314                 this.generateMipmaps = source.generateMipmaps;
4315                 this.premultiplyAlpha = source.premultiplyAlpha;
4316                 this.flipY = source.flipY;
4317                 this.unpackAlignment = source.unpackAlignment;
4318                 this.encoding = source.encoding;
4319
4320                 this.userData = JSON.parse( JSON.stringify( source.userData ) );
4321
4322                 return this;
4323
4324         }
4325
4326         toJSON( meta ) {
4327
4328                 const isRootObject = ( meta === undefined || typeof meta === 'string' );
4329
4330                 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
4331
4332                         return meta.textures[ this.uuid ];
4333
4334                 }
4335
4336                 const output = {
4337
4338                         metadata: {
4339                                 version: 4.5,
4340                                 type: 'Texture',
4341                                 generator: 'Texture.toJSON'
4342                         },
4343
4344                         uuid: this.uuid,
4345                         name: this.name,
4346
4347                         mapping: this.mapping,
4348
4349                         repeat: [ this.repeat.x, this.repeat.y ],
4350                         offset: [ this.offset.x, this.offset.y ],
4351                         center: [ this.center.x, this.center.y ],
4352                         rotation: this.rotation,
4353
4354                         wrap: [ this.wrapS, this.wrapT ],
4355
4356                         format: this.format,
4357                         type: this.type,
4358                         encoding: this.encoding,
4359
4360                         minFilter: this.minFilter,
4361                         magFilter: this.magFilter,
4362                         anisotropy: this.anisotropy,
4363
4364                         flipY: this.flipY,
4365
4366                         premultiplyAlpha: this.premultiplyAlpha,
4367                         unpackAlignment: this.unpackAlignment
4368
4369                 };
4370
4371                 if ( this.image !== undefined ) {
4372
4373                         // TODO: Move to THREE.Image
4374
4375                         const image = this.image;
4376
4377                         if ( image.uuid === undefined ) {
4378
4379                                 image.uuid = generateUUID(); // UGH
4380
4381                         }
4382
4383                         if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
4384
4385                                 let url;
4386
4387                                 if ( Array.isArray( image ) ) {
4388
4389                                         // process array of images e.g. CubeTexture
4390
4391                                         url = [];
4392
4393                                         for ( let i = 0, l = image.length; i < l; i ++ ) {
4394
4395                                                 // check cube texture with data textures
4396
4397                                                 if ( image[ i ].isDataTexture ) {
4398
4399                                                         url.push( serializeImage( image[ i ].image ) );
4400
4401                                                 } else {
4402
4403                                                         url.push( serializeImage( image[ i ] ) );
4404
4405                                                 }
4406
4407                                         }
4408
4409                                 } else {
4410
4411                                         // process single image
4412
4413                                         url = serializeImage( image );
4414
4415                                 }
4416
4417                                 meta.images[ image.uuid ] = {
4418                                         uuid: image.uuid,
4419                                         url: url
4420                                 };
4421
4422                         }
4423
4424                         output.image = image.uuid;
4425
4426                 }
4427
4428                 if ( JSON.stringify( this.userData ) !== '{}' ) output.userData = this.userData;
4429
4430                 if ( ! isRootObject ) {
4431
4432                         meta.textures[ this.uuid ] = output;
4433
4434                 }
4435
4436                 return output;
4437
4438         }
4439
4440         dispose() {
4441
4442                 this.dispatchEvent( { type: 'dispose' } );
4443
4444         }
4445
4446         transformUv( uv ) {
4447
4448                 if ( this.mapping !== UVMapping ) return uv;
4449
4450                 uv.applyMatrix3( this.matrix );
4451
4452                 if ( uv.x < 0 || uv.x > 1 ) {
4453
4454                         switch ( this.wrapS ) {
4455
4456                                 case RepeatWrapping:
4457
4458                                         uv.x = uv.x - Math.floor( uv.x );
4459                                         break;
4460
4461                                 case ClampToEdgeWrapping:
4462
4463                                         uv.x = uv.x < 0 ? 0 : 1;
4464                                         break;
4465
4466                                 case MirroredRepeatWrapping:
4467
4468                                         if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
4469
4470                                                 uv.x = Math.ceil( uv.x ) - uv.x;
4471
4472                                         } else {
4473
4474                                                 uv.x = uv.x - Math.floor( uv.x );
4475
4476                                         }
4477
4478                                         break;
4479
4480                         }
4481
4482                 }
4483
4484                 if ( uv.y < 0 || uv.y > 1 ) {
4485
4486                         switch ( this.wrapT ) {
4487
4488                                 case RepeatWrapping:
4489
4490                                         uv.y = uv.y - Math.floor( uv.y );
4491                                         break;
4492
4493                                 case ClampToEdgeWrapping:
4494
4495                                         uv.y = uv.y < 0 ? 0 : 1;
4496                                         break;
4497
4498                                 case MirroredRepeatWrapping:
4499
4500                                         if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
4501
4502                                                 uv.y = Math.ceil( uv.y ) - uv.y;
4503
4504                                         } else {
4505
4506                                                 uv.y = uv.y - Math.floor( uv.y );
4507
4508                                         }
4509
4510                                         break;
4511
4512                         }
4513
4514                 }
4515
4516                 if ( this.flipY ) {
4517
4518                         uv.y = 1 - uv.y;
4519
4520                 }
4521
4522                 return uv;
4523
4524         }
4525
4526         set needsUpdate( value ) {
4527
4528                 if ( value === true ) this.version ++;
4529
4530         }
4531
4532     }
4533
4534     Texture.DEFAULT_IMAGE = undefined;
4535     Texture.DEFAULT_MAPPING = UVMapping;
4536
4537     Texture.prototype.isTexture = true;
4538
4539     function serializeImage( image ) {
4540
4541         if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
4542                 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
4543                 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
4544
4545                 // default images
4546
4547                 return ImageUtils.getDataURL( image );
4548
4549         } else {
4550
4551                 if ( image.data ) {
4552
4553                         // images of DataTexture
4554
4555                         return {
4556                                 data: Array.prototype.slice.call( image.data ),
4557                                 width: image.width,
4558                                 height: image.height,
4559                                 type: image.data.constructor.name
4560                         };
4561
4562                 } else {
4563
4564                         console.warn( 'THREE.Texture: Unable to serialize Texture.' );
4565                         return {};
4566
4567                 }
4568
4569         }
4570
4571     }
4572
4573     class Vector4 {
4574
4575         constructor( x = 0, y = 0, z = 0, w = 1 ) {
4576
4577                 this.x = x;
4578                 this.y = y;
4579                 this.z = z;
4580                 this.w = w;
4581
4582         }
4583
4584         get width() {
4585
4586                 return this.z;
4587
4588         }
4589
4590         set width( value ) {
4591
4592                 this.z = value;
4593
4594         }
4595
4596         get height() {
4597
4598                 return this.w;
4599
4600         }
4601
4602         set height( value ) {
4603
4604                 this.w = value;
4605
4606         }
4607
4608         set( x, y, z, w ) {
4609
4610                 this.x = x;
4611                 this.y = y;
4612                 this.z = z;
4613                 this.w = w;
4614
4615                 return this;
4616
4617         }
4618
4619         setScalar( scalar ) {
4620
4621                 this.x = scalar;
4622                 this.y = scalar;
4623                 this.z = scalar;
4624                 this.w = scalar;
4625
4626                 return this;
4627
4628         }
4629
4630         setX( x ) {
4631
4632                 this.x = x;
4633
4634                 return this;
4635
4636         }
4637
4638         setY( y ) {
4639
4640                 this.y = y;
4641
4642                 return this;
4643
4644         }
4645
4646         setZ( z ) {
4647
4648                 this.z = z;
4649
4650                 return this;
4651
4652         }
4653
4654         setW( w ) {
4655
4656                 this.w = w;
4657
4658                 return this;
4659
4660         }
4661
4662         setComponent( index, value ) {
4663
4664                 switch ( index ) {
4665
4666                         case 0: this.x = value; break;
4667                         case 1: this.y = value; break;
4668                         case 2: this.z = value; break;
4669                         case 3: this.w = value; break;
4670                         default: throw new Error( 'index is out of range: ' + index );
4671
4672                 }
4673
4674                 return this;
4675
4676         }
4677
4678         getComponent( index ) {
4679
4680                 switch ( index ) {
4681
4682                         case 0: return this.x;
4683                         case 1: return this.y;
4684                         case 2: return this.z;
4685                         case 3: return this.w;
4686                         default: throw new Error( 'index is out of range: ' + index );
4687
4688                 }
4689
4690         }
4691
4692         clone() {
4693
4694                 return new this.constructor( this.x, this.y, this.z, this.w );
4695
4696         }
4697
4698         copy( v ) {
4699
4700                 this.x = v.x;
4701                 this.y = v.y;
4702                 this.z = v.z;
4703                 this.w = ( v.w !== undefined ) ? v.w : 1;
4704
4705                 return this;
4706
4707         }
4708
4709         add( v, w ) {
4710
4711                 if ( w !== undefined ) {
4712
4713                         console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
4714                         return this.addVectors( v, w );
4715
4716                 }
4717
4718                 this.x += v.x;
4719                 this.y += v.y;
4720                 this.z += v.z;
4721                 this.w += v.w;
4722
4723                 return this;
4724
4725         }
4726
4727         addScalar( s ) {
4728
4729                 this.x += s;
4730                 this.y += s;
4731                 this.z += s;
4732                 this.w += s;
4733
4734                 return this;
4735
4736         }
4737
4738         addVectors( a, b ) {
4739
4740                 this.x = a.x + b.x;
4741                 this.y = a.y + b.y;
4742                 this.z = a.z + b.z;
4743                 this.w = a.w + b.w;
4744
4745                 return this;
4746
4747         }
4748
4749         addScaledVector( v, s ) {
4750
4751                 this.x += v.x * s;
4752                 this.y += v.y * s;
4753                 this.z += v.z * s;
4754                 this.w += v.w * s;
4755
4756                 return this;
4757
4758         }
4759
4760         sub( v, w ) {
4761
4762                 if ( w !== undefined ) {
4763
4764                         console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
4765                         return this.subVectors( v, w );
4766
4767                 }
4768
4769                 this.x -= v.x;
4770                 this.y -= v.y;
4771                 this.z -= v.z;
4772                 this.w -= v.w;
4773
4774                 return this;
4775
4776         }
4777
4778         subScalar( s ) {
4779
4780                 this.x -= s;
4781                 this.y -= s;
4782                 this.z -= s;
4783                 this.w -= s;
4784
4785                 return this;
4786
4787         }
4788
4789         subVectors( a, b ) {
4790
4791                 this.x = a.x - b.x;
4792                 this.y = a.y - b.y;
4793                 this.z = a.z - b.z;
4794                 this.w = a.w - b.w;
4795
4796                 return this;
4797
4798         }
4799
4800         multiply( v ) {
4801
4802                 this.x *= v.x;
4803                 this.y *= v.y;
4804                 this.z *= v.z;
4805                 this.w *= v.w;
4806
4807                 return this;
4808
4809         }
4810
4811         multiplyScalar( scalar ) {
4812
4813                 this.x *= scalar;
4814                 this.y *= scalar;
4815                 this.z *= scalar;
4816                 this.w *= scalar;
4817
4818                 return this;
4819
4820         }
4821
4822         applyMatrix4( m ) {
4823
4824                 const x = this.x, y = this.y, z = this.z, w = this.w;
4825                 const e = m.elements;
4826
4827                 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
4828                 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
4829                 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
4830                 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
4831
4832                 return this;
4833
4834         }
4835
4836         divideScalar( scalar ) {
4837
4838                 return this.multiplyScalar( 1 / scalar );
4839
4840         }
4841
4842         setAxisAngleFromQuaternion( q ) {
4843
4844                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
4845
4846                 // q is assumed to be normalized
4847
4848                 this.w = 2 * Math.acos( q.w );
4849
4850                 const s = Math.sqrt( 1 - q.w * q.w );
4851
4852                 if ( s < 0.0001 ) {
4853
4854                         this.x = 1;
4855                         this.y = 0;
4856                         this.z = 0;
4857
4858                 } else {
4859
4860                         this.x = q.x / s;
4861                         this.y = q.y / s;
4862                         this.z = q.z / s;
4863
4864                 }
4865
4866                 return this;
4867
4868         }
4869
4870         setAxisAngleFromRotationMatrix( m ) {
4871
4872                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
4873
4874                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
4875
4876                 let angle, x, y, z; // variables for result
4877                 const epsilon = 0.01,           // margin to allow for rounding errors
4878                         epsilon2 = 0.1,         // margin to distinguish between 0 and 180 degrees
4879
4880                         te = m.elements,
4881
4882                         m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
4883                         m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
4884                         m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
4885
4886                 if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
4887                      ( Math.abs( m13 - m31 ) < epsilon ) &&
4888                      ( Math.abs( m23 - m32 ) < epsilon ) ) {
4889
4890                         // singularity found
4891                         // first check for identity matrix which must have +1 for all terms
4892                         // in leading diagonal and zero in other terms
4893
4894                         if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
4895                              ( Math.abs( m13 + m31 ) < epsilon2 ) &&
4896                              ( Math.abs( m23 + m32 ) < epsilon2 ) &&
4897                              ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
4898
4899                                 // this singularity is identity matrix so angle = 0
4900
4901                                 this.set( 1, 0, 0, 0 );
4902
4903                                 return this; // zero angle, arbitrary axis
4904
4905                         }
4906
4907                         // otherwise this singularity is angle = 180
4908
4909                         angle = Math.PI;
4910
4911                         const xx = ( m11 + 1 ) / 2;
4912                         const yy = ( m22 + 1 ) / 2;
4913                         const zz = ( m33 + 1 ) / 2;
4914                         const xy = ( m12 + m21 ) / 4;
4915                         const xz = ( m13 + m31 ) / 4;
4916                         const yz = ( m23 + m32 ) / 4;
4917
4918                         if ( ( xx > yy ) && ( xx > zz ) ) {
4919
4920                                 // m11 is the largest diagonal term
4921
4922                                 if ( xx < epsilon ) {
4923
4924                                         x = 0;
4925                                         y = 0.707106781;
4926                                         z = 0.707106781;
4927
4928                                 } else {
4929
4930                                         x = Math.sqrt( xx );
4931                                         y = xy / x;
4932                                         z = xz / x;
4933
4934                                 }
4935
4936                         } else if ( yy > zz ) {
4937
4938                                 // m22 is the largest diagonal term
4939
4940                                 if ( yy < epsilon ) {
4941
4942                                         x = 0.707106781;
4943                                         y = 0;
4944                                         z = 0.707106781;
4945
4946                                 } else {
4947
4948                                         y = Math.sqrt( yy );
4949                                         x = xy / y;
4950                                         z = yz / y;
4951
4952                                 }
4953
4954                         } else {
4955
4956                                 // m33 is the largest diagonal term so base result on this
4957
4958                                 if ( zz < epsilon ) {
4959
4960                                         x = 0.707106781;
4961                                         y = 0.707106781;
4962                                         z = 0;
4963
4964                                 } else {
4965
4966                                         z = Math.sqrt( zz );
4967                                         x = xz / z;
4968                                         y = yz / z;
4969
4970                                 }
4971
4972                         }
4973
4974                         this.set( x, y, z, angle );
4975
4976                         return this; // return 180 deg rotation
4977
4978                 }
4979
4980                 // as we have reached here there are no singularities so we can handle normally
4981
4982                 let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
4983                         ( m13 - m31 ) * ( m13 - m31 ) +
4984                         ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
4985
4986                 if ( Math.abs( s ) < 0.001 ) s = 1;
4987
4988                 // prevent divide by zero, should not happen if matrix is orthogonal and should be
4989                 // caught by singularity test above, but I've left it in just in case
4990
4991                 this.x = ( m32 - m23 ) / s;
4992                 this.y = ( m13 - m31 ) / s;
4993                 this.z = ( m21 - m12 ) / s;
4994                 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
4995
4996                 return this;
4997
4998         }
4999
5000         min( v ) {
5001
5002                 this.x = Math.min( this.x, v.x );
5003                 this.y = Math.min( this.y, v.y );
5004                 this.z = Math.min( this.z, v.z );
5005                 this.w = Math.min( this.w, v.w );
5006
5007                 return this;
5008
5009         }
5010
5011         max( v ) {
5012
5013                 this.x = Math.max( this.x, v.x );
5014                 this.y = Math.max( this.y, v.y );
5015                 this.z = Math.max( this.z, v.z );
5016                 this.w = Math.max( this.w, v.w );
5017
5018                 return this;
5019
5020         }
5021
5022         clamp( min, max ) {
5023
5024                 // assumes min < max, componentwise
5025
5026                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
5027                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
5028                 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
5029                 this.w = Math.max( min.w, Math.min( max.w, this.w ) );
5030
5031                 return this;
5032
5033         }
5034
5035         clampScalar( minVal, maxVal ) {
5036
5037                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
5038                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
5039                 this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
5040                 this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
5041
5042                 return this;
5043
5044         }
5045
5046         clampLength( min, max ) {
5047
5048                 const length = this.length();
5049
5050                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
5051
5052         }
5053
5054         floor() {
5055
5056                 this.x = Math.floor( this.x );
5057                 this.y = Math.floor( this.y );
5058                 this.z = Math.floor( this.z );
5059                 this.w = Math.floor( this.w );
5060
5061                 return this;
5062
5063         }
5064
5065         ceil() {
5066
5067                 this.x = Math.ceil( this.x );
5068                 this.y = Math.ceil( this.y );
5069                 this.z = Math.ceil( this.z );
5070                 this.w = Math.ceil( this.w );
5071
5072                 return this;
5073
5074         }
5075
5076         round() {
5077
5078                 this.x = Math.round( this.x );
5079                 this.y = Math.round( this.y );
5080                 this.z = Math.round( this.z );
5081                 this.w = Math.round( this.w );
5082
5083                 return this;
5084
5085         }
5086
5087         roundToZero() {
5088
5089                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
5090                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
5091                 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
5092                 this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
5093
5094                 return this;
5095
5096         }
5097
5098         negate() {
5099
5100                 this.x = - this.x;
5101                 this.y = - this.y;
5102                 this.z = - this.z;
5103                 this.w = - this.w;
5104
5105                 return this;
5106
5107         }
5108
5109         dot( v ) {
5110
5111                 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
5112
5113         }
5114
5115         lengthSq() {
5116
5117                 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
5118
5119         }
5120
5121         length() {
5122
5123                 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
5124
5125         }
5126
5127         manhattanLength() {
5128
5129                 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
5130
5131         }
5132
5133         normalize() {
5134
5135                 return this.divideScalar( this.length() || 1 );
5136
5137         }
5138
5139         setLength( length ) {
5140
5141                 return this.normalize().multiplyScalar( length );
5142
5143         }
5144
5145         lerp( v, alpha ) {
5146
5147                 this.x += ( v.x - this.x ) * alpha;
5148                 this.y += ( v.y - this.y ) * alpha;
5149                 this.z += ( v.z - this.z ) * alpha;
5150                 this.w += ( v.w - this.w ) * alpha;
5151
5152                 return this;
5153
5154         }
5155
5156         lerpVectors( v1, v2, alpha ) {
5157
5158                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
5159                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
5160                 this.z = v1.z + ( v2.z - v1.z ) * alpha;
5161                 this.w = v1.w + ( v2.w - v1.w ) * alpha;
5162
5163                 return this;
5164
5165         }
5166
5167         equals( v ) {
5168
5169                 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
5170
5171         }
5172
5173         fromArray( array, offset = 0 ) {
5174
5175                 this.x = array[ offset ];
5176                 this.y = array[ offset + 1 ];
5177                 this.z = array[ offset + 2 ];
5178                 this.w = array[ offset + 3 ];
5179
5180                 return this;
5181
5182         }
5183
5184         toArray( array = [], offset = 0 ) {
5185
5186                 array[ offset ] = this.x;
5187                 array[ offset + 1 ] = this.y;
5188                 array[ offset + 2 ] = this.z;
5189                 array[ offset + 3 ] = this.w;
5190
5191                 return array;
5192
5193         }
5194
5195         fromBufferAttribute( attribute, index, offset ) {
5196
5197                 if ( offset !== undefined ) {
5198
5199                         console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
5200
5201                 }
5202
5203                 this.x = attribute.getX( index );
5204                 this.y = attribute.getY( index );
5205                 this.z = attribute.getZ( index );
5206                 this.w = attribute.getW( index );
5207
5208                 return this;
5209
5210         }
5211
5212         random() {
5213
5214                 this.x = Math.random();
5215                 this.y = Math.random();
5216                 this.z = Math.random();
5217                 this.w = Math.random();
5218
5219                 return this;
5220
5221         }
5222
5223         *[ Symbol.iterator ]() {
5224
5225                 yield this.x;
5226                 yield this.y;
5227                 yield this.z;
5228                 yield this.w;
5229
5230         }
5231
5232     }
5233
5234     Vector4.prototype.isVector4 = true;
5235
5236     /*
5237      In options, we can specify:
5238      * Texture parameters for an auto-generated target texture
5239      * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
5240     */
5241     class WebGLRenderTarget extends EventDispatcher {
5242
5243         constructor( width, height, options = {} ) {
5244
5245                 super();
5246
5247                 this.width = width;
5248                 this.height = height;
5249                 this.depth = 1;
5250
5251                 this.scissor = new Vector4( 0, 0, width, height );
5252                 this.scissorTest = false;
5253
5254                 this.viewport = new Vector4( 0, 0, width, height );
5255
5256                 this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
5257                 this.texture.isRenderTargetTexture = true;
5258
5259                 this.texture.image = { width: width, height: height, depth: 1 };
5260
5261                 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
5262                 this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null;
5263                 this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
5264
5265                 this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
5266                 this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
5267                 this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
5268
5269         }
5270
5271         setTexture( texture ) {
5272
5273                 texture.image = {
5274                         width: this.width,
5275                         height: this.height,
5276                         depth: this.depth
5277                 };
5278
5279                 this.texture = texture;
5280
5281         }
5282
5283         setSize( width, height, depth = 1 ) {
5284
5285                 if ( this.width !== width || this.height !== height || this.depth !== depth ) {
5286
5287                         this.width = width;
5288                         this.height = height;
5289                         this.depth = depth;
5290
5291                         this.texture.image.width = width;
5292                         this.texture.image.height = height;
5293                         this.texture.image.depth = depth;
5294
5295                         this.dispose();
5296
5297                 }
5298
5299                 this.viewport.set( 0, 0, width, height );
5300                 this.scissor.set( 0, 0, width, height );
5301
5302         }
5303
5304         clone() {
5305
5306                 return new this.constructor().copy( this );
5307
5308         }
5309
5310         copy( source ) {
5311
5312                 this.width = source.width;
5313                 this.height = source.height;
5314                 this.depth = source.depth;
5315
5316                 this.viewport.copy( source.viewport );
5317
5318                 this.texture = source.texture.clone();
5319                 this.texture.image = { ...this.texture.image }; // See #20328.
5320
5321                 this.depthBuffer = source.depthBuffer;
5322                 this.stencilBuffer = source.stencilBuffer;
5323                 this.depthTexture = source.depthTexture;
5324
5325                 return this;
5326
5327         }
5328
5329         dispose() {
5330
5331                 this.dispatchEvent( { type: 'dispose' } );
5332
5333         }
5334
5335     }
5336
5337     WebGLRenderTarget.prototype.isWebGLRenderTarget = true;
5338
5339     class WebGLMultipleRenderTargets extends WebGLRenderTarget {
5340
5341         constructor( width, height, count ) {
5342
5343                 super( width, height );
5344
5345                 const texture = this.texture;
5346
5347                 this.texture = [];
5348
5349                 for ( let i = 0; i < count; i ++ ) {
5350
5351                         this.texture[ i ] = texture.clone();
5352
5353                 }
5354
5355         }
5356
5357         setSize( width, height, depth = 1 ) {
5358
5359                 if ( this.width !== width || this.height !== height || this.depth !== depth ) {
5360
5361                         this.width = width;
5362                         this.height = height;
5363                         this.depth = depth;
5364
5365                         for ( let i = 0, il = this.texture.length; i < il; i ++ ) {
5366
5367                                 this.texture[ i ].image.width = width;
5368                                 this.texture[ i ].image.height = height;
5369                                 this.texture[ i ].image.depth = depth;
5370
5371                         }
5372
5373                         this.dispose();
5374
5375                 }
5376
5377                 this.viewport.set( 0, 0, width, height );
5378                 this.scissor.set( 0, 0, width, height );
5379
5380                 return this;
5381
5382         }
5383
5384         copy( source ) {
5385
5386                 this.dispose();
5387
5388                 this.width = source.width;
5389                 this.height = source.height;
5390                 this.depth = source.depth;
5391
5392                 this.viewport.set( 0, 0, this.width, this.height );
5393                 this.scissor.set( 0, 0, this.width, this.height );
5394
5395                 this.depthBuffer = source.depthBuffer;
5396                 this.stencilBuffer = source.stencilBuffer;
5397                 this.depthTexture = source.depthTexture;
5398
5399                 this.texture.length = 0;
5400
5401                 for ( let i = 0, il = source.texture.length; i < il; i ++ ) {
5402
5403                         this.texture[ i ] = source.texture[ i ].clone();
5404
5405                 }
5406
5407                 return this;
5408
5409         }
5410
5411     }
5412
5413     WebGLMultipleRenderTargets.prototype.isWebGLMultipleRenderTargets = true;
5414
5415     class WebGLMultisampleRenderTarget extends WebGLRenderTarget {
5416
5417         constructor( width, height, options ) {
5418
5419                 super( width, height, options );
5420
5421                 this.samples = 4;
5422
5423         }
5424
5425         copy( source ) {
5426
5427                 super.copy.call( this, source );
5428
5429                 this.samples = source.samples;
5430
5431                 return this;
5432
5433         }
5434
5435     }
5436
5437     WebGLMultisampleRenderTarget.prototype.isWebGLMultisampleRenderTarget = true;
5438
5439     class Quaternion {
5440
5441         constructor( x = 0, y = 0, z = 0, w = 1 ) {
5442
5443                 this._x = x;
5444                 this._y = y;
5445                 this._z = z;
5446                 this._w = w;
5447
5448         }
5449
5450         static slerp( qa, qb, qm, t ) {
5451
5452                 console.warn( 'THREE.Quaternion: Static .slerp() has been deprecated. Use qm.slerpQuaternions( qa, qb, t ) instead.' );
5453                 return qm.slerpQuaternions( qa, qb, t );
5454
5455         }
5456
5457         static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
5458
5459                 // fuzz-free, array-based Quaternion SLERP operation
5460
5461                 let x0 = src0[ srcOffset0 + 0 ],
5462                         y0 = src0[ srcOffset0 + 1 ],
5463                         z0 = src0[ srcOffset0 + 2 ],
5464                         w0 = src0[ srcOffset0 + 3 ];
5465
5466                 const x1 = src1[ srcOffset1 + 0 ],
5467                         y1 = src1[ srcOffset1 + 1 ],
5468                         z1 = src1[ srcOffset1 + 2 ],
5469                         w1 = src1[ srcOffset1 + 3 ];
5470
5471                 if ( t === 0 ) {
5472
5473                         dst[ dstOffset + 0 ] = x0;
5474                         dst[ dstOffset + 1 ] = y0;
5475                         dst[ dstOffset + 2 ] = z0;
5476                         dst[ dstOffset + 3 ] = w0;
5477                         return;
5478
5479                 }
5480
5481                 if ( t === 1 ) {
5482
5483                         dst[ dstOffset + 0 ] = x1;
5484                         dst[ dstOffset + 1 ] = y1;
5485                         dst[ dstOffset + 2 ] = z1;
5486                         dst[ dstOffset + 3 ] = w1;
5487                         return;
5488
5489                 }
5490
5491                 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
5492
5493                         let s = 1 - t;
5494                         const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
5495                                 dir = ( cos >= 0 ? 1 : - 1 ),
5496                                 sqrSin = 1 - cos * cos;
5497
5498                         // Skip the Slerp for tiny steps to avoid numeric problems:
5499                         if ( sqrSin > Number.EPSILON ) {
5500
5501                                 const sin = Math.sqrt( sqrSin ),
5502                                         len = Math.atan2( sin, cos * dir );
5503
5504                                 s = Math.sin( s * len ) / sin;
5505                                 t = Math.sin( t * len ) / sin;
5506
5507                         }
5508
5509                         const tDir = t * dir;
5510
5511                         x0 = x0 * s + x1 * tDir;
5512                         y0 = y0 * s + y1 * tDir;
5513                         z0 = z0 * s + z1 * tDir;
5514                         w0 = w0 * s + w1 * tDir;
5515
5516                         // Normalize in case we just did a lerp:
5517                         if ( s === 1 - t ) {
5518
5519                                 const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
5520
5521                                 x0 *= f;
5522                                 y0 *= f;
5523                                 z0 *= f;
5524                                 w0 *= f;
5525
5526                         }
5527
5528                 }
5529
5530                 dst[ dstOffset ] = x0;
5531                 dst[ dstOffset + 1 ] = y0;
5532                 dst[ dstOffset + 2 ] = z0;
5533                 dst[ dstOffset + 3 ] = w0;
5534
5535         }
5536
5537         static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
5538
5539                 const x0 = src0[ srcOffset0 ];
5540                 const y0 = src0[ srcOffset0 + 1 ];
5541                 const z0 = src0[ srcOffset0 + 2 ];
5542                 const w0 = src0[ srcOffset0 + 3 ];
5543
5544                 const x1 = src1[ srcOffset1 ];
5545                 const y1 = src1[ srcOffset1 + 1 ];
5546                 const z1 = src1[ srcOffset1 + 2 ];
5547                 const w1 = src1[ srcOffset1 + 3 ];
5548
5549                 dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
5550                 dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
5551                 dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
5552                 dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
5553
5554                 return dst;
5555
5556         }
5557
5558         get x() {
5559
5560                 return this._x;
5561
5562         }
5563
5564         set x( value ) {
5565
5566                 this._x = value;
5567                 this._onChangeCallback();
5568
5569         }
5570
5571         get y() {
5572
5573                 return this._y;
5574
5575         }
5576
5577         set y( value ) {
5578
5579                 this._y = value;
5580                 this._onChangeCallback();
5581
5582         }
5583
5584         get z() {
5585
5586                 return this._z;
5587
5588         }
5589
5590         set z( value ) {
5591
5592                 this._z = value;
5593                 this._onChangeCallback();
5594
5595         }
5596
5597         get w() {
5598
5599                 return this._w;
5600
5601         }
5602
5603         set w( value ) {
5604
5605                 this._w = value;
5606                 this._onChangeCallback();
5607
5608         }
5609
5610         set( x, y, z, w ) {
5611
5612                 this._x = x;
5613                 this._y = y;
5614                 this._z = z;
5615                 this._w = w;
5616
5617                 this._onChangeCallback();
5618
5619                 return this;
5620
5621         }
5622
5623         clone() {
5624
5625                 return new this.constructor( this._x, this._y, this._z, this._w );
5626
5627         }
5628
5629         copy( quaternion ) {
5630
5631                 this._x = quaternion.x;
5632                 this._y = quaternion.y;
5633                 this._z = quaternion.z;
5634                 this._w = quaternion.w;
5635
5636                 this._onChangeCallback();
5637
5638                 return this;
5639
5640         }
5641
5642         setFromEuler( euler, update ) {
5643
5644                 if ( ! ( euler && euler.isEuler ) ) {
5645
5646                         throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
5647
5648                 }
5649
5650                 const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
5651
5652                 // http://www.mathworks.com/matlabcentral/fileexchange/
5653                 //      20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
5654                 //      content/SpinCalc.m
5655
5656                 const cos = Math.cos;
5657                 const sin = Math.sin;
5658
5659                 const c1 = cos( x / 2 );
5660                 const c2 = cos( y / 2 );
5661                 const c3 = cos( z / 2 );
5662
5663                 const s1 = sin( x / 2 );
5664                 const s2 = sin( y / 2 );
5665                 const s3 = sin( z / 2 );
5666
5667                 switch ( order ) {
5668
5669                         case 'XYZ':
5670                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
5671                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
5672                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
5673                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
5674                                 break;
5675
5676                         case 'YXZ':
5677                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
5678                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
5679                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
5680                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
5681                                 break;
5682
5683                         case 'ZXY':
5684                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
5685                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
5686                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
5687                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
5688                                 break;
5689
5690                         case 'ZYX':
5691                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
5692                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
5693                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
5694                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
5695                                 break;
5696
5697                         case 'YZX':
5698                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
5699                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
5700                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
5701                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
5702                                 break;
5703
5704                         case 'XZY':
5705                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
5706                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
5707                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
5708                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
5709                                 break;
5710
5711                         default:
5712                                 console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
5713
5714                 }
5715
5716                 if ( update !== false ) this._onChangeCallback();
5717
5718                 return this;
5719
5720         }
5721
5722         setFromAxisAngle( axis, angle ) {
5723
5724                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
5725
5726                 // assumes axis is normalized
5727
5728                 const halfAngle = angle / 2, s = Math.sin( halfAngle );
5729
5730                 this._x = axis.x * s;
5731                 this._y = axis.y * s;
5732                 this._z = axis.z * s;
5733                 this._w = Math.cos( halfAngle );
5734
5735                 this._onChangeCallback();
5736
5737                 return this;
5738
5739         }
5740
5741         setFromRotationMatrix( m ) {
5742
5743                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
5744
5745                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
5746
5747                 const te = m.elements,
5748
5749                         m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
5750                         m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
5751                         m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
5752
5753                         trace = m11 + m22 + m33;
5754
5755                 if ( trace > 0 ) {
5756
5757                         const s = 0.5 / Math.sqrt( trace + 1.0 );
5758
5759                         this._w = 0.25 / s;
5760                         this._x = ( m32 - m23 ) * s;
5761                         this._y = ( m13 - m31 ) * s;
5762                         this._z = ( m21 - m12 ) * s;
5763
5764                 } else if ( m11 > m22 && m11 > m33 ) {
5765
5766                         const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
5767
5768                         this._w = ( m32 - m23 ) / s;
5769                         this._x = 0.25 * s;
5770                         this._y = ( m12 + m21 ) / s;
5771                         this._z = ( m13 + m31 ) / s;
5772
5773                 } else if ( m22 > m33 ) {
5774
5775                         const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
5776
5777                         this._w = ( m13 - m31 ) / s;
5778                         this._x = ( m12 + m21 ) / s;
5779                         this._y = 0.25 * s;
5780                         this._z = ( m23 + m32 ) / s;
5781
5782                 } else {
5783
5784                         const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
5785
5786                         this._w = ( m21 - m12 ) / s;
5787                         this._x = ( m13 + m31 ) / s;
5788                         this._y = ( m23 + m32 ) / s;
5789                         this._z = 0.25 * s;
5790
5791                 }
5792
5793                 this._onChangeCallback();
5794
5795                 return this;
5796
5797         }
5798
5799         setFromUnitVectors( vFrom, vTo ) {
5800
5801                 // assumes direction vectors vFrom and vTo are normalized
5802
5803                 let r = vFrom.dot( vTo ) + 1;
5804
5805                 if ( r < Number.EPSILON ) {
5806
5807                         // vFrom and vTo point in opposite directions
5808
5809                         r = 0;
5810
5811                         if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
5812
5813                                 this._x = - vFrom.y;
5814                                 this._y = vFrom.x;
5815                                 this._z = 0;
5816                                 this._w = r;
5817
5818                         } else {
5819
5820                                 this._x = 0;
5821                                 this._y = - vFrom.z;
5822                                 this._z = vFrom.y;
5823                                 this._w = r;
5824
5825                         }
5826
5827                 } else {
5828
5829                         // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
5830
5831                         this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
5832                         this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
5833                         this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
5834                         this._w = r;
5835
5836                 }
5837
5838                 return this.normalize();
5839
5840         }
5841
5842         angleTo( q ) {
5843
5844                 return 2 * Math.acos( Math.abs( clamp$1( this.dot( q ), - 1, 1 ) ) );
5845
5846         }
5847
5848         rotateTowards( q, step ) {
5849
5850                 const angle = this.angleTo( q );
5851
5852                 if ( angle === 0 ) return this;
5853
5854                 const t = Math.min( 1, step / angle );
5855
5856                 this.slerp( q, t );
5857
5858                 return this;
5859
5860         }
5861
5862         identity() {
5863
5864                 return this.set( 0, 0, 0, 1 );
5865
5866         }
5867
5868         invert() {
5869
5870                 // quaternion is assumed to have unit length
5871
5872                 return this.conjugate();
5873
5874         }
5875
5876         conjugate() {
5877
5878                 this._x *= - 1;
5879                 this._y *= - 1;
5880                 this._z *= - 1;
5881
5882                 this._onChangeCallback();
5883
5884                 return this;
5885
5886         }
5887
5888         dot( v ) {
5889
5890                 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
5891
5892         }
5893
5894         lengthSq() {
5895
5896                 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
5897
5898         }
5899
5900         length() {
5901
5902                 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
5903
5904         }
5905
5906         normalize() {
5907
5908                 let l = this.length();
5909
5910                 if ( l === 0 ) {
5911
5912                         this._x = 0;
5913                         this._y = 0;
5914                         this._z = 0;
5915                         this._w = 1;
5916
5917                 } else {
5918
5919                         l = 1 / l;
5920
5921                         this._x = this._x * l;
5922                         this._y = this._y * l;
5923                         this._z = this._z * l;
5924                         this._w = this._w * l;
5925
5926                 }
5927
5928                 this._onChangeCallback();
5929
5930                 return this;
5931
5932         }
5933
5934         multiply( q, p ) {
5935
5936                 if ( p !== undefined ) {
5937
5938                         console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
5939                         return this.multiplyQuaternions( q, p );
5940
5941                 }
5942
5943                 return this.multiplyQuaternions( this, q );
5944
5945         }
5946
5947         premultiply( q ) {
5948
5949                 return this.multiplyQuaternions( q, this );
5950
5951         }
5952
5953         multiplyQuaternions( a, b ) {
5954
5955                 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
5956
5957                 const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
5958                 const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
5959
5960                 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
5961                 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
5962                 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
5963                 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
5964
5965                 this._onChangeCallback();
5966
5967                 return this;
5968
5969         }
5970
5971         slerp( qb, t ) {
5972
5973                 if ( t === 0 ) return this;
5974                 if ( t === 1 ) return this.copy( qb );
5975
5976                 const x = this._x, y = this._y, z = this._z, w = this._w;
5977
5978                 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
5979
5980                 let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
5981
5982                 if ( cosHalfTheta < 0 ) {
5983
5984                         this._w = - qb._w;
5985                         this._x = - qb._x;
5986                         this._y = - qb._y;
5987                         this._z = - qb._z;
5988
5989                         cosHalfTheta = - cosHalfTheta;
5990
5991                 } else {
5992
5993                         this.copy( qb );
5994
5995                 }
5996
5997                 if ( cosHalfTheta >= 1.0 ) {
5998
5999                         this._w = w;
6000                         this._x = x;
6001                         this._y = y;
6002                         this._z = z;
6003
6004                         return this;
6005
6006                 }
6007
6008                 const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
6009
6010                 if ( sqrSinHalfTheta <= Number.EPSILON ) {
6011
6012                         const s = 1 - t;
6013                         this._w = s * w + t * this._w;
6014                         this._x = s * x + t * this._x;
6015                         this._y = s * y + t * this._y;
6016                         this._z = s * z + t * this._z;
6017
6018                         this.normalize();
6019                         this._onChangeCallback();
6020
6021                         return this;
6022
6023                 }
6024
6025                 const sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
6026                 const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
6027                 const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
6028                         ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
6029
6030                 this._w = ( w * ratioA + this._w * ratioB );
6031                 this._x = ( x * ratioA + this._x * ratioB );
6032                 this._y = ( y * ratioA + this._y * ratioB );
6033                 this._z = ( z * ratioA + this._z * ratioB );
6034
6035                 this._onChangeCallback();
6036
6037                 return this;
6038
6039         }
6040
6041         slerpQuaternions( qa, qb, t ) {
6042
6043                 this.copy( qa ).slerp( qb, t );
6044
6045         }
6046
6047         random() {
6048
6049                 // Derived from http://planning.cs.uiuc.edu/node198.html
6050                 // Note, this source uses w, x, y, z ordering,
6051                 // so we swap the order below.
6052
6053                 const u1 = Math.random();
6054                 const sqrt1u1 = Math.sqrt( 1 - u1 );
6055                 const sqrtu1 = Math.sqrt( u1 );
6056
6057                 const u2 = 2 * Math.PI * Math.random();
6058
6059                 const u3 = 2 * Math.PI * Math.random();
6060
6061                 return this.set(
6062                         sqrt1u1 * Math.cos( u2 ),
6063                         sqrtu1 * Math.sin( u3 ),
6064                         sqrtu1 * Math.cos( u3 ),
6065                         sqrt1u1 * Math.sin( u2 ),
6066                 );
6067
6068         }
6069
6070         equals( quaternion ) {
6071
6072                 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
6073
6074         }
6075
6076         fromArray( array, offset = 0 ) {
6077
6078                 this._x = array[ offset ];
6079                 this._y = array[ offset + 1 ];
6080                 this._z = array[ offset + 2 ];
6081                 this._w = array[ offset + 3 ];
6082
6083                 this._onChangeCallback();
6084
6085                 return this;
6086
6087         }
6088
6089         toArray( array = [], offset = 0 ) {
6090
6091                 array[ offset ] = this._x;
6092                 array[ offset + 1 ] = this._y;
6093                 array[ offset + 2 ] = this._z;
6094                 array[ offset + 3 ] = this._w;
6095
6096                 return array;
6097
6098         }
6099
6100         fromBufferAttribute( attribute, index ) {
6101
6102                 this._x = attribute.getX( index );
6103                 this._y = attribute.getY( index );
6104                 this._z = attribute.getZ( index );
6105                 this._w = attribute.getW( index );
6106
6107                 return this;
6108
6109         }
6110
6111         _onChange( callback ) {
6112
6113                 this._onChangeCallback = callback;
6114
6115                 return this;
6116
6117         }
6118
6119         _onChangeCallback() {}
6120
6121     }
6122
6123     Quaternion.prototype.isQuaternion = true;
6124
6125     class Vector3 {
6126
6127         constructor( x = 0, y = 0, z = 0 ) {
6128
6129                 this.x = x;
6130                 this.y = y;
6131                 this.z = z;
6132
6133         }
6134
6135         set( x, y, z ) {
6136
6137                 if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
6138
6139                 this.x = x;
6140                 this.y = y;
6141                 this.z = z;
6142
6143                 return this;
6144
6145         }
6146
6147         setScalar( scalar ) {
6148
6149                 this.x = scalar;
6150                 this.y = scalar;
6151                 this.z = scalar;
6152
6153                 return this;
6154
6155         }
6156
6157         setX( x ) {
6158
6159                 this.x = x;
6160
6161                 return this;
6162
6163         }
6164
6165         setY( y ) {
6166
6167                 this.y = y;
6168
6169                 return this;
6170
6171         }
6172
6173         setZ( z ) {
6174
6175                 this.z = z;
6176
6177                 return this;
6178
6179         }
6180
6181         setComponent( index, value ) {
6182
6183                 switch ( index ) {
6184
6185                         case 0: this.x = value; break;
6186                         case 1: this.y = value; break;
6187                         case 2: this.z = value; break;
6188                         default: throw new Error( 'index is out of range: ' + index );
6189
6190                 }
6191
6192                 return this;
6193
6194         }
6195
6196         getComponent( index ) {
6197
6198                 switch ( index ) {
6199
6200                         case 0: return this.x;
6201                         case 1: return this.y;
6202                         case 2: return this.z;
6203                         default: throw new Error( 'index is out of range: ' + index );
6204
6205                 }
6206
6207         }
6208
6209         clone() {
6210
6211                 return new this.constructor( this.x, this.y, this.z );
6212
6213         }
6214
6215         copy( v ) {
6216
6217                 this.x = v.x;
6218                 this.y = v.y;
6219                 this.z = v.z;
6220
6221                 return this;
6222
6223         }
6224
6225         add( v, w ) {
6226
6227                 if ( w !== undefined ) {
6228
6229                         console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
6230                         return this.addVectors( v, w );
6231
6232                 }
6233
6234                 this.x += v.x;
6235                 this.y += v.y;
6236                 this.z += v.z;
6237
6238                 return this;
6239
6240         }
6241
6242         addScalar( s ) {
6243
6244                 this.x += s;
6245                 this.y += s;
6246                 this.z += s;
6247
6248                 return this;
6249
6250         }
6251
6252         addVectors( a, b ) {
6253
6254                 this.x = a.x + b.x;
6255                 this.y = a.y + b.y;
6256                 this.z = a.z + b.z;
6257
6258                 return this;
6259
6260         }
6261
6262         addScaledVector( v, s ) {
6263
6264                 this.x += v.x * s;
6265                 this.y += v.y * s;
6266                 this.z += v.z * s;
6267
6268                 return this;
6269
6270         }
6271
6272         sub( v, w ) {
6273
6274                 if ( w !== undefined ) {
6275
6276                         console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
6277                         return this.subVectors( v, w );
6278
6279                 }
6280
6281                 this.x -= v.x;
6282                 this.y -= v.y;
6283                 this.z -= v.z;
6284
6285                 return this;
6286
6287         }
6288
6289         subScalar( s ) {
6290
6291                 this.x -= s;
6292                 this.y -= s;
6293                 this.z -= s;
6294
6295                 return this;
6296
6297         }
6298
6299         subVectors( a, b ) {
6300
6301                 this.x = a.x - b.x;
6302                 this.y = a.y - b.y;
6303                 this.z = a.z - b.z;
6304
6305                 return this;
6306
6307         }
6308
6309         multiply( v, w ) {
6310
6311                 if ( w !== undefined ) {
6312
6313                         console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
6314                         return this.multiplyVectors( v, w );
6315
6316                 }
6317
6318                 this.x *= v.x;
6319                 this.y *= v.y;
6320                 this.z *= v.z;
6321
6322                 return this;
6323
6324         }
6325
6326         multiplyScalar( scalar ) {
6327
6328                 this.x *= scalar;
6329                 this.y *= scalar;
6330                 this.z *= scalar;
6331
6332                 return this;
6333
6334         }
6335
6336         multiplyVectors( a, b ) {
6337
6338                 this.x = a.x * b.x;
6339                 this.y = a.y * b.y;
6340                 this.z = a.z * b.z;
6341
6342                 return this;
6343
6344         }
6345
6346         applyEuler( euler ) {
6347
6348                 if ( ! ( euler && euler.isEuler ) ) {
6349
6350                         console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
6351
6352                 }
6353
6354                 return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) );
6355
6356         }
6357
6358         applyAxisAngle( axis, angle ) {
6359
6360                 return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) );
6361
6362         }
6363
6364         applyMatrix3( m ) {
6365
6366                 const x = this.x, y = this.y, z = this.z;
6367                 const e = m.elements;
6368
6369                 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
6370                 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
6371                 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
6372
6373                 return this;
6374
6375         }
6376
6377         applyNormalMatrix( m ) {
6378
6379                 return this.applyMatrix3( m ).normalize();
6380
6381         }
6382
6383         applyMatrix4( m ) {
6384
6385                 const x = this.x, y = this.y, z = this.z;
6386                 const e = m.elements;
6387
6388                 const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
6389
6390                 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
6391                 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
6392                 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
6393
6394                 return this;
6395
6396         }
6397
6398         applyQuaternion( q ) {
6399
6400                 const x = this.x, y = this.y, z = this.z;
6401                 const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
6402
6403                 // calculate quat * vector
6404
6405                 const ix = qw * x + qy * z - qz * y;
6406                 const iy = qw * y + qz * x - qx * z;
6407                 const iz = qw * z + qx * y - qy * x;
6408                 const iw = - qx * x - qy * y - qz * z;
6409
6410                 // calculate result * inverse quat
6411
6412                 this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
6413                 this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
6414                 this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
6415
6416                 return this;
6417
6418         }
6419
6420         project( camera ) {
6421
6422                 return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
6423
6424         }
6425
6426         unproject( camera ) {
6427
6428                 return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
6429
6430         }
6431
6432         transformDirection( m ) {
6433
6434                 // input: THREE.Matrix4 affine matrix
6435                 // vector interpreted as a direction
6436
6437                 const x = this.x, y = this.y, z = this.z;
6438                 const e = m.elements;
6439
6440                 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
6441                 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
6442                 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
6443
6444                 return this.normalize();
6445
6446         }
6447
6448         divide( v ) {
6449
6450                 this.x /= v.x;
6451                 this.y /= v.y;
6452                 this.z /= v.z;
6453
6454                 return this;
6455
6456         }
6457
6458         divideScalar( scalar ) {
6459
6460                 return this.multiplyScalar( 1 / scalar );
6461
6462         }
6463
6464         min( v ) {
6465
6466                 this.x = Math.min( this.x, v.x );
6467                 this.y = Math.min( this.y, v.y );
6468                 this.z = Math.min( this.z, v.z );
6469
6470                 return this;
6471
6472         }
6473
6474         max( v ) {
6475
6476                 this.x = Math.max( this.x, v.x );
6477                 this.y = Math.max( this.y, v.y );
6478                 this.z = Math.max( this.z, v.z );
6479
6480                 return this;
6481
6482         }
6483
6484         clamp( min, max ) {
6485
6486                 // assumes min < max, componentwise
6487
6488                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
6489                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
6490                 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
6491
6492                 return this;
6493
6494         }
6495
6496         clampScalar( minVal, maxVal ) {
6497
6498                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
6499                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
6500                 this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
6501
6502                 return this;
6503
6504         }
6505
6506         clampLength( min, max ) {
6507
6508                 const length = this.length();
6509
6510                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
6511
6512         }
6513
6514         floor() {
6515
6516                 this.x = Math.floor( this.x );
6517                 this.y = Math.floor( this.y );
6518                 this.z = Math.floor( this.z );
6519
6520                 return this;
6521
6522         }
6523
6524         ceil() {
6525
6526                 this.x = Math.ceil( this.x );
6527                 this.y = Math.ceil( this.y );
6528                 this.z = Math.ceil( this.z );
6529
6530                 return this;
6531
6532         }
6533
6534         round() {
6535
6536                 this.x = Math.round( this.x );
6537                 this.y = Math.round( this.y );
6538                 this.z = Math.round( this.z );
6539
6540                 return this;
6541
6542         }
6543
6544         roundToZero() {
6545
6546                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
6547                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
6548                 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
6549
6550                 return this;
6551
6552         }
6553
6554         negate() {
6555
6556                 this.x = - this.x;
6557                 this.y = - this.y;
6558                 this.z = - this.z;
6559
6560                 return this;
6561
6562         }
6563
6564         dot( v ) {
6565
6566                 return this.x * v.x + this.y * v.y + this.z * v.z;
6567
6568         }
6569
6570         // TODO lengthSquared?
6571
6572         lengthSq() {
6573
6574                 return this.x * this.x + this.y * this.y + this.z * this.z;
6575
6576         }
6577
6578         length() {
6579
6580                 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
6581
6582         }
6583
6584         manhattanLength() {
6585
6586                 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
6587
6588         }
6589
6590         normalize() {
6591
6592                 return this.divideScalar( this.length() || 1 );
6593
6594         }
6595
6596         setLength( length ) {
6597
6598                 return this.normalize().multiplyScalar( length );
6599
6600         }
6601
6602         lerp( v, alpha ) {
6603
6604                 this.x += ( v.x - this.x ) * alpha;
6605                 this.y += ( v.y - this.y ) * alpha;
6606                 this.z += ( v.z - this.z ) * alpha;
6607
6608                 return this;
6609
6610         }
6611
6612         lerpVectors( v1, v2, alpha ) {
6613
6614                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
6615                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
6616                 this.z = v1.z + ( v2.z - v1.z ) * alpha;
6617
6618                 return this;
6619
6620         }
6621
6622         cross( v, w ) {
6623
6624                 if ( w !== undefined ) {
6625
6626                         console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
6627                         return this.crossVectors( v, w );
6628
6629                 }
6630
6631                 return this.crossVectors( this, v );
6632
6633         }
6634
6635         crossVectors( a, b ) {
6636
6637                 const ax = a.x, ay = a.y, az = a.z;
6638                 const bx = b.x, by = b.y, bz = b.z;
6639
6640                 this.x = ay * bz - az * by;
6641                 this.y = az * bx - ax * bz;
6642                 this.z = ax * by - ay * bx;
6643
6644                 return this;
6645
6646         }
6647
6648         projectOnVector( v ) {
6649
6650                 const denominator = v.lengthSq();
6651
6652                 if ( denominator === 0 ) return this.set( 0, 0, 0 );
6653
6654                 const scalar = v.dot( this ) / denominator;
6655
6656                 return this.copy( v ).multiplyScalar( scalar );
6657
6658         }
6659
6660         projectOnPlane( planeNormal ) {
6661
6662                 _vector$c.copy( this ).projectOnVector( planeNormal );
6663
6664                 return this.sub( _vector$c );
6665
6666         }
6667
6668         reflect( normal ) {
6669
6670                 // reflect incident vector off plane orthogonal to normal
6671                 // normal is assumed to have unit length
6672
6673                 return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
6674
6675         }
6676
6677         angleTo( v ) {
6678
6679                 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
6680
6681                 if ( denominator === 0 ) return Math.PI / 2;
6682
6683                 const theta = this.dot( v ) / denominator;
6684
6685                 // clamp, to handle numerical problems
6686
6687                 return Math.acos( clamp$1( theta, - 1, 1 ) );
6688
6689         }
6690
6691         distanceTo( v ) {
6692
6693                 return Math.sqrt( this.distanceToSquared( v ) );
6694
6695         }
6696
6697         distanceToSquared( v ) {
6698
6699                 const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
6700
6701                 return dx * dx + dy * dy + dz * dz;
6702
6703         }
6704
6705         manhattanDistanceTo( v ) {
6706
6707                 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
6708
6709         }
6710
6711         setFromSpherical( s ) {
6712
6713                 return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
6714
6715         }
6716
6717         setFromSphericalCoords( radius, phi, theta ) {
6718
6719                 const sinPhiRadius = Math.sin( phi ) * radius;
6720
6721                 this.x = sinPhiRadius * Math.sin( theta );
6722                 this.y = Math.cos( phi ) * radius;
6723                 this.z = sinPhiRadius * Math.cos( theta );
6724
6725                 return this;
6726
6727         }
6728
6729         setFromCylindrical( c ) {
6730
6731                 return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
6732
6733         }
6734
6735         setFromCylindricalCoords( radius, theta, y ) {
6736
6737                 this.x = radius * Math.sin( theta );
6738                 this.y = y;
6739                 this.z = radius * Math.cos( theta );
6740
6741                 return this;
6742
6743         }
6744
6745         setFromMatrixPosition( m ) {
6746
6747                 const e = m.elements;
6748
6749                 this.x = e[ 12 ];
6750                 this.y = e[ 13 ];
6751                 this.z = e[ 14 ];
6752
6753                 return this;
6754
6755         }
6756
6757         setFromMatrixScale( m ) {
6758
6759                 const sx = this.setFromMatrixColumn( m, 0 ).length();
6760                 const sy = this.setFromMatrixColumn( m, 1 ).length();
6761                 const sz = this.setFromMatrixColumn( m, 2 ).length();
6762
6763                 this.x = sx;
6764                 this.y = sy;
6765                 this.z = sz;
6766
6767                 return this;
6768
6769         }
6770
6771         setFromMatrixColumn( m, index ) {
6772
6773                 return this.fromArray( m.elements, index * 4 );
6774
6775         }
6776
6777         setFromMatrix3Column( m, index ) {
6778
6779                 return this.fromArray( m.elements, index * 3 );
6780
6781         }
6782
6783         equals( v ) {
6784
6785                 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
6786
6787         }
6788
6789         fromArray( array, offset = 0 ) {
6790
6791                 this.x = array[ offset ];
6792                 this.y = array[ offset + 1 ];
6793                 this.z = array[ offset + 2 ];
6794
6795                 return this;
6796
6797         }
6798
6799         toArray( array = [], offset = 0 ) {
6800
6801                 array[ offset ] = this.x;
6802                 array[ offset + 1 ] = this.y;
6803                 array[ offset + 2 ] = this.z;
6804
6805                 return array;
6806
6807         }
6808
6809         fromBufferAttribute( attribute, index, offset ) {
6810
6811                 if ( offset !== undefined ) {
6812
6813                         console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
6814
6815                 }
6816
6817                 this.x = attribute.getX( index );
6818                 this.y = attribute.getY( index );
6819                 this.z = attribute.getZ( index );
6820
6821                 return this;
6822
6823         }
6824
6825         random() {
6826
6827                 this.x = Math.random();
6828                 this.y = Math.random();
6829                 this.z = Math.random();
6830
6831                 return this;
6832
6833         }
6834
6835         randomDirection() {
6836
6837                 // Derived from https://mathworld.wolfram.com/SpherePointPicking.html
6838
6839                 const u = ( Math.random() - 0.5 ) * 2;
6840                 const t = Math.random() * Math.PI * 2;
6841                 const f = Math.sqrt( 1 - u ** 2 );
6842
6843                 this.x = f * Math.cos( t );
6844                 this.y = f * Math.sin( t );
6845                 this.z = u;
6846
6847                 return this;
6848
6849         }
6850
6851         *[ Symbol.iterator ]() {
6852
6853                 yield this.x;
6854                 yield this.y;
6855                 yield this.z;
6856
6857         }
6858
6859     }
6860
6861     Vector3.prototype.isVector3 = true;
6862
6863     const _vector$c = /*@__PURE__*/ new Vector3();
6864     const _quaternion$4 = /*@__PURE__*/ new Quaternion();
6865
6866     class Box3 {
6867
6868         constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) {
6869
6870                 this.min = min;
6871                 this.max = max;
6872
6873         }
6874
6875         set( min, max ) {
6876
6877                 this.min.copy( min );
6878                 this.max.copy( max );
6879
6880                 return this;
6881
6882         }
6883
6884         setFromArray( array ) {
6885
6886                 let minX = + Infinity;
6887                 let minY = + Infinity;
6888                 let minZ = + Infinity;
6889
6890                 let maxX = - Infinity;
6891                 let maxY = - Infinity;
6892                 let maxZ = - Infinity;
6893
6894                 for ( let i = 0, l = array.length; i < l; i += 3 ) {
6895
6896                         const x = array[ i ];
6897                         const y = array[ i + 1 ];
6898                         const z = array[ i + 2 ];
6899
6900                         if ( x < minX ) minX = x;
6901                         if ( y < minY ) minY = y;
6902                         if ( z < minZ ) minZ = z;
6903
6904                         if ( x > maxX ) maxX = x;
6905                         if ( y > maxY ) maxY = y;
6906                         if ( z > maxZ ) maxZ = z;
6907
6908                 }
6909
6910                 this.min.set( minX, minY, minZ );
6911                 this.max.set( maxX, maxY, maxZ );
6912
6913                 return this;
6914
6915         }
6916
6917         setFromBufferAttribute( attribute ) {
6918
6919                 let minX = + Infinity;
6920                 let minY = + Infinity;
6921                 let minZ = + Infinity;
6922
6923                 let maxX = - Infinity;
6924                 let maxY = - Infinity;
6925                 let maxZ = - Infinity;
6926
6927                 for ( let i = 0, l = attribute.count; i < l; i ++ ) {
6928
6929                         const x = attribute.getX( i );
6930                         const y = attribute.getY( i );
6931                         const z = attribute.getZ( i );
6932
6933                         if ( x < minX ) minX = x;
6934                         if ( y < minY ) minY = y;
6935                         if ( z < minZ ) minZ = z;
6936
6937                         if ( x > maxX ) maxX = x;
6938                         if ( y > maxY ) maxY = y;
6939                         if ( z > maxZ ) maxZ = z;
6940
6941                 }
6942
6943                 this.min.set( minX, minY, minZ );
6944                 this.max.set( maxX, maxY, maxZ );
6945
6946                 return this;
6947
6948         }
6949
6950         setFromPoints( points ) {
6951
6952                 this.makeEmpty();
6953
6954                 for ( let i = 0, il = points.length; i < il; i ++ ) {
6955
6956                         this.expandByPoint( points[ i ] );
6957
6958                 }
6959
6960                 return this;
6961
6962         }
6963
6964         setFromCenterAndSize( center, size ) {
6965
6966                 const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 );
6967
6968                 this.min.copy( center ).sub( halfSize );
6969                 this.max.copy( center ).add( halfSize );
6970
6971                 return this;
6972
6973         }
6974
6975         setFromObject( object ) {
6976
6977                 this.makeEmpty();
6978
6979                 return this.expandByObject( object );
6980
6981         }
6982
6983         clone() {
6984
6985                 return new this.constructor().copy( this );
6986
6987         }
6988
6989         copy( box ) {
6990
6991                 this.min.copy( box.min );
6992                 this.max.copy( box.max );
6993
6994                 return this;
6995
6996         }
6997
6998         makeEmpty() {
6999
7000                 this.min.x = this.min.y = this.min.z = + Infinity;
7001                 this.max.x = this.max.y = this.max.z = - Infinity;
7002
7003                 return this;
7004
7005         }
7006
7007         isEmpty() {
7008
7009                 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
7010
7011                 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
7012
7013         }
7014
7015         getCenter( target ) {
7016
7017                 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
7018
7019         }
7020
7021         getSize( target ) {
7022
7023                 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
7024
7025         }
7026
7027         expandByPoint( point ) {
7028
7029                 this.min.min( point );
7030                 this.max.max( point );
7031
7032                 return this;
7033
7034         }
7035
7036         expandByVector( vector ) {
7037
7038                 this.min.sub( vector );
7039                 this.max.add( vector );
7040
7041                 return this;
7042
7043         }
7044
7045         expandByScalar( scalar ) {
7046
7047                 this.min.addScalar( - scalar );
7048                 this.max.addScalar( scalar );
7049
7050                 return this;
7051
7052         }
7053
7054         expandByObject( object ) {
7055
7056                 // Computes the world-axis-aligned bounding box of an object (including its children),
7057                 // accounting for both the object's, and children's, world transforms
7058
7059                 object.updateWorldMatrix( false, false );
7060
7061                 const geometry = object.geometry;
7062
7063                 if ( geometry !== undefined ) {
7064
7065                         if ( geometry.boundingBox === null ) {
7066
7067                                 geometry.computeBoundingBox();
7068
7069                         }
7070
7071                         _box$3.copy( geometry.boundingBox );
7072                         _box$3.applyMatrix4( object.matrixWorld );
7073
7074                         this.union( _box$3 );
7075
7076                 }
7077
7078                 const children = object.children;
7079
7080                 for ( let i = 0, l = children.length; i < l; i ++ ) {
7081
7082                         this.expandByObject( children[ i ] );
7083
7084                 }
7085
7086                 return this;
7087
7088         }
7089
7090         containsPoint( point ) {
7091
7092                 return point.x < this.min.x || point.x > this.max.x ||
7093                         point.y < this.min.y || point.y > this.max.y ||
7094                         point.z < this.min.z || point.z > this.max.z ? false : true;
7095
7096         }
7097
7098         containsBox( box ) {
7099
7100                 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
7101                         this.min.y <= box.min.y && box.max.y <= this.max.y &&
7102                         this.min.z <= box.min.z && box.max.z <= this.max.z;
7103
7104         }
7105
7106         getParameter( point, target ) {
7107
7108                 // This can potentially have a divide by zero if the box
7109                 // has a size dimension of 0.
7110
7111                 return target.set(
7112                         ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
7113                         ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
7114                         ( point.z - this.min.z ) / ( this.max.z - this.min.z )
7115                 );
7116
7117         }
7118
7119         intersectsBox( box ) {
7120
7121                 // using 6 splitting planes to rule out intersections.
7122                 return box.max.x < this.min.x || box.min.x > this.max.x ||
7123                         box.max.y < this.min.y || box.min.y > this.max.y ||
7124                         box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
7125
7126         }
7127
7128         intersectsSphere( sphere ) {
7129
7130                 // Find the point on the AABB closest to the sphere center.
7131                 this.clampPoint( sphere.center, _vector$b );
7132
7133                 // If that point is inside the sphere, the AABB and sphere intersect.
7134                 return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
7135
7136         }
7137
7138         intersectsPlane( plane ) {
7139
7140                 // We compute the minimum and maximum dot product values. If those values
7141                 // are on the same side (back or front) of the plane, then there is no intersection.
7142
7143                 let min, max;
7144
7145                 if ( plane.normal.x > 0 ) {
7146
7147                         min = plane.normal.x * this.min.x;
7148                         max = plane.normal.x * this.max.x;
7149
7150                 } else {
7151
7152                         min = plane.normal.x * this.max.x;
7153                         max = plane.normal.x * this.min.x;
7154
7155                 }
7156
7157                 if ( plane.normal.y > 0 ) {
7158
7159                         min += plane.normal.y * this.min.y;
7160                         max += plane.normal.y * this.max.y;
7161
7162                 } else {
7163
7164                         min += plane.normal.y * this.max.y;
7165                         max += plane.normal.y * this.min.y;
7166
7167                 }
7168
7169                 if ( plane.normal.z > 0 ) {
7170
7171                         min += plane.normal.z * this.min.z;
7172                         max += plane.normal.z * this.max.z;
7173
7174                 } else {
7175
7176                         min += plane.normal.z * this.max.z;
7177                         max += plane.normal.z * this.min.z;
7178
7179                 }
7180
7181                 return ( min <= - plane.constant && max >= - plane.constant );
7182
7183         }
7184
7185         intersectsTriangle( triangle ) {
7186
7187                 if ( this.isEmpty() ) {
7188
7189                         return false;
7190
7191                 }
7192
7193                 // compute box center and extents
7194                 this.getCenter( _center );
7195                 _extents.subVectors( this.max, _center );
7196
7197                 // translate triangle to aabb origin
7198                 _v0$2.subVectors( triangle.a, _center );
7199                 _v1$7.subVectors( triangle.b, _center );
7200                 _v2$3.subVectors( triangle.c, _center );
7201
7202                 // compute edge vectors for triangle
7203                 _f0.subVectors( _v1$7, _v0$2 );
7204                 _f1.subVectors( _v2$3, _v1$7 );
7205                 _f2.subVectors( _v0$2, _v2$3 );
7206
7207                 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
7208                 // 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
7209                 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
7210                 let axes = [
7211                         0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
7212                         _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
7213                         - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
7214                 ];
7215                 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$3, _extents ) ) {
7216
7217                         return false;
7218
7219                 }
7220
7221                 // test 3 face normals from the aabb
7222                 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
7223                 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$3, _extents ) ) {
7224
7225                         return false;
7226
7227                 }
7228
7229                 // finally testing the face normal of the triangle
7230                 // use already existing triangle edge vectors here
7231                 _triangleNormal.crossVectors( _f0, _f1 );
7232                 axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
7233
7234                 return satForAxes( axes, _v0$2, _v1$7, _v2$3, _extents );
7235
7236         }
7237
7238         clampPoint( point, target ) {
7239
7240                 return target.copy( point ).clamp( this.min, this.max );
7241
7242         }
7243
7244         distanceToPoint( point ) {
7245
7246                 const clampedPoint = _vector$b.copy( point ).clamp( this.min, this.max );
7247
7248                 return clampedPoint.sub( point ).length();
7249
7250         }
7251
7252         getBoundingSphere( target ) {
7253
7254                 this.getCenter( target.center );
7255
7256                 target.radius = this.getSize( _vector$b ).length() * 0.5;
7257
7258                 return target;
7259
7260         }
7261
7262         intersect( box ) {
7263
7264                 this.min.max( box.min );
7265                 this.max.min( box.max );
7266
7267                 // 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.
7268                 if ( this.isEmpty() ) this.makeEmpty();
7269
7270                 return this;
7271
7272         }
7273
7274         union( box ) {
7275
7276                 this.min.min( box.min );
7277                 this.max.max( box.max );
7278
7279                 return this;
7280
7281         }
7282
7283         applyMatrix4( matrix ) {
7284
7285                 // transform of empty box is an empty box.
7286                 if ( this.isEmpty() ) return this;
7287
7288                 // NOTE: I am using a binary pattern to specify all 2^3 combinations below
7289                 _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
7290                 _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
7291                 _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
7292                 _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
7293                 _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
7294                 _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
7295                 _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
7296                 _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
7297
7298                 this.setFromPoints( _points );
7299
7300                 return this;
7301
7302         }
7303
7304         translate( offset ) {
7305
7306                 this.min.add( offset );
7307                 this.max.add( offset );
7308
7309                 return this;
7310
7311         }
7312
7313         equals( box ) {
7314
7315                 return box.min.equals( this.min ) && box.max.equals( this.max );
7316
7317         }
7318
7319     }
7320
7321     Box3.prototype.isBox3 = true;
7322
7323     const _points = [
7324         /*@__PURE__*/ new Vector3(),
7325         /*@__PURE__*/ new Vector3(),
7326         /*@__PURE__*/ new Vector3(),
7327         /*@__PURE__*/ new Vector3(),
7328         /*@__PURE__*/ new Vector3(),
7329         /*@__PURE__*/ new Vector3(),
7330         /*@__PURE__*/ new Vector3(),
7331         /*@__PURE__*/ new Vector3()
7332     ];
7333
7334     const _vector$b = /*@__PURE__*/ new Vector3();
7335
7336     const _box$3 = /*@__PURE__*/ new Box3();
7337
7338     // triangle centered vertices
7339
7340     const _v0$2 = /*@__PURE__*/ new Vector3();
7341     const _v1$7 = /*@__PURE__*/ new Vector3();
7342     const _v2$3 = /*@__PURE__*/ new Vector3();
7343
7344     // triangle edge vectors
7345
7346     const _f0 = /*@__PURE__*/ new Vector3();
7347     const _f1 = /*@__PURE__*/ new Vector3();
7348     const _f2 = /*@__PURE__*/ new Vector3();
7349
7350     const _center = /*@__PURE__*/ new Vector3();
7351     const _extents = /*@__PURE__*/ new Vector3();
7352     const _triangleNormal = /*@__PURE__*/ new Vector3();
7353     const _testAxis = /*@__PURE__*/ new Vector3();
7354
7355     function satForAxes( axes, v0, v1, v2, extents ) {
7356
7357         for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
7358
7359                 _testAxis.fromArray( axes, i );
7360                 // project the aabb onto the seperating axis
7361                 const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
7362                 // project all 3 vertices of the triangle onto the seperating axis
7363                 const p0 = v0.dot( _testAxis );
7364                 const p1 = v1.dot( _testAxis );
7365                 const p2 = v2.dot( _testAxis );
7366                 // actual test, basically see if either of the most extreme of the triangle points intersects r
7367                 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
7368
7369                         // points of the projected triangle are outside the projected half-length of the aabb
7370                         // the axis is seperating and we can exit
7371                         return false;
7372
7373                 }
7374
7375         }
7376
7377         return true;
7378
7379     }
7380
7381     const _box$2 = /*@__PURE__*/ new Box3();
7382     const _v1$6 = /*@__PURE__*/ new Vector3();
7383     const _toFarthestPoint = /*@__PURE__*/ new Vector3();
7384     const _toPoint = /*@__PURE__*/ new Vector3();
7385
7386     class Sphere {
7387
7388         constructor( center = new Vector3(), radius = - 1 ) {
7389
7390                 this.center = center;
7391                 this.radius = radius;
7392
7393         }
7394
7395         set( center, radius ) {
7396
7397                 this.center.copy( center );
7398                 this.radius = radius;
7399
7400                 return this;
7401
7402         }
7403
7404         setFromPoints( points, optionalCenter ) {
7405
7406                 const center = this.center;
7407
7408                 if ( optionalCenter !== undefined ) {
7409
7410                         center.copy( optionalCenter );
7411
7412                 } else {
7413
7414                         _box$2.setFromPoints( points ).getCenter( center );
7415
7416                 }
7417
7418                 let maxRadiusSq = 0;
7419
7420                 for ( let i = 0, il = points.length; i < il; i ++ ) {
7421
7422                         maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
7423
7424                 }
7425
7426                 this.radius = Math.sqrt( maxRadiusSq );
7427
7428                 return this;
7429
7430         }
7431
7432         copy( sphere ) {
7433
7434                 this.center.copy( sphere.center );
7435                 this.radius = sphere.radius;
7436
7437                 return this;
7438
7439         }
7440
7441         isEmpty() {
7442
7443                 return ( this.radius < 0 );
7444
7445         }
7446
7447         makeEmpty() {
7448
7449                 this.center.set( 0, 0, 0 );
7450                 this.radius = - 1;
7451
7452                 return this;
7453
7454         }
7455
7456         containsPoint( point ) {
7457
7458                 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
7459
7460         }
7461
7462         distanceToPoint( point ) {
7463
7464                 return ( point.distanceTo( this.center ) - this.radius );
7465
7466         }
7467
7468         intersectsSphere( sphere ) {
7469
7470                 const radiusSum = this.radius + sphere.radius;
7471
7472                 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
7473
7474         }
7475
7476         intersectsBox( box ) {
7477
7478                 return box.intersectsSphere( this );
7479
7480         }
7481
7482         intersectsPlane( plane ) {
7483
7484                 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
7485
7486         }
7487
7488         clampPoint( point, target ) {
7489
7490                 const deltaLengthSq = this.center.distanceToSquared( point );
7491
7492                 target.copy( point );
7493
7494                 if ( deltaLengthSq > ( this.radius * this.radius ) ) {
7495
7496                         target.sub( this.center ).normalize();
7497                         target.multiplyScalar( this.radius ).add( this.center );
7498
7499                 }
7500
7501                 return target;
7502
7503         }
7504
7505         getBoundingBox( target ) {
7506
7507                 if ( this.isEmpty() ) {
7508
7509                         // Empty sphere produces empty bounding box
7510                         target.makeEmpty();
7511                         return target;
7512
7513                 }
7514
7515                 target.set( this.center, this.center );
7516                 target.expandByScalar( this.radius );
7517
7518                 return target;
7519
7520         }
7521
7522         applyMatrix4( matrix ) {
7523
7524                 this.center.applyMatrix4( matrix );
7525                 this.radius = this.radius * matrix.getMaxScaleOnAxis();
7526
7527                 return this;
7528
7529         }
7530
7531         translate( offset ) {
7532
7533                 this.center.add( offset );
7534
7535                 return this;
7536
7537         }
7538
7539         expandByPoint( point ) {
7540
7541                 // from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L649-L671
7542
7543                 _toPoint.subVectors( point, this.center );
7544
7545                 const lengthSq = _toPoint.lengthSq();
7546
7547                 if ( lengthSq > ( this.radius * this.radius ) ) {
7548
7549                         const length = Math.sqrt( lengthSq );
7550                         const missingRadiusHalf = ( length - this.radius ) * 0.5;
7551
7552                         // Nudge this sphere towards the target point. Add half the missing distance to radius,
7553                         // and the other half to position. This gives a tighter enclosure, instead of if
7554                         // the whole missing distance were just added to radius.
7555
7556                         this.center.add( _toPoint.multiplyScalar( missingRadiusHalf / length ) );
7557                         this.radius += missingRadiusHalf;
7558
7559                 }
7560
7561                 return this;
7562
7563         }
7564
7565         union( sphere ) {
7566
7567                 // from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L759-L769
7568
7569                 // To enclose another sphere into this sphere, we only need to enclose two points:
7570                 // 1) Enclose the farthest point on the other sphere into this sphere.
7571                 // 2) Enclose the opposite point of the farthest point into this sphere.
7572
7573                 _toFarthestPoint.subVectors( sphere.center, this.center ).normalize().multiplyScalar( sphere.radius );
7574
7575                 this.expandByPoint( _v1$6.copy( sphere.center ).add( _toFarthestPoint ) );
7576                 this.expandByPoint( _v1$6.copy( sphere.center ).sub( _toFarthestPoint ) );
7577
7578                 return this;
7579
7580         }
7581
7582         equals( sphere ) {
7583
7584                 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
7585
7586         }
7587
7588         clone() {
7589
7590                 return new this.constructor().copy( this );
7591
7592         }
7593
7594     }
7595
7596     const _vector$a = /*@__PURE__*/ new Vector3();
7597     const _segCenter = /*@__PURE__*/ new Vector3();
7598     const _segDir = /*@__PURE__*/ new Vector3();
7599     const _diff = /*@__PURE__*/ new Vector3();
7600
7601     const _edge1 = /*@__PURE__*/ new Vector3();
7602     const _edge2 = /*@__PURE__*/ new Vector3();
7603     const _normal$1 = /*@__PURE__*/ new Vector3();
7604
7605     class Ray {
7606
7607         constructor( origin = new Vector3(), direction = new Vector3( 0, 0, - 1 ) ) {
7608
7609                 this.origin = origin;
7610                 this.direction = direction;
7611
7612         }
7613
7614         set( origin, direction ) {
7615
7616                 this.origin.copy( origin );
7617                 this.direction.copy( direction );
7618
7619                 return this;
7620
7621         }
7622
7623         copy( ray ) {
7624
7625                 this.origin.copy( ray.origin );
7626                 this.direction.copy( ray.direction );
7627
7628                 return this;
7629
7630         }
7631
7632         at( t, target ) {
7633
7634                 return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
7635
7636         }
7637
7638         lookAt( v ) {
7639
7640                 this.direction.copy( v ).sub( this.origin ).normalize();
7641
7642                 return this;
7643
7644         }
7645
7646         recast( t ) {
7647
7648                 this.origin.copy( this.at( t, _vector$a ) );
7649
7650                 return this;
7651
7652         }
7653
7654         closestPointToPoint( point, target ) {
7655
7656                 target.subVectors( point, this.origin );
7657
7658                 const directionDistance = target.dot( this.direction );
7659
7660                 if ( directionDistance < 0 ) {
7661
7662                         return target.copy( this.origin );
7663
7664                 }
7665
7666                 return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
7667
7668         }
7669
7670         distanceToPoint( point ) {
7671
7672                 return Math.sqrt( this.distanceSqToPoint( point ) );
7673
7674         }
7675
7676         distanceSqToPoint( point ) {
7677
7678                 const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction );
7679
7680                 // point behind the ray
7681
7682                 if ( directionDistance < 0 ) {
7683
7684                         return this.origin.distanceToSquared( point );
7685
7686                 }
7687
7688                 _vector$a.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
7689
7690                 return _vector$a.distanceToSquared( point );
7691
7692         }
7693
7694         distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
7695
7696                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
7697                 // It returns the min distance between the ray and the segment
7698                 // defined by v0 and v1
7699                 // It can also set two optional targets :
7700                 // - The closest point on the ray
7701                 // - The closest point on the segment
7702
7703                 _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
7704                 _segDir.copy( v1 ).sub( v0 ).normalize();
7705                 _diff.copy( this.origin ).sub( _segCenter );
7706
7707                 const segExtent = v0.distanceTo( v1 ) * 0.5;
7708                 const a01 = - this.direction.dot( _segDir );
7709                 const b0 = _diff.dot( this.direction );
7710                 const b1 = - _diff.dot( _segDir );
7711                 const c = _diff.lengthSq();
7712                 const det = Math.abs( 1 - a01 * a01 );
7713                 let s0, s1, sqrDist, extDet;
7714
7715                 if ( det > 0 ) {
7716
7717                         // The ray and segment are not parallel.
7718
7719                         s0 = a01 * b1 - b0;
7720                         s1 = a01 * b0 - b1;
7721                         extDet = segExtent * det;
7722
7723                         if ( s0 >= 0 ) {
7724
7725                                 if ( s1 >= - extDet ) {
7726
7727                                         if ( s1 <= extDet ) {
7728
7729                                                 // region 0
7730                                                 // Minimum at interior points of ray and segment.
7731
7732                                                 const invDet = 1 / det;
7733                                                 s0 *= invDet;
7734                                                 s1 *= invDet;
7735                                                 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
7736
7737                                         } else {
7738
7739                                                 // region 1
7740
7741                                                 s1 = segExtent;
7742                                                 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
7743                                                 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7744
7745                                         }
7746
7747                                 } else {
7748
7749                                         // region 5
7750
7751                                         s1 = - segExtent;
7752                                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
7753                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7754
7755                                 }
7756
7757                         } else {
7758
7759                                 if ( s1 <= - extDet ) {
7760
7761                                         // region 4
7762
7763                                         s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
7764                                         s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
7765                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7766
7767                                 } else if ( s1 <= extDet ) {
7768
7769                                         // region 3
7770
7771                                         s0 = 0;
7772                                         s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
7773                                         sqrDist = s1 * ( s1 + 2 * b1 ) + c;
7774
7775                                 } else {
7776
7777                                         // region 2
7778
7779                                         s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
7780                                         s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
7781                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7782
7783                                 }
7784
7785                         }
7786
7787                 } else {
7788
7789                         // Ray and segment are parallel.
7790
7791                         s1 = ( a01 > 0 ) ? - segExtent : segExtent;
7792                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
7793                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7794
7795                 }
7796
7797                 if ( optionalPointOnRay ) {
7798
7799                         optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
7800
7801                 }
7802
7803                 if ( optionalPointOnSegment ) {
7804
7805                         optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );
7806
7807                 }
7808
7809                 return sqrDist;
7810
7811         }
7812
7813         intersectSphere( sphere, target ) {
7814
7815                 _vector$a.subVectors( sphere.center, this.origin );
7816                 const tca = _vector$a.dot( this.direction );
7817                 const d2 = _vector$a.dot( _vector$a ) - tca * tca;
7818                 const radius2 = sphere.radius * sphere.radius;
7819
7820                 if ( d2 > radius2 ) return null;
7821
7822                 const thc = Math.sqrt( radius2 - d2 );
7823
7824                 // t0 = first intersect point - entrance on front of sphere
7825                 const t0 = tca - thc;
7826
7827                 // t1 = second intersect point - exit point on back of sphere
7828                 const t1 = tca + thc;
7829
7830                 // test to see if both t0 and t1 are behind the ray - if so, return null
7831                 if ( t0 < 0 && t1 < 0 ) return null;
7832
7833                 // test to see if t0 is behind the ray:
7834                 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
7835                 // in order to always return an intersect point that is in front of the ray.
7836                 if ( t0 < 0 ) return this.at( t1, target );
7837
7838                 // else t0 is in front of the ray, so return the first collision point scaled by t0
7839                 return this.at( t0, target );
7840
7841         }
7842
7843         intersectsSphere( sphere ) {
7844
7845                 return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
7846
7847         }
7848
7849         distanceToPlane( plane ) {
7850
7851                 const denominator = plane.normal.dot( this.direction );
7852
7853                 if ( denominator === 0 ) {
7854
7855                         // line is coplanar, return origin
7856                         if ( plane.distanceToPoint( this.origin ) === 0 ) {
7857
7858                                 return 0;
7859
7860                         }
7861
7862                         // Null is preferable to undefined since undefined means.... it is undefined
7863
7864                         return null;
7865
7866                 }
7867
7868                 const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
7869
7870                 // Return if the ray never intersects the plane
7871
7872                 return t >= 0 ? t : null;
7873
7874         }
7875
7876         intersectPlane( plane, target ) {
7877
7878                 const t = this.distanceToPlane( plane );
7879
7880                 if ( t === null ) {
7881
7882                         return null;
7883
7884                 }
7885
7886                 return this.at( t, target );
7887
7888         }
7889
7890         intersectsPlane( plane ) {
7891
7892                 // check if the ray lies on the plane first
7893
7894                 const distToPoint = plane.distanceToPoint( this.origin );
7895
7896                 if ( distToPoint === 0 ) {
7897
7898                         return true;
7899
7900                 }
7901
7902                 const denominator = plane.normal.dot( this.direction );
7903
7904                 if ( denominator * distToPoint < 0 ) {
7905
7906                         return true;
7907
7908                 }
7909
7910                 // ray origin is behind the plane (and is pointing behind it)
7911
7912                 return false;
7913
7914         }
7915
7916         intersectBox( box, target ) {
7917
7918                 let tmin, tmax, tymin, tymax, tzmin, tzmax;
7919
7920                 const invdirx = 1 / this.direction.x,
7921                         invdiry = 1 / this.direction.y,
7922                         invdirz = 1 / this.direction.z;
7923
7924                 const origin = this.origin;
7925
7926                 if ( invdirx >= 0 ) {
7927
7928                         tmin = ( box.min.x - origin.x ) * invdirx;
7929                         tmax = ( box.max.x - origin.x ) * invdirx;
7930
7931                 } else {
7932
7933                         tmin = ( box.max.x - origin.x ) * invdirx;
7934                         tmax = ( box.min.x - origin.x ) * invdirx;
7935
7936                 }
7937
7938                 if ( invdiry >= 0 ) {
7939
7940                         tymin = ( box.min.y - origin.y ) * invdiry;
7941                         tymax = ( box.max.y - origin.y ) * invdiry;
7942
7943                 } else {
7944
7945                         tymin = ( box.max.y - origin.y ) * invdiry;
7946                         tymax = ( box.min.y - origin.y ) * invdiry;
7947
7948                 }
7949
7950                 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
7951
7952                 // These lines also handle the case where tmin or tmax is NaN
7953                 // (result of 0 * Infinity). x !== x returns true if x is NaN
7954
7955                 if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
7956
7957                 if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
7958
7959                 if ( invdirz >= 0 ) {
7960
7961                         tzmin = ( box.min.z - origin.z ) * invdirz;
7962                         tzmax = ( box.max.z - origin.z ) * invdirz;
7963
7964                 } else {
7965
7966                         tzmin = ( box.max.z - origin.z ) * invdirz;
7967                         tzmax = ( box.min.z - origin.z ) * invdirz;
7968
7969                 }
7970
7971                 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
7972
7973                 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
7974
7975                 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
7976
7977                 //return point closest to the ray (positive side)
7978
7979                 if ( tmax < 0 ) return null;
7980
7981                 return this.at( tmin >= 0 ? tmin : tmax, target );
7982
7983         }
7984
7985         intersectsBox( box ) {
7986
7987                 return this.intersectBox( box, _vector$a ) !== null;
7988
7989         }
7990
7991         intersectTriangle( a, b, c, backfaceCulling, target ) {
7992
7993                 // Compute the offset origin, edges, and normal.
7994
7995                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
7996
7997                 _edge1.subVectors( b, a );
7998                 _edge2.subVectors( c, a );
7999                 _normal$1.crossVectors( _edge1, _edge2 );
8000
8001                 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
8002                 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
8003                 //   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
8004                 //   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
8005                 //   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
8006                 let DdN = this.direction.dot( _normal$1 );
8007                 let sign;
8008
8009                 if ( DdN > 0 ) {
8010
8011                         if ( backfaceCulling ) return null;
8012                         sign = 1;
8013
8014                 } else if ( DdN < 0 ) {
8015
8016                         sign = - 1;
8017                         DdN = - DdN;
8018
8019                 } else {
8020
8021                         return null;
8022
8023                 }
8024
8025                 _diff.subVectors( this.origin, a );
8026                 const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
8027
8028                 // b1 < 0, no intersection
8029                 if ( DdQxE2 < 0 ) {
8030
8031                         return null;
8032
8033                 }
8034
8035                 const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
8036
8037                 // b2 < 0, no intersection
8038                 if ( DdE1xQ < 0 ) {
8039
8040                         return null;
8041
8042                 }
8043
8044                 // b1+b2 > 1, no intersection
8045                 if ( DdQxE2 + DdE1xQ > DdN ) {
8046
8047                         return null;
8048
8049                 }
8050
8051                 // Line intersects triangle, check if ray does.
8052                 const QdN = - sign * _diff.dot( _normal$1 );
8053
8054                 // t < 0, no intersection
8055                 if ( QdN < 0 ) {
8056
8057                         return null;
8058
8059                 }
8060
8061                 // Ray intersects triangle.
8062                 return this.at( QdN / DdN, target );
8063
8064         }
8065
8066         applyMatrix4( matrix4 ) {
8067
8068                 this.origin.applyMatrix4( matrix4 );
8069                 this.direction.transformDirection( matrix4 );
8070
8071                 return this;
8072
8073         }
8074
8075         equals( ray ) {
8076
8077                 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
8078
8079         }
8080
8081         clone() {
8082
8083                 return new this.constructor().copy( this );
8084
8085         }
8086
8087     }
8088
8089     class Matrix4 {
8090
8091         constructor() {
8092
8093                 this.elements = [
8094
8095                         1, 0, 0, 0,
8096                         0, 1, 0, 0,
8097                         0, 0, 1, 0,
8098                         0, 0, 0, 1
8099
8100                 ];
8101
8102                 if ( arguments.length > 0 ) {
8103
8104                         console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
8105
8106                 }
8107
8108         }
8109
8110         set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
8111
8112                 const te = this.elements;
8113
8114                 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
8115                 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
8116                 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
8117                 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
8118
8119                 return this;
8120
8121         }
8122
8123         identity() {
8124
8125                 this.set(
8126
8127                         1, 0, 0, 0,
8128                         0, 1, 0, 0,
8129                         0, 0, 1, 0,
8130                         0, 0, 0, 1
8131
8132                 );
8133
8134                 return this;
8135
8136         }
8137
8138         clone() {
8139
8140                 return new Matrix4().fromArray( this.elements );
8141
8142         }
8143
8144         copy( m ) {
8145
8146                 const te = this.elements;
8147                 const me = m.elements;
8148
8149                 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
8150                 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
8151                 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
8152                 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
8153
8154                 return this;
8155
8156         }
8157
8158         copyPosition( m ) {
8159
8160                 const te = this.elements, me = m.elements;
8161
8162                 te[ 12 ] = me[ 12 ];
8163                 te[ 13 ] = me[ 13 ];
8164                 te[ 14 ] = me[ 14 ];
8165
8166                 return this;
8167
8168         }
8169
8170         setFromMatrix3( m ) {
8171
8172                 const me = m.elements;
8173
8174                 this.set(
8175
8176                         me[ 0 ], me[ 3 ], me[ 6 ], 0,
8177                         me[ 1 ], me[ 4 ], me[ 7 ], 0,
8178                         me[ 2 ], me[ 5 ], me[ 8 ], 0,
8179                         0, 0, 0, 1
8180
8181                 );
8182
8183                 return this;
8184
8185         }
8186
8187         extractBasis( xAxis, yAxis, zAxis ) {
8188
8189                 xAxis.setFromMatrixColumn( this, 0 );
8190                 yAxis.setFromMatrixColumn( this, 1 );
8191                 zAxis.setFromMatrixColumn( this, 2 );
8192
8193                 return this;
8194
8195         }
8196
8197         makeBasis( xAxis, yAxis, zAxis ) {
8198
8199                 this.set(
8200                         xAxis.x, yAxis.x, zAxis.x, 0,
8201                         xAxis.y, yAxis.y, zAxis.y, 0,
8202                         xAxis.z, yAxis.z, zAxis.z, 0,
8203                         0, 0, 0, 1
8204                 );
8205
8206                 return this;
8207
8208         }
8209
8210         extractRotation( m ) {
8211
8212                 // this method does not support reflection matrices
8213
8214                 const te = this.elements;
8215                 const me = m.elements;
8216
8217                 const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length();
8218                 const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length();
8219                 const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length();
8220
8221                 te[ 0 ] = me[ 0 ] * scaleX;
8222                 te[ 1 ] = me[ 1 ] * scaleX;
8223                 te[ 2 ] = me[ 2 ] * scaleX;
8224                 te[ 3 ] = 0;
8225
8226                 te[ 4 ] = me[ 4 ] * scaleY;
8227                 te[ 5 ] = me[ 5 ] * scaleY;
8228                 te[ 6 ] = me[ 6 ] * scaleY;
8229                 te[ 7 ] = 0;
8230
8231                 te[ 8 ] = me[ 8 ] * scaleZ;
8232                 te[ 9 ] = me[ 9 ] * scaleZ;
8233                 te[ 10 ] = me[ 10 ] * scaleZ;
8234                 te[ 11 ] = 0;
8235
8236                 te[ 12 ] = 0;
8237                 te[ 13 ] = 0;
8238                 te[ 14 ] = 0;
8239                 te[ 15 ] = 1;
8240
8241                 return this;
8242
8243         }
8244
8245         makeRotationFromEuler( euler ) {
8246
8247                 if ( ! ( euler && euler.isEuler ) ) {
8248
8249                         console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
8250
8251                 }
8252
8253                 const te = this.elements;
8254
8255                 const x = euler.x, y = euler.y, z = euler.z;
8256                 const a = Math.cos( x ), b = Math.sin( x );
8257                 const c = Math.cos( y ), d = Math.sin( y );
8258                 const e = Math.cos( z ), f = Math.sin( z );
8259
8260                 if ( euler.order === 'XYZ' ) {
8261
8262                         const ae = a * e, af = a * f, be = b * e, bf = b * f;
8263
8264                         te[ 0 ] = c * e;
8265                         te[ 4 ] = - c * f;
8266                         te[ 8 ] = d;
8267
8268                         te[ 1 ] = af + be * d;
8269                         te[ 5 ] = ae - bf * d;
8270                         te[ 9 ] = - b * c;
8271
8272                         te[ 2 ] = bf - ae * d;
8273                         te[ 6 ] = be + af * d;
8274                         te[ 10 ] = a * c;
8275
8276                 } else if ( euler.order === 'YXZ' ) {
8277
8278                         const ce = c * e, cf = c * f, de = d * e, df = d * f;
8279
8280                         te[ 0 ] = ce + df * b;
8281                         te[ 4 ] = de * b - cf;
8282                         te[ 8 ] = a * d;
8283
8284                         te[ 1 ] = a * f;
8285                         te[ 5 ] = a * e;
8286                         te[ 9 ] = - b;
8287
8288                         te[ 2 ] = cf * b - de;
8289                         te[ 6 ] = df + ce * b;
8290                         te[ 10 ] = a * c;
8291
8292                 } else if ( euler.order === 'ZXY' ) {
8293
8294                         const ce = c * e, cf = c * f, de = d * e, df = d * f;
8295
8296                         te[ 0 ] = ce - df * b;
8297                         te[ 4 ] = - a * f;
8298                         te[ 8 ] = de + cf * b;
8299
8300                         te[ 1 ] = cf + de * b;
8301                         te[ 5 ] = a * e;
8302                         te[ 9 ] = df - ce * b;
8303
8304                         te[ 2 ] = - a * d;
8305                         te[ 6 ] = b;
8306                         te[ 10 ] = a * c;
8307
8308                 } else if ( euler.order === 'ZYX' ) {
8309
8310                         const ae = a * e, af = a * f, be = b * e, bf = b * f;
8311
8312                         te[ 0 ] = c * e;
8313                         te[ 4 ] = be * d - af;
8314                         te[ 8 ] = ae * d + bf;
8315
8316                         te[ 1 ] = c * f;
8317                         te[ 5 ] = bf * d + ae;
8318                         te[ 9 ] = af * d - be;
8319
8320                         te[ 2 ] = - d;
8321                         te[ 6 ] = b * c;
8322                         te[ 10 ] = a * c;
8323
8324                 } else if ( euler.order === 'YZX' ) {
8325
8326                         const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
8327
8328                         te[ 0 ] = c * e;
8329                         te[ 4 ] = bd - ac * f;
8330                         te[ 8 ] = bc * f + ad;
8331
8332                         te[ 1 ] = f;
8333                         te[ 5 ] = a * e;
8334                         te[ 9 ] = - b * e;
8335
8336                         te[ 2 ] = - d * e;
8337                         te[ 6 ] = ad * f + bc;
8338                         te[ 10 ] = ac - bd * f;
8339
8340                 } else if ( euler.order === 'XZY' ) {
8341
8342                         const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
8343
8344                         te[ 0 ] = c * e;
8345                         te[ 4 ] = - f;
8346                         te[ 8 ] = d * e;
8347
8348                         te[ 1 ] = ac * f + bd;
8349                         te[ 5 ] = a * e;
8350                         te[ 9 ] = ad * f - bc;
8351
8352                         te[ 2 ] = bc * f - ad;
8353                         te[ 6 ] = b * e;
8354                         te[ 10 ] = bd * f + ac;
8355
8356                 }
8357
8358                 // bottom row
8359                 te[ 3 ] = 0;
8360                 te[ 7 ] = 0;
8361                 te[ 11 ] = 0;
8362
8363                 // last column
8364                 te[ 12 ] = 0;
8365                 te[ 13 ] = 0;
8366                 te[ 14 ] = 0;
8367                 te[ 15 ] = 1;
8368
8369                 return this;
8370
8371         }
8372
8373         makeRotationFromQuaternion( q ) {
8374
8375                 return this.compose( _zero, q, _one );
8376
8377         }
8378
8379         lookAt( eye, target, up ) {
8380
8381                 const te = this.elements;
8382
8383                 _z.subVectors( eye, target );
8384
8385                 if ( _z.lengthSq() === 0 ) {
8386
8387                         // eye and target are in the same position
8388
8389                         _z.z = 1;
8390
8391                 }
8392
8393                 _z.normalize();
8394                 _x.crossVectors( up, _z );
8395
8396                 if ( _x.lengthSq() === 0 ) {
8397
8398                         // up and z are parallel
8399
8400                         if ( Math.abs( up.z ) === 1 ) {
8401
8402                                 _z.x += 0.0001;
8403
8404                         } else {
8405
8406                                 _z.z += 0.0001;
8407
8408                         }
8409
8410                         _z.normalize();
8411                         _x.crossVectors( up, _z );
8412
8413                 }
8414
8415                 _x.normalize();
8416                 _y.crossVectors( _z, _x );
8417
8418                 te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
8419                 te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
8420                 te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
8421
8422                 return this;
8423
8424         }
8425
8426         multiply( m, n ) {
8427
8428                 if ( n !== undefined ) {
8429
8430                         console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
8431                         return this.multiplyMatrices( m, n );
8432
8433                 }
8434
8435                 return this.multiplyMatrices( this, m );
8436
8437         }
8438
8439         premultiply( m ) {
8440
8441                 return this.multiplyMatrices( m, this );
8442
8443         }
8444
8445         multiplyMatrices( a, b ) {
8446
8447                 const ae = a.elements;
8448                 const be = b.elements;
8449                 const te = this.elements;
8450
8451                 const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
8452                 const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
8453                 const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
8454                 const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
8455
8456                 const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
8457                 const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
8458                 const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
8459                 const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
8460
8461                 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
8462                 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
8463                 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
8464                 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
8465
8466                 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
8467                 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
8468                 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
8469                 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
8470
8471                 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
8472                 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
8473                 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
8474                 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
8475
8476                 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
8477                 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
8478                 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
8479                 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
8480
8481                 return this;
8482
8483         }
8484
8485         multiplyScalar( s ) {
8486
8487                 const te = this.elements;
8488
8489                 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
8490                 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
8491                 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
8492                 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
8493
8494                 return this;
8495
8496         }
8497
8498         determinant() {
8499
8500                 const te = this.elements;
8501
8502                 const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
8503                 const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
8504                 const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
8505                 const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
8506
8507                 //TODO: make this more efficient
8508                 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
8509
8510                 return (
8511                         n41 * (
8512                                 + n14 * n23 * n32
8513                                  - n13 * n24 * n32
8514                                  - n14 * n22 * n33
8515                                  + n12 * n24 * n33
8516                                  + n13 * n22 * n34
8517                                  - n12 * n23 * n34
8518                         ) +
8519                         n42 * (
8520                                 + n11 * n23 * n34
8521                                  - n11 * n24 * n33
8522                                  + n14 * n21 * n33
8523                                  - n13 * n21 * n34
8524                                  + n13 * n24 * n31
8525                                  - n14 * n23 * n31
8526                         ) +
8527                         n43 * (
8528                                 + n11 * n24 * n32
8529                                  - n11 * n22 * n34
8530                                  - n14 * n21 * n32
8531                                  + n12 * n21 * n34
8532                                  + n14 * n22 * n31
8533                                  - n12 * n24 * n31
8534                         ) +
8535                         n44 * (
8536                                 - n13 * n22 * n31
8537                                  - n11 * n23 * n32
8538                                  + n11 * n22 * n33
8539                                  + n13 * n21 * n32
8540                                  - n12 * n21 * n33
8541                                  + n12 * n23 * n31
8542                         )
8543
8544                 );
8545
8546         }
8547
8548         transpose() {
8549
8550                 const te = this.elements;
8551                 let tmp;
8552
8553                 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
8554                 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
8555                 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
8556
8557                 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
8558                 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
8559                 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
8560
8561                 return this;
8562
8563         }
8564
8565         setPosition( x, y, z ) {
8566
8567                 const te = this.elements;
8568
8569                 if ( x.isVector3 ) {
8570
8571                         te[ 12 ] = x.x;
8572                         te[ 13 ] = x.y;
8573                         te[ 14 ] = x.z;
8574
8575                 } else {
8576
8577                         te[ 12 ] = x;
8578                         te[ 13 ] = y;
8579                         te[ 14 ] = z;
8580
8581                 }
8582
8583                 return this;
8584
8585         }
8586
8587         invert() {
8588
8589                 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
8590                 const te = this.elements,
8591
8592                         n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
8593                         n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
8594                         n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
8595                         n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
8596
8597                         t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
8598                         t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
8599                         t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
8600                         t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
8601
8602                 const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
8603
8604                 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
8605
8606                 const detInv = 1 / det;
8607
8608                 te[ 0 ] = t11 * detInv;
8609                 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
8610                 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
8611                 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
8612
8613                 te[ 4 ] = t12 * detInv;
8614                 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
8615                 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
8616                 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
8617
8618                 te[ 8 ] = t13 * detInv;
8619                 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
8620                 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
8621                 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
8622
8623                 te[ 12 ] = t14 * detInv;
8624                 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
8625                 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
8626                 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
8627
8628                 return this;
8629
8630         }
8631
8632         scale( v ) {
8633
8634                 const te = this.elements;
8635                 const x = v.x, y = v.y, z = v.z;
8636
8637                 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
8638                 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
8639                 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
8640                 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
8641
8642                 return this;
8643
8644         }
8645
8646         getMaxScaleOnAxis() {
8647
8648                 const te = this.elements;
8649
8650                 const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
8651                 const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
8652                 const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
8653
8654                 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
8655
8656         }
8657
8658         makeTranslation( x, y, z ) {
8659
8660                 this.set(
8661
8662                         1, 0, 0, x,
8663                         0, 1, 0, y,
8664                         0, 0, 1, z,
8665                         0, 0, 0, 1
8666
8667                 );
8668
8669                 return this;
8670
8671         }
8672
8673         makeRotationX( theta ) {
8674
8675                 const c = Math.cos( theta ), s = Math.sin( theta );
8676
8677                 this.set(
8678
8679                         1, 0, 0, 0,
8680                         0, c, - s, 0,
8681                         0, s, c, 0,
8682                         0, 0, 0, 1
8683
8684                 );
8685
8686                 return this;
8687
8688         }
8689
8690         makeRotationY( theta ) {
8691
8692                 const c = Math.cos( theta ), s = Math.sin( theta );
8693
8694                 this.set(
8695
8696                          c, 0, s, 0,
8697                          0, 1, 0, 0,
8698                         - s, 0, c, 0,
8699                          0, 0, 0, 1
8700
8701                 );
8702
8703                 return this;
8704
8705         }
8706
8707         makeRotationZ( theta ) {
8708
8709                 const c = Math.cos( theta ), s = Math.sin( theta );
8710
8711                 this.set(
8712
8713                         c, - s, 0, 0,
8714                         s, c, 0, 0,
8715                         0, 0, 1, 0,
8716                         0, 0, 0, 1
8717
8718                 );
8719
8720                 return this;
8721
8722         }
8723
8724         makeRotationAxis( axis, angle ) {
8725
8726                 // Based on http://www.gamedev.net/reference/articles/article1199.asp
8727
8728                 const c = Math.cos( angle );
8729                 const s = Math.sin( angle );
8730                 const t = 1 - c;
8731                 const x = axis.x, y = axis.y, z = axis.z;
8732                 const tx = t * x, ty = t * y;
8733
8734                 this.set(
8735
8736                         tx * x + c, tx * y - s * z, tx * z + s * y, 0,
8737                         tx * y + s * z, ty * y + c, ty * z - s * x, 0,
8738                         tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
8739                         0, 0, 0, 1
8740
8741                 );
8742
8743                 return this;
8744
8745         }
8746
8747         makeScale( x, y, z ) {
8748
8749                 this.set(
8750
8751                         x, 0, 0, 0,
8752                         0, y, 0, 0,
8753                         0, 0, z, 0,
8754                         0, 0, 0, 1
8755
8756                 );
8757
8758                 return this;
8759
8760         }
8761
8762         makeShear( xy, xz, yx, yz, zx, zy ) {
8763
8764                 this.set(
8765
8766                         1, yx, zx, 0,
8767                         xy, 1, zy, 0,
8768                         xz, yz, 1, 0,
8769                         0, 0, 0, 1
8770
8771                 );
8772
8773                 return this;
8774
8775         }
8776
8777         compose( position, quaternion, scale ) {
8778
8779                 const te = this.elements;
8780
8781                 const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
8782                 const x2 = x + x,       y2 = y + y, z2 = z + z;
8783                 const xx = x * x2, xy = x * y2, xz = x * z2;
8784                 const yy = y * y2, yz = y * z2, zz = z * z2;
8785                 const wx = w * x2, wy = w * y2, wz = w * z2;
8786
8787                 const sx = scale.x, sy = scale.y, sz = scale.z;
8788
8789                 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
8790                 te[ 1 ] = ( xy + wz ) * sx;
8791                 te[ 2 ] = ( xz - wy ) * sx;
8792                 te[ 3 ] = 0;
8793
8794                 te[ 4 ] = ( xy - wz ) * sy;
8795                 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
8796                 te[ 6 ] = ( yz + wx ) * sy;
8797                 te[ 7 ] = 0;
8798
8799                 te[ 8 ] = ( xz + wy ) * sz;
8800                 te[ 9 ] = ( yz - wx ) * sz;
8801                 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
8802                 te[ 11 ] = 0;
8803
8804                 te[ 12 ] = position.x;
8805                 te[ 13 ] = position.y;
8806                 te[ 14 ] = position.z;
8807                 te[ 15 ] = 1;
8808
8809                 return this;
8810
8811         }
8812
8813         decompose( position, quaternion, scale ) {
8814
8815                 const te = this.elements;
8816
8817                 let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
8818                 const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
8819                 const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
8820
8821                 // if determine is negative, we need to invert one scale
8822                 const det = this.determinant();
8823                 if ( det < 0 ) sx = - sx;
8824
8825                 position.x = te[ 12 ];
8826                 position.y = te[ 13 ];
8827                 position.z = te[ 14 ];
8828
8829                 // scale the rotation part
8830                 _m1$2.copy( this );
8831
8832                 const invSX = 1 / sx;
8833                 const invSY = 1 / sy;
8834                 const invSZ = 1 / sz;
8835
8836                 _m1$2.elements[ 0 ] *= invSX;
8837                 _m1$2.elements[ 1 ] *= invSX;
8838                 _m1$2.elements[ 2 ] *= invSX;
8839
8840                 _m1$2.elements[ 4 ] *= invSY;
8841                 _m1$2.elements[ 5 ] *= invSY;
8842                 _m1$2.elements[ 6 ] *= invSY;
8843
8844                 _m1$2.elements[ 8 ] *= invSZ;
8845                 _m1$2.elements[ 9 ] *= invSZ;
8846                 _m1$2.elements[ 10 ] *= invSZ;
8847
8848                 quaternion.setFromRotationMatrix( _m1$2 );
8849
8850                 scale.x = sx;
8851                 scale.y = sy;
8852                 scale.z = sz;
8853
8854                 return this;
8855
8856         }
8857
8858         makePerspective( left, right, top, bottom, near, far ) {
8859
8860                 if ( far === undefined ) {
8861
8862                         console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
8863
8864                 }
8865
8866                 const te = this.elements;
8867                 const x = 2 * near / ( right - left );
8868                 const y = 2 * near / ( top - bottom );
8869
8870                 const a = ( right + left ) / ( right - left );
8871                 const b = ( top + bottom ) / ( top - bottom );
8872                 const c = - ( far + near ) / ( far - near );
8873                 const d = - 2 * far * near / ( far - near );
8874
8875                 te[ 0 ] = x;    te[ 4 ] = 0;    te[ 8 ] = a;    te[ 12 ] = 0;
8876                 te[ 1 ] = 0;    te[ 5 ] = y;    te[ 9 ] = b;    te[ 13 ] = 0;
8877                 te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = c;   te[ 14 ] = d;
8878                 te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = - 1; te[ 15 ] = 0;
8879
8880                 return this;
8881
8882         }
8883
8884         makeOrthographic( left, right, top, bottom, near, far ) {
8885
8886                 const te = this.elements;
8887                 const w = 1.0 / ( right - left );
8888                 const h = 1.0 / ( top - bottom );
8889                 const p = 1.0 / ( far - near );
8890
8891                 const x = ( right + left ) * w;
8892                 const y = ( top + bottom ) * h;
8893                 const z = ( far + near ) * p;
8894
8895                 te[ 0 ] = 2 * w;        te[ 4 ] = 0;    te[ 8 ] = 0;    te[ 12 ] = - x;
8896                 te[ 1 ] = 0;    te[ 5 ] = 2 * h;        te[ 9 ] = 0;    te[ 13 ] = - y;
8897                 te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = - 2 * p;     te[ 14 ] = - z;
8898                 te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = 0;   te[ 15 ] = 1;
8899
8900                 return this;
8901
8902         }
8903
8904         equals( matrix ) {
8905
8906                 const te = this.elements;
8907                 const me = matrix.elements;
8908
8909                 for ( let i = 0; i < 16; i ++ ) {
8910
8911                         if ( te[ i ] !== me[ i ] ) return false;
8912
8913                 }
8914
8915                 return true;
8916
8917         }
8918
8919         fromArray( array, offset = 0 ) {
8920
8921                 for ( let i = 0; i < 16; i ++ ) {
8922
8923                         this.elements[ i ] = array[ i + offset ];
8924
8925                 }
8926
8927                 return this;
8928
8929         }
8930
8931         toArray( array = [], offset = 0 ) {
8932
8933                 const te = this.elements;
8934
8935                 array[ offset ] = te[ 0 ];
8936                 array[ offset + 1 ] = te[ 1 ];
8937                 array[ offset + 2 ] = te[ 2 ];
8938                 array[ offset + 3 ] = te[ 3 ];
8939
8940                 array[ offset + 4 ] = te[ 4 ];
8941                 array[ offset + 5 ] = te[ 5 ];
8942                 array[ offset + 6 ] = te[ 6 ];
8943                 array[ offset + 7 ] = te[ 7 ];
8944
8945                 array[ offset + 8 ] = te[ 8 ];
8946                 array[ offset + 9 ] = te[ 9 ];
8947                 array[ offset + 10 ] = te[ 10 ];
8948                 array[ offset + 11 ] = te[ 11 ];
8949
8950                 array[ offset + 12 ] = te[ 12 ];
8951                 array[ offset + 13 ] = te[ 13 ];
8952                 array[ offset + 14 ] = te[ 14 ];
8953                 array[ offset + 15 ] = te[ 15 ];
8954
8955                 return array;
8956
8957         }
8958
8959     }
8960
8961     Matrix4.prototype.isMatrix4 = true;
8962
8963     const _v1$5 = /*@__PURE__*/ new Vector3();
8964     const _m1$2 = /*@__PURE__*/ new Matrix4();
8965     const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
8966     const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
8967     const _x = /*@__PURE__*/ new Vector3();
8968     const _y = /*@__PURE__*/ new Vector3();
8969     const _z = /*@__PURE__*/ new Vector3();
8970
8971     const _matrix$1 = /*@__PURE__*/ new Matrix4();
8972     const _quaternion$3 = /*@__PURE__*/ new Quaternion();
8973
8974     class Euler {
8975
8976         constructor( x = 0, y = 0, z = 0, order = Euler.DefaultOrder ) {
8977
8978                 this._x = x;
8979                 this._y = y;
8980                 this._z = z;
8981                 this._order = order;
8982
8983         }
8984
8985         get x() {
8986
8987                 return this._x;
8988
8989         }
8990
8991         set x( value ) {
8992
8993                 this._x = value;
8994                 this._onChangeCallback();
8995
8996         }
8997
8998         get y() {
8999
9000                 return this._y;
9001
9002         }
9003
9004         set y( value ) {
9005
9006                 this._y = value;
9007                 this._onChangeCallback();
9008
9009         }
9010
9011         get z() {
9012
9013                 return this._z;
9014
9015         }
9016
9017         set z( value ) {
9018
9019                 this._z = value;
9020                 this._onChangeCallback();
9021
9022         }
9023
9024         get order() {
9025
9026                 return this._order;
9027
9028         }
9029
9030         set order( value ) {
9031
9032                 this._order = value;
9033                 this._onChangeCallback();
9034
9035         }
9036
9037         set( x, y, z, order = this._order ) {
9038
9039                 this._x = x;
9040                 this._y = y;
9041                 this._z = z;
9042                 this._order = order;
9043
9044                 this._onChangeCallback();
9045
9046                 return this;
9047
9048         }
9049
9050         clone() {
9051
9052                 return new this.constructor( this._x, this._y, this._z, this._order );
9053
9054         }
9055
9056         copy( euler ) {
9057
9058                 this._x = euler._x;
9059                 this._y = euler._y;
9060                 this._z = euler._z;
9061                 this._order = euler._order;
9062
9063                 this._onChangeCallback();
9064
9065                 return this;
9066
9067         }
9068
9069         setFromRotationMatrix( m, order = this._order, update = true ) {
9070
9071                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
9072
9073                 const te = m.elements;
9074                 const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
9075                 const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
9076                 const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
9077
9078                 switch ( order ) {
9079
9080                         case 'XYZ':
9081
9082                                 this._y = Math.asin( clamp$1( m13, - 1, 1 ) );
9083
9084                                 if ( Math.abs( m13 ) < 0.9999999 ) {
9085
9086                                         this._x = Math.atan2( - m23, m33 );
9087                                         this._z = Math.atan2( - m12, m11 );
9088
9089                                 } else {
9090
9091                                         this._x = Math.atan2( m32, m22 );
9092                                         this._z = 0;
9093
9094                                 }
9095
9096                                 break;
9097
9098                         case 'YXZ':
9099
9100                                 this._x = Math.asin( - clamp$1( m23, - 1, 1 ) );
9101
9102                                 if ( Math.abs( m23 ) < 0.9999999 ) {
9103
9104                                         this._y = Math.atan2( m13, m33 );
9105                                         this._z = Math.atan2( m21, m22 );
9106
9107                                 } else {
9108
9109                                         this._y = Math.atan2( - m31, m11 );
9110                                         this._z = 0;
9111
9112                                 }
9113
9114                                 break;
9115
9116                         case 'ZXY':
9117
9118                                 this._x = Math.asin( clamp$1( m32, - 1, 1 ) );
9119
9120                                 if ( Math.abs( m32 ) < 0.9999999 ) {
9121
9122                                         this._y = Math.atan2( - m31, m33 );
9123                                         this._z = Math.atan2( - m12, m22 );
9124
9125                                 } else {
9126
9127                                         this._y = 0;
9128                                         this._z = Math.atan2( m21, m11 );
9129
9130                                 }
9131
9132                                 break;
9133
9134                         case 'ZYX':
9135
9136                                 this._y = Math.asin( - clamp$1( m31, - 1, 1 ) );
9137
9138                                 if ( Math.abs( m31 ) < 0.9999999 ) {
9139
9140                                         this._x = Math.atan2( m32, m33 );
9141                                         this._z = Math.atan2( m21, m11 );
9142
9143                                 } else {
9144
9145                                         this._x = 0;
9146                                         this._z = Math.atan2( - m12, m22 );
9147
9148                                 }
9149
9150                                 break;
9151
9152                         case 'YZX':
9153
9154                                 this._z = Math.asin( clamp$1( m21, - 1, 1 ) );
9155
9156                                 if ( Math.abs( m21 ) < 0.9999999 ) {
9157
9158                                         this._x = Math.atan2( - m23, m22 );
9159                                         this._y = Math.atan2( - m31, m11 );
9160
9161                                 } else {
9162
9163                                         this._x = 0;
9164                                         this._y = Math.atan2( m13, m33 );
9165
9166                                 }
9167
9168                                 break;
9169
9170                         case 'XZY':
9171
9172                                 this._z = Math.asin( - clamp$1( m12, - 1, 1 ) );
9173
9174                                 if ( Math.abs( m12 ) < 0.9999999 ) {
9175
9176                                         this._x = Math.atan2( m32, m22 );
9177                                         this._y = Math.atan2( m13, m11 );
9178
9179                                 } else {
9180
9181                                         this._x = Math.atan2( - m23, m33 );
9182                                         this._y = 0;
9183
9184                                 }
9185
9186                                 break;
9187
9188                         default:
9189
9190                                 console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
9191
9192                 }
9193
9194                 this._order = order;
9195
9196                 if ( update === true ) this._onChangeCallback();
9197
9198                 return this;
9199
9200         }
9201
9202         setFromQuaternion( q, order, update ) {
9203
9204                 _matrix$1.makeRotationFromQuaternion( q );
9205
9206                 return this.setFromRotationMatrix( _matrix$1, order, update );
9207
9208         }
9209
9210         setFromVector3( v, order = this._order ) {
9211
9212                 return this.set( v.x, v.y, v.z, order );
9213
9214         }
9215
9216         reorder( newOrder ) {
9217
9218                 // WARNING: this discards revolution information -bhouston
9219
9220                 _quaternion$3.setFromEuler( this );
9221
9222                 return this.setFromQuaternion( _quaternion$3, newOrder );
9223
9224         }
9225
9226         equals( euler ) {
9227
9228                 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
9229
9230         }
9231
9232         fromArray( array ) {
9233
9234                 this._x = array[ 0 ];
9235                 this._y = array[ 1 ];
9236                 this._z = array[ 2 ];
9237                 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
9238
9239                 this._onChangeCallback();
9240
9241                 return this;
9242
9243         }
9244
9245         toArray( array = [], offset = 0 ) {
9246
9247                 array[ offset ] = this._x;
9248                 array[ offset + 1 ] = this._y;
9249                 array[ offset + 2 ] = this._z;
9250                 array[ offset + 3 ] = this._order;
9251
9252                 return array;
9253
9254         }
9255
9256         toVector3( optionalResult ) {
9257
9258                 if ( optionalResult ) {
9259
9260                         return optionalResult.set( this._x, this._y, this._z );
9261
9262                 } else {
9263
9264                         return new Vector3( this._x, this._y, this._z );
9265
9266                 }
9267
9268         }
9269
9270         _onChange( callback ) {
9271
9272                 this._onChangeCallback = callback;
9273
9274                 return this;
9275
9276         }
9277
9278         _onChangeCallback() {}
9279
9280     }
9281
9282     Euler.prototype.isEuler = true;
9283
9284     Euler.DefaultOrder = 'XYZ';
9285     Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
9286
9287     class Layers {
9288
9289         constructor() {
9290
9291                 this.mask = 1 | 0;
9292
9293         }
9294
9295         set( channel ) {
9296
9297                 this.mask = 1 << channel | 0;
9298
9299         }
9300
9301         enable( channel ) {
9302
9303                 this.mask |= 1 << channel | 0;
9304
9305         }
9306
9307         enableAll() {
9308
9309                 this.mask = 0xffffffff | 0;
9310
9311         }
9312
9313         toggle( channel ) {
9314
9315                 this.mask ^= 1 << channel | 0;
9316
9317         }
9318
9319         disable( channel ) {
9320
9321                 this.mask &= ~ ( 1 << channel | 0 );
9322
9323         }
9324
9325         disableAll() {
9326
9327                 this.mask = 0;
9328
9329         }
9330
9331         test( layers ) {
9332
9333                 return ( this.mask & layers.mask ) !== 0;
9334
9335         }
9336
9337     }
9338
9339     let _object3DId = 0;
9340
9341     const _v1$4 = /*@__PURE__*/ new Vector3();
9342     const _q1 = /*@__PURE__*/ new Quaternion();
9343     const _m1$1 = /*@__PURE__*/ new Matrix4();
9344     const _target = /*@__PURE__*/ new Vector3();
9345
9346     const _position$3 = /*@__PURE__*/ new Vector3();
9347     const _scale$2 = /*@__PURE__*/ new Vector3();
9348     const _quaternion$2 = /*@__PURE__*/ new Quaternion();
9349
9350     const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 );
9351     const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 );
9352     const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 );
9353
9354     const _addedEvent = { type: 'added' };
9355     const _removedEvent = { type: 'removed' };
9356
9357     class Object3D extends EventDispatcher {
9358
9359         constructor() {
9360
9361                 super();
9362
9363                 Object.defineProperty( this, 'id', { value: _object3DId ++ } );
9364
9365                 this.uuid = generateUUID();
9366
9367                 this.name = '';
9368                 this.type = 'Object3D';
9369
9370                 this.parent = null;
9371                 this.children = [];
9372
9373                 this.up = Object3D.DefaultUp.clone();
9374
9375                 const position = new Vector3();
9376                 const rotation = new Euler();
9377                 const quaternion = new Quaternion();
9378                 const scale = new Vector3( 1, 1, 1 );
9379
9380                 function onRotationChange() {
9381
9382                         quaternion.setFromEuler( rotation, false );
9383
9384                 }
9385
9386                 function onQuaternionChange() {
9387
9388                         rotation.setFromQuaternion( quaternion, undefined, false );
9389
9390                 }
9391
9392                 rotation._onChange( onRotationChange );
9393                 quaternion._onChange( onQuaternionChange );
9394
9395                 Object.defineProperties( this, {
9396                         position: {
9397                                 configurable: true,
9398                                 enumerable: true,
9399                                 value: position
9400                         },
9401                         rotation: {
9402                                 configurable: true,
9403                                 enumerable: true,
9404                                 value: rotation
9405                         },
9406                         quaternion: {
9407                                 configurable: true,
9408                                 enumerable: true,
9409                                 value: quaternion
9410                         },
9411                         scale: {
9412                                 configurable: true,
9413                                 enumerable: true,
9414                                 value: scale
9415                         },
9416                         modelViewMatrix: {
9417                                 value: new Matrix4()
9418                         },
9419                         normalMatrix: {
9420                                 value: new Matrix3()
9421                         }
9422                 } );
9423
9424                 this.matrix = new Matrix4();
9425                 this.matrixWorld = new Matrix4();
9426
9427                 this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
9428                 this.matrixWorldNeedsUpdate = false;
9429
9430                 this.layers = new Layers();
9431                 this.visible = true;
9432
9433                 this.castShadow = false;
9434                 this.receiveShadow = false;
9435
9436                 this.frustumCulled = true;
9437                 this.renderOrder = 0;
9438
9439                 this.animations = [];
9440
9441                 this.userData = {};
9442
9443         }
9444
9445         onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {}
9446
9447         onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {}
9448
9449         applyMatrix4( matrix ) {
9450
9451                 if ( this.matrixAutoUpdate ) this.updateMatrix();
9452
9453                 this.matrix.premultiply( matrix );
9454
9455                 this.matrix.decompose( this.position, this.quaternion, this.scale );
9456
9457         }
9458
9459         applyQuaternion( q ) {
9460
9461                 this.quaternion.premultiply( q );
9462
9463                 return this;
9464
9465         }
9466
9467         setRotationFromAxisAngle( axis, angle ) {
9468
9469                 // assumes axis is normalized
9470
9471                 this.quaternion.setFromAxisAngle( axis, angle );
9472
9473         }
9474
9475         setRotationFromEuler( euler ) {
9476
9477                 this.quaternion.setFromEuler( euler, true );
9478
9479         }
9480
9481         setRotationFromMatrix( m ) {
9482
9483                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
9484
9485                 this.quaternion.setFromRotationMatrix( m );
9486
9487         }
9488
9489         setRotationFromQuaternion( q ) {
9490
9491                 // assumes q is normalized
9492
9493                 this.quaternion.copy( q );
9494
9495         }
9496
9497         rotateOnAxis( axis, angle ) {
9498
9499                 // rotate object on axis in object space
9500                 // axis is assumed to be normalized
9501
9502                 _q1.setFromAxisAngle( axis, angle );
9503
9504                 this.quaternion.multiply( _q1 );
9505
9506                 return this;
9507
9508         }
9509
9510         rotateOnWorldAxis( axis, angle ) {
9511
9512                 // rotate object on axis in world space
9513                 // axis is assumed to be normalized
9514                 // method assumes no rotated parent
9515
9516                 _q1.setFromAxisAngle( axis, angle );
9517
9518                 this.quaternion.premultiply( _q1 );
9519
9520                 return this;
9521
9522         }
9523
9524         rotateX( angle ) {
9525
9526                 return this.rotateOnAxis( _xAxis, angle );
9527
9528         }
9529
9530         rotateY( angle ) {
9531
9532                 return this.rotateOnAxis( _yAxis, angle );
9533
9534         }
9535
9536         rotateZ( angle ) {
9537
9538                 return this.rotateOnAxis( _zAxis, angle );
9539
9540         }
9541
9542         translateOnAxis( axis, distance ) {
9543
9544                 // translate object by distance along axis in object space
9545                 // axis is assumed to be normalized
9546
9547                 _v1$4.copy( axis ).applyQuaternion( this.quaternion );
9548
9549                 this.position.add( _v1$4.multiplyScalar( distance ) );
9550
9551                 return this;
9552
9553         }
9554
9555         translateX( distance ) {
9556
9557                 return this.translateOnAxis( _xAxis, distance );
9558
9559         }
9560
9561         translateY( distance ) {
9562
9563                 return this.translateOnAxis( _yAxis, distance );
9564
9565         }
9566
9567         translateZ( distance ) {
9568
9569                 return this.translateOnAxis( _zAxis, distance );
9570
9571         }
9572
9573         localToWorld( vector ) {
9574
9575                 return vector.applyMatrix4( this.matrixWorld );
9576
9577         }
9578
9579         worldToLocal( vector ) {
9580
9581                 return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
9582
9583         }
9584
9585         lookAt( x, y, z ) {
9586
9587                 // This method does not support objects having non-uniformly-scaled parent(s)
9588
9589                 if ( x.isVector3 ) {
9590
9591                         _target.copy( x );
9592
9593                 } else {
9594
9595                         _target.set( x, y, z );
9596
9597                 }
9598
9599                 const parent = this.parent;
9600
9601                 this.updateWorldMatrix( true, false );
9602
9603                 _position$3.setFromMatrixPosition( this.matrixWorld );
9604
9605                 if ( this.isCamera || this.isLight ) {
9606
9607                         _m1$1.lookAt( _position$3, _target, this.up );
9608
9609                 } else {
9610
9611                         _m1$1.lookAt( _target, _position$3, this.up );
9612
9613                 }
9614
9615                 this.quaternion.setFromRotationMatrix( _m1$1 );
9616
9617                 if ( parent ) {
9618
9619                         _m1$1.extractRotation( parent.matrixWorld );
9620                         _q1.setFromRotationMatrix( _m1$1 );
9621                         this.quaternion.premultiply( _q1.invert() );
9622
9623                 }
9624
9625         }
9626
9627         add( object ) {
9628
9629                 if ( arguments.length > 1 ) {
9630
9631                         for ( let i = 0; i < arguments.length; i ++ ) {
9632
9633                                 this.add( arguments[ i ] );
9634
9635                         }
9636
9637                         return this;
9638
9639                 }
9640
9641                 if ( object === this ) {
9642
9643                         console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object );
9644                         return this;
9645
9646                 }
9647
9648                 if ( object && object.isObject3D ) {
9649
9650                         if ( object.parent !== null ) {
9651
9652                                 object.parent.remove( object );
9653
9654                         }
9655
9656                         object.parent = this;
9657                         this.children.push( object );
9658
9659                         object.dispatchEvent( _addedEvent );
9660
9661                 } else {
9662
9663                         console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object );
9664
9665                 }
9666
9667                 return this;
9668
9669         }
9670
9671         remove( object ) {
9672
9673                 if ( arguments.length > 1 ) {
9674
9675                         for ( let i = 0; i < arguments.length; i ++ ) {
9676
9677                                 this.remove( arguments[ i ] );
9678
9679                         }
9680
9681                         return this;
9682
9683                 }
9684
9685                 const index = this.children.indexOf( object );
9686
9687                 if ( index !== - 1 ) {
9688
9689                         object.parent = null;
9690                         this.children.splice( index, 1 );
9691
9692                         object.dispatchEvent( _removedEvent );
9693
9694                 }
9695
9696                 return this;
9697
9698         }
9699
9700         removeFromParent() {
9701
9702                 const parent = this.parent;
9703
9704                 if ( parent !== null ) {
9705
9706                         parent.remove( this );
9707
9708                 }
9709
9710                 return this;
9711
9712         }
9713
9714         clear() {
9715
9716                 for ( let i = 0; i < this.children.length; i ++ ) {
9717
9718                         const object = this.children[ i ];
9719
9720                         object.parent = null;
9721
9722                         object.dispatchEvent( _removedEvent );
9723
9724                 }
9725
9726                 this.children.length = 0;
9727
9728                 return this;
9729
9730
9731         }
9732
9733         attach( object ) {
9734
9735                 // adds object as a child of this, while maintaining the object's world transform
9736
9737                 this.updateWorldMatrix( true, false );
9738
9739                 _m1$1.copy( this.matrixWorld ).invert();
9740
9741                 if ( object.parent !== null ) {
9742
9743                         object.parent.updateWorldMatrix( true, false );
9744
9745                         _m1$1.multiply( object.parent.matrixWorld );
9746
9747                 }
9748
9749                 object.applyMatrix4( _m1$1 );
9750
9751                 this.add( object );
9752
9753                 object.updateWorldMatrix( false, true );
9754
9755                 return this;
9756
9757         }
9758
9759         getObjectById( id ) {
9760
9761                 return this.getObjectByProperty( 'id', id );
9762
9763         }
9764
9765         getObjectByName( name ) {
9766
9767                 return this.getObjectByProperty( 'name', name );
9768
9769         }
9770
9771         getObjectByProperty( name, value ) {
9772
9773                 if ( this[ name ] === value ) return this;
9774
9775                 for ( let i = 0, l = this.children.length; i < l; i ++ ) {
9776
9777                         const child = this.children[ i ];
9778                         const object = child.getObjectByProperty( name, value );
9779
9780                         if ( object !== undefined ) {
9781
9782                                 return object;
9783
9784                         }
9785
9786                 }
9787
9788                 return undefined;
9789
9790         }
9791
9792         getWorldPosition( target ) {
9793
9794                 this.updateWorldMatrix( true, false );
9795
9796                 return target.setFromMatrixPosition( this.matrixWorld );
9797
9798         }
9799
9800         getWorldQuaternion( target ) {
9801
9802                 this.updateWorldMatrix( true, false );
9803
9804                 this.matrixWorld.decompose( _position$3, target, _scale$2 );
9805
9806                 return target;
9807
9808         }
9809
9810         getWorldScale( target ) {
9811
9812                 this.updateWorldMatrix( true, false );
9813
9814                 this.matrixWorld.decompose( _position$3, _quaternion$2, target );
9815
9816                 return target;
9817
9818         }
9819
9820         getWorldDirection( target ) {
9821
9822                 this.updateWorldMatrix( true, false );
9823
9824                 const e = this.matrixWorld.elements;
9825
9826                 return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
9827
9828         }
9829
9830         raycast() {}
9831
9832         traverse( callback ) {
9833
9834                 callback( this );
9835
9836                 const children = this.children;
9837
9838                 for ( let i = 0, l = children.length; i < l; i ++ ) {
9839
9840                         children[ i ].traverse( callback );
9841
9842                 }
9843
9844         }
9845
9846         traverseVisible( callback ) {
9847
9848                 if ( this.visible === false ) return;
9849
9850                 callback( this );
9851
9852                 const children = this.children;
9853
9854                 for ( let i = 0, l = children.length; i < l; i ++ ) {
9855
9856                         children[ i ].traverseVisible( callback );
9857
9858                 }
9859
9860         }
9861
9862         traverseAncestors( callback ) {
9863
9864                 const parent = this.parent;
9865
9866                 if ( parent !== null ) {
9867
9868                         callback( parent );
9869
9870                         parent.traverseAncestors( callback );
9871
9872                 }
9873
9874         }
9875
9876         updateMatrix() {
9877
9878                 this.matrix.compose( this.position, this.quaternion, this.scale );
9879
9880                 this.matrixWorldNeedsUpdate = true;
9881
9882         }
9883
9884         updateMatrixWorld( force ) {
9885
9886                 if ( this.matrixAutoUpdate ) this.updateMatrix();
9887
9888                 if ( this.matrixWorldNeedsUpdate || force ) {
9889
9890                         if ( this.parent === null ) {
9891
9892                                 this.matrixWorld.copy( this.matrix );
9893
9894                         } else {
9895
9896                                 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
9897
9898                         }
9899
9900                         this.matrixWorldNeedsUpdate = false;
9901
9902                         force = true;
9903
9904                 }
9905
9906                 // update children
9907
9908                 const children = this.children;
9909
9910                 for ( let i = 0, l = children.length; i < l; i ++ ) {
9911
9912                         children[ i ].updateMatrixWorld( force );
9913
9914                 }
9915
9916         }
9917
9918         updateWorldMatrix( updateParents, updateChildren ) {
9919
9920                 const parent = this.parent;
9921
9922                 if ( updateParents === true && parent !== null ) {
9923
9924                         parent.updateWorldMatrix( true, false );
9925
9926                 }
9927
9928                 if ( this.matrixAutoUpdate ) this.updateMatrix();
9929
9930                 if ( this.parent === null ) {
9931
9932                         this.matrixWorld.copy( this.matrix );
9933
9934                 } else {
9935
9936                         this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
9937
9938                 }
9939
9940                 // update children
9941
9942                 if ( updateChildren === true ) {
9943
9944                         const children = this.children;
9945
9946                         for ( let i = 0, l = children.length; i < l; i ++ ) {
9947
9948                                 children[ i ].updateWorldMatrix( false, true );
9949
9950                         }
9951
9952                 }
9953
9954         }
9955
9956         toJSON( meta ) {
9957
9958                 // meta is a string when called from JSON.stringify
9959                 const isRootObject = ( meta === undefined || typeof meta === 'string' );
9960
9961                 const output = {};
9962
9963                 // meta is a hash used to collect geometries, materials.
9964                 // not providing it implies that this is the root object
9965                 // being serialized.
9966                 if ( isRootObject ) {
9967
9968                         // initialize meta obj
9969                         meta = {
9970                                 geometries: {},
9971                                 materials: {},
9972                                 textures: {},
9973                                 images: {},
9974                                 shapes: {},
9975                                 skeletons: {},
9976                                 animations: {}
9977                         };
9978
9979                         output.metadata = {
9980                                 version: 4.5,
9981                                 type: 'Object',
9982                                 generator: 'Object3D.toJSON'
9983                         };
9984
9985                 }
9986
9987                 // standard Object3D serialization
9988
9989                 const object = {};
9990
9991                 object.uuid = this.uuid;
9992                 object.type = this.type;
9993
9994                 if ( this.name !== '' ) object.name = this.name;
9995                 if ( this.castShadow === true ) object.castShadow = true;
9996                 if ( this.receiveShadow === true ) object.receiveShadow = true;
9997                 if ( this.visible === false ) object.visible = false;
9998                 if ( this.frustumCulled === false ) object.frustumCulled = false;
9999                 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
10000                 if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
10001
10002                 object.layers = this.layers.mask;
10003                 object.matrix = this.matrix.toArray();
10004
10005                 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
10006
10007                 // object specific properties
10008
10009                 if ( this.isInstancedMesh ) {
10010
10011                         object.type = 'InstancedMesh';
10012                         object.count = this.count;
10013                         object.instanceMatrix = this.instanceMatrix.toJSON();
10014                         if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON();
10015
10016                 }
10017
10018                 //
10019
10020                 function serialize( library, element ) {
10021
10022                         if ( library[ element.uuid ] === undefined ) {
10023
10024                                 library[ element.uuid ] = element.toJSON( meta );
10025
10026                         }
10027
10028                         return element.uuid;
10029
10030                 }
10031
10032                 if ( this.isScene ) {
10033
10034                         if ( this.background ) {
10035
10036                                 if ( this.background.isColor ) {
10037
10038                                         object.background = this.background.toJSON();
10039
10040                                 } else if ( this.background.isTexture ) {
10041
10042                                         object.background = this.background.toJSON( meta ).uuid;
10043
10044                                 }
10045
10046                         }
10047
10048                         if ( this.environment && this.environment.isTexture ) {
10049
10050                                 object.environment = this.environment.toJSON( meta ).uuid;
10051
10052                         }
10053
10054                 } else if ( this.isMesh || this.isLine || this.isPoints ) {
10055
10056                         object.geometry = serialize( meta.geometries, this.geometry );
10057
10058                         const parameters = this.geometry.parameters;
10059
10060                         if ( parameters !== undefined && parameters.shapes !== undefined ) {
10061
10062                                 const shapes = parameters.shapes;
10063
10064                                 if ( Array.isArray( shapes ) ) {
10065
10066                                         for ( let i = 0, l = shapes.length; i < l; i ++ ) {
10067
10068                                                 const shape = shapes[ i ];
10069
10070                                                 serialize( meta.shapes, shape );
10071
10072                                         }
10073
10074                                 } else {
10075
10076                                         serialize( meta.shapes, shapes );
10077
10078                                 }
10079
10080                         }
10081
10082                 }
10083
10084                 if ( this.isSkinnedMesh ) {
10085
10086                         object.bindMode = this.bindMode;
10087                         object.bindMatrix = this.bindMatrix.toArray();
10088
10089                         if ( this.skeleton !== undefined ) {
10090
10091                                 serialize( meta.skeletons, this.skeleton );
10092
10093                                 object.skeleton = this.skeleton.uuid;
10094
10095                         }
10096
10097                 }
10098
10099                 if ( this.material !== undefined ) {
10100
10101                         if ( Array.isArray( this.material ) ) {
10102
10103                                 const uuids = [];
10104
10105                                 for ( let i = 0, l = this.material.length; i < l; i ++ ) {
10106
10107                                         uuids.push( serialize( meta.materials, this.material[ i ] ) );
10108
10109                                 }
10110
10111                                 object.material = uuids;
10112
10113                         } else {
10114
10115                                 object.material = serialize( meta.materials, this.material );
10116
10117                         }
10118
10119                 }
10120
10121                 //
10122
10123                 if ( this.children.length > 0 ) {
10124
10125                         object.children = [];
10126
10127                         for ( let i = 0; i < this.children.length; i ++ ) {
10128
10129                                 object.children.push( this.children[ i ].toJSON( meta ).object );
10130
10131                         }
10132
10133                 }
10134
10135                 //
10136
10137                 if ( this.animations.length > 0 ) {
10138
10139                         object.animations = [];
10140
10141                         for ( let i = 0; i < this.animations.length; i ++ ) {
10142
10143                                 const animation = this.animations[ i ];
10144
10145                                 object.animations.push( serialize( meta.animations, animation ) );
10146
10147                         }
10148
10149                 }
10150
10151                 if ( isRootObject ) {
10152
10153                         const geometries = extractFromCache( meta.geometries );
10154                         const materials = extractFromCache( meta.materials );
10155                         const textures = extractFromCache( meta.textures );
10156                         const images = extractFromCache( meta.images );
10157                         const shapes = extractFromCache( meta.shapes );
10158                         const skeletons = extractFromCache( meta.skeletons );
10159                         const animations = extractFromCache( meta.animations );
10160
10161                         if ( geometries.length > 0 ) output.geometries = geometries;
10162                         if ( materials.length > 0 ) output.materials = materials;
10163                         if ( textures.length > 0 ) output.textures = textures;
10164                         if ( images.length > 0 ) output.images = images;
10165                         if ( shapes.length > 0 ) output.shapes = shapes;
10166                         if ( skeletons.length > 0 ) output.skeletons = skeletons;
10167                         if ( animations.length > 0 ) output.animations = animations;
10168
10169                 }
10170
10171                 output.object = object;
10172
10173                 return output;
10174
10175                 // extract data from the cache hash
10176                 // remove metadata on each item
10177                 // and return as array
10178                 function extractFromCache( cache ) {
10179
10180                         const values = [];
10181                         for ( const key in cache ) {
10182
10183                                 const data = cache[ key ];
10184                                 delete data.metadata;
10185                                 values.push( data );
10186
10187                         }
10188
10189                         return values;
10190
10191                 }
10192
10193         }
10194
10195         clone( recursive ) {
10196
10197                 return new this.constructor().copy( this, recursive );
10198
10199         }
10200
10201         copy( source, recursive = true ) {
10202
10203                 this.name = source.name;
10204
10205                 this.up.copy( source.up );
10206
10207                 this.position.copy( source.position );
10208                 this.rotation.order = source.rotation.order;
10209                 this.quaternion.copy( source.quaternion );
10210                 this.scale.copy( source.scale );
10211
10212                 this.matrix.copy( source.matrix );
10213                 this.matrixWorld.copy( source.matrixWorld );
10214
10215                 this.matrixAutoUpdate = source.matrixAutoUpdate;
10216                 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
10217
10218                 this.layers.mask = source.layers.mask;
10219                 this.visible = source.visible;
10220
10221                 this.castShadow = source.castShadow;
10222                 this.receiveShadow = source.receiveShadow;
10223
10224                 this.frustumCulled = source.frustumCulled;
10225                 this.renderOrder = source.renderOrder;
10226
10227                 this.userData = JSON.parse( JSON.stringify( source.userData ) );
10228
10229                 if ( recursive === true ) {
10230
10231                         for ( let i = 0; i < source.children.length; i ++ ) {
10232
10233                                 const child = source.children[ i ];
10234                                 this.add( child.clone() );
10235
10236                         }
10237
10238                 }
10239
10240                 return this;
10241
10242         }
10243
10244     }
10245
10246     Object3D.DefaultUp = new Vector3( 0, 1, 0 );
10247     Object3D.DefaultMatrixAutoUpdate = true;
10248
10249     Object3D.prototype.isObject3D = true;
10250
10251     const _v0$1 = /*@__PURE__*/ new Vector3();
10252     const _v1$3 = /*@__PURE__*/ new Vector3();
10253     const _v2$2 = /*@__PURE__*/ new Vector3();
10254     const _v3$1 = /*@__PURE__*/ new Vector3();
10255
10256     const _vab = /*@__PURE__*/ new Vector3();
10257     const _vac = /*@__PURE__*/ new Vector3();
10258     const _vbc = /*@__PURE__*/ new Vector3();
10259     const _vap = /*@__PURE__*/ new Vector3();
10260     const _vbp = /*@__PURE__*/ new Vector3();
10261     const _vcp = /*@__PURE__*/ new Vector3();
10262
10263     class Triangle {
10264
10265         constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) {
10266
10267                 this.a = a;
10268                 this.b = b;
10269                 this.c = c;
10270
10271         }
10272
10273         static getNormal( a, b, c, target ) {
10274
10275                 target.subVectors( c, b );
10276                 _v0$1.subVectors( a, b );
10277                 target.cross( _v0$1 );
10278
10279                 const targetLengthSq = target.lengthSq();
10280                 if ( targetLengthSq > 0 ) {
10281
10282                         return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
10283
10284                 }
10285
10286                 return target.set( 0, 0, 0 );
10287
10288         }
10289
10290         // static/instance method to calculate barycentric coordinates
10291         // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
10292         static getBarycoord( point, a, b, c, target ) {
10293
10294                 _v0$1.subVectors( c, a );
10295                 _v1$3.subVectors( b, a );
10296                 _v2$2.subVectors( point, a );
10297
10298                 const dot00 = _v0$1.dot( _v0$1 );
10299                 const dot01 = _v0$1.dot( _v1$3 );
10300                 const dot02 = _v0$1.dot( _v2$2 );
10301                 const dot11 = _v1$3.dot( _v1$3 );
10302                 const dot12 = _v1$3.dot( _v2$2 );
10303
10304                 const denom = ( dot00 * dot11 - dot01 * dot01 );
10305
10306                 // collinear or singular triangle
10307                 if ( denom === 0 ) {
10308
10309                         // arbitrary location outside of triangle?
10310                         // not sure if this is the best idea, maybe should be returning undefined
10311                         return target.set( - 2, - 1, - 1 );
10312
10313                 }
10314
10315                 const invDenom = 1 / denom;
10316                 const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
10317                 const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
10318
10319                 // barycentric coordinates must always sum to 1
10320                 return target.set( 1 - u - v, v, u );
10321
10322         }
10323
10324         static containsPoint( point, a, b, c ) {
10325
10326                 this.getBarycoord( point, a, b, c, _v3$1 );
10327
10328                 return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 );
10329
10330         }
10331
10332         static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) {
10333
10334                 this.getBarycoord( point, p1, p2, p3, _v3$1 );
10335
10336                 target.set( 0, 0 );
10337                 target.addScaledVector( uv1, _v3$1.x );
10338                 target.addScaledVector( uv2, _v3$1.y );
10339                 target.addScaledVector( uv3, _v3$1.z );
10340
10341                 return target;
10342
10343         }
10344
10345         static isFrontFacing( a, b, c, direction ) {
10346
10347                 _v0$1.subVectors( c, b );
10348                 _v1$3.subVectors( a, b );
10349
10350                 // strictly front facing
10351                 return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
10352
10353         }
10354
10355         set( a, b, c ) {
10356
10357                 this.a.copy( a );
10358                 this.b.copy( b );
10359                 this.c.copy( c );
10360
10361                 return this;
10362
10363         }
10364
10365         setFromPointsAndIndices( points, i0, i1, i2 ) {
10366
10367                 this.a.copy( points[ i0 ] );
10368                 this.b.copy( points[ i1 ] );
10369                 this.c.copy( points[ i2 ] );
10370
10371                 return this;
10372
10373         }
10374
10375         setFromAttributeAndIndices( attribute, i0, i1, i2 ) {
10376
10377                 this.a.fromBufferAttribute( attribute, i0 );
10378                 this.b.fromBufferAttribute( attribute, i1 );
10379                 this.c.fromBufferAttribute( attribute, i2 );
10380
10381                 return this;
10382
10383         }
10384
10385         clone() {
10386
10387                 return new this.constructor().copy( this );
10388
10389         }
10390
10391         copy( triangle ) {
10392
10393                 this.a.copy( triangle.a );
10394                 this.b.copy( triangle.b );
10395                 this.c.copy( triangle.c );
10396
10397                 return this;
10398
10399         }
10400
10401         getArea() {
10402
10403                 _v0$1.subVectors( this.c, this.b );
10404                 _v1$3.subVectors( this.a, this.b );
10405
10406                 return _v0$1.cross( _v1$3 ).length() * 0.5;
10407
10408         }
10409
10410         getMidpoint( target ) {
10411
10412                 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
10413
10414         }
10415
10416         getNormal( target ) {
10417
10418                 return Triangle.getNormal( this.a, this.b, this.c, target );
10419
10420         }
10421
10422         getPlane( target ) {
10423
10424                 return target.setFromCoplanarPoints( this.a, this.b, this.c );
10425
10426         }
10427
10428         getBarycoord( point, target ) {
10429
10430                 return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
10431
10432         }
10433
10434         getUV( point, uv1, uv2, uv3, target ) {
10435
10436                 return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
10437
10438         }
10439
10440         containsPoint( point ) {
10441
10442                 return Triangle.containsPoint( point, this.a, this.b, this.c );
10443
10444         }
10445
10446         isFrontFacing( direction ) {
10447
10448                 return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
10449
10450         }
10451
10452         intersectsBox( box ) {
10453
10454                 return box.intersectsTriangle( this );
10455
10456         }
10457
10458         closestPointToPoint( p, target ) {
10459
10460                 const a = this.a, b = this.b, c = this.c;
10461                 let v, w;
10462
10463                 // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
10464                 // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
10465                 // under the accompanying license; see chapter 5.1.5 for detailed explanation.
10466                 // basically, we're distinguishing which of the voronoi regions of the triangle
10467                 // the point lies in with the minimum amount of redundant computation.
10468
10469                 _vab.subVectors( b, a );
10470                 _vac.subVectors( c, a );
10471                 _vap.subVectors( p, a );
10472                 const d1 = _vab.dot( _vap );
10473                 const d2 = _vac.dot( _vap );
10474                 if ( d1 <= 0 && d2 <= 0 ) {
10475
10476                         // vertex region of A; barycentric coords (1, 0, 0)
10477                         return target.copy( a );
10478
10479                 }
10480
10481                 _vbp.subVectors( p, b );
10482                 const d3 = _vab.dot( _vbp );
10483                 const d4 = _vac.dot( _vbp );
10484                 if ( d3 >= 0 && d4 <= d3 ) {
10485
10486                         // vertex region of B; barycentric coords (0, 1, 0)
10487                         return target.copy( b );
10488
10489                 }
10490
10491                 const vc = d1 * d4 - d3 * d2;
10492                 if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
10493
10494                         v = d1 / ( d1 - d3 );
10495                         // edge region of AB; barycentric coords (1-v, v, 0)
10496                         return target.copy( a ).addScaledVector( _vab, v );
10497
10498                 }
10499
10500                 _vcp.subVectors( p, c );
10501                 const d5 = _vab.dot( _vcp );
10502                 const d6 = _vac.dot( _vcp );
10503                 if ( d6 >= 0 && d5 <= d6 ) {
10504
10505                         // vertex region of C; barycentric coords (0, 0, 1)
10506                         return target.copy( c );
10507
10508                 }
10509
10510                 const vb = d5 * d2 - d1 * d6;
10511                 if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
10512
10513                         w = d2 / ( d2 - d6 );
10514                         // edge region of AC; barycentric coords (1-w, 0, w)
10515                         return target.copy( a ).addScaledVector( _vac, w );
10516
10517                 }
10518
10519                 const va = d3 * d6 - d5 * d4;
10520                 if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
10521
10522                         _vbc.subVectors( c, b );
10523                         w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
10524                         // edge region of BC; barycentric coords (0, 1-w, w)
10525                         return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
10526
10527                 }
10528
10529                 // face region
10530                 const denom = 1 / ( va + vb + vc );
10531                 // u = va * denom
10532                 v = vb * denom;
10533                 w = vc * denom;
10534
10535                 return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
10536
10537         }
10538
10539         equals( triangle ) {
10540
10541                 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
10542
10543         }
10544
10545     }
10546
10547     let materialId = 0;
10548
10549     class Material extends EventDispatcher {
10550
10551         constructor() {
10552
10553                 super();
10554
10555                 Object.defineProperty( this, 'id', { value: materialId ++ } );
10556
10557                 this.uuid = generateUUID();
10558
10559                 this.name = '';
10560                 this.type = 'Material';
10561
10562                 this.fog = true;
10563
10564                 this.blending = NormalBlending;
10565                 this.side = FrontSide;
10566                 this.vertexColors = false;
10567
10568                 this.opacity = 1;
10569                 this.format = RGBAFormat;
10570                 this.transparent = false;
10571
10572                 this.blendSrc = SrcAlphaFactor;
10573                 this.blendDst = OneMinusSrcAlphaFactor;
10574                 this.blendEquation = AddEquation;
10575                 this.blendSrcAlpha = null;
10576                 this.blendDstAlpha = null;
10577                 this.blendEquationAlpha = null;
10578
10579                 this.depthFunc = LessEqualDepth;
10580                 this.depthTest = true;
10581                 this.depthWrite = true;
10582
10583                 this.stencilWriteMask = 0xff;
10584                 this.stencilFunc = AlwaysStencilFunc;
10585                 this.stencilRef = 0;
10586                 this.stencilFuncMask = 0xff;
10587                 this.stencilFail = KeepStencilOp;
10588                 this.stencilZFail = KeepStencilOp;
10589                 this.stencilZPass = KeepStencilOp;
10590                 this.stencilWrite = false;
10591
10592                 this.clippingPlanes = null;
10593                 this.clipIntersection = false;
10594                 this.clipShadows = false;
10595
10596                 this.shadowSide = null;
10597
10598                 this.colorWrite = true;
10599
10600                 this.precision = null; // override the renderer's default precision for this material
10601
10602                 this.polygonOffset = false;
10603                 this.polygonOffsetFactor = 0;
10604                 this.polygonOffsetUnits = 0;
10605
10606                 this.dithering = false;
10607
10608                 this.alphaToCoverage = false;
10609                 this.premultipliedAlpha = false;
10610
10611                 this.visible = true;
10612
10613                 this.toneMapped = true;
10614
10615                 this.userData = {};
10616
10617                 this.version = 0;
10618
10619                 this._alphaTest = 0;
10620
10621         }
10622
10623         get alphaTest() {
10624
10625                 return this._alphaTest;
10626
10627         }
10628
10629         set alphaTest( value ) {
10630
10631                 if ( this._alphaTest > 0 !== value > 0 ) {
10632
10633                         this.version ++;
10634
10635                 }
10636
10637                 this._alphaTest = value;
10638
10639         }
10640
10641         onBuild( /* shaderobject, renderer */ ) {}
10642
10643         onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {}
10644
10645         onBeforeCompile( /* shaderobject, renderer */ ) {}
10646
10647         customProgramCacheKey() {
10648
10649                 return this.onBeforeCompile.toString();
10650
10651         }
10652
10653         setValues( values ) {
10654
10655                 if ( values === undefined ) return;
10656
10657                 for ( const key in values ) {
10658
10659                         const newValue = values[ key ];
10660
10661                         if ( newValue === undefined ) {
10662
10663                                 console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
10664                                 continue;
10665
10666                         }
10667
10668                         // for backward compatability if shading is set in the constructor
10669                         if ( key === 'shading' ) {
10670
10671                                 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
10672                                 this.flatShading = ( newValue === FlatShading ) ? true : false;
10673                                 continue;
10674
10675                         }
10676
10677                         const currentValue = this[ key ];
10678
10679                         if ( currentValue === undefined ) {
10680
10681                                 console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' );
10682                                 continue;
10683
10684                         }
10685
10686                         if ( currentValue && currentValue.isColor ) {
10687
10688                                 currentValue.set( newValue );
10689
10690                         } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
10691
10692                                 currentValue.copy( newValue );
10693
10694                         } else {
10695
10696                                 this[ key ] = newValue;
10697
10698                         }
10699
10700                 }
10701
10702         }
10703
10704         toJSON( meta ) {
10705
10706                 const isRoot = ( meta === undefined || typeof meta === 'string' );
10707
10708                 if ( isRoot ) {
10709
10710                         meta = {
10711                                 textures: {},
10712                                 images: {}
10713                         };
10714
10715                 }
10716
10717                 const data = {
10718                         metadata: {
10719                                 version: 4.5,
10720                                 type: 'Material',
10721                                 generator: 'Material.toJSON'
10722                         }
10723                 };
10724
10725                 // standard Material serialization
10726                 data.uuid = this.uuid;
10727                 data.type = this.type;
10728
10729                 if ( this.name !== '' ) data.name = this.name;
10730
10731                 if ( this.color && this.color.isColor ) data.color = this.color.getHex();
10732
10733                 if ( this.roughness !== undefined ) data.roughness = this.roughness;
10734                 if ( this.metalness !== undefined ) data.metalness = this.metalness;
10735
10736                 if ( this.sheen !== undefined ) data.sheen = this.sheen;
10737                 if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex();
10738                 if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness;
10739                 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
10740                 if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
10741
10742                 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
10743                 if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity;
10744                 if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex();
10745                 if ( this.shininess !== undefined ) data.shininess = this.shininess;
10746                 if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
10747                 if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
10748
10749                 if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
10750
10751                         data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
10752
10753                 }
10754
10755                 if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
10756
10757                         data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
10758
10759                 }
10760
10761                 if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
10762
10763                         data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
10764                         data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
10765
10766                 }
10767
10768                 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
10769                 if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
10770                 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
10771
10772                 if ( this.lightMap && this.lightMap.isTexture ) {
10773
10774                         data.lightMap = this.lightMap.toJSON( meta ).uuid;
10775                         data.lightMapIntensity = this.lightMapIntensity;
10776
10777                 }
10778
10779                 if ( this.aoMap && this.aoMap.isTexture ) {
10780
10781                         data.aoMap = this.aoMap.toJSON( meta ).uuid;
10782                         data.aoMapIntensity = this.aoMapIntensity;
10783
10784                 }
10785
10786                 if ( this.bumpMap && this.bumpMap.isTexture ) {
10787
10788                         data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
10789                         data.bumpScale = this.bumpScale;
10790
10791                 }
10792
10793                 if ( this.normalMap && this.normalMap.isTexture ) {
10794
10795                         data.normalMap = this.normalMap.toJSON( meta ).uuid;
10796                         data.normalMapType = this.normalMapType;
10797                         data.normalScale = this.normalScale.toArray();
10798
10799                 }
10800
10801                 if ( this.displacementMap && this.displacementMap.isTexture ) {
10802
10803                         data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
10804                         data.displacementScale = this.displacementScale;
10805                         data.displacementBias = this.displacementBias;
10806
10807                 }
10808
10809                 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
10810                 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
10811
10812                 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
10813                 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
10814                 if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid;
10815                 if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid;
10816
10817                 if ( this.envMap && this.envMap.isTexture ) {
10818
10819                         data.envMap = this.envMap.toJSON( meta ).uuid;
10820
10821                         if ( this.combine !== undefined ) data.combine = this.combine;
10822
10823                 }
10824
10825                 if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
10826                 if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity;
10827                 if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio;
10828
10829                 if ( this.gradientMap && this.gradientMap.isTexture ) {
10830
10831                         data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
10832
10833                 }
10834
10835                 if ( this.transmission !== undefined ) data.transmission = this.transmission;
10836                 if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid;
10837                 if ( this.thickness !== undefined ) data.thickness = this.thickness;
10838                 if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid;
10839                 if ( this.attenuationDistance !== undefined ) data.attenuationDistance = this.attenuationDistance;
10840                 if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex();
10841
10842                 if ( this.size !== undefined ) data.size = this.size;
10843                 if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide;
10844                 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
10845
10846                 if ( this.blending !== NormalBlending ) data.blending = this.blending;
10847                 if ( this.side !== FrontSide ) data.side = this.side;
10848                 if ( this.vertexColors ) data.vertexColors = true;
10849
10850                 if ( this.opacity < 1 ) data.opacity = this.opacity;
10851                 if ( this.format !== RGBAFormat ) data.format = this.format;
10852                 if ( this.transparent === true ) data.transparent = this.transparent;
10853
10854                 data.depthFunc = this.depthFunc;
10855                 data.depthTest = this.depthTest;
10856                 data.depthWrite = this.depthWrite;
10857                 data.colorWrite = this.colorWrite;
10858
10859                 data.stencilWrite = this.stencilWrite;
10860                 data.stencilWriteMask = this.stencilWriteMask;
10861                 data.stencilFunc = this.stencilFunc;
10862                 data.stencilRef = this.stencilRef;
10863                 data.stencilFuncMask = this.stencilFuncMask;
10864                 data.stencilFail = this.stencilFail;
10865                 data.stencilZFail = this.stencilZFail;
10866                 data.stencilZPass = this.stencilZPass;
10867
10868                 // rotation (SpriteMaterial)
10869                 if ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation;
10870
10871                 if ( this.polygonOffset === true ) data.polygonOffset = true;
10872                 if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
10873                 if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
10874
10875                 if ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth;
10876                 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
10877                 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
10878                 if ( this.scale !== undefined ) data.scale = this.scale;
10879
10880                 if ( this.dithering === true ) data.dithering = true;
10881
10882                 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
10883                 if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage;
10884                 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
10885
10886                 if ( this.wireframe === true ) data.wireframe = this.wireframe;
10887                 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
10888                 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
10889                 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
10890
10891                 if ( this.flatShading === true ) data.flatShading = this.flatShading;
10892
10893                 if ( this.visible === false ) data.visible = false;
10894
10895                 if ( this.toneMapped === false ) data.toneMapped = false;
10896
10897                 if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
10898
10899                 // TODO: Copied from Object3D.toJSON
10900
10901                 function extractFromCache( cache ) {
10902
10903                         const values = [];
10904
10905                         for ( const key in cache ) {
10906
10907                                 const data = cache[ key ];
10908                                 delete data.metadata;
10909                                 values.push( data );
10910
10911                         }
10912
10913                         return values;
10914
10915                 }
10916
10917                 if ( isRoot ) {
10918
10919                         const textures = extractFromCache( meta.textures );
10920                         const images = extractFromCache( meta.images );
10921
10922                         if ( textures.length > 0 ) data.textures = textures;
10923                         if ( images.length > 0 ) data.images = images;
10924
10925                 }
10926
10927                 return data;
10928
10929         }
10930
10931         clone() {
10932
10933                 return new this.constructor().copy( this );
10934
10935         }
10936
10937         copy( source ) {
10938
10939                 this.name = source.name;
10940
10941                 this.fog = source.fog;
10942
10943                 this.blending = source.blending;
10944                 this.side = source.side;
10945                 this.vertexColors = source.vertexColors;
10946
10947                 this.opacity = source.opacity;
10948                 this.format = source.format;
10949                 this.transparent = source.transparent;
10950
10951                 this.blendSrc = source.blendSrc;
10952                 this.blendDst = source.blendDst;
10953                 this.blendEquation = source.blendEquation;
10954                 this.blendSrcAlpha = source.blendSrcAlpha;
10955                 this.blendDstAlpha = source.blendDstAlpha;
10956                 this.blendEquationAlpha = source.blendEquationAlpha;
10957
10958                 this.depthFunc = source.depthFunc;
10959                 this.depthTest = source.depthTest;
10960                 this.depthWrite = source.depthWrite;
10961
10962                 this.stencilWriteMask = source.stencilWriteMask;
10963                 this.stencilFunc = source.stencilFunc;
10964                 this.stencilRef = source.stencilRef;
10965                 this.stencilFuncMask = source.stencilFuncMask;
10966                 this.stencilFail = source.stencilFail;
10967                 this.stencilZFail = source.stencilZFail;
10968                 this.stencilZPass = source.stencilZPass;
10969                 this.stencilWrite = source.stencilWrite;
10970
10971                 const srcPlanes = source.clippingPlanes;
10972                 let dstPlanes = null;
10973
10974                 if ( srcPlanes !== null ) {
10975
10976                         const n = srcPlanes.length;
10977                         dstPlanes = new Array( n );
10978
10979                         for ( let i = 0; i !== n; ++ i ) {
10980
10981                                 dstPlanes[ i ] = srcPlanes[ i ].clone();
10982
10983                         }
10984
10985                 }
10986
10987                 this.clippingPlanes = dstPlanes;
10988                 this.clipIntersection = source.clipIntersection;
10989                 this.clipShadows = source.clipShadows;
10990
10991                 this.shadowSide = source.shadowSide;
10992
10993                 this.colorWrite = source.colorWrite;
10994
10995                 this.precision = source.precision;
10996
10997                 this.polygonOffset = source.polygonOffset;
10998                 this.polygonOffsetFactor = source.polygonOffsetFactor;
10999                 this.polygonOffsetUnits = source.polygonOffsetUnits;
11000
11001                 this.dithering = source.dithering;
11002
11003                 this.alphaTest = source.alphaTest;
11004                 this.alphaToCoverage = source.alphaToCoverage;
11005                 this.premultipliedAlpha = source.premultipliedAlpha;
11006
11007                 this.visible = source.visible;
11008
11009                 this.toneMapped = source.toneMapped;
11010
11011                 this.userData = JSON.parse( JSON.stringify( source.userData ) );
11012
11013                 return this;
11014
11015         }
11016
11017         dispose() {
11018
11019                 this.dispatchEvent( { type: 'dispose' } );
11020
11021         }
11022
11023         set needsUpdate( value ) {
11024
11025                 if ( value === true ) this.version ++;
11026
11027         }
11028
11029     }
11030
11031     Material.prototype.isMaterial = true;
11032
11033     const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
11034         'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
11035         'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
11036         'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
11037         'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
11038         'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
11039         'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
11040         'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
11041         'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
11042         'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
11043         'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
11044         'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
11045         'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
11046         'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
11047         'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
11048         'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
11049         'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
11050         'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
11051         'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
11052         'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
11053         'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
11054         'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
11055         'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
11056         'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
11057
11058     const _hslA = { h: 0, s: 0, l: 0 };
11059     const _hslB = { h: 0, s: 0, l: 0 };
11060
11061     function hue2rgb( p, q, t ) {
11062
11063         if ( t < 0 ) t += 1;
11064         if ( t > 1 ) t -= 1;
11065         if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
11066         if ( t < 1 / 2 ) return q;
11067         if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
11068         return p;
11069
11070     }
11071
11072     function SRGBToLinear( c ) {
11073
11074         return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
11075
11076     }
11077
11078     function LinearToSRGB( c ) {
11079
11080         return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
11081
11082     }
11083
11084     class Color {
11085
11086         constructor( r, g, b ) {
11087
11088                 if ( g === undefined && b === undefined ) {
11089
11090                         // r is THREE.Color, hex or string
11091                         return this.set( r );
11092
11093                 }
11094
11095                 return this.setRGB( r, g, b );
11096
11097         }
11098
11099         set( value ) {
11100
11101                 if ( value && value.isColor ) {
11102
11103                         this.copy( value );
11104
11105                 } else if ( typeof value === 'number' ) {
11106
11107                         this.setHex( value );
11108
11109                 } else if ( typeof value === 'string' ) {
11110
11111                         this.setStyle( value );
11112
11113                 }
11114
11115                 return this;
11116
11117         }
11118
11119         setScalar( scalar ) {
11120
11121                 this.r = scalar;
11122                 this.g = scalar;
11123                 this.b = scalar;
11124
11125                 return this;
11126
11127         }
11128
11129         setHex( hex ) {
11130
11131                 hex = Math.floor( hex );
11132
11133                 this.r = ( hex >> 16 & 255 ) / 255;
11134                 this.g = ( hex >> 8 & 255 ) / 255;
11135                 this.b = ( hex & 255 ) / 255;
11136
11137                 return this;
11138
11139         }
11140
11141         setRGB( r, g, b ) {
11142
11143                 this.r = r;
11144                 this.g = g;
11145                 this.b = b;
11146
11147                 return this;
11148
11149         }
11150
11151         setHSL( h, s, l ) {
11152
11153                 // h,s,l ranges are in 0.0 - 1.0
11154                 h = euclideanModulo( h, 1 );
11155                 s = clamp$1( s, 0, 1 );
11156                 l = clamp$1( l, 0, 1 );
11157
11158                 if ( s === 0 ) {
11159
11160                         this.r = this.g = this.b = l;
11161
11162                 } else {
11163
11164                         const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
11165                         const q = ( 2 * l ) - p;
11166
11167                         this.r = hue2rgb( q, p, h + 1 / 3 );
11168                         this.g = hue2rgb( q, p, h );
11169                         this.b = hue2rgb( q, p, h - 1 / 3 );
11170
11171                 }
11172
11173                 return this;
11174
11175         }
11176
11177         setStyle( style ) {
11178
11179                 function handleAlpha( string ) {
11180
11181                         if ( string === undefined ) return;
11182
11183                         if ( parseFloat( string ) < 1 ) {
11184
11185                                 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
11186
11187                         }
11188
11189                 }
11190
11191
11192                 let m;
11193
11194                 if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) {
11195
11196                         // rgb / hsl
11197
11198                         let color;
11199                         const name = m[ 1 ];
11200                         const components = m[ 2 ];
11201
11202                         switch ( name ) {
11203
11204                                 case 'rgb':
11205                                 case 'rgba':
11206
11207                                         if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
11208
11209                                                 // rgb(255,0,0) rgba(255,0,0,0.5)
11210                                                 this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
11211                                                 this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
11212                                                 this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
11213
11214                                                 handleAlpha( color[ 4 ] );
11215
11216                                                 return this;
11217
11218                                         }
11219
11220                                         if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
11221
11222                                                 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
11223                                                 this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
11224                                                 this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
11225                                                 this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
11226
11227                                                 handleAlpha( color[ 4 ] );
11228
11229                                                 return this;
11230
11231                                         }
11232
11233                                         break;
11234
11235                                 case 'hsl':
11236                                 case 'hsla':
11237
11238                                         if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
11239
11240                                                 // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
11241                                                 const h = parseFloat( color[ 1 ] ) / 360;
11242                                                 const s = parseInt( color[ 2 ], 10 ) / 100;
11243                                                 const l = parseInt( color[ 3 ], 10 ) / 100;
11244
11245                                                 handleAlpha( color[ 4 ] );
11246
11247                                                 return this.setHSL( h, s, l );
11248
11249                                         }
11250
11251                                         break;
11252
11253                         }
11254
11255                 } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
11256
11257                         // hex color
11258
11259                         const hex = m[ 1 ];
11260                         const size = hex.length;
11261
11262                         if ( size === 3 ) {
11263
11264                                 // #ff0
11265                                 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
11266                                 this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
11267                                 this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
11268
11269                                 return this;
11270
11271                         } else if ( size === 6 ) {
11272
11273                                 // #ff0000
11274                                 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
11275                                 this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
11276                                 this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
11277
11278                                 return this;
11279
11280                         }
11281
11282                 }
11283
11284                 if ( style && style.length > 0 ) {
11285
11286                         return this.setColorName( style );
11287
11288                 }
11289
11290                 return this;
11291
11292         }
11293
11294         setColorName( style ) {
11295
11296                 // color keywords
11297                 const hex = _colorKeywords[ style.toLowerCase() ];
11298
11299                 if ( hex !== undefined ) {
11300
11301                         // red
11302                         this.setHex( hex );
11303
11304                 } else {
11305
11306                         // unknown color
11307                         console.warn( 'THREE.Color: Unknown color ' + style );
11308
11309                 }
11310
11311                 return this;
11312
11313         }
11314
11315         clone() {
11316
11317                 return new this.constructor( this.r, this.g, this.b );
11318
11319         }
11320
11321         copy( color ) {
11322
11323                 this.r = color.r;
11324                 this.g = color.g;
11325                 this.b = color.b;
11326
11327                 return this;
11328
11329         }
11330
11331         copyGammaToLinear( color, gammaFactor = 2.0 ) {
11332
11333                 this.r = Math.pow( color.r, gammaFactor );
11334                 this.g = Math.pow( color.g, gammaFactor );
11335                 this.b = Math.pow( color.b, gammaFactor );
11336
11337                 return this;
11338
11339         }
11340
11341         copyLinearToGamma( color, gammaFactor = 2.0 ) {
11342
11343                 const safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
11344
11345                 this.r = Math.pow( color.r, safeInverse );
11346                 this.g = Math.pow( color.g, safeInverse );
11347                 this.b = Math.pow( color.b, safeInverse );
11348
11349                 return this;
11350
11351         }
11352
11353         convertGammaToLinear( gammaFactor ) {
11354
11355                 this.copyGammaToLinear( this, gammaFactor );
11356
11357                 return this;
11358
11359         }
11360
11361         convertLinearToGamma( gammaFactor ) {
11362
11363                 this.copyLinearToGamma( this, gammaFactor );
11364
11365                 return this;
11366
11367         }
11368
11369         copySRGBToLinear( color ) {
11370
11371                 this.r = SRGBToLinear( color.r );
11372                 this.g = SRGBToLinear( color.g );
11373                 this.b = SRGBToLinear( color.b );
11374
11375                 return this;
11376
11377         }
11378
11379         copyLinearToSRGB( color ) {
11380
11381                 this.r = LinearToSRGB( color.r );
11382                 this.g = LinearToSRGB( color.g );
11383                 this.b = LinearToSRGB( color.b );
11384
11385                 return this;
11386
11387         }
11388
11389         convertSRGBToLinear() {
11390
11391                 this.copySRGBToLinear( this );
11392
11393                 return this;
11394
11395         }
11396
11397         convertLinearToSRGB() {
11398
11399                 this.copyLinearToSRGB( this );
11400
11401                 return this;
11402
11403         }
11404
11405         getHex() {
11406
11407                 return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
11408
11409         }
11410
11411         getHexString() {
11412
11413                 return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
11414
11415         }
11416
11417         getHSL( target ) {
11418
11419                 // h,s,l ranges are in 0.0 - 1.0
11420
11421                 const r = this.r, g = this.g, b = this.b;
11422
11423                 const max = Math.max( r, g, b );
11424                 const min = Math.min( r, g, b );
11425
11426                 let hue, saturation;
11427                 const lightness = ( min + max ) / 2.0;
11428
11429                 if ( min === max ) {
11430
11431                         hue = 0;
11432                         saturation = 0;
11433
11434                 } else {
11435
11436                         const delta = max - min;
11437
11438                         saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
11439
11440                         switch ( max ) {
11441
11442                                 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
11443                                 case g: hue = ( b - r ) / delta + 2; break;
11444                                 case b: hue = ( r - g ) / delta + 4; break;
11445
11446                         }
11447
11448                         hue /= 6;
11449
11450                 }
11451
11452                 target.h = hue;
11453                 target.s = saturation;
11454                 target.l = lightness;
11455
11456                 return target;
11457
11458         }
11459
11460         getStyle() {
11461
11462                 return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
11463
11464         }
11465
11466         offsetHSL( h, s, l ) {
11467
11468                 this.getHSL( _hslA );
11469
11470                 _hslA.h += h; _hslA.s += s; _hslA.l += l;
11471
11472                 this.setHSL( _hslA.h, _hslA.s, _hslA.l );
11473
11474                 return this;
11475
11476         }
11477
11478         add( color ) {
11479
11480                 this.r += color.r;
11481                 this.g += color.g;
11482                 this.b += color.b;
11483
11484                 return this;
11485
11486         }
11487
11488         addColors( color1, color2 ) {
11489
11490                 this.r = color1.r + color2.r;
11491                 this.g = color1.g + color2.g;
11492                 this.b = color1.b + color2.b;
11493
11494                 return this;
11495
11496         }
11497
11498         addScalar( s ) {
11499
11500                 this.r += s;
11501                 this.g += s;
11502                 this.b += s;
11503
11504                 return this;
11505
11506         }
11507
11508         sub( color ) {
11509
11510                 this.r = Math.max( 0, this.r - color.r );
11511                 this.g = Math.max( 0, this.g - color.g );
11512                 this.b = Math.max( 0, this.b - color.b );
11513
11514                 return this;
11515
11516         }
11517
11518         multiply( color ) {
11519
11520                 this.r *= color.r;
11521                 this.g *= color.g;
11522                 this.b *= color.b;
11523
11524                 return this;
11525
11526         }
11527
11528         multiplyScalar( s ) {
11529
11530                 this.r *= s;
11531                 this.g *= s;
11532                 this.b *= s;
11533
11534                 return this;
11535
11536         }
11537
11538         lerp( color, alpha ) {
11539
11540                 this.r += ( color.r - this.r ) * alpha;
11541                 this.g += ( color.g - this.g ) * alpha;
11542                 this.b += ( color.b - this.b ) * alpha;
11543
11544                 return this;
11545
11546         }
11547
11548         lerpColors( color1, color2, alpha ) {
11549
11550                 this.r = color1.r + ( color2.r - color1.r ) * alpha;
11551                 this.g = color1.g + ( color2.g - color1.g ) * alpha;
11552                 this.b = color1.b + ( color2.b - color1.b ) * alpha;
11553
11554                 return this;
11555
11556         }
11557
11558         lerpHSL( color, alpha ) {
11559
11560                 this.getHSL( _hslA );
11561                 color.getHSL( _hslB );
11562
11563                 const h = lerp( _hslA.h, _hslB.h, alpha );
11564                 const s = lerp( _hslA.s, _hslB.s, alpha );
11565                 const l = lerp( _hslA.l, _hslB.l, alpha );
11566
11567                 this.setHSL( h, s, l );
11568
11569                 return this;
11570
11571         }
11572
11573         equals( c ) {
11574
11575                 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
11576
11577         }
11578
11579         fromArray( array, offset = 0 ) {
11580
11581                 this.r = array[ offset ];
11582                 this.g = array[ offset + 1 ];
11583                 this.b = array[ offset + 2 ];
11584
11585                 return this;
11586
11587         }
11588
11589         toArray( array = [], offset = 0 ) {
11590
11591                 array[ offset ] = this.r;
11592                 array[ offset + 1 ] = this.g;
11593                 array[ offset + 2 ] = this.b;
11594
11595                 return array;
11596
11597         }
11598
11599         fromBufferAttribute( attribute, index ) {
11600
11601                 this.r = attribute.getX( index );
11602                 this.g = attribute.getY( index );
11603                 this.b = attribute.getZ( index );
11604
11605                 if ( attribute.normalized === true ) {
11606
11607                         // assuming Uint8Array
11608
11609                         this.r /= 255;
11610                         this.g /= 255;
11611                         this.b /= 255;
11612
11613                 }
11614
11615                 return this;
11616
11617         }
11618
11619         toJSON() {
11620
11621                 return this.getHex();
11622
11623         }
11624
11625     }
11626
11627     Color.NAMES = _colorKeywords;
11628
11629     Color.prototype.isColor = true;
11630     Color.prototype.r = 1;
11631     Color.prototype.g = 1;
11632     Color.prototype.b = 1;
11633
11634     /**
11635      * parameters = {
11636      *  color: <hex>,
11637      *  opacity: <float>,
11638      *  map: new THREE.Texture( <Image> ),
11639      *
11640      *  lightMap: new THREE.Texture( <Image> ),
11641      *  lightMapIntensity: <float>
11642      *
11643      *  aoMap: new THREE.Texture( <Image> ),
11644      *  aoMapIntensity: <float>
11645      *
11646      *  specularMap: new THREE.Texture( <Image> ),
11647      *
11648      *  alphaMap: new THREE.Texture( <Image> ),
11649      *
11650      *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
11651      *  combine: THREE.Multiply,
11652      *  reflectivity: <float>,
11653      *  refractionRatio: <float>,
11654      *
11655      *  depthTest: <bool>,
11656      *  depthWrite: <bool>,
11657      *
11658      *  wireframe: <boolean>,
11659      *  wireframeLinewidth: <float>,
11660      * }
11661      */
11662
11663     class MeshBasicMaterial extends Material {
11664
11665         constructor( parameters ) {
11666
11667                 super();
11668
11669                 this.type = 'MeshBasicMaterial';
11670
11671                 this.color = new Color( 0xffffff ); // emissive
11672
11673                 this.map = null;
11674
11675                 this.lightMap = null;
11676                 this.lightMapIntensity = 1.0;
11677
11678                 this.aoMap = null;
11679                 this.aoMapIntensity = 1.0;
11680
11681                 this.specularMap = null;
11682
11683                 this.alphaMap = null;
11684
11685                 this.envMap = null;
11686                 this.combine = MultiplyOperation;
11687                 this.reflectivity = 1;
11688                 this.refractionRatio = 0.98;
11689
11690                 this.wireframe = false;
11691                 this.wireframeLinewidth = 1;
11692                 this.wireframeLinecap = 'round';
11693                 this.wireframeLinejoin = 'round';
11694
11695                 this.setValues( parameters );
11696
11697         }
11698
11699         copy( source ) {
11700
11701                 super.copy( source );
11702
11703                 this.color.copy( source.color );
11704
11705                 this.map = source.map;
11706
11707                 this.lightMap = source.lightMap;
11708                 this.lightMapIntensity = source.lightMapIntensity;
11709
11710                 this.aoMap = source.aoMap;
11711                 this.aoMapIntensity = source.aoMapIntensity;
11712
11713                 this.specularMap = source.specularMap;
11714
11715                 this.alphaMap = source.alphaMap;
11716
11717                 this.envMap = source.envMap;
11718                 this.combine = source.combine;
11719                 this.reflectivity = source.reflectivity;
11720                 this.refractionRatio = source.refractionRatio;
11721
11722                 this.wireframe = source.wireframe;
11723                 this.wireframeLinewidth = source.wireframeLinewidth;
11724                 this.wireframeLinecap = source.wireframeLinecap;
11725                 this.wireframeLinejoin = source.wireframeLinejoin;
11726
11727                 return this;
11728
11729         }
11730
11731     }
11732
11733     MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
11734
11735     const _vector$9 = /*@__PURE__*/ new Vector3();
11736     const _vector2$1 = /*@__PURE__*/ new Vector2();
11737
11738     class BufferAttribute {
11739
11740         constructor( array, itemSize, normalized ) {
11741
11742                 if ( Array.isArray( array ) ) {
11743
11744                         throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
11745
11746                 }
11747
11748                 this.name = '';
11749
11750                 this.array = array;
11751                 this.itemSize = itemSize;
11752                 this.count = array !== undefined ? array.length / itemSize : 0;
11753                 this.normalized = normalized === true;
11754
11755                 this.usage = StaticDrawUsage;
11756                 this.updateRange = { offset: 0, count: - 1 };
11757
11758                 this.version = 0;
11759
11760         }
11761
11762         onUploadCallback() {}
11763
11764         set needsUpdate( value ) {
11765
11766                 if ( value === true ) this.version ++;
11767
11768         }
11769
11770         setUsage( value ) {
11771
11772                 this.usage = value;
11773
11774                 return this;
11775
11776         }
11777
11778         copy( source ) {
11779
11780                 this.name = source.name;
11781                 this.array = new source.array.constructor( source.array );
11782                 this.itemSize = source.itemSize;
11783                 this.count = source.count;
11784                 this.normalized = source.normalized;
11785
11786                 this.usage = source.usage;
11787
11788                 return this;
11789
11790         }
11791
11792         copyAt( index1, attribute, index2 ) {
11793
11794                 index1 *= this.itemSize;
11795                 index2 *= attribute.itemSize;
11796
11797                 for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
11798
11799                         this.array[ index1 + i ] = attribute.array[ index2 + i ];
11800
11801                 }
11802
11803                 return this;
11804
11805         }
11806
11807         copyArray( array ) {
11808
11809                 this.array.set( array );
11810
11811                 return this;
11812
11813         }
11814
11815         copyColorsArray( colors ) {
11816
11817                 const array = this.array;
11818                 let offset = 0;
11819
11820                 for ( let i = 0, l = colors.length; i < l; i ++ ) {
11821
11822                         let color = colors[ i ];
11823
11824                         if ( color === undefined ) {
11825
11826                                 console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
11827                                 color = new Color();
11828
11829                         }
11830
11831                         array[ offset ++ ] = color.r;
11832                         array[ offset ++ ] = color.g;
11833                         array[ offset ++ ] = color.b;
11834
11835                 }
11836
11837                 return this;
11838
11839         }
11840
11841         copyVector2sArray( vectors ) {
11842
11843                 const array = this.array;
11844                 let offset = 0;
11845
11846                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
11847
11848                         let vector = vectors[ i ];
11849
11850                         if ( vector === undefined ) {
11851
11852                                 console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
11853                                 vector = new Vector2();
11854
11855                         }
11856
11857                         array[ offset ++ ] = vector.x;
11858                         array[ offset ++ ] = vector.y;
11859
11860                 }
11861
11862                 return this;
11863
11864         }
11865
11866         copyVector3sArray( vectors ) {
11867
11868                 const array = this.array;
11869                 let offset = 0;
11870
11871                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
11872
11873                         let vector = vectors[ i ];
11874
11875                         if ( vector === undefined ) {
11876
11877                                 console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
11878                                 vector = new Vector3();
11879
11880                         }
11881
11882                         array[ offset ++ ] = vector.x;
11883                         array[ offset ++ ] = vector.y;
11884                         array[ offset ++ ] = vector.z;
11885
11886                 }
11887
11888                 return this;
11889
11890         }
11891
11892         copyVector4sArray( vectors ) {
11893
11894                 const array = this.array;
11895                 let offset = 0;
11896
11897                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
11898
11899                         let vector = vectors[ i ];
11900
11901                         if ( vector === undefined ) {
11902
11903                                 console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
11904                                 vector = new Vector4();
11905
11906                         }
11907
11908                         array[ offset ++ ] = vector.x;
11909                         array[ offset ++ ] = vector.y;
11910                         array[ offset ++ ] = vector.z;
11911                         array[ offset ++ ] = vector.w;
11912
11913                 }
11914
11915                 return this;
11916
11917         }
11918
11919         applyMatrix3( m ) {
11920
11921                 if ( this.itemSize === 2 ) {
11922
11923                         for ( let i = 0, l = this.count; i < l; i ++ ) {
11924
11925                                 _vector2$1.fromBufferAttribute( this, i );
11926                                 _vector2$1.applyMatrix3( m );
11927
11928                                 this.setXY( i, _vector2$1.x, _vector2$1.y );
11929
11930                         }
11931
11932                 } else if ( this.itemSize === 3 ) {
11933
11934                         for ( let i = 0, l = this.count; i < l; i ++ ) {
11935
11936                                 _vector$9.fromBufferAttribute( this, i );
11937                                 _vector$9.applyMatrix3( m );
11938
11939                                 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
11940
11941                         }
11942
11943                 }
11944
11945                 return this;
11946
11947         }
11948
11949         applyMatrix4( m ) {
11950
11951                 for ( let i = 0, l = this.count; i < l; i ++ ) {
11952
11953                         _vector$9.x = this.getX( i );
11954                         _vector$9.y = this.getY( i );
11955                         _vector$9.z = this.getZ( i );
11956
11957                         _vector$9.applyMatrix4( m );
11958
11959                         this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
11960
11961                 }
11962
11963                 return this;
11964
11965         }
11966
11967         applyNormalMatrix( m ) {
11968
11969                 for ( let i = 0, l = this.count; i < l; i ++ ) {
11970
11971                         _vector$9.x = this.getX( i );
11972                         _vector$9.y = this.getY( i );
11973                         _vector$9.z = this.getZ( i );
11974
11975                         _vector$9.applyNormalMatrix( m );
11976
11977                         this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
11978
11979                 }
11980
11981                 return this;
11982
11983         }
11984
11985         transformDirection( m ) {
11986
11987                 for ( let i = 0, l = this.count; i < l; i ++ ) {
11988
11989                         _vector$9.x = this.getX( i );
11990                         _vector$9.y = this.getY( i );
11991                         _vector$9.z = this.getZ( i );
11992
11993                         _vector$9.transformDirection( m );
11994
11995                         this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
11996
11997                 }
11998
11999                 return this;
12000
12001         }
12002
12003         set( value, offset = 0 ) {
12004
12005                 this.array.set( value, offset );
12006
12007                 return this;
12008
12009         }
12010
12011         getX( index ) {
12012
12013                 return this.array[ index * this.itemSize ];
12014
12015         }
12016
12017         setX( index, x ) {
12018
12019                 this.array[ index * this.itemSize ] = x;
12020
12021                 return this;
12022
12023         }
12024
12025         getY( index ) {
12026
12027                 return this.array[ index * this.itemSize + 1 ];
12028
12029         }
12030
12031         setY( index, y ) {
12032
12033                 this.array[ index * this.itemSize + 1 ] = y;
12034
12035                 return this;
12036
12037         }
12038
12039         getZ( index ) {
12040
12041                 return this.array[ index * this.itemSize + 2 ];
12042
12043         }
12044
12045         setZ( index, z ) {
12046
12047                 this.array[ index * this.itemSize + 2 ] = z;
12048
12049                 return this;
12050
12051         }
12052
12053         getW( index ) {
12054
12055                 return this.array[ index * this.itemSize + 3 ];
12056
12057         }
12058
12059         setW( index, w ) {
12060
12061                 this.array[ index * this.itemSize + 3 ] = w;
12062
12063                 return this;
12064
12065         }
12066
12067         setXY( index, x, y ) {
12068
12069                 index *= this.itemSize;
12070
12071                 this.array[ index + 0 ] = x;
12072                 this.array[ index + 1 ] = y;
12073
12074                 return this;
12075
12076         }
12077
12078         setXYZ( index, x, y, z ) {
12079
12080                 index *= this.itemSize;
12081
12082                 this.array[ index + 0 ] = x;
12083                 this.array[ index + 1 ] = y;
12084                 this.array[ index + 2 ] = z;
12085
12086                 return this;
12087
12088         }
12089
12090         setXYZW( index, x, y, z, w ) {
12091
12092                 index *= this.itemSize;
12093
12094                 this.array[ index + 0 ] = x;
12095                 this.array[ index + 1 ] = y;
12096                 this.array[ index + 2 ] = z;
12097                 this.array[ index + 3 ] = w;
12098
12099                 return this;
12100
12101         }
12102
12103         onUpload( callback ) {
12104
12105                 this.onUploadCallback = callback;
12106
12107                 return this;
12108
12109         }
12110
12111         clone() {
12112
12113                 return new this.constructor( this.array, this.itemSize ).copy( this );
12114
12115         }
12116
12117         toJSON() {
12118
12119                 const data = {
12120                         itemSize: this.itemSize,
12121                         type: this.array.constructor.name,
12122                         array: Array.prototype.slice.call( this.array ),
12123                         normalized: this.normalized
12124                 };
12125
12126                 if ( this.name !== '' ) data.name = this.name;
12127                 if ( this.usage !== StaticDrawUsage ) data.usage = this.usage;
12128                 if ( this.updateRange.offset !== 0 || this.updateRange.count !== - 1 ) data.updateRange = this.updateRange;
12129
12130                 return data;
12131
12132         }
12133
12134     }
12135
12136     BufferAttribute.prototype.isBufferAttribute = true;
12137
12138     class Uint16BufferAttribute extends BufferAttribute {
12139
12140         constructor( array, itemSize, normalized ) {
12141
12142                 super( new Uint16Array( array ), itemSize, normalized );
12143
12144         }
12145
12146     }
12147
12148     class Uint32BufferAttribute extends BufferAttribute {
12149
12150         constructor( array, itemSize, normalized ) {
12151
12152                 super( new Uint32Array( array ), itemSize, normalized );
12153
12154         }
12155
12156     }
12157
12158     class Float16BufferAttribute extends BufferAttribute {
12159
12160         constructor( array, itemSize, normalized ) {
12161
12162                 super( new Uint16Array( array ), itemSize, normalized );
12163
12164         }
12165
12166     }
12167
12168     Float16BufferAttribute.prototype.isFloat16BufferAttribute = true;
12169
12170     class Float32BufferAttribute extends BufferAttribute {
12171
12172         constructor( array, itemSize, normalized ) {
12173
12174                 super( new Float32Array( array ), itemSize, normalized );
12175
12176         }
12177
12178     }
12179
12180     let _id = 0;
12181
12182     const _m1 = /*@__PURE__*/ new Matrix4();
12183     const _obj = /*@__PURE__*/ new Object3D();
12184     const _offset = /*@__PURE__*/ new Vector3();
12185     const _box$1 = /*@__PURE__*/ new Box3();
12186     const _boxMorphTargets = /*@__PURE__*/ new Box3();
12187     const _vector$8 = /*@__PURE__*/ new Vector3();
12188
12189     class BufferGeometry extends EventDispatcher {
12190
12191         constructor() {
12192
12193                 super();
12194
12195                 Object.defineProperty( this, 'id', { value: _id ++ } );
12196
12197                 this.uuid = generateUUID();
12198
12199                 this.name = '';
12200                 this.type = 'BufferGeometry';
12201
12202                 this.index = null;
12203                 this.attributes = {};
12204
12205                 this.morphAttributes = {};
12206                 this.morphTargetsRelative = false;
12207
12208                 this.groups = [];
12209
12210                 this.boundingBox = null;
12211                 this.boundingSphere = null;
12212
12213                 this.drawRange = { start: 0, count: Infinity };
12214
12215                 this.userData = {};
12216
12217         }
12218
12219         getIndex() {
12220
12221                 return this.index;
12222
12223         }
12224
12225         setIndex( index ) {
12226
12227                 if ( Array.isArray( index ) ) {
12228
12229                         this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
12230
12231                 } else {
12232
12233                         this.index = index;
12234
12235                 }
12236
12237                 return this;
12238
12239         }
12240
12241         getAttribute( name ) {
12242
12243                 return this.attributes[ name ];
12244
12245         }
12246
12247         setAttribute( name, attribute ) {
12248
12249                 this.attributes[ name ] = attribute;
12250
12251                 return this;
12252
12253         }
12254
12255         deleteAttribute( name ) {
12256
12257                 delete this.attributes[ name ];
12258
12259                 return this;
12260
12261         }
12262
12263         hasAttribute( name ) {
12264
12265                 return this.attributes[ name ] !== undefined;
12266
12267         }
12268
12269         addGroup( start, count, materialIndex = 0 ) {
12270
12271                 this.groups.push( {
12272
12273                         start: start,
12274                         count: count,
12275                         materialIndex: materialIndex
12276
12277                 } );
12278
12279         }
12280
12281         clearGroups() {
12282
12283                 this.groups = [];
12284
12285         }
12286
12287         setDrawRange( start, count ) {
12288
12289                 this.drawRange.start = start;
12290                 this.drawRange.count = count;
12291
12292         }
12293
12294         applyMatrix4( matrix ) {
12295
12296                 const position = this.attributes.position;
12297
12298                 if ( position !== undefined ) {
12299
12300                         position.applyMatrix4( matrix );
12301
12302                         position.needsUpdate = true;
12303
12304                 }
12305
12306                 const normal = this.attributes.normal;
12307
12308                 if ( normal !== undefined ) {
12309
12310                         const normalMatrix = new Matrix3().getNormalMatrix( matrix );
12311
12312                         normal.applyNormalMatrix( normalMatrix );
12313
12314                         normal.needsUpdate = true;
12315
12316                 }
12317
12318                 const tangent = this.attributes.tangent;
12319
12320                 if ( tangent !== undefined ) {
12321
12322                         tangent.transformDirection( matrix );
12323
12324                         tangent.needsUpdate = true;
12325
12326                 }
12327
12328                 if ( this.boundingBox !== null ) {
12329
12330                         this.computeBoundingBox();
12331
12332                 }
12333
12334                 if ( this.boundingSphere !== null ) {
12335
12336                         this.computeBoundingSphere();
12337
12338                 }
12339
12340                 return this;
12341
12342         }
12343
12344         applyQuaternion( q ) {
12345
12346                 _m1.makeRotationFromQuaternion( q );
12347
12348                 this.applyMatrix4( _m1 );
12349
12350                 return this;
12351
12352         }
12353
12354         rotateX( angle ) {
12355
12356                 // rotate geometry around world x-axis
12357
12358                 _m1.makeRotationX( angle );
12359
12360                 this.applyMatrix4( _m1 );
12361
12362                 return this;
12363
12364         }
12365
12366         rotateY( angle ) {
12367
12368                 // rotate geometry around world y-axis
12369
12370                 _m1.makeRotationY( angle );
12371
12372                 this.applyMatrix4( _m1 );
12373
12374                 return this;
12375
12376         }
12377
12378         rotateZ( angle ) {
12379
12380                 // rotate geometry around world z-axis
12381
12382                 _m1.makeRotationZ( angle );
12383
12384                 this.applyMatrix4( _m1 );
12385
12386                 return this;
12387
12388         }
12389
12390         translate( x, y, z ) {
12391
12392                 // translate geometry
12393
12394                 _m1.makeTranslation( x, y, z );
12395
12396                 this.applyMatrix4( _m1 );
12397
12398                 return this;
12399
12400         }
12401
12402         scale( x, y, z ) {
12403
12404                 // scale geometry
12405
12406                 _m1.makeScale( x, y, z );
12407
12408                 this.applyMatrix4( _m1 );
12409
12410                 return this;
12411
12412         }
12413
12414         lookAt( vector ) {
12415
12416                 _obj.lookAt( vector );
12417
12418                 _obj.updateMatrix();
12419
12420                 this.applyMatrix4( _obj.matrix );
12421
12422                 return this;
12423
12424         }
12425
12426         center() {
12427
12428                 this.computeBoundingBox();
12429
12430                 this.boundingBox.getCenter( _offset ).negate();
12431
12432                 this.translate( _offset.x, _offset.y, _offset.z );
12433
12434                 return this;
12435
12436         }
12437
12438         setFromPoints( points ) {
12439
12440                 const position = [];
12441
12442                 for ( let i = 0, l = points.length; i < l; i ++ ) {
12443
12444                         const point = points[ i ];
12445                         position.push( point.x, point.y, point.z || 0 );
12446
12447                 }
12448
12449                 this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
12450
12451                 return this;
12452
12453         }
12454
12455         computeBoundingBox() {
12456
12457                 if ( this.boundingBox === null ) {
12458
12459                         this.boundingBox = new Box3();
12460
12461                 }
12462
12463                 const position = this.attributes.position;
12464                 const morphAttributesPosition = this.morphAttributes.position;
12465
12466                 if ( position && position.isGLBufferAttribute ) {
12467
12468                         console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this );
12469
12470                         this.boundingBox.set(
12471                                 new Vector3( - Infinity, - Infinity, - Infinity ),
12472                                 new Vector3( + Infinity, + Infinity, + Infinity )
12473                         );
12474
12475                         return;
12476
12477                 }
12478
12479                 if ( position !== undefined ) {
12480
12481                         this.boundingBox.setFromBufferAttribute( position );
12482
12483                         // process morph attributes if present
12484
12485                         if ( morphAttributesPosition ) {
12486
12487                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
12488
12489                                         const morphAttribute = morphAttributesPosition[ i ];
12490                                         _box$1.setFromBufferAttribute( morphAttribute );
12491
12492                                         if ( this.morphTargetsRelative ) {
12493
12494                                                 _vector$8.addVectors( this.boundingBox.min, _box$1.min );
12495                                                 this.boundingBox.expandByPoint( _vector$8 );
12496
12497                                                 _vector$8.addVectors( this.boundingBox.max, _box$1.max );
12498                                                 this.boundingBox.expandByPoint( _vector$8 );
12499
12500                                         } else {
12501
12502                                                 this.boundingBox.expandByPoint( _box$1.min );
12503                                                 this.boundingBox.expandByPoint( _box$1.max );
12504
12505                                         }
12506
12507                                 }
12508
12509                         }
12510
12511                 } else {
12512
12513                         this.boundingBox.makeEmpty();
12514
12515                 }
12516
12517                 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
12518
12519                         console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
12520
12521                 }
12522
12523         }
12524
12525         computeBoundingSphere() {
12526
12527                 if ( this.boundingSphere === null ) {
12528
12529                         this.boundingSphere = new Sphere();
12530
12531                 }
12532
12533                 const position = this.attributes.position;
12534                 const morphAttributesPosition = this.morphAttributes.position;
12535
12536                 if ( position && position.isGLBufferAttribute ) {
12537
12538                         console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this );
12539
12540                         this.boundingSphere.set( new Vector3(), Infinity );
12541
12542                         return;
12543
12544                 }
12545
12546                 if ( position ) {
12547
12548                         // first, find the center of the bounding sphere
12549
12550                         const center = this.boundingSphere.center;
12551
12552                         _box$1.setFromBufferAttribute( position );
12553
12554                         // process morph attributes if present
12555
12556                         if ( morphAttributesPosition ) {
12557
12558                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
12559
12560                                         const morphAttribute = morphAttributesPosition[ i ];
12561                                         _boxMorphTargets.setFromBufferAttribute( morphAttribute );
12562
12563                                         if ( this.morphTargetsRelative ) {
12564
12565                                                 _vector$8.addVectors( _box$1.min, _boxMorphTargets.min );
12566                                                 _box$1.expandByPoint( _vector$8 );
12567
12568                                                 _vector$8.addVectors( _box$1.max, _boxMorphTargets.max );
12569                                                 _box$1.expandByPoint( _vector$8 );
12570
12571                                         } else {
12572
12573                                                 _box$1.expandByPoint( _boxMorphTargets.min );
12574                                                 _box$1.expandByPoint( _boxMorphTargets.max );
12575
12576                                         }
12577
12578                                 }
12579
12580                         }
12581
12582                         _box$1.getCenter( center );
12583
12584                         // second, try to find a boundingSphere with a radius smaller than the
12585                         // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
12586
12587                         let maxRadiusSq = 0;
12588
12589                         for ( let i = 0, il = position.count; i < il; i ++ ) {
12590
12591                                 _vector$8.fromBufferAttribute( position, i );
12592
12593                                 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
12594
12595                         }
12596
12597                         // process morph attributes if present
12598
12599                         if ( morphAttributesPosition ) {
12600
12601                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
12602
12603                                         const morphAttribute = morphAttributesPosition[ i ];
12604                                         const morphTargetsRelative = this.morphTargetsRelative;
12605
12606                                         for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
12607
12608                                                 _vector$8.fromBufferAttribute( morphAttribute, j );
12609
12610                                                 if ( morphTargetsRelative ) {
12611
12612                                                         _offset.fromBufferAttribute( position, j );
12613                                                         _vector$8.add( _offset );
12614
12615                                                 }
12616
12617                                                 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
12618
12619                                         }
12620
12621                                 }
12622
12623                         }
12624
12625                         this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
12626
12627                         if ( isNaN( this.boundingSphere.radius ) ) {
12628
12629                                 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
12630
12631                         }
12632
12633                 }
12634
12635         }
12636
12637         computeTangents() {
12638
12639                 const index = this.index;
12640                 const attributes = this.attributes;
12641
12642                 // based on http://www.terathon.com/code/tangent.html
12643                 // (per vertex tangents)
12644
12645                 if ( index === null ||
12646                          attributes.position === undefined ||
12647                          attributes.normal === undefined ||
12648                          attributes.uv === undefined ) {
12649
12650                         console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
12651                         return;
12652
12653                 }
12654
12655                 const indices = index.array;
12656                 const positions = attributes.position.array;
12657                 const normals = attributes.normal.array;
12658                 const uvs = attributes.uv.array;
12659
12660                 const nVertices = positions.length / 3;
12661
12662                 if ( attributes.tangent === undefined ) {
12663
12664                         this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
12665
12666                 }
12667
12668                 const tangents = attributes.tangent.array;
12669
12670                 const tan1 = [], tan2 = [];
12671
12672                 for ( let i = 0; i < nVertices; i ++ ) {
12673
12674                         tan1[ i ] = new Vector3();
12675                         tan2[ i ] = new Vector3();
12676
12677                 }
12678
12679                 const vA = new Vector3(),
12680                         vB = new Vector3(),
12681                         vC = new Vector3(),
12682
12683                         uvA = new Vector2(),
12684                         uvB = new Vector2(),
12685                         uvC = new Vector2(),
12686
12687                         sdir = new Vector3(),
12688                         tdir = new Vector3();
12689
12690                 function handleTriangle( a, b, c ) {
12691
12692                         vA.fromArray( positions, a * 3 );
12693                         vB.fromArray( positions, b * 3 );
12694                         vC.fromArray( positions, c * 3 );
12695
12696                         uvA.fromArray( uvs, a * 2 );
12697                         uvB.fromArray( uvs, b * 2 );
12698                         uvC.fromArray( uvs, c * 2 );
12699
12700                         vB.sub( vA );
12701                         vC.sub( vA );
12702
12703                         uvB.sub( uvA );
12704                         uvC.sub( uvA );
12705
12706                         const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
12707
12708                         // silently ignore degenerate uv triangles having coincident or colinear vertices
12709
12710                         if ( ! isFinite( r ) ) return;
12711
12712                         sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
12713                         tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
12714
12715                         tan1[ a ].add( sdir );
12716                         tan1[ b ].add( sdir );
12717                         tan1[ c ].add( sdir );
12718
12719                         tan2[ a ].add( tdir );
12720                         tan2[ b ].add( tdir );
12721                         tan2[ c ].add( tdir );
12722
12723                 }
12724
12725                 let groups = this.groups;
12726
12727                 if ( groups.length === 0 ) {
12728
12729                         groups = [ {
12730                                 start: 0,
12731                                 count: indices.length
12732                         } ];
12733
12734                 }
12735
12736                 for ( let i = 0, il = groups.length; i < il; ++ i ) {
12737
12738                         const group = groups[ i ];
12739
12740                         const start = group.start;
12741                         const count = group.count;
12742
12743                         for ( let j = start, jl = start + count; j < jl; j += 3 ) {
12744
12745                                 handleTriangle(
12746                                         indices[ j + 0 ],
12747                                         indices[ j + 1 ],
12748                                         indices[ j + 2 ]
12749                                 );
12750
12751                         }
12752
12753                 }
12754
12755                 const tmp = new Vector3(), tmp2 = new Vector3();
12756                 const n = new Vector3(), n2 = new Vector3();
12757
12758                 function handleVertex( v ) {
12759
12760                         n.fromArray( normals, v * 3 );
12761                         n2.copy( n );
12762
12763                         const t = tan1[ v ];
12764
12765                         // Gram-Schmidt orthogonalize
12766
12767                         tmp.copy( t );
12768                         tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
12769
12770                         // Calculate handedness
12771
12772                         tmp2.crossVectors( n2, t );
12773                         const test = tmp2.dot( tan2[ v ] );
12774                         const w = ( test < 0.0 ) ? - 1.0 : 1.0;
12775
12776                         tangents[ v * 4 ] = tmp.x;
12777                         tangents[ v * 4 + 1 ] = tmp.y;
12778                         tangents[ v * 4 + 2 ] = tmp.z;
12779                         tangents[ v * 4 + 3 ] = w;
12780
12781                 }
12782
12783                 for ( let i = 0, il = groups.length; i < il; ++ i ) {
12784
12785                         const group = groups[ i ];
12786
12787                         const start = group.start;
12788                         const count = group.count;
12789
12790                         for ( let j = start, jl = start + count; j < jl; j += 3 ) {
12791
12792                                 handleVertex( indices[ j + 0 ] );
12793                                 handleVertex( indices[ j + 1 ] );
12794                                 handleVertex( indices[ j + 2 ] );
12795
12796                         }
12797
12798                 }
12799
12800         }
12801
12802         computeVertexNormals() {
12803
12804                 const index = this.index;
12805                 const positionAttribute = this.getAttribute( 'position' );
12806
12807                 if ( positionAttribute !== undefined ) {
12808
12809                         let normalAttribute = this.getAttribute( 'normal' );
12810
12811                         if ( normalAttribute === undefined ) {
12812
12813                                 normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
12814                                 this.setAttribute( 'normal', normalAttribute );
12815
12816                         } else {
12817
12818                                 // reset existing normals to zero
12819
12820                                 for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
12821
12822                                         normalAttribute.setXYZ( i, 0, 0, 0 );
12823
12824                                 }
12825
12826                         }
12827
12828                         const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
12829                         const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
12830                         const cb = new Vector3(), ab = new Vector3();
12831
12832                         // indexed elements
12833
12834                         if ( index ) {
12835
12836                                 for ( let i = 0, il = index.count; i < il; i += 3 ) {
12837
12838                                         const vA = index.getX( i + 0 );
12839                                         const vB = index.getX( i + 1 );
12840                                         const vC = index.getX( i + 2 );
12841
12842                                         pA.fromBufferAttribute( positionAttribute, vA );
12843                                         pB.fromBufferAttribute( positionAttribute, vB );
12844                                         pC.fromBufferAttribute( positionAttribute, vC );
12845
12846                                         cb.subVectors( pC, pB );
12847                                         ab.subVectors( pA, pB );
12848                                         cb.cross( ab );
12849
12850                                         nA.fromBufferAttribute( normalAttribute, vA );
12851                                         nB.fromBufferAttribute( normalAttribute, vB );
12852                                         nC.fromBufferAttribute( normalAttribute, vC );
12853
12854                                         nA.add( cb );
12855                                         nB.add( cb );
12856                                         nC.add( cb );
12857
12858                                         normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
12859                                         normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
12860                                         normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
12861
12862                                 }
12863
12864                         } else {
12865
12866                                 // non-indexed elements (unconnected triangle soup)
12867
12868                                 for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
12869
12870                                         pA.fromBufferAttribute( positionAttribute, i + 0 );
12871                                         pB.fromBufferAttribute( positionAttribute, i + 1 );
12872                                         pC.fromBufferAttribute( positionAttribute, i + 2 );
12873
12874                                         cb.subVectors( pC, pB );
12875                                         ab.subVectors( pA, pB );
12876                                         cb.cross( ab );
12877
12878                                         normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
12879                                         normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
12880                                         normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
12881
12882                                 }
12883
12884                         }
12885
12886                         this.normalizeNormals();
12887
12888                         normalAttribute.needsUpdate = true;
12889
12890                 }
12891
12892         }
12893
12894         merge( geometry, offset ) {
12895
12896                 if ( ! ( geometry && geometry.isBufferGeometry ) ) {
12897
12898                         console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
12899                         return;
12900
12901                 }
12902
12903                 if ( offset === undefined ) {
12904
12905                         offset = 0;
12906
12907                         console.warn(
12908                                 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
12909                                 + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
12910                         );
12911
12912                 }
12913
12914                 const attributes = this.attributes;
12915
12916                 for ( const key in attributes ) {
12917
12918                         if ( geometry.attributes[ key ] === undefined ) continue;
12919
12920                         const attribute1 = attributes[ key ];
12921                         const attributeArray1 = attribute1.array;
12922
12923                         const attribute2 = geometry.attributes[ key ];
12924                         const attributeArray2 = attribute2.array;
12925
12926                         const attributeOffset = attribute2.itemSize * offset;
12927                         const length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );
12928
12929                         for ( let i = 0, j = attributeOffset; i < length; i ++, j ++ ) {
12930
12931                                 attributeArray1[ j ] = attributeArray2[ i ];
12932
12933                         }
12934
12935                 }
12936
12937                 return this;
12938
12939         }
12940
12941         normalizeNormals() {
12942
12943                 const normals = this.attributes.normal;
12944
12945                 for ( let i = 0, il = normals.count; i < il; i ++ ) {
12946
12947                         _vector$8.fromBufferAttribute( normals, i );
12948
12949                         _vector$8.normalize();
12950
12951                         normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
12952
12953                 }
12954
12955         }
12956
12957         toNonIndexed() {
12958
12959                 function convertBufferAttribute( attribute, indices ) {
12960
12961                         const array = attribute.array;
12962                         const itemSize = attribute.itemSize;
12963                         const normalized = attribute.normalized;
12964
12965                         const array2 = new array.constructor( indices.length * itemSize );
12966
12967                         let index = 0, index2 = 0;
12968
12969                         for ( let i = 0, l = indices.length; i < l; i ++ ) {
12970
12971                                 if ( attribute.isInterleavedBufferAttribute ) {
12972
12973                                         index = indices[ i ] * attribute.data.stride + attribute.offset;
12974
12975                                 } else {
12976
12977                                         index = indices[ i ] * itemSize;
12978
12979                                 }
12980
12981                                 for ( let j = 0; j < itemSize; j ++ ) {
12982
12983                                         array2[ index2 ++ ] = array[ index ++ ];
12984
12985                                 }
12986
12987                         }
12988
12989                         return new BufferAttribute( array2, itemSize, normalized );
12990
12991                 }
12992
12993                 //
12994
12995                 if ( this.index === null ) {
12996
12997                         console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
12998                         return this;
12999
13000                 }
13001
13002                 const geometry2 = new BufferGeometry();
13003
13004                 const indices = this.index.array;
13005                 const attributes = this.attributes;
13006
13007                 // attributes
13008
13009                 for ( const name in attributes ) {
13010
13011                         const attribute = attributes[ name ];
13012
13013                         const newAttribute = convertBufferAttribute( attribute, indices );
13014
13015                         geometry2.setAttribute( name, newAttribute );
13016
13017                 }
13018
13019                 // morph attributes
13020
13021                 const morphAttributes = this.morphAttributes;
13022
13023                 for ( const name in morphAttributes ) {
13024
13025                         const morphArray = [];
13026                         const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
13027
13028                         for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
13029
13030                                 const attribute = morphAttribute[ i ];
13031
13032                                 const newAttribute = convertBufferAttribute( attribute, indices );
13033
13034                                 morphArray.push( newAttribute );
13035
13036                         }
13037
13038                         geometry2.morphAttributes[ name ] = morphArray;
13039
13040                 }
13041
13042                 geometry2.morphTargetsRelative = this.morphTargetsRelative;
13043
13044                 // groups
13045
13046                 const groups = this.groups;
13047
13048                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
13049
13050                         const group = groups[ i ];
13051                         geometry2.addGroup( group.start, group.count, group.materialIndex );
13052
13053                 }
13054
13055                 return geometry2;
13056
13057         }
13058
13059         toJSON() {
13060
13061                 const data = {
13062                         metadata: {
13063                                 version: 4.5,
13064                                 type: 'BufferGeometry',
13065                                 generator: 'BufferGeometry.toJSON'
13066                         }
13067                 };
13068
13069                 // standard BufferGeometry serialization
13070
13071                 data.uuid = this.uuid;
13072                 data.type = this.type;
13073                 if ( this.name !== '' ) data.name = this.name;
13074                 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
13075
13076                 if ( this.parameters !== undefined ) {
13077
13078                         const parameters = this.parameters;
13079
13080                         for ( const key in parameters ) {
13081
13082                                 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
13083
13084                         }
13085
13086                         return data;
13087
13088                 }
13089
13090                 // for simplicity the code assumes attributes are not shared across geometries, see #15811
13091
13092                 data.data = { attributes: {} };
13093
13094                 const index = this.index;
13095
13096                 if ( index !== null ) {
13097
13098                         data.data.index = {
13099                                 type: index.array.constructor.name,
13100                                 array: Array.prototype.slice.call( index.array )
13101                         };
13102
13103                 }
13104
13105                 const attributes = this.attributes;
13106
13107                 for ( const key in attributes ) {
13108
13109                         const attribute = attributes[ key ];
13110
13111                         data.data.attributes[ key ] = attribute.toJSON( data.data );
13112
13113                 }
13114
13115                 const morphAttributes = {};
13116                 let hasMorphAttributes = false;
13117
13118                 for ( const key in this.morphAttributes ) {
13119
13120                         const attributeArray = this.morphAttributes[ key ];
13121
13122                         const array = [];
13123
13124                         for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
13125
13126                                 const attribute = attributeArray[ i ];
13127
13128                                 array.push( attribute.toJSON( data.data ) );
13129
13130                         }
13131
13132                         if ( array.length > 0 ) {
13133
13134                                 morphAttributes[ key ] = array;
13135
13136                                 hasMorphAttributes = true;
13137
13138                         }
13139
13140                 }
13141
13142                 if ( hasMorphAttributes ) {
13143
13144                         data.data.morphAttributes = morphAttributes;
13145                         data.data.morphTargetsRelative = this.morphTargetsRelative;
13146
13147                 }
13148
13149                 const groups = this.groups;
13150
13151                 if ( groups.length > 0 ) {
13152
13153                         data.data.groups = JSON.parse( JSON.stringify( groups ) );
13154
13155                 }
13156
13157                 const boundingSphere = this.boundingSphere;
13158
13159                 if ( boundingSphere !== null ) {
13160
13161                         data.data.boundingSphere = {
13162                                 center: boundingSphere.center.toArray(),
13163                                 radius: boundingSphere.radius
13164                         };
13165
13166                 }
13167
13168                 return data;
13169
13170         }
13171
13172         clone() {
13173
13174                  return new this.constructor().copy( this );
13175
13176         }
13177
13178         copy( source ) {
13179
13180                 // reset
13181
13182                 this.index = null;
13183                 this.attributes = {};
13184                 this.morphAttributes = {};
13185                 this.groups = [];
13186                 this.boundingBox = null;
13187                 this.boundingSphere = null;
13188
13189                 // used for storing cloned, shared data
13190
13191                 const data = {};
13192
13193                 // name
13194
13195                 this.name = source.name;
13196
13197                 // index
13198
13199                 const index = source.index;
13200
13201                 if ( index !== null ) {
13202
13203                         this.setIndex( index.clone( data ) );
13204
13205                 }
13206
13207                 // attributes
13208
13209                 const attributes = source.attributes;
13210
13211                 for ( const name in attributes ) {
13212
13213                         const attribute = attributes[ name ];
13214                         this.setAttribute( name, attribute.clone( data ) );
13215
13216                 }
13217
13218                 // morph attributes
13219
13220                 const morphAttributes = source.morphAttributes;
13221
13222                 for ( const name in morphAttributes ) {
13223
13224                         const array = [];
13225                         const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
13226
13227                         for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
13228
13229                                 array.push( morphAttribute[ i ].clone( data ) );
13230
13231                         }
13232
13233                         this.morphAttributes[ name ] = array;
13234
13235                 }
13236
13237                 this.morphTargetsRelative = source.morphTargetsRelative;
13238
13239                 // groups
13240
13241                 const groups = source.groups;
13242
13243                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
13244
13245                         const group = groups[ i ];
13246                         this.addGroup( group.start, group.count, group.materialIndex );
13247
13248                 }
13249
13250                 // bounding box
13251
13252                 const boundingBox = source.boundingBox;
13253
13254                 if ( boundingBox !== null ) {
13255
13256                         this.boundingBox = boundingBox.clone();
13257
13258                 }
13259
13260                 // bounding sphere
13261
13262                 const boundingSphere = source.boundingSphere;
13263
13264                 if ( boundingSphere !== null ) {
13265
13266                         this.boundingSphere = boundingSphere.clone();
13267
13268                 }
13269
13270                 // draw range
13271
13272                 this.drawRange.start = source.drawRange.start;
13273                 this.drawRange.count = source.drawRange.count;
13274
13275                 // user data
13276
13277                 this.userData = source.userData;
13278
13279                 // geometry generator parameters
13280
13281                 if ( source.parameters !== undefined ) this.parameters = Object.assign( {}, source.parameters );
13282
13283                 return this;
13284
13285         }
13286
13287         dispose() {
13288
13289                 this.dispatchEvent( { type: 'dispose' } );
13290
13291         }
13292
13293     }
13294
13295     BufferGeometry.prototype.isBufferGeometry = true;
13296
13297     const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4();
13298     const _ray$2 = /*@__PURE__*/ new Ray();
13299     const _sphere$3 = /*@__PURE__*/ new Sphere();
13300
13301     const _vA$1 = /*@__PURE__*/ new Vector3();
13302     const _vB$1 = /*@__PURE__*/ new Vector3();
13303     const _vC$1 = /*@__PURE__*/ new Vector3();
13304
13305     const _tempA = /*@__PURE__*/ new Vector3();
13306     const _tempB = /*@__PURE__*/ new Vector3();
13307     const _tempC = /*@__PURE__*/ new Vector3();
13308
13309     const _morphA = /*@__PURE__*/ new Vector3();
13310     const _morphB = /*@__PURE__*/ new Vector3();
13311     const _morphC = /*@__PURE__*/ new Vector3();
13312
13313     const _uvA$1 = /*@__PURE__*/ new Vector2();
13314     const _uvB$1 = /*@__PURE__*/ new Vector2();
13315     const _uvC$1 = /*@__PURE__*/ new Vector2();
13316
13317     const _intersectionPoint = /*@__PURE__*/ new Vector3();
13318     const _intersectionPointWorld = /*@__PURE__*/ new Vector3();
13319
13320     class Mesh extends Object3D {
13321
13322         constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
13323
13324                 super();
13325
13326                 this.type = 'Mesh';
13327
13328                 this.geometry = geometry;
13329                 this.material = material;
13330
13331                 this.updateMorphTargets();
13332
13333         }
13334
13335         copy( source ) {
13336
13337                 super.copy( source );
13338
13339                 if ( source.morphTargetInfluences !== undefined ) {
13340
13341                         this.morphTargetInfluences = source.morphTargetInfluences.slice();
13342
13343                 }
13344
13345                 if ( source.morphTargetDictionary !== undefined ) {
13346
13347                         this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
13348
13349                 }
13350
13351                 this.material = source.material;
13352                 this.geometry = source.geometry;
13353
13354                 return this;
13355
13356         }
13357
13358         updateMorphTargets() {
13359
13360                 const geometry = this.geometry;
13361
13362                 if ( geometry.isBufferGeometry ) {
13363
13364                         const morphAttributes = geometry.morphAttributes;
13365                         const keys = Object.keys( morphAttributes );
13366
13367                         if ( keys.length > 0 ) {
13368
13369                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
13370
13371                                 if ( morphAttribute !== undefined ) {
13372
13373                                         this.morphTargetInfluences = [];
13374                                         this.morphTargetDictionary = {};
13375
13376                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
13377
13378                                                 const name = morphAttribute[ m ].name || String( m );
13379
13380                                                 this.morphTargetInfluences.push( 0 );
13381                                                 this.morphTargetDictionary[ name ] = m;
13382
13383                                         }
13384
13385                                 }
13386
13387                         }
13388
13389                 } else {
13390
13391                         const morphTargets = geometry.morphTargets;
13392
13393                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
13394
13395                                 console.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
13396
13397                         }
13398
13399                 }
13400
13401         }
13402
13403         raycast( raycaster, intersects ) {
13404
13405                 const geometry = this.geometry;
13406                 const material = this.material;
13407                 const matrixWorld = this.matrixWorld;
13408
13409                 if ( material === undefined ) return;
13410
13411                 // Checking boundingSphere distance to ray
13412
13413                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
13414
13415                 _sphere$3.copy( geometry.boundingSphere );
13416                 _sphere$3.applyMatrix4( matrixWorld );
13417
13418                 if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
13419
13420                 //
13421
13422                 _inverseMatrix$2.copy( matrixWorld ).invert();
13423                 _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
13424
13425                 // Check boundingBox before continuing
13426
13427                 if ( geometry.boundingBox !== null ) {
13428
13429                         if ( _ray$2.intersectsBox( geometry.boundingBox ) === false ) return;
13430
13431                 }
13432
13433                 let intersection;
13434
13435                 if ( geometry.isBufferGeometry ) {
13436
13437                         const index = geometry.index;
13438                         const position = geometry.attributes.position;
13439                         const morphPosition = geometry.morphAttributes.position;
13440                         const morphTargetsRelative = geometry.morphTargetsRelative;
13441                         const uv = geometry.attributes.uv;
13442                         const uv2 = geometry.attributes.uv2;
13443                         const groups = geometry.groups;
13444                         const drawRange = geometry.drawRange;
13445
13446                         if ( index !== null ) {
13447
13448                                 // indexed buffer geometry
13449
13450                                 if ( Array.isArray( material ) ) {
13451
13452                                         for ( let i = 0, il = groups.length; i < il; i ++ ) {
13453
13454                                                 const group = groups[ i ];
13455                                                 const groupMaterial = material[ group.materialIndex ];
13456
13457                                                 const start = Math.max( group.start, drawRange.start );
13458                                                 const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
13459
13460                                                 for ( let j = start, jl = end; j < jl; j += 3 ) {
13461
13462                                                         const a = index.getX( j );
13463                                                         const b = index.getX( j + 1 );
13464                                                         const c = index.getX( j + 2 );
13465
13466                                                         intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
13467
13468                                                         if ( intersection ) {
13469
13470                                                                 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
13471                                                                 intersection.face.materialIndex = group.materialIndex;
13472                                                                 intersects.push( intersection );
13473
13474                                                         }
13475
13476                                                 }
13477
13478                                         }
13479
13480                                 } else {
13481
13482                                         const start = Math.max( 0, drawRange.start );
13483                                         const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
13484
13485                                         for ( let i = start, il = end; i < il; i += 3 ) {
13486
13487                                                 const a = index.getX( i );
13488                                                 const b = index.getX( i + 1 );
13489                                                 const c = index.getX( i + 2 );
13490
13491                                                 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
13492
13493                                                 if ( intersection ) {
13494
13495                                                         intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
13496                                                         intersects.push( intersection );
13497
13498                                                 }
13499
13500                                         }
13501
13502                                 }
13503
13504                         } else if ( position !== undefined ) {
13505
13506                                 // non-indexed buffer geometry
13507
13508                                 if ( Array.isArray( material ) ) {
13509
13510                                         for ( let i = 0, il = groups.length; i < il; i ++ ) {
13511
13512                                                 const group = groups[ i ];
13513                                                 const groupMaterial = material[ group.materialIndex ];
13514
13515                                                 const start = Math.max( group.start, drawRange.start );
13516                                                 const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
13517
13518                                                 for ( let j = start, jl = end; j < jl; j += 3 ) {
13519
13520                                                         const a = j;
13521                                                         const b = j + 1;
13522                                                         const c = j + 2;
13523
13524                                                         intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
13525
13526                                                         if ( intersection ) {
13527
13528                                                                 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
13529                                                                 intersection.face.materialIndex = group.materialIndex;
13530                                                                 intersects.push( intersection );
13531
13532                                                         }
13533
13534                                                 }
13535
13536                                         }
13537
13538                                 } else {
13539
13540                                         const start = Math.max( 0, drawRange.start );
13541                                         const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
13542
13543                                         for ( let i = start, il = end; i < il; i += 3 ) {
13544
13545                                                 const a = i;
13546                                                 const b = i + 1;
13547                                                 const c = i + 2;
13548
13549                                                 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
13550
13551                                                 if ( intersection ) {
13552
13553                                                         intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
13554                                                         intersects.push( intersection );
13555
13556                                                 }
13557
13558                                         }
13559
13560                                 }
13561
13562                         }
13563
13564                 } else if ( geometry.isGeometry ) {
13565
13566                         console.error( 'THREE.Mesh.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
13567
13568                 }
13569
13570         }
13571
13572     }
13573
13574     Mesh.prototype.isMesh = true;
13575
13576     function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
13577
13578         let intersect;
13579
13580         if ( material.side === BackSide ) {
13581
13582                 intersect = ray.intersectTriangle( pC, pB, pA, true, point );
13583
13584         } else {
13585
13586                 intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
13587
13588         }
13589
13590         if ( intersect === null ) return null;
13591
13592         _intersectionPointWorld.copy( point );
13593         _intersectionPointWorld.applyMatrix4( object.matrixWorld );
13594
13595         const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
13596
13597         if ( distance < raycaster.near || distance > raycaster.far ) return null;
13598
13599         return {
13600                 distance: distance,
13601                 point: _intersectionPointWorld.clone(),
13602                 object: object
13603         };
13604
13605     }
13606
13607     function checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {
13608
13609         _vA$1.fromBufferAttribute( position, a );
13610         _vB$1.fromBufferAttribute( position, b );
13611         _vC$1.fromBufferAttribute( position, c );
13612
13613         const morphInfluences = object.morphTargetInfluences;
13614
13615         if ( morphPosition && morphInfluences ) {
13616
13617                 _morphA.set( 0, 0, 0 );
13618                 _morphB.set( 0, 0, 0 );
13619                 _morphC.set( 0, 0, 0 );
13620
13621                 for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
13622
13623                         const influence = morphInfluences[ i ];
13624                         const morphAttribute = morphPosition[ i ];
13625
13626                         if ( influence === 0 ) continue;
13627
13628                         _tempA.fromBufferAttribute( morphAttribute, a );
13629                         _tempB.fromBufferAttribute( morphAttribute, b );
13630                         _tempC.fromBufferAttribute( morphAttribute, c );
13631
13632                         if ( morphTargetsRelative ) {
13633
13634                                 _morphA.addScaledVector( _tempA, influence );
13635                                 _morphB.addScaledVector( _tempB, influence );
13636                                 _morphC.addScaledVector( _tempC, influence );
13637
13638                         } else {
13639
13640                                 _morphA.addScaledVector( _tempA.sub( _vA$1 ), influence );
13641                                 _morphB.addScaledVector( _tempB.sub( _vB$1 ), influence );
13642                                 _morphC.addScaledVector( _tempC.sub( _vC$1 ), influence );
13643
13644                         }
13645
13646                 }
13647
13648                 _vA$1.add( _morphA );
13649                 _vB$1.add( _morphB );
13650                 _vC$1.add( _morphC );
13651
13652         }
13653
13654         if ( object.isSkinnedMesh ) {
13655
13656                 object.boneTransform( a, _vA$1 );
13657                 object.boneTransform( b, _vB$1 );
13658                 object.boneTransform( c, _vC$1 );
13659
13660         }
13661
13662         const intersection = checkIntersection( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint );
13663
13664         if ( intersection ) {
13665
13666                 if ( uv ) {
13667
13668                         _uvA$1.fromBufferAttribute( uv, a );
13669                         _uvB$1.fromBufferAttribute( uv, b );
13670                         _uvC$1.fromBufferAttribute( uv, c );
13671
13672                         intersection.uv = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
13673
13674                 }
13675
13676                 if ( uv2 ) {
13677
13678                         _uvA$1.fromBufferAttribute( uv2, a );
13679                         _uvB$1.fromBufferAttribute( uv2, b );
13680                         _uvC$1.fromBufferAttribute( uv2, c );
13681
13682                         intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
13683
13684                 }
13685
13686                 const face = {
13687                         a: a,
13688                         b: b,
13689                         c: c,
13690                         normal: new Vector3(),
13691                         materialIndex: 0
13692                 };
13693
13694                 Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal );
13695
13696                 intersection.face = face;
13697
13698         }
13699
13700         return intersection;
13701
13702     }
13703
13704     class BoxGeometry extends BufferGeometry {
13705
13706         constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
13707
13708                 super();
13709
13710                 this.type = 'BoxGeometry';
13711
13712                 this.parameters = {
13713                         width: width,
13714                         height: height,
13715                         depth: depth,
13716                         widthSegments: widthSegments,
13717                         heightSegments: heightSegments,
13718                         depthSegments: depthSegments
13719                 };
13720
13721                 const scope = this;
13722
13723                 // segments
13724
13725                 widthSegments = Math.floor( widthSegments );
13726                 heightSegments = Math.floor( heightSegments );
13727                 depthSegments = Math.floor( depthSegments );
13728
13729                 // buffers
13730
13731                 const indices = [];
13732                 const vertices = [];
13733                 const normals = [];
13734                 const uvs = [];
13735
13736                 // helper variables
13737
13738                 let numberOfVertices = 0;
13739                 let groupStart = 0;
13740
13741                 // build each side of the box geometry
13742
13743                 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
13744                 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
13745                 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
13746                 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
13747                 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
13748                 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
13749
13750                 // build geometry
13751
13752                 this.setIndex( indices );
13753                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
13754                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
13755                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
13756
13757                 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
13758
13759                         const segmentWidth = width / gridX;
13760                         const segmentHeight = height / gridY;
13761
13762                         const widthHalf = width / 2;
13763                         const heightHalf = height / 2;
13764                         const depthHalf = depth / 2;
13765
13766                         const gridX1 = gridX + 1;
13767                         const gridY1 = gridY + 1;
13768
13769                         let vertexCounter = 0;
13770                         let groupCount = 0;
13771
13772                         const vector = new Vector3();
13773
13774                         // generate vertices, normals and uvs
13775
13776                         for ( let iy = 0; iy < gridY1; iy ++ ) {
13777
13778                                 const y = iy * segmentHeight - heightHalf;
13779
13780                                 for ( let ix = 0; ix < gridX1; ix ++ ) {
13781
13782                                         const x = ix * segmentWidth - widthHalf;
13783
13784                                         // set values to correct vector component
13785
13786                                         vector[ u ] = x * udir;
13787                                         vector[ v ] = y * vdir;
13788                                         vector[ w ] = depthHalf;
13789
13790                                         // now apply vector to vertex buffer
13791
13792                                         vertices.push( vector.x, vector.y, vector.z );
13793
13794                                         // set values to correct vector component
13795
13796                                         vector[ u ] = 0;
13797                                         vector[ v ] = 0;
13798                                         vector[ w ] = depth > 0 ? 1 : - 1;
13799
13800                                         // now apply vector to normal buffer
13801
13802                                         normals.push( vector.x, vector.y, vector.z );
13803
13804                                         // uvs
13805
13806                                         uvs.push( ix / gridX );
13807                                         uvs.push( 1 - ( iy / gridY ) );
13808
13809                                         // counters
13810
13811                                         vertexCounter += 1;
13812
13813                                 }
13814
13815                         }
13816
13817                         // indices
13818
13819                         // 1. you need three indices to draw a single face
13820                         // 2. a single segment consists of two faces
13821                         // 3. so we need to generate six (2*3) indices per segment
13822
13823                         for ( let iy = 0; iy < gridY; iy ++ ) {
13824
13825                                 for ( let ix = 0; ix < gridX; ix ++ ) {
13826
13827                                         const a = numberOfVertices + ix + gridX1 * iy;
13828                                         const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
13829                                         const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
13830                                         const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
13831
13832                                         // faces
13833
13834                                         indices.push( a, b, d );
13835                                         indices.push( b, c, d );
13836
13837                                         // increase counter
13838
13839                                         groupCount += 6;
13840
13841                                 }
13842
13843                         }
13844
13845                         // add a group to the geometry. this will ensure multi material support
13846
13847                         scope.addGroup( groupStart, groupCount, materialIndex );
13848
13849                         // calculate new start value for groups
13850
13851                         groupStart += groupCount;
13852
13853                         // update total number of vertices
13854
13855                         numberOfVertices += vertexCounter;
13856
13857                 }
13858
13859         }
13860
13861         static fromJSON( data ) {
13862
13863                 return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );
13864
13865         }
13866
13867     }
13868
13869     /**
13870      * Uniform Utilities
13871      */
13872
13873     function cloneUniforms( src ) {
13874
13875         const dst = {};
13876
13877         for ( const u in src ) {
13878
13879                 dst[ u ] = {};
13880
13881                 for ( const p in src[ u ] ) {
13882
13883                         const property = src[ u ][ p ];
13884
13885                         if ( property && ( property.isColor ||
13886                                 property.isMatrix3 || property.isMatrix4 ||
13887                                 property.isVector2 || property.isVector3 || property.isVector4 ||
13888                                 property.isTexture || property.isQuaternion ) ) {
13889
13890                                 dst[ u ][ p ] = property.clone();
13891
13892                         } else if ( Array.isArray( property ) ) {
13893
13894                                 dst[ u ][ p ] = property.slice();
13895
13896                         } else {
13897
13898                                 dst[ u ][ p ] = property;
13899
13900                         }
13901
13902                 }
13903
13904         }
13905
13906         return dst;
13907
13908     }
13909
13910     function mergeUniforms( uniforms ) {
13911
13912         const merged = {};
13913
13914         for ( let u = 0; u < uniforms.length; u ++ ) {
13915
13916                 const tmp = cloneUniforms( uniforms[ u ] );
13917
13918                 for ( const p in tmp ) {
13919
13920                         merged[ p ] = tmp[ p ];
13921
13922                 }
13923
13924         }
13925
13926         return merged;
13927
13928     }
13929
13930     // Legacy
13931
13932     const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
13933
13934     var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
13935
13936     var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
13937
13938     /**
13939      * parameters = {
13940      *  defines: { "label" : "value" },
13941      *  uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
13942      *
13943      *  fragmentShader: <string>,
13944      *  vertexShader: <string>,
13945      *
13946      *  wireframe: <boolean>,
13947      *  wireframeLinewidth: <float>,
13948      *
13949      *  lights: <bool>
13950      * }
13951      */
13952
13953     class ShaderMaterial extends Material {
13954
13955         constructor( parameters ) {
13956
13957                 super();
13958
13959                 this.type = 'ShaderMaterial';
13960
13961                 this.defines = {};
13962                 this.uniforms = {};
13963
13964                 this.vertexShader = default_vertex;
13965                 this.fragmentShader = default_fragment;
13966
13967                 this.linewidth = 1;
13968
13969                 this.wireframe = false;
13970                 this.wireframeLinewidth = 1;
13971
13972                 this.fog = false; // set to use scene fog
13973                 this.lights = false; // set to use scene lights
13974                 this.clipping = false; // set to use user-defined clipping planes
13975
13976                 this.extensions = {
13977                         derivatives: false, // set to use derivatives
13978                         fragDepth: false, // set to use fragment depth values
13979                         drawBuffers: false, // set to use draw buffers
13980                         shaderTextureLOD: false // set to use shader texture LOD
13981                 };
13982
13983                 // When rendered geometry doesn't include these attributes but the material does,
13984                 // use these default values in WebGL. This avoids errors when buffer data is missing.
13985                 this.defaultAttributeValues = {
13986                         'color': [ 1, 1, 1 ],
13987                         'uv': [ 0, 0 ],
13988                         'uv2': [ 0, 0 ]
13989                 };
13990
13991                 this.index0AttributeName = undefined;
13992                 this.uniformsNeedUpdate = false;
13993
13994                 this.glslVersion = null;
13995
13996                 if ( parameters !== undefined ) {
13997
13998                         if ( parameters.attributes !== undefined ) {
13999
14000                                 console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
14001
14002                         }
14003
14004                         this.setValues( parameters );
14005
14006                 }
14007
14008         }
14009
14010         copy( source ) {
14011
14012                 super.copy( source );
14013
14014                 this.fragmentShader = source.fragmentShader;
14015                 this.vertexShader = source.vertexShader;
14016
14017                 this.uniforms = cloneUniforms( source.uniforms );
14018
14019                 this.defines = Object.assign( {}, source.defines );
14020
14021                 this.wireframe = source.wireframe;
14022                 this.wireframeLinewidth = source.wireframeLinewidth;
14023
14024                 this.lights = source.lights;
14025                 this.clipping = source.clipping;
14026
14027                 this.extensions = Object.assign( {}, source.extensions );
14028
14029                 this.glslVersion = source.glslVersion;
14030
14031                 return this;
14032
14033         }
14034
14035         toJSON( meta ) {
14036
14037                 const data = super.toJSON( meta );
14038
14039                 data.glslVersion = this.glslVersion;
14040                 data.uniforms = {};
14041
14042                 for ( const name in this.uniforms ) {
14043
14044                         const uniform = this.uniforms[ name ];
14045                         const value = uniform.value;
14046
14047                         if ( value && value.isTexture ) {
14048
14049                                 data.uniforms[ name ] = {
14050                                         type: 't',
14051                                         value: value.toJSON( meta ).uuid
14052                                 };
14053
14054                         } else if ( value && value.isColor ) {
14055
14056                                 data.uniforms[ name ] = {
14057                                         type: 'c',
14058                                         value: value.getHex()
14059                                 };
14060
14061                         } else if ( value && value.isVector2 ) {
14062
14063                                 data.uniforms[ name ] = {
14064                                         type: 'v2',
14065                                         value: value.toArray()
14066                                 };
14067
14068                         } else if ( value && value.isVector3 ) {
14069
14070                                 data.uniforms[ name ] = {
14071                                         type: 'v3',
14072                                         value: value.toArray()
14073                                 };
14074
14075                         } else if ( value && value.isVector4 ) {
14076
14077                                 data.uniforms[ name ] = {
14078                                         type: 'v4',
14079                                         value: value.toArray()
14080                                 };
14081
14082                         } else if ( value && value.isMatrix3 ) {
14083
14084                                 data.uniforms[ name ] = {
14085                                         type: 'm3',
14086                                         value: value.toArray()
14087                                 };
14088
14089                         } else if ( value && value.isMatrix4 ) {
14090
14091                                 data.uniforms[ name ] = {
14092                                         type: 'm4',
14093                                         value: value.toArray()
14094                                 };
14095
14096                         } else {
14097
14098                                 data.uniforms[ name ] = {
14099                                         value: value
14100                                 };
14101
14102                                 // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
14103
14104                         }
14105
14106                 }
14107
14108                 if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
14109
14110                 data.vertexShader = this.vertexShader;
14111                 data.fragmentShader = this.fragmentShader;
14112
14113                 const extensions = {};
14114
14115                 for ( const key in this.extensions ) {
14116
14117                         if ( this.extensions[ key ] === true ) extensions[ key ] = true;
14118
14119                 }
14120
14121                 if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
14122
14123                 return data;
14124
14125         }
14126
14127     }
14128
14129     ShaderMaterial.prototype.isShaderMaterial = true;
14130
14131     class Camera$1 extends Object3D {
14132
14133         constructor() {
14134
14135                 super();
14136
14137                 this.type = 'Camera';
14138
14139                 this.matrixWorldInverse = new Matrix4();
14140
14141                 this.projectionMatrix = new Matrix4();
14142                 this.projectionMatrixInverse = new Matrix4();
14143
14144         }
14145
14146         copy( source, recursive ) {
14147
14148                 super.copy( source, recursive );
14149
14150                 this.matrixWorldInverse.copy( source.matrixWorldInverse );
14151
14152                 this.projectionMatrix.copy( source.projectionMatrix );
14153                 this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
14154
14155                 return this;
14156
14157         }
14158
14159         getWorldDirection( target ) {
14160
14161                 this.updateWorldMatrix( true, false );
14162
14163                 const e = this.matrixWorld.elements;
14164
14165                 return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();
14166
14167         }
14168
14169         updateMatrixWorld( force ) {
14170
14171                 super.updateMatrixWorld( force );
14172
14173                 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
14174
14175         }
14176
14177         updateWorldMatrix( updateParents, updateChildren ) {
14178
14179                 super.updateWorldMatrix( updateParents, updateChildren );
14180
14181                 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
14182
14183         }
14184
14185         clone() {
14186
14187                 return new this.constructor().copy( this );
14188
14189         }
14190
14191     }
14192
14193     Camera$1.prototype.isCamera = true;
14194
14195     class PerspectiveCamera extends Camera$1 {
14196
14197         constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
14198
14199                 super();
14200
14201                 this.type = 'PerspectiveCamera';
14202
14203                 this.fov = fov;
14204                 this.zoom = 1;
14205
14206                 this.near = near;
14207                 this.far = far;
14208                 this.focus = 10;
14209
14210                 this.aspect = aspect;
14211                 this.view = null;
14212
14213                 this.filmGauge = 35;    // width of the film (default in millimeters)
14214                 this.filmOffset = 0;    // horizontal film offset (same unit as gauge)
14215
14216                 this.updateProjectionMatrix();
14217
14218         }
14219
14220         copy( source, recursive ) {
14221
14222                 super.copy( source, recursive );
14223
14224                 this.fov = source.fov;
14225                 this.zoom = source.zoom;
14226
14227                 this.near = source.near;
14228                 this.far = source.far;
14229                 this.focus = source.focus;
14230
14231                 this.aspect = source.aspect;
14232                 this.view = source.view === null ? null : Object.assign( {}, source.view );
14233
14234                 this.filmGauge = source.filmGauge;
14235                 this.filmOffset = source.filmOffset;
14236
14237                 return this;
14238
14239         }
14240
14241         /**
14242          * Sets the FOV by focal length in respect to the current .filmGauge.
14243          *
14244          * The default film gauge is 35, so that the focal length can be specified for
14245          * a 35mm (full frame) camera.
14246          *
14247          * Values for focal length and film gauge must have the same unit.
14248          */
14249         setFocalLength( focalLength ) {
14250
14251                 /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
14252                 const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
14253
14254                 this.fov = RAD2DEG$1 * 2 * Math.atan( vExtentSlope );
14255                 this.updateProjectionMatrix();
14256
14257         }
14258
14259         /**
14260          * Calculates the focal length from the current .fov and .filmGauge.
14261          */
14262         getFocalLength() {
14263
14264                 const vExtentSlope = Math.tan( DEG2RAD$1 * 0.5 * this.fov );
14265
14266                 return 0.5 * this.getFilmHeight() / vExtentSlope;
14267
14268         }
14269
14270         getEffectiveFOV() {
14271
14272                 return RAD2DEG$1 * 2 * Math.atan(
14273                         Math.tan( DEG2RAD$1 * 0.5 * this.fov ) / this.zoom );
14274
14275         }
14276
14277         getFilmWidth() {
14278
14279                 // film not completely covered in portrait format (aspect < 1)
14280                 return this.filmGauge * Math.min( this.aspect, 1 );
14281
14282         }
14283
14284         getFilmHeight() {
14285
14286                 // film not completely covered in landscape format (aspect > 1)
14287                 return this.filmGauge / Math.max( this.aspect, 1 );
14288
14289         }
14290
14291         /**
14292          * Sets an offset in a larger frustum. This is useful for multi-window or
14293          * multi-monitor/multi-machine setups.
14294          *
14295          * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
14296          * the monitors are in grid like this
14297          *
14298          *   +---+---+---+
14299          *   | A | B | C |
14300          *   +---+---+---+
14301          *   | D | E | F |
14302          *   +---+---+---+
14303          *
14304          * then for each monitor you would call it like this
14305          *
14306          *   const w = 1920;
14307          *   const h = 1080;
14308          *   const fullWidth = w * 3;
14309          *   const fullHeight = h * 2;
14310          *
14311          *   --A--
14312          *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
14313          *   --B--
14314          *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
14315          *   --C--
14316          *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
14317          *   --D--
14318          *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
14319          *   --E--
14320          *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
14321          *   --F--
14322          *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
14323          *
14324          *   Note there is no reason monitors have to be the same size or in a grid.
14325          */
14326         setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
14327
14328                 this.aspect = fullWidth / fullHeight;
14329
14330                 if ( this.view === null ) {
14331
14332                         this.view = {
14333                                 enabled: true,
14334                                 fullWidth: 1,
14335                                 fullHeight: 1,
14336                                 offsetX: 0,
14337                                 offsetY: 0,
14338                                 width: 1,
14339                                 height: 1
14340                         };
14341
14342                 }
14343
14344                 this.view.enabled = true;
14345                 this.view.fullWidth = fullWidth;
14346                 this.view.fullHeight = fullHeight;
14347                 this.view.offsetX = x;
14348                 this.view.offsetY = y;
14349                 this.view.width = width;
14350                 this.view.height = height;
14351
14352                 this.updateProjectionMatrix();
14353
14354         }
14355
14356         clearViewOffset() {
14357
14358                 if ( this.view !== null ) {
14359
14360                         this.view.enabled = false;
14361
14362                 }
14363
14364                 this.updateProjectionMatrix();
14365
14366         }
14367
14368         updateProjectionMatrix() {
14369
14370                 const near = this.near;
14371                 let top = near * Math.tan( DEG2RAD$1 * 0.5 * this.fov ) / this.zoom;
14372                 let height = 2 * top;
14373                 let width = this.aspect * height;
14374                 let left = - 0.5 * width;
14375                 const view = this.view;
14376
14377                 if ( this.view !== null && this.view.enabled ) {
14378
14379                         const fullWidth = view.fullWidth,
14380                                 fullHeight = view.fullHeight;
14381
14382                         left += view.offsetX * width / fullWidth;
14383                         top -= view.offsetY * height / fullHeight;
14384                         width *= view.width / fullWidth;
14385                         height *= view.height / fullHeight;
14386
14387                 }
14388
14389                 const skew = this.filmOffset;
14390                 if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
14391
14392                 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
14393
14394                 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
14395
14396         }
14397
14398         toJSON( meta ) {
14399
14400                 const data = super.toJSON( meta );
14401
14402                 data.object.fov = this.fov;
14403                 data.object.zoom = this.zoom;
14404
14405                 data.object.near = this.near;
14406                 data.object.far = this.far;
14407                 data.object.focus = this.focus;
14408
14409                 data.object.aspect = this.aspect;
14410
14411                 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
14412
14413                 data.object.filmGauge = this.filmGauge;
14414                 data.object.filmOffset = this.filmOffset;
14415
14416                 return data;
14417
14418         }
14419
14420     }
14421
14422     PerspectiveCamera.prototype.isPerspectiveCamera = true;
14423
14424     const fov = 90, aspect = 1;
14425
14426     class CubeCamera extends Object3D {
14427
14428         constructor( near, far, renderTarget ) {
14429
14430                 super();
14431
14432                 this.type = 'CubeCamera';
14433
14434                 if ( renderTarget.isWebGLCubeRenderTarget !== true ) {
14435
14436                         console.error( 'THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.' );
14437                         return;
14438
14439                 }
14440
14441                 this.renderTarget = renderTarget;
14442
14443                 const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
14444                 cameraPX.layers = this.layers;
14445                 cameraPX.up.set( 0, - 1, 0 );
14446                 cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
14447                 this.add( cameraPX );
14448
14449                 const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
14450                 cameraNX.layers = this.layers;
14451                 cameraNX.up.set( 0, - 1, 0 );
14452                 cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
14453                 this.add( cameraNX );
14454
14455                 const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
14456                 cameraPY.layers = this.layers;
14457                 cameraPY.up.set( 0, 0, 1 );
14458                 cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
14459                 this.add( cameraPY );
14460
14461                 const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
14462                 cameraNY.layers = this.layers;
14463                 cameraNY.up.set( 0, 0, - 1 );
14464                 cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
14465                 this.add( cameraNY );
14466
14467                 const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
14468                 cameraPZ.layers = this.layers;
14469                 cameraPZ.up.set( 0, - 1, 0 );
14470                 cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
14471                 this.add( cameraPZ );
14472
14473                 const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
14474                 cameraNZ.layers = this.layers;
14475                 cameraNZ.up.set( 0, - 1, 0 );
14476                 cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
14477                 this.add( cameraNZ );
14478
14479         }
14480
14481         update( renderer, scene ) {
14482
14483                 if ( this.parent === null ) this.updateMatrixWorld();
14484
14485                 const renderTarget = this.renderTarget;
14486
14487                 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
14488
14489                 const currentXrEnabled = renderer.xr.enabled;
14490                 const currentRenderTarget = renderer.getRenderTarget();
14491
14492                 renderer.xr.enabled = false;
14493
14494                 const generateMipmaps = renderTarget.texture.generateMipmaps;
14495
14496                 renderTarget.texture.generateMipmaps = false;
14497
14498                 renderer.setRenderTarget( renderTarget, 0 );
14499                 renderer.render( scene, cameraPX );
14500
14501                 renderer.setRenderTarget( renderTarget, 1 );
14502                 renderer.render( scene, cameraNX );
14503
14504                 renderer.setRenderTarget( renderTarget, 2 );
14505                 renderer.render( scene, cameraPY );
14506
14507                 renderer.setRenderTarget( renderTarget, 3 );
14508                 renderer.render( scene, cameraNY );
14509
14510                 renderer.setRenderTarget( renderTarget, 4 );
14511                 renderer.render( scene, cameraPZ );
14512
14513                 renderTarget.texture.generateMipmaps = generateMipmaps;
14514
14515                 renderer.setRenderTarget( renderTarget, 5 );
14516                 renderer.render( scene, cameraNZ );
14517
14518                 renderer.setRenderTarget( currentRenderTarget );
14519
14520                 renderer.xr.enabled = currentXrEnabled;
14521
14522         }
14523
14524     }
14525
14526     class CubeTexture extends Texture {
14527
14528         constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
14529
14530                 images = images !== undefined ? images : [];
14531                 mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
14532
14533                 super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
14534
14535                 this.flipY = false;
14536
14537         }
14538
14539         get images() {
14540
14541                 return this.image;
14542
14543         }
14544
14545         set images( value ) {
14546
14547                 this.image = value;
14548
14549         }
14550
14551     }
14552
14553     CubeTexture.prototype.isCubeTexture = true;
14554
14555     class WebGLCubeRenderTarget extends WebGLRenderTarget {
14556
14557         constructor( size, options, dummy ) {
14558
14559                 if ( Number.isInteger( options ) ) {
14560
14561                         console.warn( 'THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )' );
14562
14563                         options = dummy;
14564
14565                 }
14566
14567                 super( size, size, options );
14568
14569                 options = options || {};
14570
14571                 // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
14572                 // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
14573                 // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
14574
14575                 // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
14576                 // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
14577                 // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
14578
14579                 this.texture = new CubeTexture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
14580                 this.texture.isRenderTargetTexture = true;
14581
14582                 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
14583                 this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
14584
14585                 this.texture._needsFlipEnvMap = false;
14586
14587         }
14588
14589         fromEquirectangularTexture( renderer, texture ) {
14590
14591                 this.texture.type = texture.type;
14592                 this.texture.format = RGBAFormat; // see #18859
14593                 this.texture.encoding = texture.encoding;
14594
14595                 this.texture.generateMipmaps = texture.generateMipmaps;
14596                 this.texture.minFilter = texture.minFilter;
14597                 this.texture.magFilter = texture.magFilter;
14598
14599                 const shader = {
14600
14601                         uniforms: {
14602                                 tEquirect: { value: null },
14603                         },
14604
14605                         vertexShader: /* glsl */`
14606
14607                                 varying vec3 vWorldDirection;
14608
14609                                 vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
14610
14611                                         return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
14612
14613                                 }
14614
14615                                 void main() {
14616
14617                                         vWorldDirection = transformDirection( position, modelMatrix );
14618
14619                                         #include <begin_vertex>
14620                                         #include <project_vertex>
14621
14622                                 }
14623                         `,
14624
14625                         fragmentShader: /* glsl */`
14626
14627                                 uniform sampler2D tEquirect;
14628
14629                                 varying vec3 vWorldDirection;
14630
14631                                 #include <common>
14632
14633                                 void main() {
14634
14635                                         vec3 direction = normalize( vWorldDirection );
14636
14637                                         vec2 sampleUV = equirectUv( direction );
14638
14639                                         gl_FragColor = texture2D( tEquirect, sampleUV );
14640
14641                                 }
14642                         `
14643                 };
14644
14645                 const geometry = new BoxGeometry( 5, 5, 5 );
14646
14647                 const material = new ShaderMaterial( {
14648
14649                         name: 'CubemapFromEquirect',
14650
14651                         uniforms: cloneUniforms( shader.uniforms ),
14652                         vertexShader: shader.vertexShader,
14653                         fragmentShader: shader.fragmentShader,
14654                         side: BackSide,
14655                         blending: NoBlending
14656
14657                 } );
14658
14659                 material.uniforms.tEquirect.value = texture;
14660
14661                 const mesh = new Mesh( geometry, material );
14662
14663                 const currentMinFilter = texture.minFilter;
14664
14665                 // Avoid blurred poles
14666                 if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
14667
14668                 const camera = new CubeCamera( 1, 10, this );
14669                 camera.update( renderer, mesh );
14670
14671                 texture.minFilter = currentMinFilter;
14672
14673                 mesh.geometry.dispose();
14674                 mesh.material.dispose();
14675
14676                 return this;
14677
14678         }
14679
14680         clear( renderer, color, depth, stencil ) {
14681
14682                 const currentRenderTarget = renderer.getRenderTarget();
14683
14684                 for ( let i = 0; i < 6; i ++ ) {
14685
14686                         renderer.setRenderTarget( this, i );
14687
14688                         renderer.clear( color, depth, stencil );
14689
14690                 }
14691
14692                 renderer.setRenderTarget( currentRenderTarget );
14693
14694         }
14695
14696     }
14697
14698     WebGLCubeRenderTarget.prototype.isWebGLCubeRenderTarget = true;
14699
14700     const _vector1 = /*@__PURE__*/ new Vector3();
14701     const _vector2 = /*@__PURE__*/ new Vector3();
14702     const _normalMatrix = /*@__PURE__*/ new Matrix3();
14703
14704     class Plane {
14705
14706         constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) {
14707
14708                 // normal is assumed to be normalized
14709
14710                 this.normal = normal;
14711                 this.constant = constant;
14712
14713         }
14714
14715         set( normal, constant ) {
14716
14717                 this.normal.copy( normal );
14718                 this.constant = constant;
14719
14720                 return this;
14721
14722         }
14723
14724         setComponents( x, y, z, w ) {
14725
14726                 this.normal.set( x, y, z );
14727                 this.constant = w;
14728
14729                 return this;
14730
14731         }
14732
14733         setFromNormalAndCoplanarPoint( normal, point ) {
14734
14735                 this.normal.copy( normal );
14736                 this.constant = - point.dot( this.normal );
14737
14738                 return this;
14739
14740         }
14741
14742         setFromCoplanarPoints( a, b, c ) {
14743
14744                 const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
14745
14746                 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
14747
14748                 this.setFromNormalAndCoplanarPoint( normal, a );
14749
14750                 return this;
14751
14752         }
14753
14754         copy( plane ) {
14755
14756                 this.normal.copy( plane.normal );
14757                 this.constant = plane.constant;
14758
14759                 return this;
14760
14761         }
14762
14763         normalize() {
14764
14765                 // Note: will lead to a divide by zero if the plane is invalid.
14766
14767                 const inverseNormalLength = 1.0 / this.normal.length();
14768                 this.normal.multiplyScalar( inverseNormalLength );
14769                 this.constant *= inverseNormalLength;
14770
14771                 return this;
14772
14773         }
14774
14775         negate() {
14776
14777                 this.constant *= - 1;
14778                 this.normal.negate();
14779
14780                 return this;
14781
14782         }
14783
14784         distanceToPoint( point ) {
14785
14786                 return this.normal.dot( point ) + this.constant;
14787
14788         }
14789
14790         distanceToSphere( sphere ) {
14791
14792                 return this.distanceToPoint( sphere.center ) - sphere.radius;
14793
14794         }
14795
14796         projectPoint( point, target ) {
14797
14798                 return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
14799
14800         }
14801
14802         intersectLine( line, target ) {
14803
14804                 const direction = line.delta( _vector1 );
14805
14806                 const denominator = this.normal.dot( direction );
14807
14808                 if ( denominator === 0 ) {
14809
14810                         // line is coplanar, return origin
14811                         if ( this.distanceToPoint( line.start ) === 0 ) {
14812
14813                                 return target.copy( line.start );
14814
14815                         }
14816
14817                         // Unsure if this is the correct method to handle this case.
14818                         return null;
14819
14820                 }
14821
14822                 const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
14823
14824                 if ( t < 0 || t > 1 ) {
14825
14826                         return null;
14827
14828                 }
14829
14830                 return target.copy( direction ).multiplyScalar( t ).add( line.start );
14831
14832         }
14833
14834         intersectsLine( line ) {
14835
14836                 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
14837
14838                 const startSign = this.distanceToPoint( line.start );
14839                 const endSign = this.distanceToPoint( line.end );
14840
14841                 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
14842
14843         }
14844
14845         intersectsBox( box ) {
14846
14847                 return box.intersectsPlane( this );
14848
14849         }
14850
14851         intersectsSphere( sphere ) {
14852
14853                 return sphere.intersectsPlane( this );
14854
14855         }
14856
14857         coplanarPoint( target ) {
14858
14859                 return target.copy( this.normal ).multiplyScalar( - this.constant );
14860
14861         }
14862
14863         applyMatrix4( matrix, optionalNormalMatrix ) {
14864
14865                 const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
14866
14867                 const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
14868
14869                 const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
14870
14871                 this.constant = - referencePoint.dot( normal );
14872
14873                 return this;
14874
14875         }
14876
14877         translate( offset ) {
14878
14879                 this.constant -= offset.dot( this.normal );
14880
14881                 return this;
14882
14883         }
14884
14885         equals( plane ) {
14886
14887                 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
14888
14889         }
14890
14891         clone() {
14892
14893                 return new this.constructor().copy( this );
14894
14895         }
14896
14897     }
14898
14899     Plane.prototype.isPlane = true;
14900
14901     const _sphere$2 = /*@__PURE__*/ new Sphere();
14902     const _vector$7 = /*@__PURE__*/ new Vector3();
14903
14904     class Frustum {
14905
14906         constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) {
14907
14908                 this.planes = [ p0, p1, p2, p3, p4, p5 ];
14909
14910         }
14911
14912         set( p0, p1, p2, p3, p4, p5 ) {
14913
14914                 const planes = this.planes;
14915
14916                 planes[ 0 ].copy( p0 );
14917                 planes[ 1 ].copy( p1 );
14918                 planes[ 2 ].copy( p2 );
14919                 planes[ 3 ].copy( p3 );
14920                 planes[ 4 ].copy( p4 );
14921                 planes[ 5 ].copy( p5 );
14922
14923                 return this;
14924
14925         }
14926
14927         copy( frustum ) {
14928
14929                 const planes = this.planes;
14930
14931                 for ( let i = 0; i < 6; i ++ ) {
14932
14933                         planes[ i ].copy( frustum.planes[ i ] );
14934
14935                 }
14936
14937                 return this;
14938
14939         }
14940
14941         setFromProjectionMatrix( m ) {
14942
14943                 const planes = this.planes;
14944                 const me = m.elements;
14945                 const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
14946                 const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
14947                 const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
14948                 const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
14949
14950                 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
14951                 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
14952                 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
14953                 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
14954                 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
14955                 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
14956
14957                 return this;
14958
14959         }
14960
14961         intersectsObject( object ) {
14962
14963                 const geometry = object.geometry;
14964
14965                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
14966
14967                 _sphere$2.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
14968
14969                 return this.intersectsSphere( _sphere$2 );
14970
14971         }
14972
14973         intersectsSprite( sprite ) {
14974
14975                 _sphere$2.center.set( 0, 0, 0 );
14976                 _sphere$2.radius = 0.7071067811865476;
14977                 _sphere$2.applyMatrix4( sprite.matrixWorld );
14978
14979                 return this.intersectsSphere( _sphere$2 );
14980
14981         }
14982
14983         intersectsSphere( sphere ) {
14984
14985                 const planes = this.planes;
14986                 const center = sphere.center;
14987                 const negRadius = - sphere.radius;
14988
14989                 for ( let i = 0; i < 6; i ++ ) {
14990
14991                         const distance = planes[ i ].distanceToPoint( center );
14992
14993                         if ( distance < negRadius ) {
14994
14995                                 return false;
14996
14997                         }
14998
14999                 }
15000
15001                 return true;
15002
15003         }
15004
15005         intersectsBox( box ) {
15006
15007                 const planes = this.planes;
15008
15009                 for ( let i = 0; i < 6; i ++ ) {
15010
15011                         const plane = planes[ i ];
15012
15013                         // corner at max distance
15014
15015                         _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x;
15016                         _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y;
15017                         _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z;
15018
15019                         if ( plane.distanceToPoint( _vector$7 ) < 0 ) {
15020
15021                                 return false;
15022
15023                         }
15024
15025                 }
15026
15027                 return true;
15028
15029         }
15030
15031         containsPoint( point ) {
15032
15033                 const planes = this.planes;
15034
15035                 for ( let i = 0; i < 6; i ++ ) {
15036
15037                         if ( planes[ i ].distanceToPoint( point ) < 0 ) {
15038
15039                                 return false;
15040
15041                         }
15042
15043                 }
15044
15045                 return true;
15046
15047         }
15048
15049         clone() {
15050
15051                 return new this.constructor().copy( this );
15052
15053         }
15054
15055     }
15056
15057     function WebGLAnimation() {
15058
15059         let context = null;
15060         let isAnimating = false;
15061         let animationLoop = null;
15062         let requestId = null;
15063
15064         function onAnimationFrame( time, frame ) {
15065
15066                 animationLoop( time, frame );
15067
15068                 requestId = context.requestAnimationFrame( onAnimationFrame );
15069
15070         }
15071
15072         return {
15073
15074                 start: function () {
15075
15076                         if ( isAnimating === true ) return;
15077                         if ( animationLoop === null ) return;
15078
15079                         requestId = context.requestAnimationFrame( onAnimationFrame );
15080
15081                         isAnimating = true;
15082
15083                 },
15084
15085                 stop: function () {
15086
15087                         context.cancelAnimationFrame( requestId );
15088
15089                         isAnimating = false;
15090
15091                 },
15092
15093                 setAnimationLoop: function ( callback ) {
15094
15095                         animationLoop = callback;
15096
15097                 },
15098
15099                 setContext: function ( value ) {
15100
15101                         context = value;
15102
15103                 }
15104
15105         };
15106
15107     }
15108
15109     function WebGLAttributes( gl, capabilities ) {
15110
15111         const isWebGL2 = capabilities.isWebGL2;
15112
15113         const buffers = new WeakMap();
15114
15115         function createBuffer( attribute, bufferType ) {
15116
15117                 const array = attribute.array;
15118                 const usage = attribute.usage;
15119
15120                 const buffer = gl.createBuffer();
15121
15122                 gl.bindBuffer( bufferType, buffer );
15123                 gl.bufferData( bufferType, array, usage );
15124
15125                 attribute.onUploadCallback();
15126
15127                 let type = 5126;
15128
15129                 if ( array instanceof Float32Array ) {
15130
15131                         type = 5126;
15132
15133                 } else if ( array instanceof Float64Array ) {
15134
15135                         console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
15136
15137                 } else if ( array instanceof Uint16Array ) {
15138
15139                         if ( attribute.isFloat16BufferAttribute ) {
15140
15141                                 if ( isWebGL2 ) {
15142
15143                                         type = 5131;
15144
15145                                 } else {
15146
15147                                         console.warn( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' );
15148
15149                                 }
15150
15151                         } else {
15152
15153                                 type = 5123;
15154
15155                         }
15156
15157                 } else if ( array instanceof Int16Array ) {
15158
15159                         type = 5122;
15160
15161                 } else if ( array instanceof Uint32Array ) {
15162
15163                         type = 5125;
15164
15165                 } else if ( array instanceof Int32Array ) {
15166
15167                         type = 5124;
15168
15169                 } else if ( array instanceof Int8Array ) {
15170
15171                         type = 5120;
15172
15173                 } else if ( array instanceof Uint8Array ) {
15174
15175                         type = 5121;
15176
15177                 } else if ( array instanceof Uint8ClampedArray ) {
15178
15179                         type = 5121;
15180
15181                 }
15182
15183                 return {
15184                         buffer: buffer,
15185                         type: type,
15186                         bytesPerElement: array.BYTES_PER_ELEMENT,
15187                         version: attribute.version
15188                 };
15189
15190         }
15191
15192         function updateBuffer( buffer, attribute, bufferType ) {
15193
15194                 const array = attribute.array;
15195                 const updateRange = attribute.updateRange;
15196
15197                 gl.bindBuffer( bufferType, buffer );
15198
15199                 if ( updateRange.count === - 1 ) {
15200
15201                         // Not using update ranges
15202
15203                         gl.bufferSubData( bufferType, 0, array );
15204
15205                 } else {
15206
15207                         if ( isWebGL2 ) {
15208
15209                                 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
15210                                         array, updateRange.offset, updateRange.count );
15211
15212                         } else {
15213
15214                                 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
15215                                         array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
15216
15217                         }
15218
15219                         updateRange.count = - 1; // reset range
15220
15221                 }
15222
15223         }
15224
15225         //
15226
15227         function get( attribute ) {
15228
15229                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
15230
15231                 return buffers.get( attribute );
15232
15233         }
15234
15235         function remove( attribute ) {
15236
15237                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
15238
15239                 const data = buffers.get( attribute );
15240
15241                 if ( data ) {
15242
15243                         gl.deleteBuffer( data.buffer );
15244
15245                         buffers.delete( attribute );
15246
15247                 }
15248
15249         }
15250
15251         function update( attribute, bufferType ) {
15252
15253                 if ( attribute.isGLBufferAttribute ) {
15254
15255                         const cached = buffers.get( attribute );
15256
15257                         if ( ! cached || cached.version < attribute.version ) {
15258
15259                                 buffers.set( attribute, {
15260                                         buffer: attribute.buffer,
15261                                         type: attribute.type,
15262                                         bytesPerElement: attribute.elementSize,
15263                                         version: attribute.version
15264                                 } );
15265
15266                         }
15267
15268                         return;
15269
15270                 }
15271
15272                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
15273
15274                 const data = buffers.get( attribute );
15275
15276                 if ( data === undefined ) {
15277
15278                         buffers.set( attribute, createBuffer( attribute, bufferType ) );
15279
15280                 } else if ( data.version < attribute.version ) {
15281
15282                         updateBuffer( data.buffer, attribute, bufferType );
15283
15284                         data.version = attribute.version;
15285
15286                 }
15287
15288         }
15289
15290         return {
15291
15292                 get: get,
15293                 remove: remove,
15294                 update: update
15295
15296         };
15297
15298     }
15299
15300     class PlaneGeometry extends BufferGeometry {
15301
15302         constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
15303
15304                 super();
15305                 this.type = 'PlaneGeometry';
15306
15307                 this.parameters = {
15308                         width: width,
15309                         height: height,
15310                         widthSegments: widthSegments,
15311                         heightSegments: heightSegments
15312                 };
15313
15314                 const width_half = width / 2;
15315                 const height_half = height / 2;
15316
15317                 const gridX = Math.floor( widthSegments );
15318                 const gridY = Math.floor( heightSegments );
15319
15320                 const gridX1 = gridX + 1;
15321                 const gridY1 = gridY + 1;
15322
15323                 const segment_width = width / gridX;
15324                 const segment_height = height / gridY;
15325
15326                 //
15327
15328                 const indices = [];
15329                 const vertices = [];
15330                 const normals = [];
15331                 const uvs = [];
15332
15333                 for ( let iy = 0; iy < gridY1; iy ++ ) {
15334
15335                         const y = iy * segment_height - height_half;
15336
15337                         for ( let ix = 0; ix < gridX1; ix ++ ) {
15338
15339                                 const x = ix * segment_width - width_half;
15340
15341                                 vertices.push( x, - y, 0 );
15342
15343                                 normals.push( 0, 0, 1 );
15344
15345                                 uvs.push( ix / gridX );
15346                                 uvs.push( 1 - ( iy / gridY ) );
15347
15348                         }
15349
15350                 }
15351
15352                 for ( let iy = 0; iy < gridY; iy ++ ) {
15353
15354                         for ( let ix = 0; ix < gridX; ix ++ ) {
15355
15356                                 const a = ix + gridX1 * iy;
15357                                 const b = ix + gridX1 * ( iy + 1 );
15358                                 const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
15359                                 const d = ( ix + 1 ) + gridX1 * iy;
15360
15361                                 indices.push( a, b, d );
15362                                 indices.push( b, c, d );
15363
15364                         }
15365
15366                 }
15367
15368                 this.setIndex( indices );
15369                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
15370                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
15371                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
15372
15373         }
15374
15375         static fromJSON( data ) {
15376
15377                 return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments );
15378
15379         }
15380
15381     }
15382
15383     var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
15384
15385     var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
15386
15387     var alphatest_fragment = "#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTest ) discard;\n#endif";
15388
15389     var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif";
15390
15391     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.roughness );\n\t#endif\n#endif";
15392
15393     var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
15394
15395     var begin_vertex = "vec3 transformed = vec3( position );";
15396
15397     var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
15398
15399     var bsdfs = "vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat V_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_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( V * 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}\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_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif";
15400
15401     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, float faceDirection ) {\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 ) * faceDirection;\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";
15402
15403     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";
15404
15405     var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
15406
15407     var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
15408
15409     var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
15410
15411     var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif";
15412
15413     var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif";
15414
15415     var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";
15416
15417     var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif";
15418
15419     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 max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\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 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 USE_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}\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}";
15420
15421     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";
15422
15423     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";
15424
15425     var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
15426
15427     var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif";
15428
15429     var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
15430
15431     var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
15432
15433     var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
15434
15435     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}";
15436
15437     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\tenvColor = envMapTexelToLinear( envColor );\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#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";
15438
15439     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";
15440
15441     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";
15442
15443     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";
15444
15445     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";
15446
15447     var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif";
15448
15449     var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif";
15450
15451     var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif";
15452
15453     var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\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";
15454
15455     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}";
15456
15457     var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tlightMapIrradiance *= PI;\n\t#endif\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif";
15458
15459     var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
15460
15461     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.normal );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry.normal );\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\tgetPointLightInfo( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = 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\tgetSpotLightInfo( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = 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\tgetDirectionalLightInfo( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = 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.normal );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry.normal );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif";
15462
15463     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 vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\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 getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.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 getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.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 getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.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 vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif";
15464
15465     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 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec;\n\t\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\t\treflectVec = reflect( - viewDir, normal );\n\t\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\t#else\n\t\t\t\treflectVec = refract( - viewDir, normal, refractionRatio );\n\t\t\t#endif\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif";
15466
15467     var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
15468
15469     var lights_toon_pars_fragment = "varying vec3 vViewPosition;\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\treflectedLight.directDiffuse += irradiance * BRDF_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_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)";
15470
15471     var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
15472
15473     var lights_phong_pars_fragment = "varying vec3 vViewPosition;\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\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, 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_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)";
15474
15475     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.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= specularColorMapTexelToLinear( texture2D( specularColorMap, vUv ) ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\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 = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= sheenColorMapTexelToLinear( texture2D( sheenColorMap, vUv ) ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif";
15476
15477     var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\tvec3 FssEss = specularColor * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.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}\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.roughness;\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#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\treflectedLight.directDiffuse += irradiance * BRDF_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_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 USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += 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}";
15478
15479     var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_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\tgetPointLightInfo( 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\tgetSpotLightInfo( 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\tgetDirectionalLightInfo( 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.normal );\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.normal );\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";
15480
15481     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 += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif";
15482
15483     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";
15484
15485     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";
15486
15487     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";
15488
15489     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";
15490
15491     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";
15492
15493     var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif";
15494
15495     var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
15496
15497     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";
15498
15499     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";
15500
15501     var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
15502
15503     var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
15504
15505     var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1, 2 ) * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif";
15506
15507     var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform vec2 morphTargetsTextureSize;\n\t\tvec3 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset, const in int stride ) {\n\t\t\tfloat texelIndex = float( vertexIndex * stride + offset );\n\t\t\tfloat y = floor( texelIndex / morphTargetsTextureSize.x );\n\t\t\tfloat x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tvec3 morphUV = vec3( ( x + 0.5 ) / morphTargetsTextureSize.x, y / morphTargetsTextureSize.y, morphTargetIndex );\n\t\t\treturn texture( morphTargetsTexture, morphUV ).xyz;\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif";
15508
15509     var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\t#ifndef USE_MORPHNORMALS\n\t\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0, 1 ) * morphTargetInfluences[ i ];\n\t\t\t#else\n\t\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0, 2 ) * morphTargetInfluences[ i ];\n\t\t\t#endif\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif";
15510
15511     var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#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 * faceDirection;\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 * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\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;";
15512
15513     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 * faceDirection;\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, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif";
15514
15515     var normal_pars_fragment = "#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";
15516
15517     var normal_pars_vertex = "#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";
15518
15519     var normal_vertex = "#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";
15520
15521     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, float faceDirection ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif";
15522
15523     var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif";
15524
15525     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, faceDirection );\n\t#endif\n#endif";
15526
15527     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";
15528
15529     var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );";
15530
15531     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}";
15532
15533     var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
15534
15535     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;";
15536
15537     var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
15538
15539     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";
15540
15541     var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
15542
15543     var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
15544
15545     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";
15546
15547     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";
15548
15549     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";
15550
15551     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}";
15552
15553     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";
15554
15555     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";
15556
15557     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";
15558
15559     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";
15560
15561     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";
15562
15563     var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
15564
15565     var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
15566
15567     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; }";
15568
15569     var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tfloat transmissionAlpha = 1.0;\n\tfloat transmissionFactor = transmission;\n\tfloat thicknessFactor = thickness;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\ttransmissionFactor *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tthicknessFactor *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n\t\tattenuationColor, attenuationDistance );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n\ttransmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );\n#endif";
15570
15571     var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( float roughness, float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( vec2 fragCoord, float roughness, float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( vec3 radiance, float transmissionDistance, vec3 attenuationColor, float attenuationDistance ) {\n\t\tif ( attenuationDistance == 0.0 ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 specularColor, float specularF90,\n\t\tvec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness,\n\t\tvec3 attenuationColor, float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif";
15572
15573     var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif";
15574
15575     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";
15576
15577     var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
15578
15579     var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
15580
15581     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";
15582
15583     var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif";
15584
15585     var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )\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";
15586
15587     const vertex$g = "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}";
15588
15589     const fragment$g = "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}";
15590
15591     const vertex$f = "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}";
15592
15593     const fragment$f = "#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}";
15594
15595     const vertex$e = "#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}";
15596
15597     const fragment$e = "#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 <alphatest_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}";
15598
15599     const vertex$d = "#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}";
15600
15601     const fragment$d = "#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 <alphatest_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}";
15602
15603     const vertex$c = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}";
15604
15605     const fragment$c = "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}";
15606
15607     const vertex$b = "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}";
15608
15609     const fragment$b = "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\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
15610
15611     const vertex$a = "#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#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\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 <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}";
15612
15613     const fragment$a = "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 <alphatest_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\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\t#include <output_fragment>\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}";
15614
15615     const vertex$9 = "#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}";
15616
15617     const fragment$9 = "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 <alphatest_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_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_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\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}";
15618
15619     const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\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 <normal_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#include <normal_vertex>\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}";
15620
15621     const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\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 <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <normal_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\t#include <output_fragment>\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}";
15622
15623     const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <normal_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\t#include <normal_vertex>\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}";
15624
15625     const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <normal_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}";
15626
15627     const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\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 <normal_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 <normal_vertex>\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}";
15628
15629     const fragment$6 = "#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 <alphatest_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 <normal_pars_fragment>\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\t#include <output_fragment>\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}";
15630
15631     const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\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 <normal_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 <normal_vertex>\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#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}";
15632
15633     const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\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 <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_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 <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_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#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 <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 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include <transmission_fragment>\n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - clearcoat * Fcc ) + clearcoatSpecular * clearcoat;\n\t#endif\n\t#include <output_fragment>\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}";
15634
15635     const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\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 <normal_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 <normal_vertex>\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}";
15636
15637     const fragment$4 = "#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 <alphatest_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 <normal_pars_fragment>\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\t#include <output_fragment>\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}";
15638
15639     const vertex$3 = "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}";
15640
15641     const fragment$3 = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <alphatest_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\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
15642
15643     const vertex$2 = "#include <common>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\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 <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
15644
15645     const fragment$2 = "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}";
15646
15647     const vertex$1 = "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}";
15648
15649     const fragment$1 = "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 <alphatest_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\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
15650
15651     const ShaderChunk = {
15652         alphamap_fragment: alphamap_fragment,
15653         alphamap_pars_fragment: alphamap_pars_fragment,
15654         alphatest_fragment: alphatest_fragment,
15655         alphatest_pars_fragment: alphatest_pars_fragment,
15656         aomap_fragment: aomap_fragment,
15657         aomap_pars_fragment: aomap_pars_fragment,
15658         begin_vertex: begin_vertex,
15659         beginnormal_vertex: beginnormal_vertex,
15660         bsdfs: bsdfs,
15661         bumpmap_pars_fragment: bumpmap_pars_fragment,
15662         clipping_planes_fragment: clipping_planes_fragment,
15663         clipping_planes_pars_fragment: clipping_planes_pars_fragment,
15664         clipping_planes_pars_vertex: clipping_planes_pars_vertex,
15665         clipping_planes_vertex: clipping_planes_vertex,
15666         color_fragment: color_fragment,
15667         color_pars_fragment: color_pars_fragment,
15668         color_pars_vertex: color_pars_vertex,
15669         color_vertex: color_vertex,
15670         common: common$1,
15671         cube_uv_reflection_fragment: cube_uv_reflection_fragment,
15672         defaultnormal_vertex: defaultnormal_vertex,
15673         displacementmap_pars_vertex: displacementmap_pars_vertex,
15674         displacementmap_vertex: displacementmap_vertex,
15675         emissivemap_fragment: emissivemap_fragment,
15676         emissivemap_pars_fragment: emissivemap_pars_fragment,
15677         encodings_fragment: encodings_fragment,
15678         encodings_pars_fragment: encodings_pars_fragment,
15679         envmap_fragment: envmap_fragment,
15680         envmap_common_pars_fragment: envmap_common_pars_fragment,
15681         envmap_pars_fragment: envmap_pars_fragment,
15682         envmap_pars_vertex: envmap_pars_vertex,
15683         envmap_physical_pars_fragment: envmap_physical_pars_fragment,
15684         envmap_vertex: envmap_vertex,
15685         fog_vertex: fog_vertex,
15686         fog_pars_vertex: fog_pars_vertex,
15687         fog_fragment: fog_fragment,
15688         fog_pars_fragment: fog_pars_fragment,
15689         gradientmap_pars_fragment: gradientmap_pars_fragment,
15690         lightmap_fragment: lightmap_fragment,
15691         lightmap_pars_fragment: lightmap_pars_fragment,
15692         lights_lambert_vertex: lights_lambert_vertex,
15693         lights_pars_begin: lights_pars_begin,
15694         lights_toon_fragment: lights_toon_fragment,
15695         lights_toon_pars_fragment: lights_toon_pars_fragment,
15696         lights_phong_fragment: lights_phong_fragment,
15697         lights_phong_pars_fragment: lights_phong_pars_fragment,
15698         lights_physical_fragment: lights_physical_fragment,
15699         lights_physical_pars_fragment: lights_physical_pars_fragment,
15700         lights_fragment_begin: lights_fragment_begin,
15701         lights_fragment_maps: lights_fragment_maps,
15702         lights_fragment_end: lights_fragment_end,
15703         logdepthbuf_fragment: logdepthbuf_fragment,
15704         logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
15705         logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
15706         logdepthbuf_vertex: logdepthbuf_vertex,
15707         map_fragment: map_fragment,
15708         map_pars_fragment: map_pars_fragment,
15709         map_particle_fragment: map_particle_fragment,
15710         map_particle_pars_fragment: map_particle_pars_fragment,
15711         metalnessmap_fragment: metalnessmap_fragment,
15712         metalnessmap_pars_fragment: metalnessmap_pars_fragment,
15713         morphnormal_vertex: morphnormal_vertex,
15714         morphtarget_pars_vertex: morphtarget_pars_vertex,
15715         morphtarget_vertex: morphtarget_vertex,
15716         normal_fragment_begin: normal_fragment_begin,
15717         normal_fragment_maps: normal_fragment_maps,
15718         normal_pars_fragment: normal_pars_fragment,
15719         normal_pars_vertex: normal_pars_vertex,
15720         normal_vertex: normal_vertex,
15721         normalmap_pars_fragment: normalmap_pars_fragment,
15722         clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
15723         clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
15724         clearcoat_pars_fragment: clearcoat_pars_fragment,
15725         output_fragment: output_fragment,
15726         packing: packing,
15727         premultiplied_alpha_fragment: premultiplied_alpha_fragment,
15728         project_vertex: project_vertex,
15729         dithering_fragment: dithering_fragment,
15730         dithering_pars_fragment: dithering_pars_fragment,
15731         roughnessmap_fragment: roughnessmap_fragment,
15732         roughnessmap_pars_fragment: roughnessmap_pars_fragment,
15733         shadowmap_pars_fragment: shadowmap_pars_fragment,
15734         shadowmap_pars_vertex: shadowmap_pars_vertex,
15735         shadowmap_vertex: shadowmap_vertex,
15736         shadowmask_pars_fragment: shadowmask_pars_fragment,
15737         skinbase_vertex: skinbase_vertex,
15738         skinning_pars_vertex: skinning_pars_vertex,
15739         skinning_vertex: skinning_vertex,
15740         skinnormal_vertex: skinnormal_vertex,
15741         specularmap_fragment: specularmap_fragment,
15742         specularmap_pars_fragment: specularmap_pars_fragment,
15743         tonemapping_fragment: tonemapping_fragment,
15744         tonemapping_pars_fragment: tonemapping_pars_fragment,
15745         transmission_fragment: transmission_fragment,
15746         transmission_pars_fragment: transmission_pars_fragment,
15747         uv_pars_fragment: uv_pars_fragment,
15748         uv_pars_vertex: uv_pars_vertex,
15749         uv_vertex: uv_vertex,
15750         uv2_pars_fragment: uv2_pars_fragment,
15751         uv2_pars_vertex: uv2_pars_vertex,
15752         uv2_vertex: uv2_vertex,
15753         worldpos_vertex: worldpos_vertex,
15754
15755         background_vert: vertex$g,
15756         background_frag: fragment$g,
15757         cube_vert: vertex$f,
15758         cube_frag: fragment$f,
15759         depth_vert: vertex$e,
15760         depth_frag: fragment$e,
15761         distanceRGBA_vert: vertex$d,
15762         distanceRGBA_frag: fragment$d,
15763         equirect_vert: vertex$c,
15764         equirect_frag: fragment$c,
15765         linedashed_vert: vertex$b,
15766         linedashed_frag: fragment$b,
15767         meshbasic_vert: vertex$a,
15768         meshbasic_frag: fragment$a,
15769         meshlambert_vert: vertex$9,
15770         meshlambert_frag: fragment$9,
15771         meshmatcap_vert: vertex$8,
15772         meshmatcap_frag: fragment$8,
15773         meshnormal_vert: vertex$7,
15774         meshnormal_frag: fragment$7,
15775         meshphong_vert: vertex$6,
15776         meshphong_frag: fragment$6,
15777         meshphysical_vert: vertex$5,
15778         meshphysical_frag: fragment$5,
15779         meshtoon_vert: vertex$4,
15780         meshtoon_frag: fragment$4,
15781         points_vert: vertex$3,
15782         points_frag: fragment$3,
15783         shadow_vert: vertex$2,
15784         shadow_frag: fragment$2,
15785         sprite_vert: vertex$1,
15786         sprite_frag: fragment$1
15787     };
15788
15789     /**
15790      * Uniforms library for shared webgl shaders
15791      */
15792
15793     const UniformsLib = {
15794
15795         common: {
15796
15797                 diffuse: { value: new Color( 0xffffff ) },
15798                 opacity: { value: 1.0 },
15799
15800                 map: { value: null },
15801                 uvTransform: { value: new Matrix3() },
15802                 uv2Transform: { value: new Matrix3() },
15803
15804                 alphaMap: { value: null },
15805                 alphaTest: { value: 0 }
15806
15807         },
15808
15809         specularmap: {
15810
15811                 specularMap: { value: null },
15812
15813         },
15814
15815         envmap: {
15816
15817                 envMap: { value: null },
15818                 flipEnvMap: { value: - 1 },
15819                 reflectivity: { value: 1.0 }, // basic, lambert, phong
15820                 ior: { value: 1.5 }, // standard, physical
15821                 refractionRatio: { value: 0.98 },
15822                 maxMipLevel: { value: 0 }
15823
15824         },
15825
15826         aomap: {
15827
15828                 aoMap: { value: null },
15829                 aoMapIntensity: { value: 1 }
15830
15831         },
15832
15833         lightmap: {
15834
15835                 lightMap: { value: null },
15836                 lightMapIntensity: { value: 1 }
15837
15838         },
15839
15840         emissivemap: {
15841
15842                 emissiveMap: { value: null }
15843
15844         },
15845
15846         bumpmap: {
15847
15848                 bumpMap: { value: null },
15849                 bumpScale: { value: 1 }
15850
15851         },
15852
15853         normalmap: {
15854
15855                 normalMap: { value: null },
15856                 normalScale: { value: new Vector2( 1, 1 ) }
15857
15858         },
15859
15860         displacementmap: {
15861
15862                 displacementMap: { value: null },
15863                 displacementScale: { value: 1 },
15864                 displacementBias: { value: 0 }
15865
15866         },
15867
15868         roughnessmap: {
15869
15870                 roughnessMap: { value: null }
15871
15872         },
15873
15874         metalnessmap: {
15875
15876                 metalnessMap: { value: null }
15877
15878         },
15879
15880         gradientmap: {
15881
15882                 gradientMap: { value: null }
15883
15884         },
15885
15886         fog: {
15887
15888                 fogDensity: { value: 0.00025 },
15889                 fogNear: { value: 1 },
15890                 fogFar: { value: 2000 },
15891                 fogColor: { value: new Color( 0xffffff ) }
15892
15893         },
15894
15895         lights: {
15896
15897                 ambientLightColor: { value: [] },
15898
15899                 lightProbe: { value: [] },
15900
15901                 directionalLights: { value: [], properties: {
15902                         direction: {},
15903                         color: {}
15904                 } },
15905
15906                 directionalLightShadows: { value: [], properties: {
15907                         shadowBias: {},
15908                         shadowNormalBias: {},
15909                         shadowRadius: {},
15910                         shadowMapSize: {}
15911                 } },
15912
15913                 directionalShadowMap: { value: [] },
15914                 directionalShadowMatrix: { value: [] },
15915
15916                 spotLights: { value: [], properties: {
15917                         color: {},
15918                         position: {},
15919                         direction: {},
15920                         distance: {},
15921                         coneCos: {},
15922                         penumbraCos: {},
15923                         decay: {}
15924                 } },
15925
15926                 spotLightShadows: { value: [], properties: {
15927                         shadowBias: {},
15928                         shadowNormalBias: {},
15929                         shadowRadius: {},
15930                         shadowMapSize: {}
15931                 } },
15932
15933                 spotShadowMap: { value: [] },
15934                 spotShadowMatrix: { value: [] },
15935
15936                 pointLights: { value: [], properties: {
15937                         color: {},
15938                         position: {},
15939                         decay: {},
15940                         distance: {}
15941                 } },
15942
15943                 pointLightShadows: { value: [], properties: {
15944                         shadowBias: {},
15945                         shadowNormalBias: {},
15946                         shadowRadius: {},
15947                         shadowMapSize: {},
15948                         shadowCameraNear: {},
15949                         shadowCameraFar: {}
15950                 } },
15951
15952                 pointShadowMap: { value: [] },
15953                 pointShadowMatrix: { value: [] },
15954
15955                 hemisphereLights: { value: [], properties: {
15956                         direction: {},
15957                         skyColor: {},
15958                         groundColor: {}
15959                 } },
15960
15961                 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
15962                 rectAreaLights: { value: [], properties: {
15963                         color: {},
15964                         position: {},
15965                         width: {},
15966                         height: {}
15967                 } },
15968
15969                 ltc_1: { value: null },
15970                 ltc_2: { value: null }
15971
15972         },
15973
15974         points: {
15975
15976                 diffuse: { value: new Color( 0xffffff ) },
15977                 opacity: { value: 1.0 },
15978                 size: { value: 1.0 },
15979                 scale: { value: 1.0 },
15980                 map: { value: null },
15981                 alphaMap: { value: null },
15982                 alphaTest: { value: 0 },
15983                 uvTransform: { value: new Matrix3() }
15984
15985         },
15986
15987         sprite: {
15988
15989                 diffuse: { value: new Color( 0xffffff ) },
15990                 opacity: { value: 1.0 },
15991                 center: { value: new Vector2( 0.5, 0.5 ) },
15992                 rotation: { value: 0.0 },
15993                 map: { value: null },
15994                 alphaMap: { value: null },
15995                 alphaTest: { value: 0 },
15996                 uvTransform: { value: new Matrix3() }
15997
15998         }
15999
16000     };
16001
16002     const ShaderLib = {
16003
16004         basic: {
16005
16006                 uniforms: mergeUniforms( [
16007                         UniformsLib.common,
16008                         UniformsLib.specularmap,
16009                         UniformsLib.envmap,
16010                         UniformsLib.aomap,
16011                         UniformsLib.lightmap,
16012                         UniformsLib.fog
16013                 ] ),
16014
16015                 vertexShader: ShaderChunk.meshbasic_vert,
16016                 fragmentShader: ShaderChunk.meshbasic_frag
16017
16018         },
16019
16020         lambert: {
16021
16022                 uniforms: mergeUniforms( [
16023                         UniformsLib.common,
16024                         UniformsLib.specularmap,
16025                         UniformsLib.envmap,
16026                         UniformsLib.aomap,
16027                         UniformsLib.lightmap,
16028                         UniformsLib.emissivemap,
16029                         UniformsLib.fog,
16030                         UniformsLib.lights,
16031                         {
16032                                 emissive: { value: new Color( 0x000000 ) }
16033                         }
16034                 ] ),
16035
16036                 vertexShader: ShaderChunk.meshlambert_vert,
16037                 fragmentShader: ShaderChunk.meshlambert_frag
16038
16039         },
16040
16041         phong: {
16042
16043                 uniforms: mergeUniforms( [
16044                         UniformsLib.common,
16045                         UniformsLib.specularmap,
16046                         UniformsLib.envmap,
16047                         UniformsLib.aomap,
16048                         UniformsLib.lightmap,
16049                         UniformsLib.emissivemap,
16050                         UniformsLib.bumpmap,
16051                         UniformsLib.normalmap,
16052                         UniformsLib.displacementmap,
16053                         UniformsLib.fog,
16054                         UniformsLib.lights,
16055                         {
16056                                 emissive: { value: new Color( 0x000000 ) },
16057                                 specular: { value: new Color( 0x111111 ) },
16058                                 shininess: { value: 30 }
16059                         }
16060                 ] ),
16061
16062                 vertexShader: ShaderChunk.meshphong_vert,
16063                 fragmentShader: ShaderChunk.meshphong_frag
16064
16065         },
16066
16067         standard: {
16068
16069                 uniforms: mergeUniforms( [
16070                         UniformsLib.common,
16071                         UniformsLib.envmap,
16072                         UniformsLib.aomap,
16073                         UniformsLib.lightmap,
16074                         UniformsLib.emissivemap,
16075                         UniformsLib.bumpmap,
16076                         UniformsLib.normalmap,
16077                         UniformsLib.displacementmap,
16078                         UniformsLib.roughnessmap,
16079                         UniformsLib.metalnessmap,
16080                         UniformsLib.fog,
16081                         UniformsLib.lights,
16082                         {
16083                                 emissive: { value: new Color( 0x000000 ) },
16084                                 roughness: { value: 1.0 },
16085                                 metalness: { value: 0.0 },
16086                                 envMapIntensity: { value: 1 } // temporary
16087                         }
16088                 ] ),
16089
16090                 vertexShader: ShaderChunk.meshphysical_vert,
16091                 fragmentShader: ShaderChunk.meshphysical_frag
16092
16093         },
16094
16095         toon: {
16096
16097                 uniforms: mergeUniforms( [
16098                         UniformsLib.common,
16099                         UniformsLib.aomap,
16100                         UniformsLib.lightmap,
16101                         UniformsLib.emissivemap,
16102                         UniformsLib.bumpmap,
16103                         UniformsLib.normalmap,
16104                         UniformsLib.displacementmap,
16105                         UniformsLib.gradientmap,
16106                         UniformsLib.fog,
16107                         UniformsLib.lights,
16108                         {
16109                                 emissive: { value: new Color( 0x000000 ) }
16110                         }
16111                 ] ),
16112
16113                 vertexShader: ShaderChunk.meshtoon_vert,
16114                 fragmentShader: ShaderChunk.meshtoon_frag
16115
16116         },
16117
16118         matcap: {
16119
16120                 uniforms: mergeUniforms( [
16121                         UniformsLib.common,
16122                         UniformsLib.bumpmap,
16123                         UniformsLib.normalmap,
16124                         UniformsLib.displacementmap,
16125                         UniformsLib.fog,
16126                         {
16127                                 matcap: { value: null }
16128                         }
16129                 ] ),
16130
16131                 vertexShader: ShaderChunk.meshmatcap_vert,
16132                 fragmentShader: ShaderChunk.meshmatcap_frag
16133
16134         },
16135
16136         points: {
16137
16138                 uniforms: mergeUniforms( [
16139                         UniformsLib.points,
16140                         UniformsLib.fog
16141                 ] ),
16142
16143                 vertexShader: ShaderChunk.points_vert,
16144                 fragmentShader: ShaderChunk.points_frag
16145
16146         },
16147
16148         dashed: {
16149
16150                 uniforms: mergeUniforms( [
16151                         UniformsLib.common,
16152                         UniformsLib.fog,
16153                         {
16154                                 scale: { value: 1 },
16155                                 dashSize: { value: 1 },
16156                                 totalSize: { value: 2 }
16157                         }
16158                 ] ),
16159
16160                 vertexShader: ShaderChunk.linedashed_vert,
16161                 fragmentShader: ShaderChunk.linedashed_frag
16162
16163         },
16164
16165         depth: {
16166
16167                 uniforms: mergeUniforms( [
16168                         UniformsLib.common,
16169                         UniformsLib.displacementmap
16170                 ] ),
16171
16172                 vertexShader: ShaderChunk.depth_vert,
16173                 fragmentShader: ShaderChunk.depth_frag
16174
16175         },
16176
16177         normal: {
16178
16179                 uniforms: mergeUniforms( [
16180                         UniformsLib.common,
16181                         UniformsLib.bumpmap,
16182                         UniformsLib.normalmap,
16183                         UniformsLib.displacementmap,
16184                         {
16185                                 opacity: { value: 1.0 }
16186                         }
16187                 ] ),
16188
16189                 vertexShader: ShaderChunk.meshnormal_vert,
16190                 fragmentShader: ShaderChunk.meshnormal_frag
16191
16192         },
16193
16194         sprite: {
16195
16196                 uniforms: mergeUniforms( [
16197                         UniformsLib.sprite,
16198                         UniformsLib.fog
16199                 ] ),
16200
16201                 vertexShader: ShaderChunk.sprite_vert,
16202                 fragmentShader: ShaderChunk.sprite_frag
16203
16204         },
16205
16206         background: {
16207
16208                 uniforms: {
16209                         uvTransform: { value: new Matrix3() },
16210                         t2D: { value: null },
16211                 },
16212
16213                 vertexShader: ShaderChunk.background_vert,
16214                 fragmentShader: ShaderChunk.background_frag
16215
16216         },
16217         /* -------------------------------------------------------------------------
16218         //      Cube map shader
16219          ------------------------------------------------------------------------- */
16220
16221         cube: {
16222
16223                 uniforms: mergeUniforms( [
16224                         UniformsLib.envmap,
16225                         {
16226                                 opacity: { value: 1.0 }
16227                         }
16228                 ] ),
16229
16230                 vertexShader: ShaderChunk.cube_vert,
16231                 fragmentShader: ShaderChunk.cube_frag
16232
16233         },
16234
16235         equirect: {
16236
16237                 uniforms: {
16238                         tEquirect: { value: null },
16239                 },
16240
16241                 vertexShader: ShaderChunk.equirect_vert,
16242                 fragmentShader: ShaderChunk.equirect_frag
16243
16244         },
16245
16246         distanceRGBA: {
16247
16248                 uniforms: mergeUniforms( [
16249                         UniformsLib.common,
16250                         UniformsLib.displacementmap,
16251                         {
16252                                 referencePosition: { value: new Vector3() },
16253                                 nearDistance: { value: 1 },
16254                                 farDistance: { value: 1000 }
16255                         }
16256                 ] ),
16257
16258                 vertexShader: ShaderChunk.distanceRGBA_vert,
16259                 fragmentShader: ShaderChunk.distanceRGBA_frag
16260
16261         },
16262
16263         shadow: {
16264
16265                 uniforms: mergeUniforms( [
16266                         UniformsLib.lights,
16267                         UniformsLib.fog,
16268                         {
16269                                 color: { value: new Color( 0x00000 ) },
16270                                 opacity: { value: 1.0 }
16271                         },
16272                 ] ),
16273
16274                 vertexShader: ShaderChunk.shadow_vert,
16275                 fragmentShader: ShaderChunk.shadow_frag
16276
16277         }
16278
16279     };
16280
16281     ShaderLib.physical = {
16282
16283         uniforms: mergeUniforms( [
16284                 ShaderLib.standard.uniforms,
16285                 {
16286                         clearcoat: { value: 0 },
16287                         clearcoatMap: { value: null },
16288                         clearcoatRoughness: { value: 0 },
16289                         clearcoatRoughnessMap: { value: null },
16290                         clearcoatNormalScale: { value: new Vector2( 1, 1 ) },
16291                         clearcoatNormalMap: { value: null },
16292                         sheen: { value: 0 },
16293                         sheenColor: { value: new Color( 0x000000 ) },
16294                         sheenColorMap: { value: null },
16295                         sheenRoughness: { value: 0 },
16296                         sheenRoughnessMap: { value: null },
16297                         transmission: { value: 0 },
16298                         transmissionMap: { value: null },
16299                         transmissionSamplerSize: { value: new Vector2() },
16300                         transmissionSamplerMap: { value: null },
16301                         thickness: { value: 0 },
16302                         thicknessMap: { value: null },
16303                         attenuationDistance: { value: 0 },
16304                         attenuationColor: { value: new Color( 0x000000 ) },
16305                         specularIntensity: { value: 0 },
16306                         specularIntensityMap: { value: null },
16307                         specularColor: { value: new Color( 1, 1, 1 ) },
16308                         specularColorMap: { value: null },
16309                 }
16310         ] ),
16311
16312         vertexShader: ShaderChunk.meshphysical_vert,
16313         fragmentShader: ShaderChunk.meshphysical_frag
16314
16315     };
16316
16317     function WebGLBackground( renderer, cubemaps, state, objects, premultipliedAlpha ) {
16318
16319         const clearColor = new Color( 0x000000 );
16320         let clearAlpha = 0;
16321
16322         let planeMesh;
16323         let boxMesh;
16324
16325         let currentBackground = null;
16326         let currentBackgroundVersion = 0;
16327         let currentTonemapping = null;
16328
16329         function render( renderList, scene ) {
16330
16331                 let forceClear = false;
16332                 let background = scene.isScene === true ? scene.background : null;
16333
16334                 if ( background && background.isTexture ) {
16335
16336                         background = cubemaps.get( background );
16337
16338                 }
16339
16340                 // Ignore background in AR
16341                 // TODO: Reconsider this.
16342
16343                 const xr = renderer.xr;
16344                 const session = xr.getSession && xr.getSession();
16345
16346                 if ( session && session.environmentBlendMode === 'additive' ) {
16347
16348                         background = null;
16349
16350                 }
16351
16352                 if ( background === null ) {
16353
16354                         setClear( clearColor, clearAlpha );
16355
16356                 } else if ( background && background.isColor ) {
16357
16358                         setClear( background, 1 );
16359                         forceClear = true;
16360
16361                 }
16362
16363                 if ( renderer.autoClear || forceClear ) {
16364
16365                         renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
16366
16367                 }
16368
16369                 if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) {
16370
16371                         if ( boxMesh === undefined ) {
16372
16373                                 boxMesh = new Mesh(
16374                                         new BoxGeometry( 1, 1, 1 ),
16375                                         new ShaderMaterial( {
16376                                                 name: 'BackgroundCubeMaterial',
16377                                                 uniforms: cloneUniforms( ShaderLib.cube.uniforms ),
16378                                                 vertexShader: ShaderLib.cube.vertexShader,
16379                                                 fragmentShader: ShaderLib.cube.fragmentShader,
16380                                                 side: BackSide,
16381                                                 depthTest: false,
16382                                                 depthWrite: false,
16383                                                 fog: false
16384                                         } )
16385                                 );
16386
16387                                 boxMesh.geometry.deleteAttribute( 'normal' );
16388                                 boxMesh.geometry.deleteAttribute( 'uv' );
16389
16390                                 boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
16391
16392                                         this.matrixWorld.copyPosition( camera.matrixWorld );
16393
16394                                 };
16395
16396                                 // enable code injection for non-built-in material
16397                                 Object.defineProperty( boxMesh.material, 'envMap', {
16398
16399                                         get: function () {
16400
16401                                                 return this.uniforms.envMap.value;
16402
16403                                         }
16404
16405                                 } );
16406
16407                                 objects.update( boxMesh );
16408
16409                         }
16410
16411                         boxMesh.material.uniforms.envMap.value = background;
16412                         boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1;
16413
16414                         if ( currentBackground !== background ||
16415                                 currentBackgroundVersion !== background.version ||
16416                                 currentTonemapping !== renderer.toneMapping ) {
16417
16418                                 boxMesh.material.needsUpdate = true;
16419
16420                                 currentBackground = background;
16421                                 currentBackgroundVersion = background.version;
16422                                 currentTonemapping = renderer.toneMapping;
16423
16424                         }
16425
16426                         // push to the pre-sorted opaque render list
16427                         renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
16428
16429                 } else if ( background && background.isTexture ) {
16430
16431                         if ( planeMesh === undefined ) {
16432
16433                                 planeMesh = new Mesh(
16434                                         new PlaneGeometry( 2, 2 ),
16435                                         new ShaderMaterial( {
16436                                                 name: 'BackgroundMaterial',
16437                                                 uniforms: cloneUniforms( ShaderLib.background.uniforms ),
16438                                                 vertexShader: ShaderLib.background.vertexShader,
16439                                                 fragmentShader: ShaderLib.background.fragmentShader,
16440                                                 side: FrontSide,
16441                                                 depthTest: false,
16442                                                 depthWrite: false,
16443                                                 fog: false
16444                                         } )
16445                                 );
16446
16447                                 planeMesh.geometry.deleteAttribute( 'normal' );
16448
16449                                 // enable code injection for non-built-in material
16450                                 Object.defineProperty( planeMesh.material, 'map', {
16451
16452                                         get: function () {
16453
16454                                                 return this.uniforms.t2D.value;
16455
16456                                         }
16457
16458                                 } );
16459
16460                                 objects.update( planeMesh );
16461
16462                         }
16463
16464                         planeMesh.material.uniforms.t2D.value = background;
16465
16466                         if ( background.matrixAutoUpdate === true ) {
16467
16468                                 background.updateMatrix();
16469
16470                         }
16471
16472                         planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
16473
16474                         if ( currentBackground !== background ||
16475                                 currentBackgroundVersion !== background.version ||
16476                                 currentTonemapping !== renderer.toneMapping ) {
16477
16478                                 planeMesh.material.needsUpdate = true;
16479
16480                                 currentBackground = background;
16481                                 currentBackgroundVersion = background.version;
16482                                 currentTonemapping = renderer.toneMapping;
16483
16484                         }
16485
16486
16487                         // push to the pre-sorted opaque render list
16488                         renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
16489
16490                 }
16491
16492         }
16493
16494         function setClear( color, alpha ) {
16495
16496                 state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
16497
16498         }
16499
16500         return {
16501
16502                 getClearColor: function () {
16503
16504                         return clearColor;
16505
16506                 },
16507                 setClearColor: function ( color, alpha = 1 ) {
16508
16509                         clearColor.set( color );
16510                         clearAlpha = alpha;
16511                         setClear( clearColor, clearAlpha );
16512
16513                 },
16514                 getClearAlpha: function () {
16515
16516                         return clearAlpha;
16517
16518                 },
16519                 setClearAlpha: function ( alpha ) {
16520
16521                         clearAlpha = alpha;
16522                         setClear( clearColor, clearAlpha );
16523
16524                 },
16525                 render: render
16526
16527         };
16528
16529     }
16530
16531     function WebGLBindingStates( gl, extensions, attributes, capabilities ) {
16532
16533         const maxVertexAttributes = gl.getParameter( 34921 );
16534
16535         const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' );
16536         const vaoAvailable = capabilities.isWebGL2 || extension !== null;
16537
16538         const bindingStates = {};
16539
16540         const defaultState = createBindingState( null );
16541         let currentState = defaultState;
16542
16543         function setup( object, material, program, geometry, index ) {
16544
16545                 let updateBuffers = false;
16546
16547                 if ( vaoAvailable ) {
16548
16549                         const state = getBindingState( geometry, program, material );
16550
16551                         if ( currentState !== state ) {
16552
16553                                 currentState = state;
16554                                 bindVertexArrayObject( currentState.object );
16555
16556                         }
16557
16558                         updateBuffers = needsUpdate( geometry, index );
16559
16560                         if ( updateBuffers ) saveCache( geometry, index );
16561
16562                 } else {
16563
16564                         const wireframe = ( material.wireframe === true );
16565
16566                         if ( currentState.geometry !== geometry.id ||
16567                                 currentState.program !== program.id ||
16568                                 currentState.wireframe !== wireframe ) {
16569
16570                                 currentState.geometry = geometry.id;
16571                                 currentState.program = program.id;
16572                                 currentState.wireframe = wireframe;
16573
16574                                 updateBuffers = true;
16575
16576                         }
16577
16578                 }
16579
16580                 if ( object.isInstancedMesh === true ) {
16581
16582                         updateBuffers = true;
16583
16584                 }
16585
16586                 if ( index !== null ) {
16587
16588                         attributes.update( index, 34963 );
16589
16590                 }
16591
16592                 if ( updateBuffers ) {
16593
16594                         setupVertexAttributes( object, material, program, geometry );
16595
16596                         if ( index !== null ) {
16597
16598                                 gl.bindBuffer( 34963, attributes.get( index ).buffer );
16599
16600                         }
16601
16602                 }
16603
16604         }
16605
16606         function createVertexArrayObject() {
16607
16608                 if ( capabilities.isWebGL2 ) return gl.createVertexArray();
16609
16610                 return extension.createVertexArrayOES();
16611
16612         }
16613
16614         function bindVertexArrayObject( vao ) {
16615
16616                 if ( capabilities.isWebGL2 ) return gl.bindVertexArray( vao );
16617
16618                 return extension.bindVertexArrayOES( vao );
16619
16620         }
16621
16622         function deleteVertexArrayObject( vao ) {
16623
16624                 if ( capabilities.isWebGL2 ) return gl.deleteVertexArray( vao );
16625
16626                 return extension.deleteVertexArrayOES( vao );
16627
16628         }
16629
16630         function getBindingState( geometry, program, material ) {
16631
16632                 const wireframe = ( material.wireframe === true );
16633
16634                 let programMap = bindingStates[ geometry.id ];
16635
16636                 if ( programMap === undefined ) {
16637
16638                         programMap = {};
16639                         bindingStates[ geometry.id ] = programMap;
16640
16641                 }
16642
16643                 let stateMap = programMap[ program.id ];
16644
16645                 if ( stateMap === undefined ) {
16646
16647                         stateMap = {};
16648                         programMap[ program.id ] = stateMap;
16649
16650                 }
16651
16652                 let state = stateMap[ wireframe ];
16653
16654                 if ( state === undefined ) {
16655
16656                         state = createBindingState( createVertexArrayObject() );
16657                         stateMap[ wireframe ] = state;
16658
16659                 }
16660
16661                 return state;
16662
16663         }
16664
16665         function createBindingState( vao ) {
16666
16667                 const newAttributes = [];
16668                 const enabledAttributes = [];
16669                 const attributeDivisors = [];
16670
16671                 for ( let i = 0; i < maxVertexAttributes; i ++ ) {
16672
16673                         newAttributes[ i ] = 0;
16674                         enabledAttributes[ i ] = 0;
16675                         attributeDivisors[ i ] = 0;
16676
16677                 }
16678
16679                 return {
16680
16681                         // for backward compatibility on non-VAO support browser
16682                         geometry: null,
16683                         program: null,
16684                         wireframe: false,
16685
16686                         newAttributes: newAttributes,
16687                         enabledAttributes: enabledAttributes,
16688                         attributeDivisors: attributeDivisors,
16689                         object: vao,
16690                         attributes: {},
16691                         index: null
16692
16693                 };
16694
16695         }
16696
16697         function needsUpdate( geometry, index ) {
16698
16699                 const cachedAttributes = currentState.attributes;
16700                 const geometryAttributes = geometry.attributes;
16701
16702                 let attributesNum = 0;
16703
16704                 for ( const key in geometryAttributes ) {
16705
16706                         const cachedAttribute = cachedAttributes[ key ];
16707                         const geometryAttribute = geometryAttributes[ key ];
16708
16709                         if ( cachedAttribute === undefined ) return true;
16710
16711                         if ( cachedAttribute.attribute !== geometryAttribute ) return true;
16712
16713                         if ( cachedAttribute.data !== geometryAttribute.data ) return true;
16714
16715                         attributesNum ++;
16716
16717                 }
16718
16719                 if ( currentState.attributesNum !== attributesNum ) return true;
16720
16721                 if ( currentState.index !== index ) return true;
16722
16723                 return false;
16724
16725         }
16726
16727         function saveCache( geometry, index ) {
16728
16729                 const cache = {};
16730                 const attributes = geometry.attributes;
16731                 let attributesNum = 0;
16732
16733                 for ( const key in attributes ) {
16734
16735                         const attribute = attributes[ key ];
16736
16737                         const data = {};
16738                         data.attribute = attribute;
16739
16740                         if ( attribute.data ) {
16741
16742                                 data.data = attribute.data;
16743
16744                         }
16745
16746                         cache[ key ] = data;
16747
16748                         attributesNum ++;
16749
16750                 }
16751
16752                 currentState.attributes = cache;
16753                 currentState.attributesNum = attributesNum;
16754
16755                 currentState.index = index;
16756
16757         }
16758
16759         function initAttributes() {
16760
16761                 const newAttributes = currentState.newAttributes;
16762
16763                 for ( let i = 0, il = newAttributes.length; i < il; i ++ ) {
16764
16765                         newAttributes[ i ] = 0;
16766
16767                 }
16768
16769         }
16770
16771         function enableAttribute( attribute ) {
16772
16773                 enableAttributeAndDivisor( attribute, 0 );
16774
16775         }
16776
16777         function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
16778
16779                 const newAttributes = currentState.newAttributes;
16780                 const enabledAttributes = currentState.enabledAttributes;
16781                 const attributeDivisors = currentState.attributeDivisors;
16782
16783                 newAttributes[ attribute ] = 1;
16784
16785                 if ( enabledAttributes[ attribute ] === 0 ) {
16786
16787                         gl.enableVertexAttribArray( attribute );
16788                         enabledAttributes[ attribute ] = 1;
16789
16790                 }
16791
16792                 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
16793
16794                         const extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
16795
16796                         extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
16797                         attributeDivisors[ attribute ] = meshPerAttribute;
16798
16799                 }
16800
16801         }
16802
16803         function disableUnusedAttributes() {
16804
16805                 const newAttributes = currentState.newAttributes;
16806                 const enabledAttributes = currentState.enabledAttributes;
16807
16808                 for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) {
16809
16810                         if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
16811
16812                                 gl.disableVertexAttribArray( i );
16813                                 enabledAttributes[ i ] = 0;
16814
16815                         }
16816
16817                 }
16818
16819         }
16820
16821         function vertexAttribPointer( index, size, type, normalized, stride, offset ) {
16822
16823                 if ( capabilities.isWebGL2 === true && ( type === 5124 || type === 5125 ) ) {
16824
16825                         gl.vertexAttribIPointer( index, size, type, stride, offset );
16826
16827                 } else {
16828
16829                         gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
16830
16831                 }
16832
16833         }
16834
16835         function setupVertexAttributes( object, material, program, geometry ) {
16836
16837                 if ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {
16838
16839                         if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return;
16840
16841                 }
16842
16843                 initAttributes();
16844
16845                 const geometryAttributes = geometry.attributes;
16846
16847                 const programAttributes = program.getAttributes();
16848
16849                 const materialDefaultAttributeValues = material.defaultAttributeValues;
16850
16851                 for ( const name in programAttributes ) {
16852
16853                         const programAttribute = programAttributes[ name ];
16854
16855                         if ( programAttribute.location >= 0 ) {
16856
16857                                 let geometryAttribute = geometryAttributes[ name ];
16858
16859                                 if ( geometryAttribute === undefined ) {
16860
16861                                         if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
16862                                         if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
16863
16864                                 }
16865
16866                                 if ( geometryAttribute !== undefined ) {
16867
16868                                         const normalized = geometryAttribute.normalized;
16869                                         const size = geometryAttribute.itemSize;
16870
16871                                         const attribute = attributes.get( geometryAttribute );
16872
16873                                         // TODO Attribute may not be available on context restore
16874
16875                                         if ( attribute === undefined ) continue;
16876
16877                                         const buffer = attribute.buffer;
16878                                         const type = attribute.type;
16879                                         const bytesPerElement = attribute.bytesPerElement;
16880
16881                                         if ( geometryAttribute.isInterleavedBufferAttribute ) {
16882
16883                                                 const data = geometryAttribute.data;
16884                                                 const stride = data.stride;
16885                                                 const offset = geometryAttribute.offset;
16886
16887                                                 if ( data && data.isInstancedInterleavedBuffer ) {
16888
16889                                                         for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
16890
16891                                                                 enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute );
16892
16893                                                         }
16894
16895                                                         if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
16896
16897                                                                 geometry._maxInstanceCount = data.meshPerAttribute * data.count;
16898
16899                                                         }
16900
16901                                                 } else {
16902
16903                                                         for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
16904
16905                                                                 enableAttribute( programAttribute.location + i );
16906
16907                                                         }
16908
16909                                                 }
16910
16911                                                 gl.bindBuffer( 34962, buffer );
16912
16913                                                 for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
16914
16915                                                         vertexAttribPointer(
16916                                                                 programAttribute.location + i,
16917                                                                 size / programAttribute.locationSize,
16918                                                                 type,
16919                                                                 normalized,
16920                                                                 stride * bytesPerElement,
16921                                                                 ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement
16922                                                         );
16923
16924                                                 }
16925
16926                                         } else {
16927
16928                                                 if ( geometryAttribute.isInstancedBufferAttribute ) {
16929
16930                                                         for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
16931
16932                                                                 enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute );
16933
16934                                                         }
16935
16936                                                         if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
16937
16938                                                                 geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
16939
16940                                                         }
16941
16942                                                 } else {
16943
16944                                                         for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
16945
16946                                                                 enableAttribute( programAttribute.location + i );
16947
16948                                                         }
16949
16950                                                 }
16951
16952                                                 gl.bindBuffer( 34962, buffer );
16953
16954                                                 for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
16955
16956                                                         vertexAttribPointer(
16957                                                                 programAttribute.location + i,
16958                                                                 size / programAttribute.locationSize,
16959                                                                 type,
16960                                                                 normalized,
16961                                                                 size * bytesPerElement,
16962                                                                 ( size / programAttribute.locationSize ) * i * bytesPerElement
16963                                                         );
16964
16965                                                 }
16966
16967                                         }
16968
16969                                 } else if ( materialDefaultAttributeValues !== undefined ) {
16970
16971                                         const value = materialDefaultAttributeValues[ name ];
16972
16973                                         if ( value !== undefined ) {
16974
16975                                                 switch ( value.length ) {
16976
16977                                                         case 2:
16978                                                                 gl.vertexAttrib2fv( programAttribute.location, value );
16979                                                                 break;
16980
16981                                                         case 3:
16982                                                                 gl.vertexAttrib3fv( programAttribute.location, value );
16983                                                                 break;
16984
16985                                                         case 4:
16986                                                                 gl.vertexAttrib4fv( programAttribute.location, value );
16987                                                                 break;
16988
16989                                                         default:
16990                                                                 gl.vertexAttrib1fv( programAttribute.location, value );
16991
16992                                                 }
16993
16994                                         }
16995
16996                                 }
16997
16998                         }
16999
17000                 }
17001
17002                 disableUnusedAttributes();
17003
17004         }
17005
17006         function dispose() {
17007
17008                 reset();
17009
17010                 for ( const geometryId in bindingStates ) {
17011
17012                         const programMap = bindingStates[ geometryId ];
17013
17014                         for ( const programId in programMap ) {
17015
17016                                 const stateMap = programMap[ programId ];
17017
17018                                 for ( const wireframe in stateMap ) {
17019
17020                                         deleteVertexArrayObject( stateMap[ wireframe ].object );
17021
17022                                         delete stateMap[ wireframe ];
17023
17024                                 }
17025
17026                                 delete programMap[ programId ];
17027
17028                         }
17029
17030                         delete bindingStates[ geometryId ];
17031
17032                 }
17033
17034         }
17035
17036         function releaseStatesOfGeometry( geometry ) {
17037
17038                 if ( bindingStates[ geometry.id ] === undefined ) return;
17039
17040                 const programMap = bindingStates[ geometry.id ];
17041
17042                 for ( const programId in programMap ) {
17043
17044                         const stateMap = programMap[ programId ];
17045
17046                         for ( const wireframe in stateMap ) {
17047
17048                                 deleteVertexArrayObject( stateMap[ wireframe ].object );
17049
17050                                 delete stateMap[ wireframe ];
17051
17052                         }
17053
17054                         delete programMap[ programId ];
17055
17056                 }
17057
17058                 delete bindingStates[ geometry.id ];
17059
17060         }
17061
17062         function releaseStatesOfProgram( program ) {
17063
17064                 for ( const geometryId in bindingStates ) {
17065
17066                         const programMap = bindingStates[ geometryId ];
17067
17068                         if ( programMap[ program.id ] === undefined ) continue;
17069
17070                         const stateMap = programMap[ program.id ];
17071
17072                         for ( const wireframe in stateMap ) {
17073
17074                                 deleteVertexArrayObject( stateMap[ wireframe ].object );
17075
17076                                 delete stateMap[ wireframe ];
17077
17078                         }
17079
17080                         delete programMap[ program.id ];
17081
17082                 }
17083
17084         }
17085
17086         function reset() {
17087
17088                 resetDefaultState();
17089
17090                 if ( currentState === defaultState ) return;
17091
17092                 currentState = defaultState;
17093                 bindVertexArrayObject( currentState.object );
17094
17095         }
17096
17097         // for backward-compatilibity
17098
17099         function resetDefaultState() {
17100
17101                 defaultState.geometry = null;
17102                 defaultState.program = null;
17103                 defaultState.wireframe = false;
17104
17105         }
17106
17107         return {
17108
17109                 setup: setup,
17110                 reset: reset,
17111                 resetDefaultState: resetDefaultState,
17112                 dispose: dispose,
17113                 releaseStatesOfGeometry: releaseStatesOfGeometry,
17114                 releaseStatesOfProgram: releaseStatesOfProgram,
17115
17116                 initAttributes: initAttributes,
17117                 enableAttribute: enableAttribute,
17118                 disableUnusedAttributes: disableUnusedAttributes
17119
17120         };
17121
17122     }
17123
17124     function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
17125
17126         const isWebGL2 = capabilities.isWebGL2;
17127
17128         let mode;
17129
17130         function setMode( value ) {
17131
17132                 mode = value;
17133
17134         }
17135
17136         function render( start, count ) {
17137
17138                 gl.drawArrays( mode, start, count );
17139
17140                 info.update( count, mode, 1 );
17141
17142         }
17143
17144         function renderInstances( start, count, primcount ) {
17145
17146                 if ( primcount === 0 ) return;
17147
17148                 let extension, methodName;
17149
17150                 if ( isWebGL2 ) {
17151
17152                         extension = gl;
17153                         methodName = 'drawArraysInstanced';
17154
17155                 } else {
17156
17157                         extension = extensions.get( 'ANGLE_instanced_arrays' );
17158                         methodName = 'drawArraysInstancedANGLE';
17159
17160                         if ( extension === null ) {
17161
17162                                 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
17163                                 return;
17164
17165                         }
17166
17167                 }
17168
17169                 extension[ methodName ]( mode, start, count, primcount );
17170
17171                 info.update( count, mode, primcount );
17172
17173         }
17174
17175         //
17176
17177         this.setMode = setMode;
17178         this.render = render;
17179         this.renderInstances = renderInstances;
17180
17181     }
17182
17183     function WebGLCapabilities( gl, extensions, parameters ) {
17184
17185         let maxAnisotropy;
17186
17187         function getMaxAnisotropy() {
17188
17189                 if ( maxAnisotropy !== undefined ) return maxAnisotropy;
17190
17191                 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) {
17192
17193                         const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
17194
17195                         maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
17196
17197                 } else {
17198
17199                         maxAnisotropy = 0;
17200
17201                 }
17202
17203                 return maxAnisotropy;
17204
17205         }
17206
17207         function getMaxPrecision( precision ) {
17208
17209                 if ( precision === 'highp' ) {
17210
17211                         if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&
17212                                 gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {
17213
17214                                 return 'highp';
17215
17216                         }
17217
17218                         precision = 'mediump';
17219
17220                 }
17221
17222                 if ( precision === 'mediump' ) {
17223
17224                         if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&
17225                                 gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {
17226
17227                                 return 'mediump';
17228
17229                         }
17230
17231                 }
17232
17233                 return 'lowp';
17234
17235         }
17236
17237         /* eslint-disable no-undef */
17238         const isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||
17239                 ( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );
17240         /* eslint-enable no-undef */
17241
17242         let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
17243         const maxPrecision = getMaxPrecision( precision );
17244
17245         if ( maxPrecision !== precision ) {
17246
17247                 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
17248                 precision = maxPrecision;
17249
17250         }
17251
17252         const drawBuffers = isWebGL2 || extensions.has( 'WEBGL_draw_buffers' );
17253
17254         const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
17255
17256         const maxTextures = gl.getParameter( 34930 );
17257         const maxVertexTextures = gl.getParameter( 35660 );
17258         const maxTextureSize = gl.getParameter( 3379 );
17259         const maxCubemapSize = gl.getParameter( 34076 );
17260
17261         const maxAttributes = gl.getParameter( 34921 );
17262         const maxVertexUniforms = gl.getParameter( 36347 );
17263         const maxVaryings = gl.getParameter( 36348 );
17264         const maxFragmentUniforms = gl.getParameter( 36349 );
17265
17266         const vertexTextures = maxVertexTextures > 0;
17267         const floatFragmentTextures = isWebGL2 || extensions.has( 'OES_texture_float' );
17268         const floatVertexTextures = vertexTextures && floatFragmentTextures;
17269
17270         const maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;
17271
17272         return {
17273
17274                 isWebGL2: isWebGL2,
17275
17276                 drawBuffers: drawBuffers,
17277
17278                 getMaxAnisotropy: getMaxAnisotropy,
17279                 getMaxPrecision: getMaxPrecision,
17280
17281                 precision: precision,
17282                 logarithmicDepthBuffer: logarithmicDepthBuffer,
17283
17284                 maxTextures: maxTextures,
17285                 maxVertexTextures: maxVertexTextures,
17286                 maxTextureSize: maxTextureSize,
17287                 maxCubemapSize: maxCubemapSize,
17288
17289                 maxAttributes: maxAttributes,
17290                 maxVertexUniforms: maxVertexUniforms,
17291                 maxVaryings: maxVaryings,
17292                 maxFragmentUniforms: maxFragmentUniforms,
17293
17294                 vertexTextures: vertexTextures,
17295                 floatFragmentTextures: floatFragmentTextures,
17296                 floatVertexTextures: floatVertexTextures,
17297
17298                 maxSamples: maxSamples
17299
17300         };
17301
17302     }
17303
17304     function WebGLClipping( properties ) {
17305
17306         const scope = this;
17307
17308         let globalState = null,
17309                 numGlobalPlanes = 0,
17310                 localClippingEnabled = false,
17311                 renderingShadows = false;
17312
17313         const plane = new Plane(),
17314                 viewNormalMatrix = new Matrix3(),
17315
17316                 uniform = { value: null, needsUpdate: false };
17317
17318         this.uniform = uniform;
17319         this.numPlanes = 0;
17320         this.numIntersection = 0;
17321
17322         this.init = function ( planes, enableLocalClipping, camera ) {
17323
17324                 const enabled =
17325                         planes.length !== 0 ||
17326                         enableLocalClipping ||
17327                         // enable state of previous frame - the clipping code has to
17328                         // run another frame in order to reset the state:
17329                         numGlobalPlanes !== 0 ||
17330                         localClippingEnabled;
17331
17332                 localClippingEnabled = enableLocalClipping;
17333
17334                 globalState = projectPlanes( planes, camera, 0 );
17335                 numGlobalPlanes = planes.length;
17336
17337                 return enabled;
17338
17339         };
17340
17341         this.beginShadows = function () {
17342
17343                 renderingShadows = true;
17344                 projectPlanes( null );
17345
17346         };
17347
17348         this.endShadows = function () {
17349
17350                 renderingShadows = false;
17351                 resetGlobalState();
17352
17353         };
17354
17355         this.setState = function ( material, camera, useCache ) {
17356
17357                 const planes = material.clippingPlanes,
17358                         clipIntersection = material.clipIntersection,
17359                         clipShadows = material.clipShadows;
17360
17361                 const materialProperties = properties.get( material );
17362
17363                 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
17364
17365                         // there's no local clipping
17366
17367                         if ( renderingShadows ) {
17368
17369                                 // there's no global clipping
17370
17371                                 projectPlanes( null );
17372
17373                         } else {
17374
17375                                 resetGlobalState();
17376
17377                         }
17378
17379                 } else {
17380
17381                         const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
17382                                 lGlobal = nGlobal * 4;
17383
17384                         let dstArray = materialProperties.clippingState || null;
17385
17386                         uniform.value = dstArray; // ensure unique state
17387
17388                         dstArray = projectPlanes( planes, camera, lGlobal, useCache );
17389
17390                         for ( let i = 0; i !== lGlobal; ++ i ) {
17391
17392                                 dstArray[ i ] = globalState[ i ];
17393
17394                         }
17395
17396                         materialProperties.clippingState = dstArray;
17397                         this.numIntersection = clipIntersection ? this.numPlanes : 0;
17398                         this.numPlanes += nGlobal;
17399
17400                 }
17401
17402
17403         };
17404
17405         function resetGlobalState() {
17406
17407                 if ( uniform.value !== globalState ) {
17408
17409                         uniform.value = globalState;
17410                         uniform.needsUpdate = numGlobalPlanes > 0;
17411
17412                 }
17413
17414                 scope.numPlanes = numGlobalPlanes;
17415                 scope.numIntersection = 0;
17416
17417         }
17418
17419         function projectPlanes( planes, camera, dstOffset, skipTransform ) {
17420
17421                 const nPlanes = planes !== null ? planes.length : 0;
17422                 let dstArray = null;
17423
17424                 if ( nPlanes !== 0 ) {
17425
17426                         dstArray = uniform.value;
17427
17428                         if ( skipTransform !== true || dstArray === null ) {
17429
17430                                 const flatSize = dstOffset + nPlanes * 4,
17431                                         viewMatrix = camera.matrixWorldInverse;
17432
17433                                 viewNormalMatrix.getNormalMatrix( viewMatrix );
17434
17435                                 if ( dstArray === null || dstArray.length < flatSize ) {
17436
17437                                         dstArray = new Float32Array( flatSize );
17438
17439                                 }
17440
17441                                 for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
17442
17443                                         plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
17444
17445                                         plane.normal.toArray( dstArray, i4 );
17446                                         dstArray[ i4 + 3 ] = plane.constant;
17447
17448                                 }
17449
17450                         }
17451
17452                         uniform.value = dstArray;
17453                         uniform.needsUpdate = true;
17454
17455                 }
17456
17457                 scope.numPlanes = nPlanes;
17458                 scope.numIntersection = 0;
17459
17460                 return dstArray;
17461
17462         }
17463
17464     }
17465
17466     function WebGLCubeMaps( renderer ) {
17467
17468         let cubemaps = new WeakMap();
17469
17470         function mapTextureMapping( texture, mapping ) {
17471
17472                 if ( mapping === EquirectangularReflectionMapping ) {
17473
17474                         texture.mapping = CubeReflectionMapping;
17475
17476                 } else if ( mapping === EquirectangularRefractionMapping ) {
17477
17478                         texture.mapping = CubeRefractionMapping;
17479
17480                 }
17481
17482                 return texture;
17483
17484         }
17485
17486         function get( texture ) {
17487
17488                 if ( texture && texture.isTexture && texture.isRenderTargetTexture === false ) {
17489
17490                         const mapping = texture.mapping;
17491
17492                         if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
17493
17494                                 if ( cubemaps.has( texture ) ) {
17495
17496                                         const cubemap = cubemaps.get( texture ).texture;
17497                                         return mapTextureMapping( cubemap, texture.mapping );
17498
17499                                 } else {
17500
17501                                         const image = texture.image;
17502
17503                                         if ( image && image.height > 0 ) {
17504
17505                                                 const currentRenderTarget = renderer.getRenderTarget();
17506
17507                                                 const renderTarget = new WebGLCubeRenderTarget( image.height / 2 );
17508                                                 renderTarget.fromEquirectangularTexture( renderer, texture );
17509                                                 cubemaps.set( texture, renderTarget );
17510
17511                                                 renderer.setRenderTarget( currentRenderTarget );
17512
17513                                                 texture.addEventListener( 'dispose', onTextureDispose );
17514
17515                                                 return mapTextureMapping( renderTarget.texture, texture.mapping );
17516
17517                                         } else {
17518
17519                                                 // image not yet ready. try the conversion next frame
17520
17521                                                 return null;
17522
17523                                         }
17524
17525                                 }
17526
17527                         }
17528
17529                 }
17530
17531                 return texture;
17532
17533         }
17534
17535         function onTextureDispose( event ) {
17536
17537                 const texture = event.target;
17538
17539                 texture.removeEventListener( 'dispose', onTextureDispose );
17540
17541                 const cubemap = cubemaps.get( texture );
17542
17543                 if ( cubemap !== undefined ) {
17544
17545                         cubemaps.delete( texture );
17546                         cubemap.dispose();
17547
17548                 }
17549
17550         }
17551
17552         function dispose() {
17553
17554                 cubemaps = new WeakMap();
17555
17556         }
17557
17558         return {
17559                 get: get,
17560                 dispose: dispose
17561         };
17562
17563     }
17564
17565     class OrthographicCamera extends Camera$1 {
17566
17567         constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
17568
17569                 super();
17570
17571                 this.type = 'OrthographicCamera';
17572
17573                 this.zoom = 1;
17574                 this.view = null;
17575
17576                 this.left = left;
17577                 this.right = right;
17578                 this.top = top;
17579                 this.bottom = bottom;
17580
17581                 this.near = near;
17582                 this.far = far;
17583
17584                 this.updateProjectionMatrix();
17585
17586         }
17587
17588         copy( source, recursive ) {
17589
17590                 super.copy( source, recursive );
17591
17592                 this.left = source.left;
17593                 this.right = source.right;
17594                 this.top = source.top;
17595                 this.bottom = source.bottom;
17596                 this.near = source.near;
17597                 this.far = source.far;
17598
17599                 this.zoom = source.zoom;
17600                 this.view = source.view === null ? null : Object.assign( {}, source.view );
17601
17602                 return this;
17603
17604         }
17605
17606         setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
17607
17608                 if ( this.view === null ) {
17609
17610                         this.view = {
17611                                 enabled: true,
17612                                 fullWidth: 1,
17613                                 fullHeight: 1,
17614                                 offsetX: 0,
17615                                 offsetY: 0,
17616                                 width: 1,
17617                                 height: 1
17618                         };
17619
17620                 }
17621
17622                 this.view.enabled = true;
17623                 this.view.fullWidth = fullWidth;
17624                 this.view.fullHeight = fullHeight;
17625                 this.view.offsetX = x;
17626                 this.view.offsetY = y;
17627                 this.view.width = width;
17628                 this.view.height = height;
17629
17630                 this.updateProjectionMatrix();
17631
17632         }
17633
17634         clearViewOffset() {
17635
17636                 if ( this.view !== null ) {
17637
17638                         this.view.enabled = false;
17639
17640                 }
17641
17642                 this.updateProjectionMatrix();
17643
17644         }
17645
17646         updateProjectionMatrix() {
17647
17648                 const dx = ( this.right - this.left ) / ( 2 * this.zoom );
17649                 const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
17650                 const cx = ( this.right + this.left ) / 2;
17651                 const cy = ( this.top + this.bottom ) / 2;
17652
17653                 let left = cx - dx;
17654                 let right = cx + dx;
17655                 let top = cy + dy;
17656                 let bottom = cy - dy;
17657
17658                 if ( this.view !== null && this.view.enabled ) {
17659
17660                         const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
17661                         const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
17662
17663                         left += scaleW * this.view.offsetX;
17664                         right = left + scaleW * this.view.width;
17665                         top -= scaleH * this.view.offsetY;
17666                         bottom = top - scaleH * this.view.height;
17667
17668                 }
17669
17670                 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
17671
17672                 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
17673
17674         }
17675
17676         toJSON( meta ) {
17677
17678                 const data = super.toJSON( meta );
17679
17680                 data.object.zoom = this.zoom;
17681                 data.object.left = this.left;
17682                 data.object.right = this.right;
17683                 data.object.top = this.top;
17684                 data.object.bottom = this.bottom;
17685                 data.object.near = this.near;
17686                 data.object.far = this.far;
17687
17688                 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
17689
17690                 return data;
17691
17692         }
17693
17694     }
17695
17696     OrthographicCamera.prototype.isOrthographicCamera = true;
17697
17698     class RawShaderMaterial extends ShaderMaterial {
17699
17700         constructor( parameters ) {
17701
17702                 super( parameters );
17703
17704                 this.type = 'RawShaderMaterial';
17705
17706         }
17707
17708     }
17709
17710     RawShaderMaterial.prototype.isRawShaderMaterial = true;
17711
17712     const LOD_MIN = 4;
17713     const LOD_MAX = 8;
17714     const SIZE_MAX = Math.pow( 2, LOD_MAX );
17715
17716     // The standard deviations (radians) associated with the extra mips. These are
17717     // chosen to approximate a Trowbridge-Reitz distribution function times the
17718     // geometric shadowing function. These sigma values squared must match the
17719     // variance #defines in cube_uv_reflection_fragment.glsl.js.
17720     const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
17721
17722     const TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
17723
17724     // The maximum length of the blur for loop. Smaller sigmas will use fewer
17725     // samples and exit early, but not recompile the shader.
17726     const MAX_SAMPLES = 20;
17727
17728     const ENCODINGS = {
17729         [ LinearEncoding ]: 0,
17730         [ sRGBEncoding ]: 1,
17731         [ RGBEEncoding ]: 2,
17732         [ RGBM7Encoding ]: 3,
17733         [ RGBM16Encoding ]: 4,
17734         [ RGBDEncoding ]: 5,
17735         [ GammaEncoding ]: 6
17736     };
17737
17738     const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
17739     const { _lodPlanes, _sizeLods, _sigmas } = /*@__PURE__*/ _createPlanes();
17740     const _clearColor = /*@__PURE__*/ new Color();
17741     let _oldTarget = null;
17742
17743     // Golden Ratio
17744     const PHI = ( 1 + Math.sqrt( 5 ) ) / 2;
17745     const INV_PHI = 1 / PHI;
17746
17747     // Vertices of a dodecahedron (except the opposites, which represent the
17748     // same axis), used as axis directions evenly spread on a sphere.
17749     const _axisDirections = [
17750         /*@__PURE__*/ new Vector3( 1, 1, 1 ),
17751         /*@__PURE__*/ new Vector3( - 1, 1, 1 ),
17752         /*@__PURE__*/ new Vector3( 1, 1, - 1 ),
17753         /*@__PURE__*/ new Vector3( - 1, 1, - 1 ),
17754         /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ),
17755         /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ),
17756         /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ),
17757         /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ),
17758         /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ),
17759         /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ];
17760
17761     /**
17762      * This class generates a Prefiltered, Mipmapped Radiance Environment Map
17763      * (PMREM) from a cubeMap environment texture. This allows different levels of
17764      * blur to be quickly accessed based on material roughness. It is packed into a
17765      * special CubeUV format that allows us to perform custom interpolation so that
17766      * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
17767      * chain, it only goes down to the LOD_MIN level (above), and then creates extra
17768      * even more filtered 'mips' at the same LOD_MIN resolution, associated with
17769      * higher roughness levels. In this way we maintain resolution to smoothly
17770      * interpolate diffuse lighting while limiting sampling computation.
17771      *
17772      * Paper: Fast, Accurate Image-Based Lighting
17773      * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view
17774     */
17775
17776     class PMREMGenerator {
17777
17778         constructor( renderer ) {
17779
17780                 this._renderer = renderer;
17781                 this._pingPongRenderTarget = null;
17782
17783                 this._blurMaterial = _getBlurShader( MAX_SAMPLES );
17784                 this._equirectShader = null;
17785                 this._cubemapShader = null;
17786
17787                 this._compileMaterial( this._blurMaterial );
17788
17789         }
17790
17791         /**
17792          * Generates a PMREM from a supplied Scene, which can be faster than using an
17793          * image if networking bandwidth is low. Optional sigma specifies a blur radius
17794          * in radians to be applied to the scene before PMREM generation. Optional near
17795          * and far planes ensure the scene is rendered in its entirety (the cubeCamera
17796          * is placed at the origin).
17797          */
17798         fromScene( scene, sigma = 0, near = 0.1, far = 100 ) {
17799
17800                 _oldTarget = this._renderer.getRenderTarget();
17801                 const cubeUVRenderTarget = this._allocateTargets();
17802
17803                 this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
17804                 if ( sigma > 0 ) {
17805
17806                         this._blur( cubeUVRenderTarget, 0, 0, sigma );
17807
17808                 }
17809
17810                 this._applyPMREM( cubeUVRenderTarget );
17811                 this._cleanup( cubeUVRenderTarget );
17812
17813                 return cubeUVRenderTarget;
17814
17815         }
17816
17817         /**
17818          * Generates a PMREM from an equirectangular texture, which can be either LDR
17819          * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512),
17820          * as this matches best with the 256 x 256 cubemap output.
17821          */
17822         fromEquirectangular( equirectangular ) {
17823
17824                 return this._fromTexture( equirectangular );
17825
17826         }
17827
17828         /**
17829          * Generates a PMREM from an cubemap texture, which can be either LDR
17830          * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256,
17831          * as this matches best with the 256 x 256 cubemap output.
17832          */
17833         fromCubemap( cubemap ) {
17834
17835                 return this._fromTexture( cubemap );
17836
17837         }
17838
17839         /**
17840          * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
17841          * your texture's network fetch for increased concurrency.
17842          */
17843         compileCubemapShader() {
17844
17845                 if ( this._cubemapShader === null ) {
17846
17847                         this._cubemapShader = _getCubemapShader();
17848                         this._compileMaterial( this._cubemapShader );
17849
17850                 }
17851
17852         }
17853
17854         /**
17855          * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
17856          * your texture's network fetch for increased concurrency.
17857          */
17858         compileEquirectangularShader() {
17859
17860                 if ( this._equirectShader === null ) {
17861
17862                         this._equirectShader = _getEquirectShader();
17863                         this._compileMaterial( this._equirectShader );
17864
17865                 }
17866
17867         }
17868
17869         /**
17870          * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
17871          * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
17872          * one of them will cause any others to also become unusable.
17873          */
17874         dispose() {
17875
17876                 this._blurMaterial.dispose();
17877
17878                 if ( this._cubemapShader !== null ) this._cubemapShader.dispose();
17879                 if ( this._equirectShader !== null ) this._equirectShader.dispose();
17880
17881                 for ( let i = 0; i < _lodPlanes.length; i ++ ) {
17882
17883                         _lodPlanes[ i ].dispose();
17884
17885                 }
17886
17887         }
17888
17889         // private interface
17890
17891         _cleanup( outputTarget ) {
17892
17893                 this._pingPongRenderTarget.dispose();
17894                 this._renderer.setRenderTarget( _oldTarget );
17895                 outputTarget.scissorTest = false;
17896                 _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
17897
17898         }
17899
17900         _fromTexture( texture ) {
17901
17902                 _oldTarget = this._renderer.getRenderTarget();
17903                 const cubeUVRenderTarget = this._allocateTargets( texture );
17904                 this._textureToCubeUV( texture, cubeUVRenderTarget );
17905                 this._applyPMREM( cubeUVRenderTarget );
17906                 this._cleanup( cubeUVRenderTarget );
17907
17908                 return cubeUVRenderTarget;
17909
17910         }
17911
17912         _allocateTargets( texture ) { // warning: null texture is valid
17913
17914                 const params = {
17915                         magFilter: NearestFilter,
17916                         minFilter: NearestFilter,
17917                         generateMipmaps: false,
17918                         type: UnsignedByteType,
17919                         format: RGBEFormat,
17920                         encoding: _isLDR( texture ) ? texture.encoding : RGBEEncoding,
17921                         depthBuffer: false
17922                 };
17923
17924                 const cubeUVRenderTarget = _createRenderTarget( params );
17925                 cubeUVRenderTarget.depthBuffer = texture ? false : true;
17926                 this._pingPongRenderTarget = _createRenderTarget( params );
17927                 return cubeUVRenderTarget;
17928
17929         }
17930
17931         _compileMaterial( material ) {
17932
17933                 const tmpMesh = new Mesh( _lodPlanes[ 0 ], material );
17934                 this._renderer.compile( tmpMesh, _flatCamera );
17935
17936         }
17937
17938         _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
17939
17940                 const fov = 90;
17941                 const aspect = 1;
17942                 const cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
17943                 const upSign = [ 1, - 1, 1, 1, 1, 1 ];
17944                 const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ];
17945                 const renderer = this._renderer;
17946
17947                 const originalAutoClear = renderer.autoClear;
17948                 const outputEncoding = renderer.outputEncoding;
17949                 const toneMapping = renderer.toneMapping;
17950                 renderer.getClearColor( _clearColor );
17951
17952                 renderer.toneMapping = NoToneMapping;
17953                 renderer.outputEncoding = LinearEncoding;
17954                 renderer.autoClear = false;
17955
17956                 const backgroundMaterial = new MeshBasicMaterial( {
17957                         name: 'PMREM.Background',
17958                         side: BackSide,
17959                         depthWrite: false,
17960                         depthTest: false,
17961                 } );
17962
17963                 const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial );
17964
17965                 let useSolidColor = false;
17966                 const background = scene.background;
17967
17968                 if ( background ) {
17969
17970                         if ( background.isColor ) {
17971
17972                                 backgroundMaterial.color.copy( background );
17973                                 scene.background = null;
17974                                 useSolidColor = true;
17975
17976                         }
17977
17978                 } else {
17979
17980                         backgroundMaterial.color.copy( _clearColor );
17981                         useSolidColor = true;
17982
17983                 }
17984
17985                 for ( let i = 0; i < 6; i ++ ) {
17986
17987                         const col = i % 3;
17988                         if ( col == 0 ) {
17989
17990                                 cubeCamera.up.set( 0, upSign[ i ], 0 );
17991                                 cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
17992
17993                         } else if ( col == 1 ) {
17994
17995                                 cubeCamera.up.set( 0, 0, upSign[ i ] );
17996                                 cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
17997
17998                         } else {
17999
18000                                 cubeCamera.up.set( 0, upSign[ i ], 0 );
18001                                 cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
18002
18003                         }
18004
18005                         _setViewport( cubeUVRenderTarget,
18006                                 col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX );
18007                         renderer.setRenderTarget( cubeUVRenderTarget );
18008
18009                         if ( useSolidColor ) {
18010
18011                                 renderer.render( backgroundBox, cubeCamera );
18012
18013                         }
18014
18015                         renderer.render( scene, cubeCamera );
18016
18017                 }
18018
18019                 backgroundBox.geometry.dispose();
18020                 backgroundBox.material.dispose();
18021
18022                 renderer.toneMapping = toneMapping;
18023                 renderer.outputEncoding = outputEncoding;
18024                 renderer.autoClear = originalAutoClear;
18025                 scene.background = background;
18026
18027         }
18028
18029         _setEncoding( uniform, texture ) {
18030
18031                 if ( this._renderer.capabilities.isWebGL2 === true && texture.format === RGBAFormat && texture.type === UnsignedByteType && texture.encoding === sRGBEncoding ) {
18032
18033                         uniform.value = ENCODINGS[ LinearEncoding ];
18034
18035                 } else {
18036
18037                         uniform.value = ENCODINGS[ texture.encoding ];
18038
18039                 }
18040
18041         }
18042
18043         _textureToCubeUV( texture, cubeUVRenderTarget ) {
18044
18045                 const renderer = this._renderer;
18046
18047                 const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping );
18048
18049                 if ( isCubeTexture ) {
18050
18051                         if ( this._cubemapShader == null ) {
18052
18053                                 this._cubemapShader = _getCubemapShader();
18054
18055                         }
18056
18057                 } else {
18058
18059                         if ( this._equirectShader == null ) {
18060
18061                                 this._equirectShader = _getEquirectShader();
18062
18063                         }
18064
18065                 }
18066
18067                 const material = isCubeTexture ? this._cubemapShader : this._equirectShader;
18068                 const mesh = new Mesh( _lodPlanes[ 0 ], material );
18069
18070                 const uniforms = material.uniforms;
18071
18072                 uniforms[ 'envMap' ].value = texture;
18073
18074                 if ( ! isCubeTexture ) {
18075
18076                         uniforms[ 'texelSize' ].value.set( 1.0 / texture.image.width, 1.0 / texture.image.height );
18077
18078                 }
18079
18080                 this._setEncoding( uniforms[ 'inputEncoding' ], texture );
18081                 this._setEncoding( uniforms[ 'outputEncoding' ], cubeUVRenderTarget.texture );
18082
18083                 _setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
18084
18085                 renderer.setRenderTarget( cubeUVRenderTarget );
18086                 renderer.render( mesh, _flatCamera );
18087
18088         }
18089
18090         _applyPMREM( cubeUVRenderTarget ) {
18091
18092                 const renderer = this._renderer;
18093                 const autoClear = renderer.autoClear;
18094                 renderer.autoClear = false;
18095
18096                 for ( let i = 1; i < TOTAL_LODS; i ++ ) {
18097
18098                         const sigma = Math.sqrt( _sigmas[ i ] * _sigmas[ i ] - _sigmas[ i - 1 ] * _sigmas[ i - 1 ] );
18099
18100                         const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ];
18101
18102                         this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
18103
18104                 }
18105
18106                 renderer.autoClear = autoClear;
18107
18108         }
18109
18110         /**
18111          * This is a two-pass Gaussian blur for a cubemap. Normally this is done
18112          * vertically and horizontally, but this breaks down on a cube. Here we apply
18113          * the blur latitudinally (around the poles), and then longitudinally (towards
18114          * the poles) to approximate the orthogonally-separable blur. It is least
18115          * accurate at the poles, but still does a decent job.
18116          */
18117         _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
18118
18119                 const pingPongRenderTarget = this._pingPongRenderTarget;
18120
18121                 this._halfBlur(
18122                         cubeUVRenderTarget,
18123                         pingPongRenderTarget,
18124                         lodIn,
18125                         lodOut,
18126                         sigma,
18127                         'latitudinal',
18128                         poleAxis );
18129
18130                 this._halfBlur(
18131                         pingPongRenderTarget,
18132                         cubeUVRenderTarget,
18133                         lodOut,
18134                         lodOut,
18135                         sigma,
18136                         'longitudinal',
18137                         poleAxis );
18138
18139         }
18140
18141         _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
18142
18143                 const renderer = this._renderer;
18144                 const blurMaterial = this._blurMaterial;
18145
18146                 if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
18147
18148                         console.error(
18149                                 'blur direction must be either latitudinal or longitudinal!' );
18150
18151                 }
18152
18153                 // Number of standard deviations at which to cut off the discrete approximation.
18154                 const STANDARD_DEVIATIONS = 3;
18155
18156                 const blurMesh = new Mesh( _lodPlanes[ lodOut ], blurMaterial );
18157                 const blurUniforms = blurMaterial.uniforms;
18158
18159                 const pixels = _sizeLods[ lodIn ] - 1;
18160                 const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
18161                 const sigmaPixels = sigmaRadians / radiansPerPixel;
18162                 const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
18163
18164                 if ( samples > MAX_SAMPLES ) {
18165
18166                         console.warn( `sigmaRadians, ${
18167                                 sigmaRadians}, is too large and will clip, as it requested ${
18168                                 samples} samples when the maximum is set to ${MAX_SAMPLES}` );
18169
18170                 }
18171
18172                 const weights = [];
18173                 let sum = 0;
18174
18175                 for ( let i = 0; i < MAX_SAMPLES; ++ i ) {
18176
18177                         const x = i / sigmaPixels;
18178                         const weight = Math.exp( - x * x / 2 );
18179                         weights.push( weight );
18180
18181                         if ( i == 0 ) {
18182
18183                                 sum += weight;
18184
18185                         } else if ( i < samples ) {
18186
18187                                 sum += 2 * weight;
18188
18189                         }
18190
18191                 }
18192
18193                 for ( let i = 0; i < weights.length; i ++ ) {
18194
18195                         weights[ i ] = weights[ i ] / sum;
18196
18197                 }
18198
18199                 blurUniforms[ 'envMap' ].value = targetIn.texture;
18200                 blurUniforms[ 'samples' ].value = samples;
18201                 blurUniforms[ 'weights' ].value = weights;
18202                 blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal';
18203
18204                 if ( poleAxis ) {
18205
18206                         blurUniforms[ 'poleAxis' ].value = poleAxis;
18207
18208                 }
18209
18210                 blurUniforms[ 'dTheta' ].value = radiansPerPixel;
18211                 blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn;
18212
18213                 this._setEncoding( blurUniforms[ 'inputEncoding' ], targetIn.texture );
18214                 this._setEncoding( blurUniforms[ 'outputEncoding' ], targetIn.texture );
18215
18216                 const outputSize = _sizeLods[ lodOut ];
18217                 const x = 3 * Math.max( 0, SIZE_MAX - 2 * outputSize );
18218                 const y = ( lodOut === 0 ? 0 : 2 * SIZE_MAX ) + 2 * outputSize * ( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 );
18219
18220                 _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
18221                 renderer.setRenderTarget( targetOut );
18222                 renderer.render( blurMesh, _flatCamera );
18223
18224         }
18225
18226     }
18227
18228     function _isLDR( texture ) {
18229
18230         if ( texture === undefined || texture.type !== UnsignedByteType ) return false;
18231
18232         return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding;
18233
18234     }
18235
18236     function _createPlanes() {
18237
18238         const _lodPlanes = [];
18239         const _sizeLods = [];
18240         const _sigmas = [];
18241
18242         let lod = LOD_MAX;
18243
18244         for ( let i = 0; i < TOTAL_LODS; i ++ ) {
18245
18246                 const sizeLod = Math.pow( 2, lod );
18247                 _sizeLods.push( sizeLod );
18248                 let sigma = 1.0 / sizeLod;
18249
18250                 if ( i > LOD_MAX - LOD_MIN ) {
18251
18252                         sigma = EXTRA_LOD_SIGMA[ i - LOD_MAX + LOD_MIN - 1 ];
18253
18254                 } else if ( i == 0 ) {
18255
18256                         sigma = 0;
18257
18258                 }
18259
18260                 _sigmas.push( sigma );
18261
18262                 const texelSize = 1.0 / ( sizeLod - 1 );
18263                 const min = - texelSize / 2;
18264                 const max = 1 + texelSize / 2;
18265                 const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
18266
18267                 const cubeFaces = 6;
18268                 const vertices = 6;
18269                 const positionSize = 3;
18270                 const uvSize = 2;
18271                 const faceIndexSize = 1;
18272
18273                 const position = new Float32Array( positionSize * vertices * cubeFaces );
18274                 const uv = new Float32Array( uvSize * vertices * cubeFaces );
18275                 const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
18276
18277                 for ( let face = 0; face < cubeFaces; face ++ ) {
18278
18279                         const x = ( face % 3 ) * 2 / 3 - 1;
18280                         const y = face > 2 ? 0 : - 1;
18281                         const coordinates = [
18282                                 x, y, 0,
18283                                 x + 2 / 3, y, 0,
18284                                 x + 2 / 3, y + 1, 0,
18285                                 x, y, 0,
18286                                 x + 2 / 3, y + 1, 0,
18287                                 x, y + 1, 0
18288                         ];
18289                         position.set( coordinates, positionSize * vertices * face );
18290                         uv.set( uv1, uvSize * vertices * face );
18291                         const fill = [ face, face, face, face, face, face ];
18292                         faceIndex.set( fill, faceIndexSize * vertices * face );
18293
18294                 }
18295
18296                 const planes = new BufferGeometry();
18297                 planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
18298                 planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
18299                 planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
18300                 _lodPlanes.push( planes );
18301
18302                 if ( lod > LOD_MIN ) {
18303
18304                         lod --;
18305
18306                 }
18307
18308         }
18309
18310         return { _lodPlanes, _sizeLods, _sigmas };
18311
18312     }
18313
18314     function _createRenderTarget( params ) {
18315
18316         const cubeUVRenderTarget = new WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
18317         cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
18318         cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
18319         cubeUVRenderTarget.scissorTest = true;
18320         return cubeUVRenderTarget;
18321
18322     }
18323
18324     function _setViewport( target, x, y, width, height ) {
18325
18326         target.viewport.set( x, y, width, height );
18327         target.scissor.set( x, y, width, height );
18328
18329     }
18330
18331     function _getBlurShader( maxSamples ) {
18332
18333         const weights = new Float32Array( maxSamples );
18334         const poleAxis = new Vector3( 0, 1, 0 );
18335         const shaderMaterial = new RawShaderMaterial( {
18336
18337                 name: 'SphericalGaussianBlur',
18338
18339                 defines: { 'n': maxSamples },
18340
18341                 uniforms: {
18342                         'envMap': { value: null },
18343                         'samples': { value: 1 },
18344                         'weights': { value: weights },
18345                         'latitudinal': { value: false },
18346                         'dTheta': { value: 0 },
18347                         'mipInt': { value: 0 },
18348                         'poleAxis': { value: poleAxis },
18349                         'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
18350                         'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
18351                 },
18352
18353                 vertexShader: _getCommonVertexShader(),
18354
18355                 fragmentShader: /* glsl */`
18356
18357                         precision mediump float;
18358                         precision mediump int;
18359
18360                         varying vec3 vOutputDirection;
18361
18362                         uniform sampler2D envMap;
18363                         uniform int samples;
18364                         uniform float weights[ n ];
18365                         uniform bool latitudinal;
18366                         uniform float dTheta;
18367                         uniform float mipInt;
18368                         uniform vec3 poleAxis;
18369
18370                         ${ _getEncodings() }
18371
18372                         #define ENVMAP_TYPE_CUBE_UV
18373                         #include <cube_uv_reflection_fragment>
18374
18375                         vec3 getSample( float theta, vec3 axis ) {
18376
18377                                 float cosTheta = cos( theta );
18378                                 // Rodrigues' axis-angle rotation
18379                                 vec3 sampleDirection = vOutputDirection * cosTheta
18380                                         + cross( axis, vOutputDirection ) * sin( theta )
18381                                         + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
18382
18383                                 return bilinearCubeUV( envMap, sampleDirection, mipInt );
18384
18385                         }
18386
18387                         void main() {
18388
18389                                 vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
18390
18391                                 if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
18392
18393                                         axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
18394
18395                                 }
18396
18397                                 axis = normalize( axis );
18398
18399                                 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
18400                                 gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
18401
18402                                 for ( int i = 1; i < n; i++ ) {
18403
18404                                         if ( i >= samples ) {
18405
18406                                                 break;
18407
18408                                         }
18409
18410                                         float theta = dTheta * float( i );
18411                                         gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
18412                                         gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
18413
18414                                 }
18415
18416                                 gl_FragColor = linearToOutputTexel( gl_FragColor );
18417
18418                         }
18419                 `,
18420
18421                 blending: NoBlending,
18422                 depthTest: false,
18423                 depthWrite: false
18424
18425         } );
18426
18427         return shaderMaterial;
18428
18429     }
18430
18431     function _getEquirectShader() {
18432
18433         const texelSize = new Vector2( 1, 1 );
18434         const shaderMaterial = new RawShaderMaterial( {
18435
18436                 name: 'EquirectangularToCubeUV',
18437
18438                 uniforms: {
18439                         'envMap': { value: null },
18440                         'texelSize': { value: texelSize },
18441                         'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
18442                         'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
18443                 },
18444
18445                 vertexShader: _getCommonVertexShader(),
18446
18447                 fragmentShader: /* glsl */`
18448
18449                         precision mediump float;
18450                         precision mediump int;
18451
18452                         varying vec3 vOutputDirection;
18453
18454                         uniform sampler2D envMap;
18455                         uniform vec2 texelSize;
18456
18457                         ${ _getEncodings() }
18458
18459                         #include <common>
18460
18461                         void main() {
18462
18463                                 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
18464
18465                                 vec3 outputDirection = normalize( vOutputDirection );
18466                                 vec2 uv = equirectUv( outputDirection );
18467
18468                                 vec2 f = fract( uv / texelSize - 0.5 );
18469                                 uv -= f * texelSize;
18470                                 vec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
18471                                 uv.x += texelSize.x;
18472                                 vec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
18473                                 uv.y += texelSize.y;
18474                                 vec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
18475                                 uv.x -= texelSize.x;
18476                                 vec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
18477
18478                                 vec3 tm = mix( tl, tr, f.x );
18479                                 vec3 bm = mix( bl, br, f.x );
18480                                 gl_FragColor.rgb = mix( tm, bm, f.y );
18481
18482                                 gl_FragColor = linearToOutputTexel( gl_FragColor );
18483
18484                         }
18485                 `,
18486
18487                 blending: NoBlending,
18488                 depthTest: false,
18489                 depthWrite: false
18490
18491         } );
18492
18493         return shaderMaterial;
18494
18495     }
18496
18497     function _getCubemapShader() {
18498
18499         const shaderMaterial = new RawShaderMaterial( {
18500
18501                 name: 'CubemapToCubeUV',
18502
18503                 uniforms: {
18504                         'envMap': { value: null },
18505                         'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
18506                         'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
18507                 },
18508
18509                 vertexShader: _getCommonVertexShader(),
18510
18511                 fragmentShader: /* glsl */`
18512
18513                         precision mediump float;
18514                         precision mediump int;
18515
18516                         varying vec3 vOutputDirection;
18517
18518                         uniform samplerCube envMap;
18519
18520                         ${ _getEncodings() }
18521
18522                         void main() {
18523
18524                                 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
18525                                 gl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb;
18526                                 gl_FragColor = linearToOutputTexel( gl_FragColor );
18527
18528                         }
18529                 `,
18530
18531                 blending: NoBlending,
18532                 depthTest: false,
18533                 depthWrite: false
18534
18535         } );
18536
18537         return shaderMaterial;
18538
18539     }
18540
18541     function _getCommonVertexShader() {
18542
18543         return /* glsl */`
18544
18545                 precision mediump float;
18546                 precision mediump int;
18547
18548                 attribute vec3 position;
18549                 attribute vec2 uv;
18550                 attribute float faceIndex;
18551
18552                 varying vec3 vOutputDirection;
18553
18554                 // RH coordinate system; PMREM face-indexing convention
18555                 vec3 getDirection( vec2 uv, float face ) {
18556
18557                         uv = 2.0 * uv - 1.0;
18558
18559                         vec3 direction = vec3( uv, 1.0 );
18560
18561                         if ( face == 0.0 ) {
18562
18563                                 direction = direction.zyx; // ( 1, v, u ) pos x
18564
18565                         } else if ( face == 1.0 ) {
18566
18567                                 direction = direction.xzy;
18568                                 direction.xz *= -1.0; // ( -u, 1, -v ) pos y
18569
18570                         } else if ( face == 2.0 ) {
18571
18572                                 direction.x *= -1.0; // ( -u, v, 1 ) pos z
18573
18574                         } else if ( face == 3.0 ) {
18575
18576                                 direction = direction.zyx;
18577                                 direction.xz *= -1.0; // ( -1, v, -u ) neg x
18578
18579                         } else if ( face == 4.0 ) {
18580
18581                                 direction = direction.xzy;
18582                                 direction.xy *= -1.0; // ( -u, -1, v ) neg y
18583
18584                         } else if ( face == 5.0 ) {
18585
18586                                 direction.z *= -1.0; // ( u, v, -1 ) neg z
18587
18588                         }
18589
18590                         return direction;
18591
18592                 }
18593
18594                 void main() {
18595
18596                         vOutputDirection = getDirection( uv, faceIndex );
18597                         gl_Position = vec4( position, 1.0 );
18598
18599                 }
18600         `;
18601
18602     }
18603
18604     function _getEncodings() {
18605
18606         return /* glsl */`
18607
18608                 uniform int inputEncoding;
18609                 uniform int outputEncoding;
18610
18611                 #include <encodings_pars_fragment>
18612
18613                 vec4 inputTexelToLinear( vec4 value ) {
18614
18615                         if ( inputEncoding == 0 ) {
18616
18617                                 return value;
18618
18619                         } else if ( inputEncoding == 1 ) {
18620
18621                                 return sRGBToLinear( value );
18622
18623                         } else if ( inputEncoding == 2 ) {
18624
18625                                 return RGBEToLinear( value );
18626
18627                         } else if ( inputEncoding == 3 ) {
18628
18629                                 return RGBMToLinear( value, 7.0 );
18630
18631                         } else if ( inputEncoding == 4 ) {
18632
18633                                 return RGBMToLinear( value, 16.0 );
18634
18635                         } else if ( inputEncoding == 5 ) {
18636
18637                                 return RGBDToLinear( value, 256.0 );
18638
18639                         } else {
18640
18641                                 return GammaToLinear( value, 2.2 );
18642
18643                         }
18644
18645                 }
18646
18647                 vec4 linearToOutputTexel( vec4 value ) {
18648
18649                         if ( outputEncoding == 0 ) {
18650
18651                                 return value;
18652
18653                         } else if ( outputEncoding == 1 ) {
18654
18655                                 return LinearTosRGB( value );
18656
18657                         } else if ( outputEncoding == 2 ) {
18658
18659                                 return LinearToRGBE( value );
18660
18661                         } else if ( outputEncoding == 3 ) {
18662
18663                                 return LinearToRGBM( value, 7.0 );
18664
18665                         } else if ( outputEncoding == 4 ) {
18666
18667                                 return LinearToRGBM( value, 16.0 );
18668
18669                         } else if ( outputEncoding == 5 ) {
18670
18671                                 return LinearToRGBD( value, 256.0 );
18672
18673                         } else {
18674
18675                                 return LinearToGamma( value, 2.2 );
18676
18677                         }
18678
18679                 }
18680
18681                 vec4 envMapTexelToLinear( vec4 color ) {
18682
18683                         return inputTexelToLinear( color );
18684
18685                 }
18686         `;
18687
18688     }
18689
18690     function WebGLCubeUVMaps( renderer ) {
18691
18692         let cubeUVmaps = new WeakMap();
18693
18694         let pmremGenerator = null;
18695
18696         function get( texture ) {
18697
18698                 if ( texture && texture.isTexture && texture.isRenderTargetTexture === false ) {
18699
18700                         const mapping = texture.mapping;
18701
18702                         const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping );
18703                         const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping );
18704
18705                         if ( isEquirectMap || isCubeMap ) {
18706
18707                                 // equirect/cube map to cubeUV conversion
18708
18709                                 if ( cubeUVmaps.has( texture ) ) {
18710
18711                                         return cubeUVmaps.get( texture ).texture;
18712
18713                                 } else {
18714
18715                                         const image = texture.image;
18716
18717                                         if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) {
18718
18719                                                 const currentRenderTarget = renderer.getRenderTarget();
18720
18721                                                 if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
18722
18723                                                 const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture );
18724                                                 cubeUVmaps.set( texture, renderTarget );
18725
18726                                                 renderer.setRenderTarget( currentRenderTarget );
18727
18728                                                 texture.addEventListener( 'dispose', onTextureDispose );
18729
18730                                                 return renderTarget.texture;
18731
18732                                         } else {
18733
18734                                                 // image not yet ready. try the conversion next frame
18735
18736                                                 return null;
18737
18738                                         }
18739
18740                                 }
18741
18742                         }
18743
18744                 }
18745
18746                 return texture;
18747
18748         }
18749
18750         function isCubeTextureComplete( image ) {
18751
18752                 let count = 0;
18753                 const length = 6;
18754
18755                 for ( let i = 0; i < length; i ++ ) {
18756
18757                         if ( image[ i ] !== undefined ) count ++;
18758
18759                 }
18760
18761                 return count === length;
18762
18763
18764         }
18765
18766         function onTextureDispose( event ) {
18767
18768                 const texture = event.target;
18769
18770                 texture.removeEventListener( 'dispose', onTextureDispose );
18771
18772                 const cubemapUV = cubeUVmaps.get( texture );
18773
18774                 if ( cubemapUV !== undefined ) {
18775
18776                         cubeUVmaps.delete( texture );
18777                         cubemapUV.dispose();
18778
18779                 }
18780
18781         }
18782
18783         function dispose() {
18784
18785                 cubeUVmaps = new WeakMap();
18786
18787                 if ( pmremGenerator !== null ) {
18788
18789                         pmremGenerator.dispose();
18790                         pmremGenerator = null;
18791
18792                 }
18793
18794         }
18795
18796         return {
18797                 get: get,
18798                 dispose: dispose
18799         };
18800
18801     }
18802
18803     function WebGLExtensions( gl ) {
18804
18805         const extensions = {};
18806
18807         function getExtension( name ) {
18808
18809                 if ( extensions[ name ] !== undefined ) {
18810
18811                         return extensions[ name ];
18812
18813                 }
18814
18815                 let extension;
18816
18817                 switch ( name ) {
18818
18819                         case 'WEBGL_depth_texture':
18820                                 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
18821                                 break;
18822
18823                         case 'EXT_texture_filter_anisotropic':
18824                                 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
18825                                 break;
18826
18827                         case 'WEBGL_compressed_texture_s3tc':
18828                                 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
18829                                 break;
18830
18831                         case 'WEBGL_compressed_texture_pvrtc':
18832                                 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
18833                                 break;
18834
18835                         default:
18836                                 extension = gl.getExtension( name );
18837
18838                 }
18839
18840                 extensions[ name ] = extension;
18841
18842                 return extension;
18843
18844         }
18845
18846         return {
18847
18848                 has: function ( name ) {
18849
18850                         return getExtension( name ) !== null;
18851
18852                 },
18853
18854                 init: function ( capabilities ) {
18855
18856                         if ( capabilities.isWebGL2 ) {
18857
18858                                 getExtension( 'EXT_color_buffer_float' );
18859
18860                         } else {
18861
18862                                 getExtension( 'WEBGL_depth_texture' );
18863                                 getExtension( 'OES_texture_float' );
18864                                 getExtension( 'OES_texture_half_float' );
18865                                 getExtension( 'OES_texture_half_float_linear' );
18866                                 getExtension( 'OES_standard_derivatives' );
18867                                 getExtension( 'OES_element_index_uint' );
18868                                 getExtension( 'OES_vertex_array_object' );
18869                                 getExtension( 'ANGLE_instanced_arrays' );
18870
18871                         }
18872
18873                         getExtension( 'OES_texture_float_linear' );
18874                         getExtension( 'EXT_color_buffer_half_float' );
18875
18876                 },
18877
18878                 get: function ( name ) {
18879
18880                         const extension = getExtension( name );
18881
18882                         if ( extension === null ) {
18883
18884                                 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
18885
18886                         }
18887
18888                         return extension;
18889
18890                 }
18891
18892         };
18893
18894     }
18895
18896     function WebGLGeometries( gl, attributes, info, bindingStates ) {
18897
18898         const geometries = {};
18899         const wireframeAttributes = new WeakMap();
18900
18901         function onGeometryDispose( event ) {
18902
18903                 const geometry = event.target;
18904
18905                 if ( geometry.index !== null ) {
18906
18907                         attributes.remove( geometry.index );
18908
18909                 }
18910
18911                 for ( const name in geometry.attributes ) {
18912
18913                         attributes.remove( geometry.attributes[ name ] );
18914
18915                 }
18916
18917                 geometry.removeEventListener( 'dispose', onGeometryDispose );
18918
18919                 delete geometries[ geometry.id ];
18920
18921                 const attribute = wireframeAttributes.get( geometry );
18922
18923                 if ( attribute ) {
18924
18925                         attributes.remove( attribute );
18926                         wireframeAttributes.delete( geometry );
18927
18928                 }
18929
18930                 bindingStates.releaseStatesOfGeometry( geometry );
18931
18932                 if ( geometry.isInstancedBufferGeometry === true ) {
18933
18934                         delete geometry._maxInstanceCount;
18935
18936                 }
18937
18938                 //
18939
18940                 info.memory.geometries --;
18941
18942         }
18943
18944         function get( object, geometry ) {
18945
18946                 if ( geometries[ geometry.id ] === true ) return geometry;
18947
18948                 geometry.addEventListener( 'dispose', onGeometryDispose );
18949
18950                 geometries[ geometry.id ] = true;
18951
18952                 info.memory.geometries ++;
18953
18954                 return geometry;
18955
18956         }
18957
18958         function update( geometry ) {
18959
18960                 const geometryAttributes = geometry.attributes;
18961
18962                 // Updating index buffer in VAO now. See WebGLBindingStates.
18963
18964                 for ( const name in geometryAttributes ) {
18965
18966                         attributes.update( geometryAttributes[ name ], 34962 );
18967
18968                 }
18969
18970                 // morph targets
18971
18972                 const morphAttributes = geometry.morphAttributes;
18973
18974                 for ( const name in morphAttributes ) {
18975
18976                         const array = morphAttributes[ name ];
18977
18978                         for ( let i = 0, l = array.length; i < l; i ++ ) {
18979
18980                                 attributes.update( array[ i ], 34962 );
18981
18982                         }
18983
18984                 }
18985
18986         }
18987
18988         function updateWireframeAttribute( geometry ) {
18989
18990                 const indices = [];
18991
18992                 const geometryIndex = geometry.index;
18993                 const geometryPosition = geometry.attributes.position;
18994                 let version = 0;
18995
18996                 if ( geometryIndex !== null ) {
18997
18998                         const array = geometryIndex.array;
18999                         version = geometryIndex.version;
19000
19001                         for ( let i = 0, l = array.length; i < l; i += 3 ) {
19002
19003                                 const a = array[ i + 0 ];
19004                                 const b = array[ i + 1 ];
19005                                 const c = array[ i + 2 ];
19006
19007                                 indices.push( a, b, b, c, c, a );
19008
19009                         }
19010
19011                 } else {
19012
19013                         const array = geometryPosition.array;
19014                         version = geometryPosition.version;
19015
19016                         for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
19017
19018                                 const a = i + 0;
19019                                 const b = i + 1;
19020                                 const c = i + 2;
19021
19022                                 indices.push( a, b, b, c, c, a );
19023
19024                         }
19025
19026                 }
19027
19028                 const attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
19029                 attribute.version = version;
19030
19031                 // Updating index buffer in VAO now. See WebGLBindingStates
19032
19033                 //
19034
19035                 const previousAttribute = wireframeAttributes.get( geometry );
19036
19037                 if ( previousAttribute ) attributes.remove( previousAttribute );
19038
19039                 //
19040
19041                 wireframeAttributes.set( geometry, attribute );
19042
19043         }
19044
19045         function getWireframeAttribute( geometry ) {
19046
19047                 const currentAttribute = wireframeAttributes.get( geometry );
19048
19049                 if ( currentAttribute ) {
19050
19051                         const geometryIndex = geometry.index;
19052
19053                         if ( geometryIndex !== null ) {
19054
19055                                 // if the attribute is obsolete, create a new one
19056
19057                                 if ( currentAttribute.version < geometryIndex.version ) {
19058
19059                                         updateWireframeAttribute( geometry );
19060
19061                                 }
19062
19063                         }
19064
19065                 } else {
19066
19067                         updateWireframeAttribute( geometry );
19068
19069                 }
19070
19071                 return wireframeAttributes.get( geometry );
19072
19073         }
19074
19075         return {
19076
19077                 get: get,
19078                 update: update,
19079
19080                 getWireframeAttribute: getWireframeAttribute
19081
19082         };
19083
19084     }
19085
19086     function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
19087
19088         const isWebGL2 = capabilities.isWebGL2;
19089
19090         let mode;
19091
19092         function setMode( value ) {
19093
19094                 mode = value;
19095
19096         }
19097
19098         let type, bytesPerElement;
19099
19100         function setIndex( value ) {
19101
19102                 type = value.type;
19103                 bytesPerElement = value.bytesPerElement;
19104
19105         }
19106
19107         function render( start, count ) {
19108
19109                 gl.drawElements( mode, count, type, start * bytesPerElement );
19110
19111                 info.update( count, mode, 1 );
19112
19113         }
19114
19115         function renderInstances( start, count, primcount ) {
19116
19117                 if ( primcount === 0 ) return;
19118
19119                 let extension, methodName;
19120
19121                 if ( isWebGL2 ) {
19122
19123                         extension = gl;
19124                         methodName = 'drawElementsInstanced';
19125
19126                 } else {
19127
19128                         extension = extensions.get( 'ANGLE_instanced_arrays' );
19129                         methodName = 'drawElementsInstancedANGLE';
19130
19131                         if ( extension === null ) {
19132
19133                                 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
19134                                 return;
19135
19136                         }
19137
19138                 }
19139
19140                 extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );
19141
19142                 info.update( count, mode, primcount );
19143
19144         }
19145
19146         //
19147
19148         this.setMode = setMode;
19149         this.setIndex = setIndex;
19150         this.render = render;
19151         this.renderInstances = renderInstances;
19152
19153     }
19154
19155     function WebGLInfo( gl ) {
19156
19157         const memory = {
19158                 geometries: 0,
19159                 textures: 0
19160         };
19161
19162         const render = {
19163                 frame: 0,
19164                 calls: 0,
19165                 triangles: 0,
19166                 points: 0,
19167                 lines: 0
19168         };
19169
19170         function update( count, mode, instanceCount ) {
19171
19172                 render.calls ++;
19173
19174                 switch ( mode ) {
19175
19176                         case 4:
19177                                 render.triangles += instanceCount * ( count / 3 );
19178                                 break;
19179
19180                         case 1:
19181                                 render.lines += instanceCount * ( count / 2 );
19182                                 break;
19183
19184                         case 3:
19185                                 render.lines += instanceCount * ( count - 1 );
19186                                 break;
19187
19188                         case 2:
19189                                 render.lines += instanceCount * count;
19190                                 break;
19191
19192                         case 0:
19193                                 render.points += instanceCount * count;
19194                                 break;
19195
19196                         default:
19197                                 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
19198                                 break;
19199
19200                 }
19201
19202         }
19203
19204         function reset() {
19205
19206                 render.frame ++;
19207                 render.calls = 0;
19208                 render.triangles = 0;
19209                 render.points = 0;
19210                 render.lines = 0;
19211
19212         }
19213
19214         return {
19215                 memory: memory,
19216                 render: render,
19217                 programs: null,
19218                 autoReset: true,
19219                 reset: reset,
19220                 update: update
19221         };
19222
19223     }
19224
19225     class DataTexture2DArray extends Texture {
19226
19227         constructor( data = null, width = 1, height = 1, depth = 1 ) {
19228
19229                 super( null );
19230
19231                 this.image = { data, width, height, depth };
19232
19233                 this.magFilter = NearestFilter;
19234                 this.minFilter = NearestFilter;
19235
19236                 this.wrapR = ClampToEdgeWrapping;
19237
19238                 this.generateMipmaps = false;
19239                 this.flipY = false;
19240                 this.unpackAlignment = 1;
19241
19242                 this.needsUpdate = true;
19243
19244         }
19245
19246     }
19247
19248     DataTexture2DArray.prototype.isDataTexture2DArray = true;
19249
19250     function numericalSort( a, b ) {
19251
19252         return a[ 0 ] - b[ 0 ];
19253
19254     }
19255
19256     function absNumericalSort( a, b ) {
19257
19258         return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
19259
19260     }
19261
19262     function denormalize( morph, attribute ) {
19263
19264         let denominator = 1;
19265         const array = attribute.isInterleavedBufferAttribute ? attribute.data.array : attribute.array;
19266
19267         if ( array instanceof Int8Array ) denominator = 127;
19268         else if ( array instanceof Int16Array ) denominator = 32767;
19269         else if ( array instanceof Int32Array ) denominator = 2147483647;
19270         else console.error( 'THREE.WebGLMorphtargets: Unsupported morph attribute data type: ', array );
19271
19272         morph.divideScalar( denominator );
19273
19274     }
19275
19276     function WebGLMorphtargets( gl, capabilities, textures ) {
19277
19278         const influencesList = {};
19279         const morphInfluences = new Float32Array( 8 );
19280         const morphTextures = new WeakMap();
19281         const morph = new Vector3();
19282
19283         const workInfluences = [];
19284
19285         for ( let i = 0; i < 8; i ++ ) {
19286
19287                 workInfluences[ i ] = [ i, 0 ];
19288
19289         }
19290
19291         function update( object, geometry, material, program ) {
19292
19293                 const objectInfluences = object.morphTargetInfluences;
19294
19295                 if ( capabilities.isWebGL2 === true ) {
19296
19297                         // instead of using attributes, the WebGL 2 code path encodes morph targets
19298                         // into an array of data textures. Each layer represents a single morph target.
19299
19300                         const numberOfMorphTargets = geometry.morphAttributes.position.length;
19301
19302                         let entry = morphTextures.get( geometry );
19303
19304                         if ( entry === undefined || entry.count !== numberOfMorphTargets ) {
19305
19306                                 if ( entry !== undefined ) entry.texture.dispose();
19307
19308                                 const hasMorphNormals = geometry.morphAttributes.normal !== undefined;
19309
19310                                 const morphTargets = geometry.morphAttributes.position;
19311                                 const morphNormals = geometry.morphAttributes.normal || [];
19312
19313                                 const numberOfVertices = geometry.attributes.position.count;
19314                                 const numberOfVertexData = ( hasMorphNormals === true ) ? 2 : 1; // (v,n) vs. (v)
19315
19316                                 let width = numberOfVertices * numberOfVertexData;
19317                                 let height = 1;
19318
19319                                 if ( width > capabilities.maxTextureSize ) {
19320
19321                                         height = Math.ceil( width / capabilities.maxTextureSize );
19322                                         width = capabilities.maxTextureSize;
19323
19324                                 }
19325
19326                                 const buffer = new Float32Array( width * height * 4 * numberOfMorphTargets );
19327
19328                                 const texture = new DataTexture2DArray( buffer, width, height, numberOfMorphTargets );
19329                                 texture.format = RGBAFormat; // using RGBA since RGB might be emulated (and is thus slower)
19330                                 texture.type = FloatType;
19331
19332                                 // fill buffer
19333
19334                                 const vertexDataStride = numberOfVertexData * 4;
19335
19336                                 for ( let i = 0; i < numberOfMorphTargets; i ++ ) {
19337
19338                                         const morphTarget = morphTargets[ i ];
19339                                         const morphNormal = morphNormals[ i ];
19340
19341                                         const offset = width * height * 4 * i;
19342
19343                                         for ( let j = 0; j < morphTarget.count; j ++ ) {
19344
19345                                                 morph.fromBufferAttribute( morphTarget, j );
19346
19347                                                 if ( morphTarget.normalized === true ) denormalize( morph, morphTarget );
19348
19349                                                 const stride = j * vertexDataStride;
19350
19351                                                 buffer[ offset + stride + 0 ] = morph.x;
19352                                                 buffer[ offset + stride + 1 ] = morph.y;
19353                                                 buffer[ offset + stride + 2 ] = morph.z;
19354                                                 buffer[ offset + stride + 3 ] = 0;
19355
19356                                                 if ( hasMorphNormals === true ) {
19357
19358                                                         morph.fromBufferAttribute( morphNormal, j );
19359
19360                                                         if ( morphNormal.normalized === true ) denormalize( morph, morphNormal );
19361
19362                                                         buffer[ offset + stride + 4 ] = morph.x;
19363                                                         buffer[ offset + stride + 5 ] = morph.y;
19364                                                         buffer[ offset + stride + 6 ] = morph.z;
19365                                                         buffer[ offset + stride + 7 ] = 0;
19366
19367                                                 }
19368
19369                                         }
19370
19371                                 }
19372
19373                                 entry = {
19374                                         count: numberOfMorphTargets,
19375                                         texture: texture,
19376                                         size: new Vector2( width, height )
19377                                 };
19378
19379                                 morphTextures.set( geometry, entry );
19380
19381                         }
19382
19383                         //
19384
19385                         let morphInfluencesSum = 0;
19386
19387                         for ( let i = 0; i < objectInfluences.length; i ++ ) {
19388
19389                                 morphInfluencesSum += objectInfluences[ i ];
19390
19391                         }
19392
19393                         const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
19394
19395                         program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
19396                         program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences );
19397
19398                         program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures );
19399                         program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size );
19400
19401
19402                 } else {
19403
19404                         // When object doesn't have morph target influences defined, we treat it as a 0-length array
19405                         // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
19406
19407                         const length = objectInfluences === undefined ? 0 : objectInfluences.length;
19408
19409                         let influences = influencesList[ geometry.id ];
19410
19411                         if ( influences === undefined || influences.length !== length ) {
19412
19413                                 // initialise list
19414
19415                                 influences = [];
19416
19417                                 for ( let i = 0; i < length; i ++ ) {
19418
19419                                         influences[ i ] = [ i, 0 ];
19420
19421                                 }
19422
19423                                 influencesList[ geometry.id ] = influences;
19424
19425                         }
19426
19427                         // Collect influences
19428
19429                         for ( let i = 0; i < length; i ++ ) {
19430
19431                                 const influence = influences[ i ];
19432
19433                                 influence[ 0 ] = i;
19434                                 influence[ 1 ] = objectInfluences[ i ];
19435
19436                         }
19437
19438                         influences.sort( absNumericalSort );
19439
19440                         for ( let i = 0; i < 8; i ++ ) {
19441
19442                                 if ( i < length && influences[ i ][ 1 ] ) {
19443
19444                                         workInfluences[ i ][ 0 ] = influences[ i ][ 0 ];
19445                                         workInfluences[ i ][ 1 ] = influences[ i ][ 1 ];
19446
19447                                 } else {
19448
19449                                         workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER;
19450                                         workInfluences[ i ][ 1 ] = 0;
19451
19452                                 }
19453
19454                         }
19455
19456                         workInfluences.sort( numericalSort );
19457
19458                         const morphTargets = geometry.morphAttributes.position;
19459                         const morphNormals = geometry.morphAttributes.normal;
19460
19461                         let morphInfluencesSum = 0;
19462
19463                         for ( let i = 0; i < 8; i ++ ) {
19464
19465                                 const influence = workInfluences[ i ];
19466                                 const index = influence[ 0 ];
19467                                 const value = influence[ 1 ];
19468
19469                                 if ( index !== Number.MAX_SAFE_INTEGER && value ) {
19470
19471                                         if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) {
19472
19473                                                 geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );
19474
19475                                         }
19476
19477                                         if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) {
19478
19479                                                 geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );
19480
19481                                         }
19482
19483                                         morphInfluences[ i ] = value;
19484                                         morphInfluencesSum += value;
19485
19486                                 } else {
19487
19488                                         if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) {
19489
19490                                                 geometry.deleteAttribute( 'morphTarget' + i );
19491
19492                                         }
19493
19494                                         if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) {
19495
19496                                                 geometry.deleteAttribute( 'morphNormal' + i );
19497
19498                                         }
19499
19500                                         morphInfluences[ i ] = 0;
19501
19502                                 }
19503
19504                         }
19505
19506                         // GLSL shader uses formula baseinfluence * base + sum(target * influence)
19507                         // This allows us to switch between absolute morphs and relative morphs without changing shader code
19508                         // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
19509                         const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
19510
19511                         program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
19512                         program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
19513
19514                 }
19515
19516         }
19517
19518         return {
19519
19520                 update: update
19521
19522         };
19523
19524     }
19525
19526     function WebGLObjects( gl, geometries, attributes, info ) {
19527
19528         let updateMap = new WeakMap();
19529
19530         function update( object ) {
19531
19532                 const frame = info.render.frame;
19533
19534                 const geometry = object.geometry;
19535                 const buffergeometry = geometries.get( object, geometry );
19536
19537                 // Update once per frame
19538
19539                 if ( updateMap.get( buffergeometry ) !== frame ) {
19540
19541                         geometries.update( buffergeometry );
19542
19543                         updateMap.set( buffergeometry, frame );
19544
19545                 }
19546
19547                 if ( object.isInstancedMesh ) {
19548
19549                         if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) {
19550
19551                                 object.addEventListener( 'dispose', onInstancedMeshDispose );
19552
19553                         }
19554
19555                         attributes.update( object.instanceMatrix, 34962 );
19556
19557                         if ( object.instanceColor !== null ) {
19558
19559                                 attributes.update( object.instanceColor, 34962 );
19560
19561                         }
19562
19563                 }
19564
19565                 return buffergeometry;
19566
19567         }
19568
19569         function dispose() {
19570
19571                 updateMap = new WeakMap();
19572
19573         }
19574
19575         function onInstancedMeshDispose( event ) {
19576
19577                 const instancedMesh = event.target;
19578
19579                 instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
19580
19581                 attributes.remove( instancedMesh.instanceMatrix );
19582
19583                 if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );
19584
19585         }
19586
19587         return {
19588
19589                 update: update,
19590                 dispose: dispose
19591
19592         };
19593
19594     }
19595
19596     class DataTexture3D extends Texture {
19597
19598         constructor( data = null, width = 1, height = 1, depth = 1 ) {
19599
19600                 // We're going to add .setXXX() methods for setting properties later.
19601                 // Users can still set in DataTexture3D directly.
19602                 //
19603                 //      const texture = new THREE.DataTexture3D( data, width, height, depth );
19604                 //      texture.anisotropy = 16;
19605                 //
19606                 // See #14839
19607
19608                 super( null );
19609
19610                 this.image = { data, width, height, depth };
19611
19612                 this.magFilter = NearestFilter;
19613                 this.minFilter = NearestFilter;
19614
19615                 this.wrapR = ClampToEdgeWrapping;
19616
19617                 this.generateMipmaps = false;
19618                 this.flipY = false;
19619                 this.unpackAlignment = 1;
19620
19621                 this.needsUpdate = true;
19622
19623         }
19624
19625     }
19626
19627     DataTexture3D.prototype.isDataTexture3D = true;
19628
19629     /**
19630      * Uniforms of a program.
19631      * Those form a tree structure with a special top-level container for the root,
19632      * which you get by calling 'new WebGLUniforms( gl, program )'.
19633      *
19634      *
19635      * Properties of inner nodes including the top-level container:
19636      *
19637      * .seq - array of nested uniforms
19638      * .map - nested uniforms by name
19639      *
19640      *
19641      * Methods of all nodes except the top-level container:
19642      *
19643      * .setValue( gl, value, [textures] )
19644      *
19645      *          uploads a uniform value(s)
19646      *          the 'textures' parameter is needed for sampler uniforms
19647      *
19648      *
19649      * Static methods of the top-level container (textures factorizations):
19650      *
19651      * .upload( gl, seq, values, textures )
19652      *
19653      *          sets uniforms in 'seq' to 'values[id].value'
19654      *
19655      * .seqWithValue( seq, values ) : filteredSeq
19656      *
19657      *          filters 'seq' entries with corresponding entry in values
19658      *
19659      *
19660      * Methods of the top-level container (textures factorizations):
19661      *
19662      * .setValue( gl, name, value, textures )
19663      *
19664      *          sets uniform with  name 'name' to 'value'
19665      *
19666      * .setOptional( gl, obj, prop )
19667      *
19668      *          like .set for an optional property of the object
19669      *
19670      */
19671
19672     const emptyTexture = new Texture();
19673     const emptyTexture2dArray = new DataTexture2DArray();
19674     const emptyTexture3d = new DataTexture3D();
19675     const emptyCubeTexture = new CubeTexture();
19676
19677     // --- Utilities ---
19678
19679     // Array Caches (provide typed arrays for temporary by size)
19680
19681     const arrayCacheF32 = [];
19682     const arrayCacheI32 = [];
19683
19684     // Float32Array caches used for uploading Matrix uniforms
19685
19686     const mat4array = new Float32Array( 16 );
19687     const mat3array = new Float32Array( 9 );
19688     const mat2array = new Float32Array( 4 );
19689
19690     // Flattening for arrays of vectors and matrices
19691
19692     function flatten( array, nBlocks, blockSize ) {
19693
19694         const firstElem = array[ 0 ];
19695
19696         if ( firstElem <= 0 || firstElem > 0 ) return array;
19697         // unoptimized: ! isNaN( firstElem )
19698         // see http://jacksondunstan.com/articles/983
19699
19700         const n = nBlocks * blockSize;
19701         let r = arrayCacheF32[ n ];
19702
19703         if ( r === undefined ) {
19704
19705                 r = new Float32Array( n );
19706                 arrayCacheF32[ n ] = r;
19707
19708         }
19709
19710         if ( nBlocks !== 0 ) {
19711
19712                 firstElem.toArray( r, 0 );
19713
19714                 for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) {
19715
19716                         offset += blockSize;
19717                         array[ i ].toArray( r, offset );
19718
19719                 }
19720
19721         }
19722
19723         return r;
19724
19725     }
19726
19727     function arraysEqual( a, b ) {
19728
19729         if ( a.length !== b.length ) return false;
19730
19731         for ( let i = 0, l = a.length; i < l; i ++ ) {
19732
19733                 if ( a[ i ] !== b[ i ] ) return false;
19734
19735         }
19736
19737         return true;
19738
19739     }
19740
19741     function copyArray( a, b ) {
19742
19743         for ( let i = 0, l = b.length; i < l; i ++ ) {
19744
19745                 a[ i ] = b[ i ];
19746
19747         }
19748
19749     }
19750
19751     // Texture unit allocation
19752
19753     function allocTexUnits( textures, n ) {
19754
19755         let r = arrayCacheI32[ n ];
19756
19757         if ( r === undefined ) {
19758
19759                 r = new Int32Array( n );
19760                 arrayCacheI32[ n ] = r;
19761
19762         }
19763
19764         for ( let i = 0; i !== n; ++ i ) {
19765
19766                 r[ i ] = textures.allocateTextureUnit();
19767
19768         }
19769
19770         return r;
19771
19772     }
19773
19774     // --- Setters ---
19775
19776     // Note: Defining these methods externally, because they come in a bunch
19777     // and this way their names minify.
19778
19779     // Single scalar
19780
19781     function setValueV1f( gl, v ) {
19782
19783         const cache = this.cache;
19784
19785         if ( cache[ 0 ] === v ) return;
19786
19787         gl.uniform1f( this.addr, v );
19788
19789         cache[ 0 ] = v;
19790
19791     }
19792
19793     // Single float vector (from flat array or THREE.VectorN)
19794
19795     function setValueV2f( gl, v ) {
19796
19797         const cache = this.cache;
19798
19799         if ( v.x !== undefined ) {
19800
19801                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
19802
19803                         gl.uniform2f( this.addr, v.x, v.y );
19804
19805                         cache[ 0 ] = v.x;
19806                         cache[ 1 ] = v.y;
19807
19808                 }
19809
19810         } else {
19811
19812                 if ( arraysEqual( cache, v ) ) return;
19813
19814                 gl.uniform2fv( this.addr, v );
19815
19816                 copyArray( cache, v );
19817
19818         }
19819
19820     }
19821
19822     function setValueV3f( gl, v ) {
19823
19824         const cache = this.cache;
19825
19826         if ( v.x !== undefined ) {
19827
19828                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
19829
19830                         gl.uniform3f( this.addr, v.x, v.y, v.z );
19831
19832                         cache[ 0 ] = v.x;
19833                         cache[ 1 ] = v.y;
19834                         cache[ 2 ] = v.z;
19835
19836                 }
19837
19838         } else if ( v.r !== undefined ) {
19839
19840                 if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
19841
19842                         gl.uniform3f( this.addr, v.r, v.g, v.b );
19843
19844                         cache[ 0 ] = v.r;
19845                         cache[ 1 ] = v.g;
19846                         cache[ 2 ] = v.b;
19847
19848                 }
19849
19850         } else {
19851
19852                 if ( arraysEqual( cache, v ) ) return;
19853
19854                 gl.uniform3fv( this.addr, v );
19855
19856                 copyArray( cache, v );
19857
19858         }
19859
19860     }
19861
19862     function setValueV4f( gl, v ) {
19863
19864         const cache = this.cache;
19865
19866         if ( v.x !== undefined ) {
19867
19868                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
19869
19870                         gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
19871
19872                         cache[ 0 ] = v.x;
19873                         cache[ 1 ] = v.y;
19874                         cache[ 2 ] = v.z;
19875                         cache[ 3 ] = v.w;
19876
19877                 }
19878
19879         } else {
19880
19881                 if ( arraysEqual( cache, v ) ) return;
19882
19883                 gl.uniform4fv( this.addr, v );
19884
19885                 copyArray( cache, v );
19886
19887         }
19888
19889     }
19890
19891     // Single matrix (from flat array or THREE.MatrixN)
19892
19893     function setValueM2( gl, v ) {
19894
19895         const cache = this.cache;
19896         const elements = v.elements;
19897
19898         if ( elements === undefined ) {
19899
19900                 if ( arraysEqual( cache, v ) ) return;
19901
19902                 gl.uniformMatrix2fv( this.addr, false, v );
19903
19904                 copyArray( cache, v );
19905
19906         } else {
19907
19908                 if ( arraysEqual( cache, elements ) ) return;
19909
19910                 mat2array.set( elements );
19911
19912                 gl.uniformMatrix2fv( this.addr, false, mat2array );
19913
19914                 copyArray( cache, elements );
19915
19916         }
19917
19918     }
19919
19920     function setValueM3( gl, v ) {
19921
19922         const cache = this.cache;
19923         const elements = v.elements;
19924
19925         if ( elements === undefined ) {
19926
19927                 if ( arraysEqual( cache, v ) ) return;
19928
19929                 gl.uniformMatrix3fv( this.addr, false, v );
19930
19931                 copyArray( cache, v );
19932
19933         } else {
19934
19935                 if ( arraysEqual( cache, elements ) ) return;
19936
19937                 mat3array.set( elements );
19938
19939                 gl.uniformMatrix3fv( this.addr, false, mat3array );
19940
19941                 copyArray( cache, elements );
19942
19943         }
19944
19945     }
19946
19947     function setValueM4( gl, v ) {
19948
19949         const cache = this.cache;
19950         const elements = v.elements;
19951
19952         if ( elements === undefined ) {
19953
19954                 if ( arraysEqual( cache, v ) ) return;
19955
19956                 gl.uniformMatrix4fv( this.addr, false, v );
19957
19958                 copyArray( cache, v );
19959
19960         } else {
19961
19962                 if ( arraysEqual( cache, elements ) ) return;
19963
19964                 mat4array.set( elements );
19965
19966                 gl.uniformMatrix4fv( this.addr, false, mat4array );
19967
19968                 copyArray( cache, elements );
19969
19970         }
19971
19972     }
19973
19974     // Single integer / boolean
19975
19976     function setValueV1i( gl, v ) {
19977
19978         const cache = this.cache;
19979
19980         if ( cache[ 0 ] === v ) return;
19981
19982         gl.uniform1i( this.addr, v );
19983
19984         cache[ 0 ] = v;
19985
19986     }
19987
19988     // Single integer / boolean vector (from flat array)
19989
19990     function setValueV2i( gl, v ) {
19991
19992         const cache = this.cache;
19993
19994         if ( arraysEqual( cache, v ) ) return;
19995
19996         gl.uniform2iv( this.addr, v );
19997
19998         copyArray( cache, v );
19999
20000     }
20001
20002     function setValueV3i( gl, v ) {
20003
20004         const cache = this.cache;
20005
20006         if ( arraysEqual( cache, v ) ) return;
20007
20008         gl.uniform3iv( this.addr, v );
20009
20010         copyArray( cache, v );
20011
20012     }
20013
20014     function setValueV4i( gl, v ) {
20015
20016         const cache = this.cache;
20017
20018         if ( arraysEqual( cache, v ) ) return;
20019
20020         gl.uniform4iv( this.addr, v );
20021
20022         copyArray( cache, v );
20023
20024     }
20025
20026     // Single unsigned integer
20027
20028     function setValueV1ui( gl, v ) {
20029
20030         const cache = this.cache;
20031
20032         if ( cache[ 0 ] === v ) return;
20033
20034         gl.uniform1ui( this.addr, v );
20035
20036         cache[ 0 ] = v;
20037
20038     }
20039
20040     // Single unsigned integer vector (from flat array)
20041
20042     function setValueV2ui( gl, v ) {
20043
20044         const cache = this.cache;
20045
20046         if ( arraysEqual( cache, v ) ) return;
20047
20048         gl.uniform2uiv( this.addr, v );
20049
20050         copyArray( cache, v );
20051
20052     }
20053
20054     function setValueV3ui( gl, v ) {
20055
20056         const cache = this.cache;
20057
20058         if ( arraysEqual( cache, v ) ) return;
20059
20060         gl.uniform3uiv( this.addr, v );
20061
20062         copyArray( cache, v );
20063
20064     }
20065
20066     function setValueV4ui( gl, v ) {
20067
20068         const cache = this.cache;
20069
20070         if ( arraysEqual( cache, v ) ) return;
20071
20072         gl.uniform4uiv( this.addr, v );
20073
20074         copyArray( cache, v );
20075
20076     }
20077
20078
20079     // Single texture (2D / Cube)
20080
20081     function setValueT1( gl, v, textures ) {
20082
20083         const cache = this.cache;
20084         const unit = textures.allocateTextureUnit();
20085
20086         if ( cache[ 0 ] !== unit ) {
20087
20088                 gl.uniform1i( this.addr, unit );
20089                 cache[ 0 ] = unit;
20090
20091         }
20092
20093         textures.safeSetTexture2D( v || emptyTexture, unit );
20094
20095     }
20096
20097     function setValueT3D1( gl, v, textures ) {
20098
20099         const cache = this.cache;
20100         const unit = textures.allocateTextureUnit();
20101
20102         if ( cache[ 0 ] !== unit ) {
20103
20104                 gl.uniform1i( this.addr, unit );
20105                 cache[ 0 ] = unit;
20106
20107         }
20108
20109         textures.setTexture3D( v || emptyTexture3d, unit );
20110
20111     }
20112
20113     function setValueT6( gl, v, textures ) {
20114
20115         const cache = this.cache;
20116         const unit = textures.allocateTextureUnit();
20117
20118         if ( cache[ 0 ] !== unit ) {
20119
20120                 gl.uniform1i( this.addr, unit );
20121                 cache[ 0 ] = unit;
20122
20123         }
20124
20125         textures.safeSetTextureCube( v || emptyCubeTexture, unit );
20126
20127     }
20128
20129     function setValueT2DArray1( gl, v, textures ) {
20130
20131         const cache = this.cache;
20132         const unit = textures.allocateTextureUnit();
20133
20134         if ( cache[ 0 ] !== unit ) {
20135
20136                 gl.uniform1i( this.addr, unit );
20137                 cache[ 0 ] = unit;
20138
20139         }
20140
20141         textures.setTexture2DArray( v || emptyTexture2dArray, unit );
20142
20143     }
20144
20145     // Helper to pick the right setter for the singular case
20146
20147     function getSingularSetter( type ) {
20148
20149         switch ( type ) {
20150
20151                 case 0x1406: return setValueV1f; // FLOAT
20152                 case 0x8b50: return setValueV2f; // _VEC2
20153                 case 0x8b51: return setValueV3f; // _VEC3
20154                 case 0x8b52: return setValueV4f; // _VEC4
20155
20156                 case 0x8b5a: return setValueM2; // _MAT2
20157                 case 0x8b5b: return setValueM3; // _MAT3
20158                 case 0x8b5c: return setValueM4; // _MAT4
20159
20160                 case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
20161                 case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
20162                 case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
20163                 case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
20164
20165                 case 0x1405: return setValueV1ui; // UINT
20166                 case 0x8dc6: return setValueV2ui; // _VEC2
20167                 case 0x8dc7: return setValueV3ui; // _VEC3
20168                 case 0x8dc8: return setValueV4ui; // _VEC4
20169
20170                 case 0x8b5e: // SAMPLER_2D
20171                 case 0x8d66: // SAMPLER_EXTERNAL_OES
20172                 case 0x8dca: // INT_SAMPLER_2D
20173                 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
20174                 case 0x8b62: // SAMPLER_2D_SHADOW
20175                         return setValueT1;
20176
20177                 case 0x8b5f: // SAMPLER_3D
20178                 case 0x8dcb: // INT_SAMPLER_3D
20179                 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
20180                         return setValueT3D1;
20181
20182                 case 0x8b60: // SAMPLER_CUBE
20183                 case 0x8dcc: // INT_SAMPLER_CUBE
20184                 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
20185                 case 0x8dc5: // SAMPLER_CUBE_SHADOW
20186                         return setValueT6;
20187
20188                 case 0x8dc1: // SAMPLER_2D_ARRAY
20189                 case 0x8dcf: // INT_SAMPLER_2D_ARRAY
20190                 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
20191                 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
20192                         return setValueT2DArray1;
20193
20194         }
20195
20196     }
20197
20198
20199     // Array of scalars
20200
20201     function setValueV1fArray( gl, v ) {
20202
20203         gl.uniform1fv( this.addr, v );
20204
20205     }
20206
20207     // Array of vectors (from flat array or array of THREE.VectorN)
20208
20209     function setValueV2fArray( gl, v ) {
20210
20211         const data = flatten( v, this.size, 2 );
20212
20213         gl.uniform2fv( this.addr, data );
20214
20215     }
20216
20217     function setValueV3fArray( gl, v ) {
20218
20219         const data = flatten( v, this.size, 3 );
20220
20221         gl.uniform3fv( this.addr, data );
20222
20223     }
20224
20225     function setValueV4fArray( gl, v ) {
20226
20227         const data = flatten( v, this.size, 4 );
20228
20229         gl.uniform4fv( this.addr, data );
20230
20231     }
20232
20233     // Array of matrices (from flat array or array of THREE.MatrixN)
20234
20235     function setValueM2Array( gl, v ) {
20236
20237         const data = flatten( v, this.size, 4 );
20238
20239         gl.uniformMatrix2fv( this.addr, false, data );
20240
20241     }
20242
20243     function setValueM3Array( gl, v ) {
20244
20245         const data = flatten( v, this.size, 9 );
20246
20247         gl.uniformMatrix3fv( this.addr, false, data );
20248
20249     }
20250
20251     function setValueM4Array( gl, v ) {
20252
20253         const data = flatten( v, this.size, 16 );
20254
20255         gl.uniformMatrix4fv( this.addr, false, data );
20256
20257     }
20258
20259     // Array of integer / boolean
20260
20261     function setValueV1iArray( gl, v ) {
20262
20263         gl.uniform1iv( this.addr, v );
20264
20265     }
20266
20267     // Array of integer / boolean vectors (from flat array)
20268
20269     function setValueV2iArray( gl, v ) {
20270
20271         gl.uniform2iv( this.addr, v );
20272
20273     }
20274
20275     function setValueV3iArray( gl, v ) {
20276
20277         gl.uniform3iv( this.addr, v );
20278
20279     }
20280
20281     function setValueV4iArray( gl, v ) {
20282
20283         gl.uniform4iv( this.addr, v );
20284
20285     }
20286
20287     // Array of unsigned integer
20288
20289     function setValueV1uiArray( gl, v ) {
20290
20291         gl.uniform1uiv( this.addr, v );
20292
20293     }
20294
20295     // Array of unsigned integer vectors (from flat array)
20296
20297     function setValueV2uiArray( gl, v ) {
20298
20299         gl.uniform2uiv( this.addr, v );
20300
20301     }
20302
20303     function setValueV3uiArray( gl, v ) {
20304
20305         gl.uniform3uiv( this.addr, v );
20306
20307     }
20308
20309     function setValueV4uiArray( gl, v ) {
20310
20311         gl.uniform4uiv( this.addr, v );
20312
20313     }
20314
20315
20316     // Array of textures (2D / Cube)
20317
20318     function setValueT1Array( gl, v, textures ) {
20319
20320         const n = v.length;
20321
20322         const units = allocTexUnits( textures, n );
20323
20324         gl.uniform1iv( this.addr, units );
20325
20326         for ( let i = 0; i !== n; ++ i ) {
20327
20328                 textures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );
20329
20330         }
20331
20332     }
20333
20334     function setValueT6Array( gl, v, textures ) {
20335
20336         const n = v.length;
20337
20338         const units = allocTexUnits( textures, n );
20339
20340         gl.uniform1iv( this.addr, units );
20341
20342         for ( let i = 0; i !== n; ++ i ) {
20343
20344                 textures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
20345
20346         }
20347
20348     }
20349
20350     // Helper to pick the right setter for a pure (bottom-level) array
20351
20352     function getPureArraySetter( type ) {
20353
20354         switch ( type ) {
20355
20356                 case 0x1406: return setValueV1fArray; // FLOAT
20357                 case 0x8b50: return setValueV2fArray; // _VEC2
20358                 case 0x8b51: return setValueV3fArray; // _VEC3
20359                 case 0x8b52: return setValueV4fArray; // _VEC4
20360
20361                 case 0x8b5a: return setValueM2Array; // _MAT2
20362                 case 0x8b5b: return setValueM3Array; // _MAT3
20363                 case 0x8b5c: return setValueM4Array; // _MAT4
20364
20365                 case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
20366                 case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
20367                 case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
20368                 case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
20369
20370                 case 0x1405: return setValueV1uiArray; // UINT
20371                 case 0x8dc6: return setValueV2uiArray; // _VEC2
20372                 case 0x8dc7: return setValueV3uiArray; // _VEC3
20373                 case 0x8dc8: return setValueV4uiArray; // _VEC4
20374
20375                 case 0x8b5e: // SAMPLER_2D
20376                 case 0x8d66: // SAMPLER_EXTERNAL_OES
20377                 case 0x8dca: // INT_SAMPLER_2D
20378                 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
20379                 case 0x8b62: // SAMPLER_2D_SHADOW
20380                         return setValueT1Array;
20381
20382                 case 0x8b60: // SAMPLER_CUBE
20383                 case 0x8dcc: // INT_SAMPLER_CUBE
20384                 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
20385                 case 0x8dc5: // SAMPLER_CUBE_SHADOW
20386                         return setValueT6Array;
20387
20388         }
20389
20390     }
20391
20392     // --- Uniform Classes ---
20393
20394     function SingleUniform( id, activeInfo, addr ) {
20395
20396         this.id = id;
20397         this.addr = addr;
20398         this.cache = [];
20399         this.setValue = getSingularSetter( activeInfo.type );
20400
20401         // this.path = activeInfo.name; // DEBUG
20402
20403     }
20404
20405     function PureArrayUniform( id, activeInfo, addr ) {
20406
20407         this.id = id;
20408         this.addr = addr;
20409         this.cache = [];
20410         this.size = activeInfo.size;
20411         this.setValue = getPureArraySetter( activeInfo.type );
20412
20413         // this.path = activeInfo.name; // DEBUG
20414
20415     }
20416
20417     PureArrayUniform.prototype.updateCache = function ( data ) {
20418
20419         const cache = this.cache;
20420
20421         if ( data instanceof Float32Array && cache.length !== data.length ) {
20422
20423                 this.cache = new Float32Array( data.length );
20424
20425         }
20426
20427         copyArray( cache, data );
20428
20429     };
20430
20431     function StructuredUniform( id ) {
20432
20433         this.id = id;
20434
20435         this.seq = [];
20436         this.map = {};
20437
20438     }
20439
20440     StructuredUniform.prototype.setValue = function ( gl, value, textures ) {
20441
20442         const seq = this.seq;
20443
20444         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
20445
20446                 const u = seq[ i ];
20447                 u.setValue( gl, value[ u.id ], textures );
20448
20449         }
20450
20451     };
20452
20453     // --- Top-level ---
20454
20455     // Parser - builds up the property tree from the path strings
20456
20457     const RePathPart = /(\w+)(\])?(\[|\.)?/g;
20458
20459     // extracts
20460     //  - the identifier (member name or array index)
20461     //  - followed by an optional right bracket (found when array index)
20462     //  - followed by an optional left bracket or dot (type of subscript)
20463     //
20464     // Note: These portions can be read in a non-overlapping fashion and
20465     // allow straightforward parsing of the hierarchy that WebGL encodes
20466     // in the uniform names.
20467
20468     function addUniform( container, uniformObject ) {
20469
20470         container.seq.push( uniformObject );
20471         container.map[ uniformObject.id ] = uniformObject;
20472
20473     }
20474
20475     function parseUniform( activeInfo, addr, container ) {
20476
20477         const path = activeInfo.name,
20478                 pathLength = path.length;
20479
20480         // reset RegExp object, because of the early exit of a previous run
20481         RePathPart.lastIndex = 0;
20482
20483         while ( true ) {
20484
20485                 const match = RePathPart.exec( path ),
20486                         matchEnd = RePathPart.lastIndex;
20487
20488                 let id = match[ 1 ];
20489                 const idIsIndex = match[ 2 ] === ']',
20490                         subscript = match[ 3 ];
20491
20492                 if ( idIsIndex ) id = id | 0; // convert to integer
20493
20494                 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
20495
20496                         // bare name or "pure" bottom-level array "[0]" suffix
20497
20498                         addUniform( container, subscript === undefined ?
20499                                 new SingleUniform( id, activeInfo, addr ) :
20500                                 new PureArrayUniform( id, activeInfo, addr ) );
20501
20502                         break;
20503
20504                 } else {
20505
20506                         // step into inner node / create it in case it doesn't exist
20507
20508                         const map = container.map;
20509                         let next = map[ id ];
20510
20511                         if ( next === undefined ) {
20512
20513                                 next = new StructuredUniform( id );
20514                                 addUniform( container, next );
20515
20516                         }
20517
20518                         container = next;
20519
20520                 }
20521
20522         }
20523
20524     }
20525
20526     // Root Container
20527
20528     function WebGLUniforms( gl, program ) {
20529
20530         this.seq = [];
20531         this.map = {};
20532
20533         const n = gl.getProgramParameter( program, 35718 );
20534
20535         for ( let i = 0; i < n; ++ i ) {
20536
20537                 const info = gl.getActiveUniform( program, i ),
20538                         addr = gl.getUniformLocation( program, info.name );
20539
20540                 parseUniform( info, addr, this );
20541
20542         }
20543
20544     }
20545
20546     WebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {
20547
20548         const u = this.map[ name ];
20549
20550         if ( u !== undefined ) u.setValue( gl, value, textures );
20551
20552     };
20553
20554     WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
20555
20556         const v = object[ name ];
20557
20558         if ( v !== undefined ) this.setValue( gl, name, v );
20559
20560     };
20561
20562
20563     // Static interface
20564
20565     WebGLUniforms.upload = function ( gl, seq, values, textures ) {
20566
20567         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
20568
20569                 const u = seq[ i ],
20570                         v = values[ u.id ];
20571
20572                 if ( v.needsUpdate !== false ) {
20573
20574                         // note: always updating when .needsUpdate is undefined
20575                         u.setValue( gl, v.value, textures );
20576
20577                 }
20578
20579         }
20580
20581     };
20582
20583     WebGLUniforms.seqWithValue = function ( seq, values ) {
20584
20585         const r = [];
20586
20587         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
20588
20589                 const u = seq[ i ];
20590                 if ( u.id in values ) r.push( u );
20591
20592         }
20593
20594         return r;
20595
20596     };
20597
20598     function WebGLShader( gl, type, string ) {
20599
20600         const shader = gl.createShader( type );
20601
20602         gl.shaderSource( shader, string );
20603         gl.compileShader( shader );
20604
20605         return shader;
20606
20607     }
20608
20609     let programIdCount = 0;
20610
20611     function addLineNumbers( string ) {
20612
20613         const lines = string.split( '\n' );
20614
20615         for ( let i = 0; i < lines.length; i ++ ) {
20616
20617                 lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
20618
20619         }
20620
20621         return lines.join( '\n' );
20622
20623     }
20624
20625     function getEncodingComponents( encoding ) {
20626
20627         switch ( encoding ) {
20628
20629                 case LinearEncoding:
20630                         return [ 'Linear', '( value )' ];
20631                 case sRGBEncoding:
20632                         return [ 'sRGB', '( value )' ];
20633                 case RGBEEncoding:
20634                         return [ 'RGBE', '( value )' ];
20635                 case RGBM7Encoding:
20636                         return [ 'RGBM', '( value, 7.0 )' ];
20637                 case RGBM16Encoding:
20638                         return [ 'RGBM', '( value, 16.0 )' ];
20639                 case RGBDEncoding:
20640                         return [ 'RGBD', '( value, 256.0 )' ];
20641                 case GammaEncoding:
20642                         return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
20643                 case LogLuvEncoding:
20644                         return [ 'LogLuv', '( value )' ];
20645                 default:
20646                         console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding );
20647                         return [ 'Linear', '( value )' ];
20648
20649         }
20650
20651     }
20652
20653     function getShaderErrors( gl, shader, type ) {
20654
20655         const status = gl.getShaderParameter( shader, 35713 );
20656         const errors = gl.getShaderInfoLog( shader ).trim();
20657
20658         if ( status && errors === '' ) return '';
20659
20660         // --enable-privileged-webgl-extension
20661         // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
20662
20663         return type.toUpperCase() + '\n\n' + errors + '\n\n' + addLineNumbers( gl.getShaderSource( shader ) );
20664
20665     }
20666
20667     function getTexelDecodingFunction( functionName, encoding ) {
20668
20669         const components = getEncodingComponents( encoding );
20670         return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
20671
20672     }
20673
20674     function getTexelEncodingFunction( functionName, encoding ) {
20675
20676         const components = getEncodingComponents( encoding );
20677         return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
20678
20679     }
20680
20681     function getToneMappingFunction( functionName, toneMapping ) {
20682
20683         let toneMappingName;
20684
20685         switch ( toneMapping ) {
20686
20687                 case LinearToneMapping:
20688                         toneMappingName = 'Linear';
20689                         break;
20690
20691                 case ReinhardToneMapping:
20692                         toneMappingName = 'Reinhard';
20693                         break;
20694
20695                 case CineonToneMapping:
20696                         toneMappingName = 'OptimizedCineon';
20697                         break;
20698
20699                 case ACESFilmicToneMapping:
20700                         toneMappingName = 'ACESFilmic';
20701                         break;
20702
20703                 case CustomToneMapping:
20704                         toneMappingName = 'Custom';
20705                         break;
20706
20707                 default:
20708                         console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping );
20709                         toneMappingName = 'Linear';
20710
20711         }
20712
20713         return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
20714
20715     }
20716
20717     function generateExtensions( parameters ) {
20718
20719         const chunks = [
20720                 ( parameters.extensionDerivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '',
20721                 ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',
20722                 ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '',
20723                 ( parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''
20724         ];
20725
20726         return chunks.filter( filterEmptyLine ).join( '\n' );
20727
20728     }
20729
20730     function generateDefines( defines ) {
20731
20732         const chunks = [];
20733
20734         for ( const name in defines ) {
20735
20736                 const value = defines[ name ];
20737
20738                 if ( value === false ) continue;
20739
20740                 chunks.push( '#define ' + name + ' ' + value );
20741
20742         }
20743
20744         return chunks.join( '\n' );
20745
20746     }
20747
20748     function fetchAttributeLocations( gl, program ) {
20749
20750         const attributes = {};
20751
20752         const n = gl.getProgramParameter( program, 35721 );
20753
20754         for ( let i = 0; i < n; i ++ ) {
20755
20756                 const info = gl.getActiveAttrib( program, i );
20757                 const name = info.name;
20758
20759                 let locationSize = 1;
20760                 if ( info.type === 35674 ) locationSize = 2;
20761                 if ( info.type === 35675 ) locationSize = 3;
20762                 if ( info.type === 35676 ) locationSize = 4;
20763
20764                 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
20765
20766                 attributes[ name ] = {
20767                         type: info.type,
20768                         location: gl.getAttribLocation( program, name ),
20769                         locationSize: locationSize
20770                 };
20771
20772         }
20773
20774         return attributes;
20775
20776     }
20777
20778     function filterEmptyLine( string ) {
20779
20780         return string !== '';
20781
20782     }
20783
20784     function replaceLightNums( string, parameters ) {
20785
20786         return string
20787                 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
20788                 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
20789                 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
20790                 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
20791                 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
20792                 .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
20793                 .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
20794                 .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
20795
20796     }
20797
20798     function replaceClippingPlaneNums( string, parameters ) {
20799
20800         return string
20801                 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
20802                 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
20803
20804     }
20805
20806     // Resolve Includes
20807
20808     const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
20809
20810     function resolveIncludes( string ) {
20811
20812         return string.replace( includePattern, includeReplacer );
20813
20814     }
20815
20816     function includeReplacer( match, include ) {
20817
20818         const string = ShaderChunk[ include ];
20819
20820         if ( string === undefined ) {
20821
20822                 throw new Error( 'Can not resolve #include <' + include + '>' );
20823
20824         }
20825
20826         return resolveIncludes( string );
20827
20828     }
20829
20830     // Unroll Loops
20831
20832     const deprecatedUnrollLoopPattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
20833     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;
20834
20835     function unrollLoops( string ) {
20836
20837         return string
20838                 .replace( unrollLoopPattern, loopReplacer )
20839                 .replace( deprecatedUnrollLoopPattern, deprecatedLoopReplacer );
20840
20841     }
20842
20843     function deprecatedLoopReplacer( match, start, end, snippet ) {
20844
20845         console.warn( 'WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.' );
20846         return loopReplacer( match, start, end, snippet );
20847
20848     }
20849
20850     function loopReplacer( match, start, end, snippet ) {
20851
20852         let string = '';
20853
20854         for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) {
20855
20856                 string += snippet
20857                         .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' )
20858                         .replace( /UNROLLED_LOOP_INDEX/g, i );
20859
20860         }
20861
20862         return string;
20863
20864     }
20865
20866     //
20867
20868     function generatePrecision( parameters ) {
20869
20870         let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;';
20871
20872         if ( parameters.precision === 'highp' ) {
20873
20874                 precisionstring += '\n#define HIGH_PRECISION';
20875
20876         } else if ( parameters.precision === 'mediump' ) {
20877
20878                 precisionstring += '\n#define MEDIUM_PRECISION';
20879
20880         } else if ( parameters.precision === 'lowp' ) {
20881
20882                 precisionstring += '\n#define LOW_PRECISION';
20883
20884         }
20885
20886         return precisionstring;
20887
20888     }
20889
20890     function generateShadowMapTypeDefine( parameters ) {
20891
20892         let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
20893
20894         if ( parameters.shadowMapType === PCFShadowMap ) {
20895
20896                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
20897
20898         } else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
20899
20900                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
20901
20902         } else if ( parameters.shadowMapType === VSMShadowMap ) {
20903
20904                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
20905
20906         }
20907
20908         return shadowMapTypeDefine;
20909
20910     }
20911
20912     function generateEnvMapTypeDefine( parameters ) {
20913
20914         let envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
20915
20916         if ( parameters.envMap ) {
20917
20918                 switch ( parameters.envMapMode ) {
20919
20920                         case CubeReflectionMapping:
20921                         case CubeRefractionMapping:
20922                                 envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
20923                                 break;
20924
20925                         case CubeUVReflectionMapping:
20926                         case CubeUVRefractionMapping:
20927                                 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
20928                                 break;
20929
20930                 }
20931
20932         }
20933
20934         return envMapTypeDefine;
20935
20936     }
20937
20938     function generateEnvMapModeDefine( parameters ) {
20939
20940         let envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
20941
20942         if ( parameters.envMap ) {
20943
20944                 switch ( parameters.envMapMode ) {
20945
20946                         case CubeRefractionMapping:
20947                         case CubeUVRefractionMapping:
20948
20949                                 envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
20950                                 break;
20951
20952                 }
20953
20954         }
20955
20956         return envMapModeDefine;
20957
20958     }
20959
20960     function generateEnvMapBlendingDefine( parameters ) {
20961
20962         let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
20963
20964         if ( parameters.envMap ) {
20965
20966                 switch ( parameters.combine ) {
20967
20968                         case MultiplyOperation:
20969                                 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
20970                                 break;
20971
20972                         case MixOperation:
20973                                 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
20974                                 break;
20975
20976                         case AddOperation:
20977                                 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
20978                                 break;
20979
20980                 }
20981
20982         }
20983
20984         return envMapBlendingDefine;
20985
20986     }
20987
20988     function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
20989
20990         // TODO Send this event to Three.js DevTools
20991         // console.log( 'WebGLProgram', cacheKey );
20992
20993         const gl = renderer.getContext();
20994
20995         const defines = parameters.defines;
20996
20997         let vertexShader = parameters.vertexShader;
20998         let fragmentShader = parameters.fragmentShader;
20999
21000         const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
21001         const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
21002         const envMapModeDefine = generateEnvMapModeDefine( parameters );
21003         const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
21004
21005
21006         const gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
21007
21008         const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );
21009
21010         const customDefines = generateDefines( defines );
21011
21012         const program = gl.createProgram();
21013
21014         let prefixVertex, prefixFragment;
21015         let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
21016
21017         if ( parameters.isRawShaderMaterial ) {
21018
21019                 prefixVertex = [
21020
21021                         customDefines
21022
21023                 ].filter( filterEmptyLine ).join( '\n' );
21024
21025                 if ( prefixVertex.length > 0 ) {
21026
21027                         prefixVertex += '\n';
21028
21029                 }
21030
21031                 prefixFragment = [
21032
21033                         customExtensions,
21034                         customDefines
21035
21036                 ].filter( filterEmptyLine ).join( '\n' );
21037
21038                 if ( prefixFragment.length > 0 ) {
21039
21040                         prefixFragment += '\n';
21041
21042                 }
21043
21044         } else {
21045
21046                 prefixVertex = [
21047
21048                         generatePrecision( parameters ),
21049
21050                         '#define SHADER_NAME ' + parameters.shaderName,
21051
21052                         customDefines,
21053
21054                         parameters.instancing ? '#define USE_INSTANCING' : '',
21055                         parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
21056
21057                         parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
21058
21059                         '#define GAMMA_FACTOR ' + gammaFactorDefine,
21060
21061                         '#define MAX_BONES ' + parameters.maxBones,
21062                         ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
21063                         ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
21064
21065                         parameters.map ? '#define USE_MAP' : '',
21066                         parameters.envMap ? '#define USE_ENVMAP' : '',
21067                         parameters.envMap ? '#define ' + envMapModeDefine : '',
21068                         parameters.lightMap ? '#define USE_LIGHTMAP' : '',
21069                         parameters.aoMap ? '#define USE_AOMAP' : '',
21070                         parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
21071                         parameters.bumpMap ? '#define USE_BUMPMAP' : '',
21072                         parameters.normalMap ? '#define USE_NORMALMAP' : '',
21073                         ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
21074                         ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
21075
21076                         parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
21077                         parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
21078                         parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
21079
21080                         parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
21081
21082                         parameters.specularMap ? '#define USE_SPECULARMAP' : '',
21083                         parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '',
21084                         parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '',
21085
21086                         parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
21087                         parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
21088                         parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
21089
21090                         parameters.transmission ? '#define USE_TRANSMISSION' : '',
21091                         parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
21092                         parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
21093
21094                         parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '',
21095                         parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '',
21096
21097                         parameters.vertexTangents ? '#define USE_TANGENT' : '',
21098                         parameters.vertexColors ? '#define USE_COLOR' : '',
21099                         parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
21100                         parameters.vertexUvs ? '#define USE_UV' : '',
21101                         parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
21102
21103                         parameters.flatShading ? '#define FLAT_SHADED' : '',
21104
21105                         parameters.skinning ? '#define USE_SKINNING' : '',
21106                         parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
21107
21108                         parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
21109                         parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
21110                         ( parameters.morphTargets && parameters.isWebGL2 ) ? '#define MORPHTARGETS_TEXTURE' : '',
21111                         ( parameters.morphTargets && parameters.isWebGL2 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '',
21112                         parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
21113                         parameters.flipSided ? '#define FLIP_SIDED' : '',
21114
21115                         parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
21116                         parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
21117
21118                         parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
21119
21120                         parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
21121                         ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
21122
21123                         'uniform mat4 modelMatrix;',
21124                         'uniform mat4 modelViewMatrix;',
21125                         'uniform mat4 projectionMatrix;',
21126                         'uniform mat4 viewMatrix;',
21127                         'uniform mat3 normalMatrix;',
21128                         'uniform vec3 cameraPosition;',
21129                         'uniform bool isOrthographic;',
21130
21131                         '#ifdef USE_INSTANCING',
21132
21133                         '       attribute mat4 instanceMatrix;',
21134
21135                         '#endif',
21136
21137                         '#ifdef USE_INSTANCING_COLOR',
21138
21139                         '       attribute vec3 instanceColor;',
21140
21141                         '#endif',
21142
21143                         'attribute vec3 position;',
21144                         'attribute vec3 normal;',
21145                         'attribute vec2 uv;',
21146
21147                         '#ifdef USE_TANGENT',
21148
21149                         '       attribute vec4 tangent;',
21150
21151                         '#endif',
21152
21153                         '#if defined( USE_COLOR_ALPHA )',
21154
21155                         '       attribute vec4 color;',
21156
21157                         '#elif defined( USE_COLOR )',
21158
21159                         '       attribute vec3 color;',
21160
21161                         '#endif',
21162
21163                         '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )',
21164
21165                         '       attribute vec3 morphTarget0;',
21166                         '       attribute vec3 morphTarget1;',
21167                         '       attribute vec3 morphTarget2;',
21168                         '       attribute vec3 morphTarget3;',
21169
21170                         '       #ifdef USE_MORPHNORMALS',
21171
21172                         '               attribute vec3 morphNormal0;',
21173                         '               attribute vec3 morphNormal1;',
21174                         '               attribute vec3 morphNormal2;',
21175                         '               attribute vec3 morphNormal3;',
21176
21177                         '       #else',
21178
21179                         '               attribute vec3 morphTarget4;',
21180                         '               attribute vec3 morphTarget5;',
21181                         '               attribute vec3 morphTarget6;',
21182                         '               attribute vec3 morphTarget7;',
21183
21184                         '       #endif',
21185
21186                         '#endif',
21187
21188                         '#ifdef USE_SKINNING',
21189
21190                         '       attribute vec4 skinIndex;',
21191                         '       attribute vec4 skinWeight;',
21192
21193                         '#endif',
21194
21195                         '\n'
21196
21197                 ].filter( filterEmptyLine ).join( '\n' );
21198
21199                 prefixFragment = [
21200
21201                         customExtensions,
21202
21203                         generatePrecision( parameters ),
21204
21205                         '#define SHADER_NAME ' + parameters.shaderName,
21206
21207                         customDefines,
21208
21209                         '#define GAMMA_FACTOR ' + gammaFactorDefine,
21210
21211                         ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
21212                         ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
21213
21214                         parameters.map ? '#define USE_MAP' : '',
21215                         parameters.matcap ? '#define USE_MATCAP' : '',
21216                         parameters.envMap ? '#define USE_ENVMAP' : '',
21217                         parameters.envMap ? '#define ' + envMapTypeDefine : '',
21218                         parameters.envMap ? '#define ' + envMapModeDefine : '',
21219                         parameters.envMap ? '#define ' + envMapBlendingDefine : '',
21220                         parameters.lightMap ? '#define USE_LIGHTMAP' : '',
21221                         parameters.aoMap ? '#define USE_AOMAP' : '',
21222                         parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
21223                         parameters.bumpMap ? '#define USE_BUMPMAP' : '',
21224                         parameters.normalMap ? '#define USE_NORMALMAP' : '',
21225                         ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
21226                         ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
21227
21228                         parameters.clearcoat ? '#define USE_CLEARCOAT' : '',
21229                         parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
21230                         parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
21231                         parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
21232
21233                         parameters.specularMap ? '#define USE_SPECULARMAP' : '',
21234                         parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '',
21235                         parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '',
21236                         parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
21237                         parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
21238
21239                         parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
21240                         parameters.alphaTest ? '#define USE_ALPHATEST' : '',
21241
21242                         parameters.sheen ? '#define USE_SHEEN' : '',
21243                         parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '',
21244                         parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '',
21245
21246                         parameters.transmission ? '#define USE_TRANSMISSION' : '',
21247                         parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
21248                         parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
21249
21250                         parameters.vertexTangents ? '#define USE_TANGENT' : '',
21251                         parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
21252                         parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
21253                         parameters.vertexUvs ? '#define USE_UV' : '',
21254                         parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
21255
21256                         parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
21257
21258                         parameters.flatShading ? '#define FLAT_SHADED' : '',
21259
21260                         parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
21261                         parameters.flipSided ? '#define FLIP_SIDED' : '',
21262
21263                         parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
21264                         parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
21265
21266                         parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
21267
21268                         parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
21269
21270                         parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
21271                         ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
21272
21273                         ( ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ) ? '#define TEXTURE_LOD_EXT' : '',
21274
21275                         'uniform mat4 viewMatrix;',
21276                         'uniform vec3 cameraPosition;',
21277                         'uniform bool isOrthographic;',
21278
21279                         ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
21280                         ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
21281                         ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
21282
21283                         parameters.dithering ? '#define DITHERING' : '',
21284                         parameters.format === RGBFormat ? '#define OPAQUE' : '',
21285
21286                         ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below
21287                         parameters.map ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
21288                         parameters.matcap ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
21289                         parameters.envMap ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
21290                         parameters.emissiveMap ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
21291                         parameters.specularColorMap ? getTexelDecodingFunction( 'specularColorMapTexelToLinear', parameters.specularColorMapEncoding ) : '',
21292                         parameters.sheenColorMap ? getTexelDecodingFunction( 'sheenColorMapTexelToLinear', parameters.sheenColorMapEncoding ) : '',
21293                         parameters.lightMap ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',
21294                         getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ),
21295
21296                         parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
21297
21298                         '\n'
21299
21300                 ].filter( filterEmptyLine ).join( '\n' );
21301
21302         }
21303
21304         vertexShader = resolveIncludes( vertexShader );
21305         vertexShader = replaceLightNums( vertexShader, parameters );
21306         vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
21307
21308         fragmentShader = resolveIncludes( fragmentShader );
21309         fragmentShader = replaceLightNums( fragmentShader, parameters );
21310         fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
21311
21312         vertexShader = unrollLoops( vertexShader );
21313         fragmentShader = unrollLoops( fragmentShader );
21314
21315         if ( parameters.isWebGL2 && parameters.isRawShaderMaterial !== true ) {
21316
21317                 // GLSL 3.0 conversion for built-in materials and ShaderMaterial
21318
21319                 versionString = '#version 300 es\n';
21320
21321                 prefixVertex = [
21322                         'precision mediump sampler2DArray;',
21323                         '#define attribute in',
21324                         '#define varying out',
21325                         '#define texture2D texture'
21326                 ].join( '\n' ) + '\n' + prefixVertex;
21327
21328                 prefixFragment = [
21329                         '#define varying in',
21330                         ( parameters.glslVersion === GLSL3 ) ? '' : 'out highp vec4 pc_fragColor;',
21331                         ( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor',
21332                         '#define gl_FragDepthEXT gl_FragDepth',
21333                         '#define texture2D texture',
21334                         '#define textureCube texture',
21335                         '#define texture2DProj textureProj',
21336                         '#define texture2DLodEXT textureLod',
21337                         '#define texture2DProjLodEXT textureProjLod',
21338                         '#define textureCubeLodEXT textureLod',
21339                         '#define texture2DGradEXT textureGrad',
21340                         '#define texture2DProjGradEXT textureProjGrad',
21341                         '#define textureCubeGradEXT textureGrad'
21342                 ].join( '\n' ) + '\n' + prefixFragment;
21343
21344         }
21345
21346         const vertexGlsl = versionString + prefixVertex + vertexShader;
21347         const fragmentGlsl = versionString + prefixFragment + fragmentShader;
21348
21349         // console.log( '*VERTEX*', vertexGlsl );
21350         // console.log( '*FRAGMENT*', fragmentGlsl );
21351
21352         const glVertexShader = WebGLShader( gl, 35633, vertexGlsl );
21353         const glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );
21354
21355         gl.attachShader( program, glVertexShader );
21356         gl.attachShader( program, glFragmentShader );
21357
21358         // Force a particular attribute to index 0.
21359
21360         if ( parameters.index0AttributeName !== undefined ) {
21361
21362                 gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
21363
21364         } else if ( parameters.morphTargets === true ) {
21365
21366                 // programs with morphTargets displace position out of attribute 0
21367                 gl.bindAttribLocation( program, 0, 'position' );
21368
21369         }
21370
21371         gl.linkProgram( program );
21372
21373         // check for link errors
21374         if ( renderer.debug.checkShaderErrors ) {
21375
21376                 const programLog = gl.getProgramInfoLog( program ).trim();
21377                 const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
21378                 const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
21379
21380                 let runnable = true;
21381                 let haveDiagnostics = true;
21382
21383                 if ( gl.getProgramParameter( program, 35714 ) === false ) {
21384
21385                         runnable = false;
21386
21387                         const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
21388                         const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
21389
21390                         console.error(
21391                                 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
21392                                 'VALIDATE_STATUS ' + gl.getProgramParameter( program, 35715 ) + '\n\n' +
21393                                 'Program Info Log: ' + programLog + '\n' +
21394                                 vertexErrors + '\n' +
21395                                 fragmentErrors
21396                         );
21397
21398                 } else if ( programLog !== '' ) {
21399
21400                         console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
21401
21402                 } else if ( vertexLog === '' || fragmentLog === '' ) {
21403
21404                         haveDiagnostics = false;
21405
21406                 }
21407
21408                 if ( haveDiagnostics ) {
21409
21410                         this.diagnostics = {
21411
21412                                 runnable: runnable,
21413
21414                                 programLog: programLog,
21415
21416                                 vertexShader: {
21417
21418                                         log: vertexLog,
21419                                         prefix: prefixVertex
21420
21421                                 },
21422
21423                                 fragmentShader: {
21424
21425                                         log: fragmentLog,
21426                                         prefix: prefixFragment
21427
21428                                 }
21429
21430                         };
21431
21432                 }
21433
21434         }
21435
21436         // Clean up
21437
21438         // Crashes in iOS9 and iOS10. #18402
21439         // gl.detachShader( program, glVertexShader );
21440         // gl.detachShader( program, glFragmentShader );
21441
21442         gl.deleteShader( glVertexShader );
21443         gl.deleteShader( glFragmentShader );
21444
21445         // set up caching for uniform locations
21446
21447         let cachedUniforms;
21448
21449         this.getUniforms = function () {
21450
21451                 if ( cachedUniforms === undefined ) {
21452
21453                         cachedUniforms = new WebGLUniforms( gl, program );
21454
21455                 }
21456
21457                 return cachedUniforms;
21458
21459         };
21460
21461         // set up caching for attribute locations
21462
21463         let cachedAttributes;
21464
21465         this.getAttributes = function () {
21466
21467                 if ( cachedAttributes === undefined ) {
21468
21469                         cachedAttributes = fetchAttributeLocations( gl, program );
21470
21471                 }
21472
21473                 return cachedAttributes;
21474
21475         };
21476
21477         // free resource
21478
21479         this.destroy = function () {
21480
21481                 bindingStates.releaseStatesOfProgram( this );
21482
21483                 gl.deleteProgram( program );
21484                 this.program = undefined;
21485
21486         };
21487
21488         //
21489
21490         this.name = parameters.shaderName;
21491         this.id = programIdCount ++;
21492         this.cacheKey = cacheKey;
21493         this.usedTimes = 1;
21494         this.program = program;
21495         this.vertexShader = glVertexShader;
21496         this.fragmentShader = glFragmentShader;
21497
21498         return this;
21499
21500     }
21501
21502     function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) {
21503
21504         const programs = [];
21505
21506         const isWebGL2 = capabilities.isWebGL2;
21507         const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
21508         const floatVertexTextures = capabilities.floatVertexTextures;
21509         const maxVertexUniforms = capabilities.maxVertexUniforms;
21510         const vertexTextures = capabilities.vertexTextures;
21511
21512         let precision = capabilities.precision;
21513
21514         const shaderIDs = {
21515                 MeshDepthMaterial: 'depth',
21516                 MeshDistanceMaterial: 'distanceRGBA',
21517                 MeshNormalMaterial: 'normal',
21518                 MeshBasicMaterial: 'basic',
21519                 MeshLambertMaterial: 'lambert',
21520                 MeshPhongMaterial: 'phong',
21521                 MeshToonMaterial: 'toon',
21522                 MeshStandardMaterial: 'physical',
21523                 MeshPhysicalMaterial: 'physical',
21524                 MeshMatcapMaterial: 'matcap',
21525                 LineBasicMaterial: 'basic',
21526                 LineDashedMaterial: 'dashed',
21527                 PointsMaterial: 'points',
21528                 ShadowMaterial: 'shadow',
21529                 SpriteMaterial: 'sprite'
21530         };
21531
21532         const parameterNames = [
21533                 'precision', 'isWebGL2', 'supportsVertexTextures', 'outputEncoding', 'instancing', 'instancingColor',
21534                 'map', 'mapEncoding', 'matcap', 'matcapEncoding', 'envMap', 'envMapMode', 'envMapEncoding', 'envMapCubeUV',
21535                 'lightMap', 'lightMapEncoding', 'aoMap', 'emissiveMap', 'emissiveMapEncoding', 'bumpMap', 'normalMap',
21536                 'objectSpaceNormalMap', 'tangentSpaceNormalMap',
21537                 'clearcoat', 'clearcoatMap', 'clearcoatRoughnessMap', 'clearcoatNormalMap',
21538                 'displacementMap', 'specularMap', , 'roughnessMap', 'metalnessMap', 'gradientMap',
21539                 'alphaMap', 'alphaTest', 'combine', 'vertexColors', 'vertexAlphas', 'vertexTangents', 'vertexUvs', 'uvsVertexOnly', 'fog', 'useFog', 'fogExp2',
21540                 'flatShading', 'sizeAttenuation', 'logarithmicDepthBuffer', 'skinning',
21541                 'maxBones', 'useVertexTexture', 'morphTargets', 'morphNormals', 'morphTargetsCount', 'premultipliedAlpha',
21542                 'numDirLights', 'numPointLights', 'numSpotLights', 'numHemiLights', 'numRectAreaLights',
21543                 'numDirLightShadows', 'numPointLightShadows', 'numSpotLightShadows',
21544                 'shadowMapEnabled', 'shadowMapType', 'toneMapping', 'physicallyCorrectLights',
21545                 'doubleSided', 'flipSided', 'numClippingPlanes', 'numClipIntersection', 'depthPacking', 'dithering', 'format',
21546                 'specularIntensityMap', 'specularColorMap', 'specularColorMapEncoding',
21547                 'transmission', 'transmissionMap', 'thicknessMap',
21548                 'sheen', 'sheenColorMap', 'sheenColorMapEncoding', 'sheenRoughnessMap'
21549         ];
21550
21551         function getMaxBones( object ) {
21552
21553                 const skeleton = object.skeleton;
21554                 const bones = skeleton.bones;
21555
21556                 if ( floatVertexTextures ) {
21557
21558                         return 1024;
21559
21560                 } else {
21561
21562                         // default for when object is not specified
21563                         // ( for example when prebuilding shader to be used with multiple objects )
21564                         //
21565                         //  - leave some extra space for other uniforms
21566                         //  - limit here is ANGLE's 254 max uniform vectors
21567                         //    (up to 54 should be safe)
21568
21569                         const nVertexUniforms = maxVertexUniforms;
21570                         const nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
21571
21572                         const maxBones = Math.min( nVertexMatrices, bones.length );
21573
21574                         if ( maxBones < bones.length ) {
21575
21576                                 console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
21577                                 return 0;
21578
21579                         }
21580
21581                         return maxBones;
21582
21583                 }
21584
21585         }
21586
21587         function getTextureEncodingFromMap( map ) {
21588
21589                 let encoding;
21590
21591                 if ( map && map.isTexture ) {
21592
21593                         encoding = map.encoding;
21594
21595                 } else if ( map && map.isWebGLRenderTarget ) {
21596
21597                         console.warn( 'THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.' );
21598                         encoding = map.texture.encoding;
21599
21600                 } else {
21601
21602                         encoding = LinearEncoding;
21603
21604                 }
21605
21606                 if ( isWebGL2 && map && map.isTexture && map.format === RGBAFormat && map.type === UnsignedByteType && map.encoding === sRGBEncoding ) {
21607
21608                         encoding = LinearEncoding; // disable inline decode for sRGB textures in WebGL 2
21609
21610                 }
21611
21612                 return encoding;
21613
21614         }
21615
21616         function getParameters( material, lights, shadows, scene, object ) {
21617
21618                 const fog = scene.fog;
21619                 const environment = material.isMeshStandardMaterial ? scene.environment : null;
21620
21621                 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
21622
21623                 const shaderID = shaderIDs[ material.type ];
21624
21625                 // heuristics to create shader parameters according to lights in the scene
21626                 // (not to blow over maxLights budget)
21627
21628                 const maxBones = object.isSkinnedMesh ? getMaxBones( object ) : 0;
21629
21630                 if ( material.precision !== null ) {
21631
21632                         precision = capabilities.getMaxPrecision( material.precision );
21633
21634                         if ( precision !== material.precision ) {
21635
21636                                 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
21637
21638                         }
21639
21640                 }
21641
21642                 let vertexShader, fragmentShader;
21643
21644                 if ( shaderID ) {
21645
21646                         const shader = ShaderLib[ shaderID ];
21647
21648                         vertexShader = shader.vertexShader;
21649                         fragmentShader = shader.fragmentShader;
21650
21651                 } else {
21652
21653                         vertexShader = material.vertexShader;
21654                         fragmentShader = material.fragmentShader;
21655
21656                 }
21657
21658                 const currentRenderTarget = renderer.getRenderTarget();
21659
21660                 const useAlphaTest = material.alphaTest > 0;
21661                 const useClearcoat = material.clearcoat > 0;
21662
21663                 const parameters = {
21664
21665                         isWebGL2: isWebGL2,
21666
21667                         shaderID: shaderID,
21668                         shaderName: material.type,
21669
21670                         vertexShader: vertexShader,
21671                         fragmentShader: fragmentShader,
21672                         defines: material.defines,
21673
21674                         isRawShaderMaterial: material.isRawShaderMaterial === true,
21675                         glslVersion: material.glslVersion,
21676
21677                         precision: precision,
21678
21679                         instancing: object.isInstancedMesh === true,
21680                         instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
21681
21682                         supportsVertexTextures: vertexTextures,
21683                         outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,
21684                         map: !! material.map,
21685                         mapEncoding: getTextureEncodingFromMap( material.map ),
21686                         matcap: !! material.matcap,
21687                         matcapEncoding: getTextureEncodingFromMap( material.matcap ),
21688                         envMap: !! envMap,
21689                         envMapMode: envMap && envMap.mapping,
21690                         envMapEncoding: getTextureEncodingFromMap( envMap ),
21691                         envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),
21692                         lightMap: !! material.lightMap,
21693                         lightMapEncoding: getTextureEncodingFromMap( material.lightMap ),
21694                         aoMap: !! material.aoMap,
21695                         emissiveMap: !! material.emissiveMap,
21696                         emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),
21697                         bumpMap: !! material.bumpMap,
21698                         normalMap: !! material.normalMap,
21699                         objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
21700                         tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
21701
21702                         clearcoat: useClearcoat,
21703                         clearcoatMap: useClearcoat && !! material.clearcoatMap,
21704                         clearcoatRoughnessMap: useClearcoat && !! material.clearcoatRoughnessMap,
21705                         clearcoatNormalMap: useClearcoat && !! material.clearcoatNormalMap,
21706
21707                         displacementMap: !! material.displacementMap,
21708                         roughnessMap: !! material.roughnessMap,
21709                         metalnessMap: !! material.metalnessMap,
21710                         specularMap: !! material.specularMap,
21711                         specularIntensityMap: !! material.specularIntensityMap,
21712                         specularColorMap: !! material.specularColorMap,
21713                         specularColorMapEncoding: getTextureEncodingFromMap( material.specularColorMap ),
21714
21715                         alphaMap: !! material.alphaMap,
21716                         alphaTest: useAlphaTest,
21717
21718                         gradientMap: !! material.gradientMap,
21719
21720                         sheen: material.sheen > 0,
21721                         sheenColorMap: !! material.sheenColorMap,
21722                         sheenColorMapEncoding: getTextureEncodingFromMap( material.sheenColorMap ),
21723                         sheenRoughnessMap: !! material.sheenRoughnessMap,
21724
21725                         transmission: material.transmission > 0,
21726                         transmissionMap: !! material.transmissionMap,
21727                         thicknessMap: !! material.thicknessMap,
21728
21729                         combine: material.combine,
21730
21731                         vertexTangents: ( !! material.normalMap && !! object.geometry && !! object.geometry.attributes.tangent ),
21732                         vertexColors: material.vertexColors,
21733                         vertexAlphas: material.vertexColors === true && !! object.geometry && !! object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4,
21734                         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 || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || !! material.sheenColorMap || material.sheenRoughnessMap,
21735                         uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || material.transmission > 0 || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || !! material.sheen > 0 || !! material.sheenColorMap || !! material.sheenRoughnessMap ) && !! material.displacementMap,
21736
21737                         fog: !! fog,
21738                         useFog: material.fog,
21739                         fogExp2: ( fog && fog.isFogExp2 ),
21740
21741                         flatShading: !! material.flatShading,
21742
21743                         sizeAttenuation: material.sizeAttenuation,
21744                         logarithmicDepthBuffer: logarithmicDepthBuffer,
21745
21746                         skinning: object.isSkinnedMesh === true && maxBones > 0,
21747                         maxBones: maxBones,
21748                         useVertexTexture: floatVertexTextures,
21749
21750                         morphTargets: !! object.geometry && !! object.geometry.morphAttributes.position,
21751                         morphNormals: !! object.geometry && !! object.geometry.morphAttributes.normal,
21752                         morphTargetsCount: ( !! object.geometry && !! object.geometry.morphAttributes.position ) ? object.geometry.morphAttributes.position.length : 0,
21753
21754                         numDirLights: lights.directional.length,
21755                         numPointLights: lights.point.length,
21756                         numSpotLights: lights.spot.length,
21757                         numRectAreaLights: lights.rectArea.length,
21758                         numHemiLights: lights.hemi.length,
21759
21760                         numDirLightShadows: lights.directionalShadowMap.length,
21761                         numPointLightShadows: lights.pointShadowMap.length,
21762                         numSpotLightShadows: lights.spotShadowMap.length,
21763
21764                         numClippingPlanes: clipping.numPlanes,
21765                         numClipIntersection: clipping.numIntersection,
21766
21767                         format: material.format,
21768                         dithering: material.dithering,
21769
21770                         shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
21771                         shadowMapType: renderer.shadowMap.type,
21772
21773                         toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
21774                         physicallyCorrectLights: renderer.physicallyCorrectLights,
21775
21776                         premultipliedAlpha: material.premultipliedAlpha,
21777
21778                         doubleSided: material.side === DoubleSide,
21779                         flipSided: material.side === BackSide,
21780
21781                         depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,
21782
21783                         index0AttributeName: material.index0AttributeName,
21784
21785                         extensionDerivatives: material.extensions && material.extensions.derivatives,
21786                         extensionFragDepth: material.extensions && material.extensions.fragDepth,
21787                         extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
21788                         extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,
21789
21790                         rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ),
21791                         rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ),
21792                         rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ),
21793
21794                         customProgramCacheKey: material.customProgramCacheKey()
21795
21796                 };
21797
21798                 return parameters;
21799
21800         }
21801
21802         function getProgramCacheKey( parameters ) {
21803
21804                 const array = [];
21805
21806                 if ( parameters.shaderID ) {
21807
21808                         array.push( parameters.shaderID );
21809
21810                 } else {
21811
21812                         array.push( hashString( parameters.fragmentShader ) );
21813                         array.push( hashString( parameters.vertexShader ) );
21814
21815                 }
21816
21817                 if ( parameters.defines !== undefined ) {
21818
21819                         for ( const name in parameters.defines ) {
21820
21821                                 array.push( name );
21822                                 array.push( parameters.defines[ name ] );
21823
21824                         }
21825
21826                 }
21827
21828                 if ( parameters.isRawShaderMaterial === false ) {
21829
21830                         for ( let i = 0; i < parameterNames.length; i ++ ) {
21831
21832                                 array.push( parameters[ parameterNames[ i ] ] );
21833
21834                         }
21835
21836                         array.push( renderer.outputEncoding );
21837                         array.push( renderer.gammaFactor );
21838
21839                 }
21840
21841                 array.push( parameters.customProgramCacheKey );
21842
21843                 return array.join();
21844
21845         }
21846
21847         function getUniforms( material ) {
21848
21849                 const shaderID = shaderIDs[ material.type ];
21850                 let uniforms;
21851
21852                 if ( shaderID ) {
21853
21854                         const shader = ShaderLib[ shaderID ];
21855                         uniforms = UniformsUtils.clone( shader.uniforms );
21856
21857                 } else {
21858
21859                         uniforms = material.uniforms;
21860
21861                 }
21862
21863                 return uniforms;
21864
21865         }
21866
21867         function acquireProgram( parameters, cacheKey ) {
21868
21869                 let program;
21870
21871                 // Check if code has been already compiled
21872                 for ( let p = 0, pl = programs.length; p < pl; p ++ ) {
21873
21874                         const preexistingProgram = programs[ p ];
21875
21876                         if ( preexistingProgram.cacheKey === cacheKey ) {
21877
21878                                 program = preexistingProgram;
21879                                 ++ program.usedTimes;
21880
21881                                 break;
21882
21883                         }
21884
21885                 }
21886
21887                 if ( program === undefined ) {
21888
21889                         program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
21890                         programs.push( program );
21891
21892                 }
21893
21894                 return program;
21895
21896         }
21897
21898         function releaseProgram( program ) {
21899
21900                 if ( -- program.usedTimes === 0 ) {
21901
21902                         // Remove from unordered set
21903                         const i = programs.indexOf( program );
21904                         programs[ i ] = programs[ programs.length - 1 ];
21905                         programs.pop();
21906
21907                         // Free WebGL resources
21908                         program.destroy();
21909
21910                 }
21911
21912         }
21913
21914         return {
21915                 getParameters: getParameters,
21916                 getProgramCacheKey: getProgramCacheKey,
21917                 getUniforms: getUniforms,
21918                 acquireProgram: acquireProgram,
21919                 releaseProgram: releaseProgram,
21920                 // Exposed for resource monitoring & error feedback via renderer.info:
21921                 programs: programs
21922         };
21923
21924     }
21925
21926     function WebGLProperties() {
21927
21928         let properties = new WeakMap();
21929
21930         function get( object ) {
21931
21932                 let map = properties.get( object );
21933
21934                 if ( map === undefined ) {
21935
21936                         map = {};
21937                         properties.set( object, map );
21938
21939                 }
21940
21941                 return map;
21942
21943         }
21944
21945         function remove( object ) {
21946
21947                 properties.delete( object );
21948
21949         }
21950
21951         function update( object, key, value ) {
21952
21953                 properties.get( object )[ key ] = value;
21954
21955         }
21956
21957         function dispose() {
21958
21959                 properties = new WeakMap();
21960
21961         }
21962
21963         return {
21964                 get: get,
21965                 remove: remove,
21966                 update: update,
21967                 dispose: dispose
21968         };
21969
21970     }
21971
21972     function painterSortStable( a, b ) {
21973
21974         if ( a.groupOrder !== b.groupOrder ) {
21975
21976                 return a.groupOrder - b.groupOrder;
21977
21978         } else if ( a.renderOrder !== b.renderOrder ) {
21979
21980                 return a.renderOrder - b.renderOrder;
21981
21982         } else if ( a.program !== b.program ) {
21983
21984                 return a.program.id - b.program.id;
21985
21986         } else if ( a.material.id !== b.material.id ) {
21987
21988                 return a.material.id - b.material.id;
21989
21990         } else if ( a.z !== b.z ) {
21991
21992                 return a.z - b.z;
21993
21994         } else {
21995
21996                 return a.id - b.id;
21997
21998         }
21999
22000     }
22001
22002     function reversePainterSortStable( a, b ) {
22003
22004         if ( a.groupOrder !== b.groupOrder ) {
22005
22006                 return a.groupOrder - b.groupOrder;
22007
22008         } else if ( a.renderOrder !== b.renderOrder ) {
22009
22010                 return a.renderOrder - b.renderOrder;
22011
22012         } else if ( a.z !== b.z ) {
22013
22014                 return b.z - a.z;
22015
22016         } else {
22017
22018                 return a.id - b.id;
22019
22020         }
22021
22022     }
22023
22024
22025     function WebGLRenderList( properties ) {
22026
22027         const renderItems = [];
22028         let renderItemsIndex = 0;
22029
22030         const opaque = [];
22031         const transmissive = [];
22032         const transparent = [];
22033
22034         const defaultProgram = { id: - 1 };
22035
22036         function init() {
22037
22038                 renderItemsIndex = 0;
22039
22040                 opaque.length = 0;
22041                 transmissive.length = 0;
22042                 transparent.length = 0;
22043
22044         }
22045
22046         function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
22047
22048                 let renderItem = renderItems[ renderItemsIndex ];
22049                 const materialProperties = properties.get( material );
22050
22051                 if ( renderItem === undefined ) {
22052
22053                         renderItem = {
22054                                 id: object.id,
22055                                 object: object,
22056                                 geometry: geometry,
22057                                 material: material,
22058                                 program: materialProperties.program || defaultProgram,
22059                                 groupOrder: groupOrder,
22060                                 renderOrder: object.renderOrder,
22061                                 z: z,
22062                                 group: group
22063                         };
22064
22065                         renderItems[ renderItemsIndex ] = renderItem;
22066
22067                 } else {
22068
22069                         renderItem.id = object.id;
22070                         renderItem.object = object;
22071                         renderItem.geometry = geometry;
22072                         renderItem.material = material;
22073                         renderItem.program = materialProperties.program || defaultProgram;
22074                         renderItem.groupOrder = groupOrder;
22075                         renderItem.renderOrder = object.renderOrder;
22076                         renderItem.z = z;
22077                         renderItem.group = group;
22078
22079                 }
22080
22081                 renderItemsIndex ++;
22082
22083                 return renderItem;
22084
22085         }
22086
22087         function push( object, geometry, material, groupOrder, z, group ) {
22088
22089                 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
22090
22091                 if ( material.transmission > 0.0 ) {
22092
22093                         transmissive.push( renderItem );
22094
22095                 } else if ( material.transparent === true ) {
22096
22097                         transparent.push( renderItem );
22098
22099                 } else {
22100
22101                         opaque.push( renderItem );
22102
22103                 }
22104
22105         }
22106
22107         function unshift( object, geometry, material, groupOrder, z, group ) {
22108
22109                 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
22110
22111                 if ( material.transmission > 0.0 ) {
22112
22113                         transmissive.unshift( renderItem );
22114
22115                 } else if ( material.transparent === true ) {
22116
22117                         transparent.unshift( renderItem );
22118
22119                 } else {
22120
22121                         opaque.unshift( renderItem );
22122
22123                 }
22124
22125         }
22126
22127         function sort( customOpaqueSort, customTransparentSort ) {
22128
22129                 if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
22130                 if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable );
22131                 if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
22132
22133         }
22134
22135         function finish() {
22136
22137                 // Clear references from inactive renderItems in the list
22138
22139                 for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
22140
22141                         const renderItem = renderItems[ i ];
22142
22143                         if ( renderItem.id === null ) break;
22144
22145                         renderItem.id = null;
22146                         renderItem.object = null;
22147                         renderItem.geometry = null;
22148                         renderItem.material = null;
22149                         renderItem.program = null;
22150                         renderItem.group = null;
22151
22152                 }
22153
22154         }
22155
22156         return {
22157
22158                 opaque: opaque,
22159                 transmissive: transmissive,
22160                 transparent: transparent,
22161
22162                 init: init,
22163                 push: push,
22164                 unshift: unshift,
22165                 finish: finish,
22166
22167                 sort: sort
22168         };
22169
22170     }
22171
22172     function WebGLRenderLists( properties ) {
22173
22174         let lists = new WeakMap();
22175
22176         function get( scene, renderCallDepth ) {
22177
22178                 let list;
22179
22180                 if ( lists.has( scene ) === false ) {
22181
22182                         list = new WebGLRenderList( properties );
22183                         lists.set( scene, [ list ] );
22184
22185                 } else {
22186
22187                         if ( renderCallDepth >= lists.get( scene ).length ) {
22188
22189                                 list = new WebGLRenderList( properties );
22190                                 lists.get( scene ).push( list );
22191
22192                         } else {
22193
22194                                 list = lists.get( scene )[ renderCallDepth ];
22195
22196                         }
22197
22198                 }
22199
22200                 return list;
22201
22202         }
22203
22204         function dispose() {
22205
22206                 lists = new WeakMap();
22207
22208         }
22209
22210         return {
22211                 get: get,
22212                 dispose: dispose
22213         };
22214
22215     }
22216
22217     function UniformsCache() {
22218
22219         const lights = {};
22220
22221         return {
22222
22223                 get: function ( light ) {
22224
22225                         if ( lights[ light.id ] !== undefined ) {
22226
22227                                 return lights[ light.id ];
22228
22229                         }
22230
22231                         let uniforms;
22232
22233                         switch ( light.type ) {
22234
22235                                 case 'DirectionalLight':
22236                                         uniforms = {
22237                                                 direction: new Vector3(),
22238                                                 color: new Color()
22239                                         };
22240                                         break;
22241
22242                                 case 'SpotLight':
22243                                         uniforms = {
22244                                                 position: new Vector3(),
22245                                                 direction: new Vector3(),
22246                                                 color: new Color(),
22247                                                 distance: 0,
22248                                                 coneCos: 0,
22249                                                 penumbraCos: 0,
22250                                                 decay: 0
22251                                         };
22252                                         break;
22253
22254                                 case 'PointLight':
22255                                         uniforms = {
22256                                                 position: new Vector3(),
22257                                                 color: new Color(),
22258                                                 distance: 0,
22259                                                 decay: 0
22260                                         };
22261                                         break;
22262
22263                                 case 'HemisphereLight':
22264                                         uniforms = {
22265                                                 direction: new Vector3(),
22266                                                 skyColor: new Color(),
22267                                                 groundColor: new Color()
22268                                         };
22269                                         break;
22270
22271                                 case 'RectAreaLight':
22272                                         uniforms = {
22273                                                 color: new Color(),
22274                                                 position: new Vector3(),
22275                                                 halfWidth: new Vector3(),
22276                                                 halfHeight: new Vector3()
22277                                         };
22278                                         break;
22279
22280                         }
22281
22282                         lights[ light.id ] = uniforms;
22283
22284                         return uniforms;
22285
22286                 }
22287
22288         };
22289
22290     }
22291
22292     function ShadowUniformsCache() {
22293
22294         const lights = {};
22295
22296         return {
22297
22298                 get: function ( light ) {
22299
22300                         if ( lights[ light.id ] !== undefined ) {
22301
22302                                 return lights[ light.id ];
22303
22304                         }
22305
22306                         let uniforms;
22307
22308                         switch ( light.type ) {
22309
22310                                 case 'DirectionalLight':
22311                                         uniforms = {
22312                                                 shadowBias: 0,
22313                                                 shadowNormalBias: 0,
22314                                                 shadowRadius: 1,
22315                                                 shadowMapSize: new Vector2()
22316                                         };
22317                                         break;
22318
22319                                 case 'SpotLight':
22320                                         uniforms = {
22321                                                 shadowBias: 0,
22322                                                 shadowNormalBias: 0,
22323                                                 shadowRadius: 1,
22324                                                 shadowMapSize: new Vector2()
22325                                         };
22326                                         break;
22327
22328                                 case 'PointLight':
22329                                         uniforms = {
22330                                                 shadowBias: 0,
22331                                                 shadowNormalBias: 0,
22332                                                 shadowRadius: 1,
22333                                                 shadowMapSize: new Vector2(),
22334                                                 shadowCameraNear: 1,
22335                                                 shadowCameraFar: 1000
22336                                         };
22337                                         break;
22338
22339                                 // TODO (abelnation): set RectAreaLight shadow uniforms
22340
22341                         }
22342
22343                         lights[ light.id ] = uniforms;
22344
22345                         return uniforms;
22346
22347                 }
22348
22349         };
22350
22351     }
22352
22353
22354
22355     let nextVersion = 0;
22356
22357     function shadowCastingLightsFirst( lightA, lightB ) {
22358
22359         return ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );
22360
22361     }
22362
22363     function WebGLLights( extensions, capabilities ) {
22364
22365         const cache = new UniformsCache();
22366
22367         const shadowCache = ShadowUniformsCache();
22368
22369         const state = {
22370
22371                 version: 0,
22372
22373                 hash: {
22374                         directionalLength: - 1,
22375                         pointLength: - 1,
22376                         spotLength: - 1,
22377                         rectAreaLength: - 1,
22378                         hemiLength: - 1,
22379
22380                         numDirectionalShadows: - 1,
22381                         numPointShadows: - 1,
22382                         numSpotShadows: - 1
22383                 },
22384
22385                 ambient: [ 0, 0, 0 ],
22386                 probe: [],
22387                 directional: [],
22388                 directionalShadow: [],
22389                 directionalShadowMap: [],
22390                 directionalShadowMatrix: [],
22391                 spot: [],
22392                 spotShadow: [],
22393                 spotShadowMap: [],
22394                 spotShadowMatrix: [],
22395                 rectArea: [],
22396                 rectAreaLTC1: null,
22397                 rectAreaLTC2: null,
22398                 point: [],
22399                 pointShadow: [],
22400                 pointShadowMap: [],
22401                 pointShadowMatrix: [],
22402                 hemi: []
22403
22404         };
22405
22406         for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
22407
22408         const vector3 = new Vector3();
22409         const matrix4 = new Matrix4();
22410         const matrix42 = new Matrix4();
22411
22412         function setup( lights, physicallyCorrectLights ) {
22413
22414                 let r = 0, g = 0, b = 0;
22415
22416                 for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
22417
22418                 let directionalLength = 0;
22419                 let pointLength = 0;
22420                 let spotLength = 0;
22421                 let rectAreaLength = 0;
22422                 let hemiLength = 0;
22423
22424                 let numDirectionalShadows = 0;
22425                 let numPointShadows = 0;
22426                 let numSpotShadows = 0;
22427
22428                 lights.sort( shadowCastingLightsFirst );
22429
22430                 // artist-friendly light intensity scaling factor
22431                 const scaleFactor = ( physicallyCorrectLights !== true ) ? Math.PI : 1;
22432
22433                 for ( let i = 0, l = lights.length; i < l; i ++ ) {
22434
22435                         const light = lights[ i ];
22436
22437                         const color = light.color;
22438                         const intensity = light.intensity;
22439                         const distance = light.distance;
22440
22441                         const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
22442
22443                         if ( light.isAmbientLight ) {
22444
22445                                 r += color.r * intensity * scaleFactor;
22446                                 g += color.g * intensity * scaleFactor;
22447                                 b += color.b * intensity * scaleFactor;
22448
22449                         } else if ( light.isLightProbe ) {
22450
22451                                 for ( let j = 0; j < 9; j ++ ) {
22452
22453                                         state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
22454
22455                                 }
22456
22457                         } else if ( light.isDirectionalLight ) {
22458
22459                                 const uniforms = cache.get( light );
22460
22461                                 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor );
22462
22463                                 if ( light.castShadow ) {
22464
22465                                         const shadow = light.shadow;
22466
22467                                         const shadowUniforms = shadowCache.get( light );
22468
22469                                         shadowUniforms.shadowBias = shadow.bias;
22470                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
22471                                         shadowUniforms.shadowRadius = shadow.radius;
22472                                         shadowUniforms.shadowMapSize = shadow.mapSize;
22473
22474                                         state.directionalShadow[ directionalLength ] = shadowUniforms;
22475                                         state.directionalShadowMap[ directionalLength ] = shadowMap;
22476                                         state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
22477
22478                                         numDirectionalShadows ++;
22479
22480                                 }
22481
22482                                 state.directional[ directionalLength ] = uniforms;
22483
22484                                 directionalLength ++;
22485
22486                         } else if ( light.isSpotLight ) {
22487
22488                                 const uniforms = cache.get( light );
22489
22490                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22491
22492                                 uniforms.color.copy( color ).multiplyScalar( intensity * scaleFactor );
22493                                 uniforms.distance = distance;
22494
22495                                 uniforms.coneCos = Math.cos( light.angle );
22496                                 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
22497                                 uniforms.decay = light.decay;
22498
22499                                 if ( light.castShadow ) {
22500
22501                                         const shadow = light.shadow;
22502
22503                                         const shadowUniforms = shadowCache.get( light );
22504
22505                                         shadowUniforms.shadowBias = shadow.bias;
22506                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
22507                                         shadowUniforms.shadowRadius = shadow.radius;
22508                                         shadowUniforms.shadowMapSize = shadow.mapSize;
22509
22510                                         state.spotShadow[ spotLength ] = shadowUniforms;
22511                                         state.spotShadowMap[ spotLength ] = shadowMap;
22512                                         state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
22513
22514                                         numSpotShadows ++;
22515
22516                                 }
22517
22518                                 state.spot[ spotLength ] = uniforms;
22519
22520                                 spotLength ++;
22521
22522                         } else if ( light.isRectAreaLight ) {
22523
22524                                 const uniforms = cache.get( light );
22525
22526                                 // (a) intensity is the total visible light emitted
22527                                 //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
22528
22529                                 // (b) intensity is the brightness of the light
22530                                 uniforms.color.copy( color ).multiplyScalar( intensity );
22531
22532                                 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
22533                                 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
22534
22535                                 state.rectArea[ rectAreaLength ] = uniforms;
22536
22537                                 rectAreaLength ++;
22538
22539                         } else if ( light.isPointLight ) {
22540
22541                                 const uniforms = cache.get( light );
22542
22543                                 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor );
22544                                 uniforms.distance = light.distance;
22545                                 uniforms.decay = light.decay;
22546
22547                                 if ( light.castShadow ) {
22548
22549                                         const shadow = light.shadow;
22550
22551                                         const shadowUniforms = shadowCache.get( light );
22552
22553                                         shadowUniforms.shadowBias = shadow.bias;
22554                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
22555                                         shadowUniforms.shadowRadius = shadow.radius;
22556                                         shadowUniforms.shadowMapSize = shadow.mapSize;
22557                                         shadowUniforms.shadowCameraNear = shadow.camera.near;
22558                                         shadowUniforms.shadowCameraFar = shadow.camera.far;
22559
22560                                         state.pointShadow[ pointLength ] = shadowUniforms;
22561                                         state.pointShadowMap[ pointLength ] = shadowMap;
22562                                         state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
22563
22564                                         numPointShadows ++;
22565
22566                                 }
22567
22568                                 state.point[ pointLength ] = uniforms;
22569
22570                                 pointLength ++;
22571
22572                         } else if ( light.isHemisphereLight ) {
22573
22574                                 const uniforms = cache.get( light );
22575
22576                                 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity * scaleFactor );
22577                                 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity * scaleFactor );
22578
22579                                 state.hemi[ hemiLength ] = uniforms;
22580
22581                                 hemiLength ++;
22582
22583                         }
22584
22585                 }
22586
22587                 if ( rectAreaLength > 0 ) {
22588
22589                         if ( capabilities.isWebGL2 ) {
22590
22591                                 // WebGL 2
22592
22593                                 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
22594                                 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
22595
22596                         } else {
22597
22598                                 // WebGL 1
22599
22600                                 if ( extensions.has( 'OES_texture_float_linear' ) === true ) {
22601
22602                                         state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
22603                                         state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
22604
22605                                 } else if ( extensions.has( 'OES_texture_half_float_linear' ) === true ) {
22606
22607                                         state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
22608                                         state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
22609
22610                                 } else {
22611
22612                                         console.error( 'THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.' );
22613
22614                                 }
22615
22616                         }
22617
22618                 }
22619
22620                 state.ambient[ 0 ] = r;
22621                 state.ambient[ 1 ] = g;
22622                 state.ambient[ 2 ] = b;
22623
22624                 const hash = state.hash;
22625
22626                 if ( hash.directionalLength !== directionalLength ||
22627                         hash.pointLength !== pointLength ||
22628                         hash.spotLength !== spotLength ||
22629                         hash.rectAreaLength !== rectAreaLength ||
22630                         hash.hemiLength !== hemiLength ||
22631                         hash.numDirectionalShadows !== numDirectionalShadows ||
22632                         hash.numPointShadows !== numPointShadows ||
22633                         hash.numSpotShadows !== numSpotShadows ) {
22634
22635                         state.directional.length = directionalLength;
22636                         state.spot.length = spotLength;
22637                         state.rectArea.length = rectAreaLength;
22638                         state.point.length = pointLength;
22639                         state.hemi.length = hemiLength;
22640
22641                         state.directionalShadow.length = numDirectionalShadows;
22642                         state.directionalShadowMap.length = numDirectionalShadows;
22643                         state.pointShadow.length = numPointShadows;
22644                         state.pointShadowMap.length = numPointShadows;
22645                         state.spotShadow.length = numSpotShadows;
22646                         state.spotShadowMap.length = numSpotShadows;
22647                         state.directionalShadowMatrix.length = numDirectionalShadows;
22648                         state.pointShadowMatrix.length = numPointShadows;
22649                         state.spotShadowMatrix.length = numSpotShadows;
22650
22651                         hash.directionalLength = directionalLength;
22652                         hash.pointLength = pointLength;
22653                         hash.spotLength = spotLength;
22654                         hash.rectAreaLength = rectAreaLength;
22655                         hash.hemiLength = hemiLength;
22656
22657                         hash.numDirectionalShadows = numDirectionalShadows;
22658                         hash.numPointShadows = numPointShadows;
22659                         hash.numSpotShadows = numSpotShadows;
22660
22661                         state.version = nextVersion ++;
22662
22663                 }
22664
22665         }
22666
22667         function setupView( lights, camera ) {
22668
22669                 let directionalLength = 0;
22670                 let pointLength = 0;
22671                 let spotLength = 0;
22672                 let rectAreaLength = 0;
22673                 let hemiLength = 0;
22674
22675                 const viewMatrix = camera.matrixWorldInverse;
22676
22677                 for ( let i = 0, l = lights.length; i < l; i ++ ) {
22678
22679                         const light = lights[ i ];
22680
22681                         if ( light.isDirectionalLight ) {
22682
22683                                 const uniforms = state.directional[ directionalLength ];
22684
22685                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
22686                                 vector3.setFromMatrixPosition( light.target.matrixWorld );
22687                                 uniforms.direction.sub( vector3 );
22688                                 uniforms.direction.transformDirection( viewMatrix );
22689
22690                                 directionalLength ++;
22691
22692                         } else if ( light.isSpotLight ) {
22693
22694                                 const uniforms = state.spot[ spotLength ];
22695
22696                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22697                                 uniforms.position.applyMatrix4( viewMatrix );
22698
22699                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
22700                                 vector3.setFromMatrixPosition( light.target.matrixWorld );
22701                                 uniforms.direction.sub( vector3 );
22702                                 uniforms.direction.transformDirection( viewMatrix );
22703
22704                                 spotLength ++;
22705
22706                         } else if ( light.isRectAreaLight ) {
22707
22708                                 const uniforms = state.rectArea[ rectAreaLength ];
22709
22710                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22711                                 uniforms.position.applyMatrix4( viewMatrix );
22712
22713                                 // extract local rotation of light to derive width/height half vectors
22714                                 matrix42.identity();
22715                                 matrix4.copy( light.matrixWorld );
22716                                 matrix4.premultiply( viewMatrix );
22717                                 matrix42.extractRotation( matrix4 );
22718
22719                                 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
22720                                 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
22721
22722                                 uniforms.halfWidth.applyMatrix4( matrix42 );
22723                                 uniforms.halfHeight.applyMatrix4( matrix42 );
22724
22725                                 rectAreaLength ++;
22726
22727                         } else if ( light.isPointLight ) {
22728
22729                                 const uniforms = state.point[ pointLength ];
22730
22731                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22732                                 uniforms.position.applyMatrix4( viewMatrix );
22733
22734                                 pointLength ++;
22735
22736                         } else if ( light.isHemisphereLight ) {
22737
22738                                 const uniforms = state.hemi[ hemiLength ];
22739
22740                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
22741                                 uniforms.direction.transformDirection( viewMatrix );
22742                                 uniforms.direction.normalize();
22743
22744                                 hemiLength ++;
22745
22746                         }
22747
22748                 }
22749
22750         }
22751
22752         return {
22753                 setup: setup,
22754                 setupView: setupView,
22755                 state: state
22756         };
22757
22758     }
22759
22760     function WebGLRenderState( extensions, capabilities ) {
22761
22762         const lights = new WebGLLights( extensions, capabilities );
22763
22764         const lightsArray = [];
22765         const shadowsArray = [];
22766
22767         function init() {
22768
22769                 lightsArray.length = 0;
22770                 shadowsArray.length = 0;
22771
22772         }
22773
22774         function pushLight( light ) {
22775
22776                 lightsArray.push( light );
22777
22778         }
22779
22780         function pushShadow( shadowLight ) {
22781
22782                 shadowsArray.push( shadowLight );
22783
22784         }
22785
22786         function setupLights( physicallyCorrectLights ) {
22787
22788                 lights.setup( lightsArray, physicallyCorrectLights );
22789
22790         }
22791
22792         function setupLightsView( camera ) {
22793
22794                 lights.setupView( lightsArray, camera );
22795
22796         }
22797
22798         const state = {
22799                 lightsArray: lightsArray,
22800                 shadowsArray: shadowsArray,
22801
22802                 lights: lights
22803         };
22804
22805         return {
22806                 init: init,
22807                 state: state,
22808                 setupLights: setupLights,
22809                 setupLightsView: setupLightsView,
22810
22811                 pushLight: pushLight,
22812                 pushShadow: pushShadow
22813         };
22814
22815     }
22816
22817     function WebGLRenderStates( extensions, capabilities ) {
22818
22819         let renderStates = new WeakMap();
22820
22821         function get( scene, renderCallDepth = 0 ) {
22822
22823                 let renderState;
22824
22825                 if ( renderStates.has( scene ) === false ) {
22826
22827                         renderState = new WebGLRenderState( extensions, capabilities );
22828                         renderStates.set( scene, [ renderState ] );
22829
22830                 } else {
22831
22832                         if ( renderCallDepth >= renderStates.get( scene ).length ) {
22833
22834                                 renderState = new WebGLRenderState( extensions, capabilities );
22835                                 renderStates.get( scene ).push( renderState );
22836
22837                         } else {
22838
22839                                 renderState = renderStates.get( scene )[ renderCallDepth ];
22840
22841                         }
22842
22843                 }
22844
22845                 return renderState;
22846
22847         }
22848
22849         function dispose() {
22850
22851                 renderStates = new WeakMap();
22852
22853         }
22854
22855         return {
22856                 get: get,
22857                 dispose: dispose
22858         };
22859
22860     }
22861
22862     /**
22863      * parameters = {
22864      *
22865      *  opacity: <float>,
22866      *
22867      *  map: new THREE.Texture( <Image> ),
22868      *
22869      *  alphaMap: new THREE.Texture( <Image> ),
22870      *
22871      *  displacementMap: new THREE.Texture( <Image> ),
22872      *  displacementScale: <float>,
22873      *  displacementBias: <float>,
22874      *
22875      *  wireframe: <boolean>,
22876      *  wireframeLinewidth: <float>
22877      * }
22878      */
22879
22880     class MeshDepthMaterial extends Material {
22881
22882         constructor( parameters ) {
22883
22884                 super();
22885
22886                 this.type = 'MeshDepthMaterial';
22887
22888                 this.depthPacking = BasicDepthPacking;
22889
22890                 this.map = null;
22891
22892                 this.alphaMap = null;
22893
22894                 this.displacementMap = null;
22895                 this.displacementScale = 1;
22896                 this.displacementBias = 0;
22897
22898                 this.wireframe = false;
22899                 this.wireframeLinewidth = 1;
22900
22901                 this.fog = false;
22902
22903                 this.setValues( parameters );
22904
22905         }
22906
22907         copy( source ) {
22908
22909                 super.copy( source );
22910
22911                 this.depthPacking = source.depthPacking;
22912
22913                 this.map = source.map;
22914
22915                 this.alphaMap = source.alphaMap;
22916
22917                 this.displacementMap = source.displacementMap;
22918                 this.displacementScale = source.displacementScale;
22919                 this.displacementBias = source.displacementBias;
22920
22921                 this.wireframe = source.wireframe;
22922                 this.wireframeLinewidth = source.wireframeLinewidth;
22923
22924                 return this;
22925
22926         }
22927
22928     }
22929
22930     MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
22931
22932     /**
22933      * parameters = {
22934      *
22935      *  referencePosition: <float>,
22936      *  nearDistance: <float>,
22937      *  farDistance: <float>,
22938      *
22939      *  map: new THREE.Texture( <Image> ),
22940      *
22941      *  alphaMap: new THREE.Texture( <Image> ),
22942      *
22943      *  displacementMap: new THREE.Texture( <Image> ),
22944      *  displacementScale: <float>,
22945      *  displacementBias: <float>
22946      *
22947      * }
22948      */
22949
22950     class MeshDistanceMaterial extends Material {
22951
22952         constructor( parameters ) {
22953
22954                 super();
22955
22956                 this.type = 'MeshDistanceMaterial';
22957
22958                 this.referencePosition = new Vector3();
22959                 this.nearDistance = 1;
22960                 this.farDistance = 1000;
22961
22962                 this.map = null;
22963
22964                 this.alphaMap = null;
22965
22966                 this.displacementMap = null;
22967                 this.displacementScale = 1;
22968                 this.displacementBias = 0;
22969
22970                 this.fog = false;
22971
22972                 this.setValues( parameters );
22973
22974         }
22975
22976         copy( source ) {
22977
22978                 super.copy( source );
22979
22980                 this.referencePosition.copy( source.referencePosition );
22981                 this.nearDistance = source.nearDistance;
22982                 this.farDistance = source.farDistance;
22983
22984                 this.map = source.map;
22985
22986                 this.alphaMap = source.alphaMap;
22987
22988                 this.displacementMap = source.displacementMap;
22989                 this.displacementScale = source.displacementScale;
22990                 this.displacementBias = source.displacementBias;
22991
22992                 return this;
22993
22994         }
22995
22996     }
22997
22998     MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
22999
23000     const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
23001
23002     const fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 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, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
23003
23004     function WebGLShadowMap( _renderer, _objects, _capabilities ) {
23005
23006         let _frustum = new Frustum();
23007
23008         const _shadowMapSize = new Vector2(),
23009                 _viewportSize = new Vector2(),
23010
23011                 _viewport = new Vector4(),
23012
23013                 _depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ),
23014                 _distanceMaterial = new MeshDistanceMaterial(),
23015
23016                 _materialCache = {},
23017
23018                 _maxTextureSize = _capabilities.maxTextureSize;
23019
23020         const shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
23021
23022         const shadowMaterialVertical = new ShaderMaterial( {
23023                 defines: {
23024                         VSM_SAMPLES: 8
23025                 },
23026                 uniforms: {
23027                         shadow_pass: { value: null },
23028                         resolution: { value: new Vector2() },
23029                         radius: { value: 4.0 }
23030                 },
23031
23032                 vertexShader: vertex,
23033                 fragmentShader: fragment
23034
23035         } );
23036
23037         const shadowMaterialHorizontal = shadowMaterialVertical.clone();
23038         shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
23039
23040         const fullScreenTri = new BufferGeometry();
23041         fullScreenTri.setAttribute(
23042                 'position',
23043                 new BufferAttribute(
23044                         new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
23045                         3
23046                 )
23047         );
23048
23049         const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
23050
23051         const scope = this;
23052
23053         this.enabled = false;
23054
23055         this.autoUpdate = true;
23056         this.needsUpdate = false;
23057
23058         this.type = PCFShadowMap;
23059
23060         this.render = function ( lights, scene, camera ) {
23061
23062                 if ( scope.enabled === false ) return;
23063                 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
23064
23065                 if ( lights.length === 0 ) return;
23066
23067                 const currentRenderTarget = _renderer.getRenderTarget();
23068                 const activeCubeFace = _renderer.getActiveCubeFace();
23069                 const activeMipmapLevel = _renderer.getActiveMipmapLevel();
23070
23071                 const _state = _renderer.state;
23072
23073                 // Set GL state for depth map.
23074                 _state.setBlending( NoBlending );
23075                 _state.buffers.color.setClear( 1, 1, 1, 1 );
23076                 _state.buffers.depth.setTest( true );
23077                 _state.setScissorTest( false );
23078
23079                 // render depth map
23080
23081                 for ( let i = 0, il = lights.length; i < il; i ++ ) {
23082
23083                         const light = lights[ i ];
23084                         const shadow = light.shadow;
23085
23086                         if ( shadow === undefined ) {
23087
23088                                 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
23089                                 continue;
23090
23091                         }
23092
23093                         if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue;
23094
23095                         _shadowMapSize.copy( shadow.mapSize );
23096
23097                         const shadowFrameExtents = shadow.getFrameExtents();
23098
23099                         _shadowMapSize.multiply( shadowFrameExtents );
23100
23101                         _viewportSize.copy( shadow.mapSize );
23102
23103                         if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) {
23104
23105                                 if ( _shadowMapSize.x > _maxTextureSize ) {
23106
23107                                         _viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x );
23108                                         _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
23109                                         shadow.mapSize.x = _viewportSize.x;
23110
23111                                 }
23112
23113                                 if ( _shadowMapSize.y > _maxTextureSize ) {
23114
23115                                         _viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y );
23116                                         _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
23117                                         shadow.mapSize.y = _viewportSize.y;
23118
23119                                 }
23120
23121                         }
23122
23123                         if ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
23124
23125                                 const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
23126
23127                                 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
23128                                 shadow.map.texture.name = light.name + '.shadowMap';
23129
23130                                 shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
23131
23132                                 shadow.camera.updateProjectionMatrix();
23133
23134                         }
23135
23136                         if ( shadow.map === null ) {
23137
23138                                 const pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
23139
23140                                 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
23141                                 shadow.map.texture.name = light.name + '.shadowMap';
23142
23143                                 shadow.camera.updateProjectionMatrix();
23144
23145                         }
23146
23147                         _renderer.setRenderTarget( shadow.map );
23148                         _renderer.clear();
23149
23150                         const viewportCount = shadow.getViewportCount();
23151
23152                         for ( let vp = 0; vp < viewportCount; vp ++ ) {
23153
23154                                 const viewport = shadow.getViewport( vp );
23155
23156                                 _viewport.set(
23157                                         _viewportSize.x * viewport.x,
23158                                         _viewportSize.y * viewport.y,
23159                                         _viewportSize.x * viewport.z,
23160                                         _viewportSize.y * viewport.w
23161                                 );
23162
23163                                 _state.viewport( _viewport );
23164
23165                                 shadow.updateMatrices( light, vp );
23166
23167                                 _frustum = shadow.getFrustum();
23168
23169                                 renderObject( scene, camera, shadow.camera, light, this.type );
23170
23171                         }
23172
23173                         // do blur pass for VSM
23174
23175                         if ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
23176
23177                                 VSMPass( shadow, camera );
23178
23179                         }
23180
23181                         shadow.needsUpdate = false;
23182
23183                 }
23184
23185                 scope.needsUpdate = false;
23186
23187                 _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
23188
23189         };
23190
23191         function VSMPass( shadow, camera ) {
23192
23193                 const geometry = _objects.update( fullScreenMesh );
23194
23195                 if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) {
23196
23197                         shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples;
23198                         shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples;
23199
23200                         shadowMaterialVertical.needsUpdate = true;
23201                         shadowMaterialHorizontal.needsUpdate = true;
23202
23203                 }
23204
23205                 // vertical pass
23206
23207                 shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
23208                 shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
23209                 shadowMaterialVertical.uniforms.radius.value = shadow.radius;
23210                 _renderer.setRenderTarget( shadow.mapPass );
23211                 _renderer.clear();
23212                 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
23213
23214                 // horizontal pass
23215
23216                 shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
23217                 shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
23218                 shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
23219                 _renderer.setRenderTarget( shadow.map );
23220                 _renderer.clear();
23221                 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
23222
23223         }
23224
23225         function getDepthMaterial( object, geometry, material, light, shadowCameraNear, shadowCameraFar, type ) {
23226
23227                 let result = null;
23228
23229                 const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial;
23230
23231                 if ( customMaterial !== undefined ) {
23232
23233                         result = customMaterial;
23234
23235                 } else {
23236
23237                         result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial;
23238
23239                 }
23240
23241                 if ( ( _renderer.localClippingEnabled && material.clipShadows === true && material.clippingPlanes.length !== 0 ) ||
23242                         ( material.displacementMap && material.displacementScale !== 0 ) ||
23243                         ( material.alphaMap && material.alphaTest > 0 ) ) {
23244
23245                         // in this case we need a unique material instance reflecting the
23246                         // appropriate state
23247
23248                         const keyA = result.uuid, keyB = material.uuid;
23249
23250                         let materialsForVariant = _materialCache[ keyA ];
23251
23252                         if ( materialsForVariant === undefined ) {
23253
23254                                 materialsForVariant = {};
23255                                 _materialCache[ keyA ] = materialsForVariant;
23256
23257                         }
23258
23259                         let cachedMaterial = materialsForVariant[ keyB ];
23260
23261                         if ( cachedMaterial === undefined ) {
23262
23263                                 cachedMaterial = result.clone();
23264                                 materialsForVariant[ keyB ] = cachedMaterial;
23265
23266                         }
23267
23268                         result = cachedMaterial;
23269
23270                 }
23271
23272                 result.visible = material.visible;
23273                 result.wireframe = material.wireframe;
23274
23275                 if ( type === VSMShadowMap ) {
23276
23277                         result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
23278
23279                 } else {
23280
23281                         result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
23282
23283                 }
23284
23285                 result.alphaMap = material.alphaMap;
23286                 result.alphaTest = material.alphaTest;
23287
23288                 result.clipShadows = material.clipShadows;
23289                 result.clippingPlanes = material.clippingPlanes;
23290                 result.clipIntersection = material.clipIntersection;
23291
23292                 result.displacementMap = material.displacementMap;
23293                 result.displacementScale = material.displacementScale;
23294                 result.displacementBias = material.displacementBias;
23295
23296                 result.wireframeLinewidth = material.wireframeLinewidth;
23297                 result.linewidth = material.linewidth;
23298
23299                 if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
23300
23301                         result.referencePosition.setFromMatrixPosition( light.matrixWorld );
23302                         result.nearDistance = shadowCameraNear;
23303                         result.farDistance = shadowCameraFar;
23304
23305                 }
23306
23307                 return result;
23308
23309         }
23310
23311         function renderObject( object, camera, shadowCamera, light, type ) {
23312
23313                 if ( object.visible === false ) return;
23314
23315                 const visible = object.layers.test( camera.layers );
23316
23317                 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
23318
23319                         if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
23320
23321                                 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
23322
23323                                 const geometry = _objects.update( object );
23324                                 const material = object.material;
23325
23326                                 if ( Array.isArray( material ) ) {
23327
23328                                         const groups = geometry.groups;
23329
23330                                         for ( let k = 0, kl = groups.length; k < kl; k ++ ) {
23331
23332                                                 const group = groups[ k ];
23333                                                 const groupMaterial = material[ group.materialIndex ];
23334
23335                                                 if ( groupMaterial && groupMaterial.visible ) {
23336
23337                                                         const depthMaterial = getDepthMaterial( object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );
23338
23339                                                         _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
23340
23341                                                 }
23342
23343                                         }
23344
23345                                 } else if ( material.visible ) {
23346
23347                                         const depthMaterial = getDepthMaterial( object, geometry, material, light, shadowCamera.near, shadowCamera.far, type );
23348
23349                                         _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
23350
23351                                 }
23352
23353                         }
23354
23355                 }
23356
23357                 const children = object.children;
23358
23359                 for ( let i = 0, l = children.length; i < l; i ++ ) {
23360
23361                         renderObject( children[ i ], camera, shadowCamera, light, type );
23362
23363                 }
23364
23365         }
23366
23367     }
23368
23369     function WebGLState( gl, extensions, capabilities ) {
23370
23371         const isWebGL2 = capabilities.isWebGL2;
23372
23373         function ColorBuffer() {
23374
23375                 let locked = false;
23376
23377                 const color = new Vector4();
23378                 let currentColorMask = null;
23379                 const currentColorClear = new Vector4( 0, 0, 0, 0 );
23380
23381                 return {
23382
23383                         setMask: function ( colorMask ) {
23384
23385                                 if ( currentColorMask !== colorMask && ! locked ) {
23386
23387                                         gl.colorMask( colorMask, colorMask, colorMask, colorMask );
23388                                         currentColorMask = colorMask;
23389
23390                                 }
23391
23392                         },
23393
23394                         setLocked: function ( lock ) {
23395
23396                                 locked = lock;
23397
23398                         },
23399
23400                         setClear: function ( r, g, b, a, premultipliedAlpha ) {
23401
23402                                 if ( premultipliedAlpha === true ) {
23403
23404                                         r *= a; g *= a; b *= a;
23405
23406                                 }
23407
23408                                 color.set( r, g, b, a );
23409
23410                                 if ( currentColorClear.equals( color ) === false ) {
23411
23412                                         gl.clearColor( r, g, b, a );
23413                                         currentColorClear.copy( color );
23414
23415                                 }
23416
23417                         },
23418
23419                         reset: function () {
23420
23421                                 locked = false;
23422
23423                                 currentColorMask = null;
23424                                 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
23425
23426                         }
23427
23428                 };
23429
23430         }
23431
23432         function DepthBuffer() {
23433
23434                 let locked = false;
23435
23436                 let currentDepthMask = null;
23437                 let currentDepthFunc = null;
23438                 let currentDepthClear = null;
23439
23440                 return {
23441
23442                         setTest: function ( depthTest ) {
23443
23444                                 if ( depthTest ) {
23445
23446                                         enable( 2929 );
23447
23448                                 } else {
23449
23450                                         disable( 2929 );
23451
23452                                 }
23453
23454                         },
23455
23456                         setMask: function ( depthMask ) {
23457
23458                                 if ( currentDepthMask !== depthMask && ! locked ) {
23459
23460                                         gl.depthMask( depthMask );
23461                                         currentDepthMask = depthMask;
23462
23463                                 }
23464
23465                         },
23466
23467                         setFunc: function ( depthFunc ) {
23468
23469                                 if ( currentDepthFunc !== depthFunc ) {
23470
23471                                         if ( depthFunc ) {
23472
23473                                                 switch ( depthFunc ) {
23474
23475                                                         case NeverDepth:
23476
23477                                                                 gl.depthFunc( 512 );
23478                                                                 break;
23479
23480                                                         case AlwaysDepth:
23481
23482                                                                 gl.depthFunc( 519 );
23483                                                                 break;
23484
23485                                                         case LessDepth:
23486
23487                                                                 gl.depthFunc( 513 );
23488                                                                 break;
23489
23490                                                         case LessEqualDepth:
23491
23492                                                                 gl.depthFunc( 515 );
23493                                                                 break;
23494
23495                                                         case EqualDepth:
23496
23497                                                                 gl.depthFunc( 514 );
23498                                                                 break;
23499
23500                                                         case GreaterEqualDepth:
23501
23502                                                                 gl.depthFunc( 518 );
23503                                                                 break;
23504
23505                                                         case GreaterDepth:
23506
23507                                                                 gl.depthFunc( 516 );
23508                                                                 break;
23509
23510                                                         case NotEqualDepth:
23511
23512                                                                 gl.depthFunc( 517 );
23513                                                                 break;
23514
23515                                                         default:
23516
23517                                                                 gl.depthFunc( 515 );
23518
23519                                                 }
23520
23521                                         } else {
23522
23523                                                 gl.depthFunc( 515 );
23524
23525                                         }
23526
23527                                         currentDepthFunc = depthFunc;
23528
23529                                 }
23530
23531                         },
23532
23533                         setLocked: function ( lock ) {
23534
23535                                 locked = lock;
23536
23537                         },
23538
23539                         setClear: function ( depth ) {
23540
23541                                 if ( currentDepthClear !== depth ) {
23542
23543                                         gl.clearDepth( depth );
23544                                         currentDepthClear = depth;
23545
23546                                 }
23547
23548                         },
23549
23550                         reset: function () {
23551
23552                                 locked = false;
23553
23554                                 currentDepthMask = null;
23555                                 currentDepthFunc = null;
23556                                 currentDepthClear = null;
23557
23558                         }
23559
23560                 };
23561
23562         }
23563
23564         function StencilBuffer() {
23565
23566                 let locked = false;
23567
23568                 let currentStencilMask = null;
23569                 let currentStencilFunc = null;
23570                 let currentStencilRef = null;
23571                 let currentStencilFuncMask = null;
23572                 let currentStencilFail = null;
23573                 let currentStencilZFail = null;
23574                 let currentStencilZPass = null;
23575                 let currentStencilClear = null;
23576
23577                 return {
23578
23579                         setTest: function ( stencilTest ) {
23580
23581                                 if ( ! locked ) {
23582
23583                                         if ( stencilTest ) {
23584
23585                                                 enable( 2960 );
23586
23587                                         } else {
23588
23589                                                 disable( 2960 );
23590
23591                                         }
23592
23593                                 }
23594
23595                         },
23596
23597                         setMask: function ( stencilMask ) {
23598
23599                                 if ( currentStencilMask !== stencilMask && ! locked ) {
23600
23601                                         gl.stencilMask( stencilMask );
23602                                         currentStencilMask = stencilMask;
23603
23604                                 }
23605
23606                         },
23607
23608                         setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
23609
23610                                 if ( currentStencilFunc !== stencilFunc ||
23611                                      currentStencilRef !== stencilRef ||
23612                                      currentStencilFuncMask !== stencilMask ) {
23613
23614                                         gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
23615
23616                                         currentStencilFunc = stencilFunc;
23617                                         currentStencilRef = stencilRef;
23618                                         currentStencilFuncMask = stencilMask;
23619
23620                                 }
23621
23622                         },
23623
23624                         setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
23625
23626                                 if ( currentStencilFail !== stencilFail ||
23627                                      currentStencilZFail !== stencilZFail ||
23628                                      currentStencilZPass !== stencilZPass ) {
23629
23630                                         gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
23631
23632                                         currentStencilFail = stencilFail;
23633                                         currentStencilZFail = stencilZFail;
23634                                         currentStencilZPass = stencilZPass;
23635
23636                                 }
23637
23638                         },
23639
23640                         setLocked: function ( lock ) {
23641
23642                                 locked = lock;
23643
23644                         },
23645
23646                         setClear: function ( stencil ) {
23647
23648                                 if ( currentStencilClear !== stencil ) {
23649
23650                                         gl.clearStencil( stencil );
23651                                         currentStencilClear = stencil;
23652
23653                                 }
23654
23655                         },
23656
23657                         reset: function () {
23658
23659                                 locked = false;
23660
23661                                 currentStencilMask = null;
23662                                 currentStencilFunc = null;
23663                                 currentStencilRef = null;
23664                                 currentStencilFuncMask = null;
23665                                 currentStencilFail = null;
23666                                 currentStencilZFail = null;
23667                                 currentStencilZPass = null;
23668                                 currentStencilClear = null;
23669
23670                         }
23671
23672                 };
23673
23674         }
23675
23676         //
23677
23678         const colorBuffer = new ColorBuffer();
23679         const depthBuffer = new DepthBuffer();
23680         const stencilBuffer = new StencilBuffer();
23681
23682         let enabledCapabilities = {};
23683
23684         let xrFramebuffer = null;
23685         let currentBoundFramebuffers = {};
23686
23687         let currentProgram = null;
23688
23689         let currentBlendingEnabled = false;
23690         let currentBlending = null;
23691         let currentBlendEquation = null;
23692         let currentBlendSrc = null;
23693         let currentBlendDst = null;
23694         let currentBlendEquationAlpha = null;
23695         let currentBlendSrcAlpha = null;
23696         let currentBlendDstAlpha = null;
23697         let currentPremultipledAlpha = false;
23698
23699         let currentFlipSided = null;
23700         let currentCullFace = null;
23701
23702         let currentLineWidth = null;
23703
23704         let currentPolygonOffsetFactor = null;
23705         let currentPolygonOffsetUnits = null;
23706
23707         const maxTextures = gl.getParameter( 35661 );
23708
23709         let lineWidthAvailable = false;
23710         let version = 0;
23711         const glVersion = gl.getParameter( 7938 );
23712
23713         if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
23714
23715                 version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] );
23716                 lineWidthAvailable = ( version >= 1.0 );
23717
23718         } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
23719
23720                 version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] );
23721                 lineWidthAvailable = ( version >= 2.0 );
23722
23723         }
23724
23725         let currentTextureSlot = null;
23726         let currentBoundTextures = {};
23727
23728         const scissorParam = gl.getParameter( 3088 );
23729         const viewportParam = gl.getParameter( 2978 );
23730
23731         const currentScissor = new Vector4().fromArray( scissorParam );
23732         const currentViewport = new Vector4().fromArray( viewportParam );
23733
23734         function createTexture( type, target, count ) {
23735
23736                 const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
23737                 const texture = gl.createTexture();
23738
23739                 gl.bindTexture( type, texture );
23740                 gl.texParameteri( type, 10241, 9728 );
23741                 gl.texParameteri( type, 10240, 9728 );
23742
23743                 for ( let i = 0; i < count; i ++ ) {
23744
23745                         gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );
23746
23747                 }
23748
23749                 return texture;
23750
23751         }
23752
23753         const emptyTextures = {};
23754         emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );
23755         emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );
23756
23757         // init
23758
23759         colorBuffer.setClear( 0, 0, 0, 1 );
23760         depthBuffer.setClear( 1 );
23761         stencilBuffer.setClear( 0 );
23762
23763         enable( 2929 );
23764         depthBuffer.setFunc( LessEqualDepth );
23765
23766         setFlipSided( false );
23767         setCullFace( CullFaceBack );
23768         enable( 2884 );
23769
23770         setBlending( NoBlending );
23771
23772         //
23773
23774         function enable( id ) {
23775
23776                 if ( enabledCapabilities[ id ] !== true ) {
23777
23778                         gl.enable( id );
23779                         enabledCapabilities[ id ] = true;
23780
23781                 }
23782
23783         }
23784
23785         function disable( id ) {
23786
23787                 if ( enabledCapabilities[ id ] !== false ) {
23788
23789                         gl.disable( id );
23790                         enabledCapabilities[ id ] = false;
23791
23792                 }
23793
23794         }
23795
23796         function bindXRFramebuffer( framebuffer ) {
23797
23798                 if ( framebuffer !== xrFramebuffer ) {
23799
23800                         gl.bindFramebuffer( 36160, framebuffer );
23801
23802                         xrFramebuffer = framebuffer;
23803
23804                 }
23805
23806         }
23807
23808         function bindFramebuffer( target, framebuffer ) {
23809
23810                 if ( framebuffer === null && xrFramebuffer !== null ) framebuffer = xrFramebuffer; // use active XR framebuffer if available
23811
23812                 if ( currentBoundFramebuffers[ target ] !== framebuffer ) {
23813
23814                         gl.bindFramebuffer( target, framebuffer );
23815
23816                         currentBoundFramebuffers[ target ] = framebuffer;
23817
23818                         if ( isWebGL2 ) {
23819
23820                                 // 36009 is equivalent to 36160
23821
23822                                 if ( target === 36009 ) {
23823
23824                                         currentBoundFramebuffers[ 36160 ] = framebuffer;
23825
23826                                 }
23827
23828                                 if ( target === 36160 ) {
23829
23830                                         currentBoundFramebuffers[ 36009 ] = framebuffer;
23831
23832                                 }
23833
23834                         }
23835
23836                         return true;
23837
23838                 }
23839
23840                 return false;
23841
23842         }
23843
23844         function useProgram( program ) {
23845
23846                 if ( currentProgram !== program ) {
23847
23848                         gl.useProgram( program );
23849
23850                         currentProgram = program;
23851
23852                         return true;
23853
23854                 }
23855
23856                 return false;
23857
23858         }
23859
23860         const equationToGL = {
23861                 [ AddEquation ]: 32774,
23862                 [ SubtractEquation ]: 32778,
23863                 [ ReverseSubtractEquation ]: 32779
23864         };
23865
23866         if ( isWebGL2 ) {
23867
23868                 equationToGL[ MinEquation ] = 32775;
23869                 equationToGL[ MaxEquation ] = 32776;
23870
23871         } else {
23872
23873                 const extension = extensions.get( 'EXT_blend_minmax' );
23874
23875                 if ( extension !== null ) {
23876
23877                         equationToGL[ MinEquation ] = extension.MIN_EXT;
23878                         equationToGL[ MaxEquation ] = extension.MAX_EXT;
23879
23880                 }
23881
23882         }
23883
23884         const factorToGL = {
23885                 [ ZeroFactor ]: 0,
23886                 [ OneFactor ]: 1,
23887                 [ SrcColorFactor ]: 768,
23888                 [ SrcAlphaFactor ]: 770,
23889                 [ SrcAlphaSaturateFactor ]: 776,
23890                 [ DstColorFactor ]: 774,
23891                 [ DstAlphaFactor ]: 772,
23892                 [ OneMinusSrcColorFactor ]: 769,
23893                 [ OneMinusSrcAlphaFactor ]: 771,
23894                 [ OneMinusDstColorFactor ]: 775,
23895                 [ OneMinusDstAlphaFactor ]: 773
23896         };
23897
23898         function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
23899
23900                 if ( blending === NoBlending ) {
23901
23902                         if ( currentBlendingEnabled === true ) {
23903
23904                                 disable( 3042 );
23905                                 currentBlendingEnabled = false;
23906
23907                         }
23908
23909                         return;
23910
23911                 }
23912
23913                 if ( currentBlendingEnabled === false ) {
23914
23915                         enable( 3042 );
23916                         currentBlendingEnabled = true;
23917
23918                 }
23919
23920                 if ( blending !== CustomBlending ) {
23921
23922                         if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
23923
23924                                 if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
23925
23926                                         gl.blendEquation( 32774 );
23927
23928                                         currentBlendEquation = AddEquation;
23929                                         currentBlendEquationAlpha = AddEquation;
23930
23931                                 }
23932
23933                                 if ( premultipliedAlpha ) {
23934
23935                                         switch ( blending ) {
23936
23937                                                 case NormalBlending:
23938                                                         gl.blendFuncSeparate( 1, 771, 1, 771 );
23939                                                         break;
23940
23941                                                 case AdditiveBlending:
23942                                                         gl.blendFunc( 1, 1 );
23943                                                         break;
23944
23945                                                 case SubtractiveBlending:
23946                                                         gl.blendFuncSeparate( 0, 0, 769, 771 );
23947                                                         break;
23948
23949                                                 case MultiplyBlending:
23950                                                         gl.blendFuncSeparate( 0, 768, 0, 770 );
23951                                                         break;
23952
23953                                                 default:
23954                                                         console.error( 'THREE.WebGLState: Invalid blending: ', blending );
23955                                                         break;
23956
23957                                         }
23958
23959                                 } else {
23960
23961                                         switch ( blending ) {
23962
23963                                                 case NormalBlending:
23964                                                         gl.blendFuncSeparate( 770, 771, 1, 771 );
23965                                                         break;
23966
23967                                                 case AdditiveBlending:
23968                                                         gl.blendFunc( 770, 1 );
23969                                                         break;
23970
23971                                                 case SubtractiveBlending:
23972                                                         gl.blendFunc( 0, 769 );
23973                                                         break;
23974
23975                                                 case MultiplyBlending:
23976                                                         gl.blendFunc( 0, 768 );
23977                                                         break;
23978
23979                                                 default:
23980                                                         console.error( 'THREE.WebGLState: Invalid blending: ', blending );
23981                                                         break;
23982
23983                                         }
23984
23985                                 }
23986
23987                                 currentBlendSrc = null;
23988                                 currentBlendDst = null;
23989                                 currentBlendSrcAlpha = null;
23990                                 currentBlendDstAlpha = null;
23991
23992                                 currentBlending = blending;
23993                                 currentPremultipledAlpha = premultipliedAlpha;
23994
23995                         }
23996
23997                         return;
23998
23999                 }
24000
24001                 // custom blending
24002
24003                 blendEquationAlpha = blendEquationAlpha || blendEquation;
24004                 blendSrcAlpha = blendSrcAlpha || blendSrc;
24005                 blendDstAlpha = blendDstAlpha || blendDst;
24006
24007                 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
24008
24009                         gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
24010
24011                         currentBlendEquation = blendEquation;
24012                         currentBlendEquationAlpha = blendEquationAlpha;
24013
24014                 }
24015
24016                 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
24017
24018                         gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
24019
24020                         currentBlendSrc = blendSrc;
24021                         currentBlendDst = blendDst;
24022                         currentBlendSrcAlpha = blendSrcAlpha;
24023                         currentBlendDstAlpha = blendDstAlpha;
24024
24025                 }
24026
24027                 currentBlending = blending;
24028                 currentPremultipledAlpha = null;
24029
24030         }
24031
24032         function setMaterial( material, frontFaceCW ) {
24033
24034                 material.side === DoubleSide
24035                         ? disable( 2884 )
24036                         : enable( 2884 );
24037
24038                 let flipSided = ( material.side === BackSide );
24039                 if ( frontFaceCW ) flipSided = ! flipSided;
24040
24041                 setFlipSided( flipSided );
24042
24043                 ( material.blending === NormalBlending && material.transparent === false )
24044                         ? setBlending( NoBlending )
24045                         : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
24046
24047                 depthBuffer.setFunc( material.depthFunc );
24048                 depthBuffer.setTest( material.depthTest );
24049                 depthBuffer.setMask( material.depthWrite );
24050                 colorBuffer.setMask( material.colorWrite );
24051
24052                 const stencilWrite = material.stencilWrite;
24053                 stencilBuffer.setTest( stencilWrite );
24054                 if ( stencilWrite ) {
24055
24056                         stencilBuffer.setMask( material.stencilWriteMask );
24057                         stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
24058                         stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
24059
24060                 }
24061
24062                 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
24063
24064                 material.alphaToCoverage === true
24065                         ? enable( 32926 )
24066                         : disable( 32926 );
24067
24068         }
24069
24070         //
24071
24072         function setFlipSided( flipSided ) {
24073
24074                 if ( currentFlipSided !== flipSided ) {
24075
24076                         if ( flipSided ) {
24077
24078                                 gl.frontFace( 2304 );
24079
24080                         } else {
24081
24082                                 gl.frontFace( 2305 );
24083
24084                         }
24085
24086                         currentFlipSided = flipSided;
24087
24088                 }
24089
24090         }
24091
24092         function setCullFace( cullFace ) {
24093
24094                 if ( cullFace !== CullFaceNone ) {
24095
24096                         enable( 2884 );
24097
24098                         if ( cullFace !== currentCullFace ) {
24099
24100                                 if ( cullFace === CullFaceBack ) {
24101
24102                                         gl.cullFace( 1029 );
24103
24104                                 } else if ( cullFace === CullFaceFront ) {
24105
24106                                         gl.cullFace( 1028 );
24107
24108                                 } else {
24109
24110                                         gl.cullFace( 1032 );
24111
24112                                 }
24113
24114                         }
24115
24116                 } else {
24117
24118                         disable( 2884 );
24119
24120                 }
24121
24122                 currentCullFace = cullFace;
24123
24124         }
24125
24126         function setLineWidth( width ) {
24127
24128                 if ( width !== currentLineWidth ) {
24129
24130                         if ( lineWidthAvailable ) gl.lineWidth( width );
24131
24132                         currentLineWidth = width;
24133
24134                 }
24135
24136         }
24137
24138         function setPolygonOffset( polygonOffset, factor, units ) {
24139
24140                 if ( polygonOffset ) {
24141
24142                         enable( 32823 );
24143
24144                         if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
24145
24146                                 gl.polygonOffset( factor, units );
24147
24148                                 currentPolygonOffsetFactor = factor;
24149                                 currentPolygonOffsetUnits = units;
24150
24151                         }
24152
24153                 } else {
24154
24155                         disable( 32823 );
24156
24157                 }
24158
24159         }
24160
24161         function setScissorTest( scissorTest ) {
24162
24163                 if ( scissorTest ) {
24164
24165                         enable( 3089 );
24166
24167                 } else {
24168
24169                         disable( 3089 );
24170
24171                 }
24172
24173         }
24174
24175         // texture
24176
24177         function activeTexture( webglSlot ) {
24178
24179                 if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1;
24180
24181                 if ( currentTextureSlot !== webglSlot ) {
24182
24183                         gl.activeTexture( webglSlot );
24184                         currentTextureSlot = webglSlot;
24185
24186                 }
24187
24188         }
24189
24190         function bindTexture( webglType, webglTexture ) {
24191
24192                 if ( currentTextureSlot === null ) {
24193
24194                         activeTexture();
24195
24196                 }
24197
24198                 let boundTexture = currentBoundTextures[ currentTextureSlot ];
24199
24200                 if ( boundTexture === undefined ) {
24201
24202                         boundTexture = { type: undefined, texture: undefined };
24203                         currentBoundTextures[ currentTextureSlot ] = boundTexture;
24204
24205                 }
24206
24207                 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
24208
24209                         gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
24210
24211                         boundTexture.type = webglType;
24212                         boundTexture.texture = webglTexture;
24213
24214                 }
24215
24216         }
24217
24218         function unbindTexture() {
24219
24220                 const boundTexture = currentBoundTextures[ currentTextureSlot ];
24221
24222                 if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
24223
24224                         gl.bindTexture( boundTexture.type, null );
24225
24226                         boundTexture.type = undefined;
24227                         boundTexture.texture = undefined;
24228
24229                 }
24230
24231         }
24232
24233         function compressedTexImage2D() {
24234
24235                 try {
24236
24237                         gl.compressedTexImage2D.apply( gl, arguments );
24238
24239                 } catch ( error ) {
24240
24241                         console.error( 'THREE.WebGLState:', error );
24242
24243                 }
24244
24245         }
24246
24247         function texImage2D() {
24248
24249                 try {
24250
24251                         gl.texImage2D.apply( gl, arguments );
24252
24253                 } catch ( error ) {
24254
24255                         console.error( 'THREE.WebGLState:', error );
24256
24257                 }
24258
24259         }
24260
24261         function texImage3D() {
24262
24263                 try {
24264
24265                         gl.texImage3D.apply( gl, arguments );
24266
24267                 } catch ( error ) {
24268
24269                         console.error( 'THREE.WebGLState:', error );
24270
24271                 }
24272
24273         }
24274
24275         //
24276
24277         function scissor( scissor ) {
24278
24279                 if ( currentScissor.equals( scissor ) === false ) {
24280
24281                         gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
24282                         currentScissor.copy( scissor );
24283
24284                 }
24285
24286         }
24287
24288         function viewport( viewport ) {
24289
24290                 if ( currentViewport.equals( viewport ) === false ) {
24291
24292                         gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
24293                         currentViewport.copy( viewport );
24294
24295                 }
24296
24297         }
24298
24299         //
24300
24301         function reset() {
24302
24303                 // reset state
24304
24305                 gl.disable( 3042 );
24306                 gl.disable( 2884 );
24307                 gl.disable( 2929 );
24308                 gl.disable( 32823 );
24309                 gl.disable( 3089 );
24310                 gl.disable( 2960 );
24311                 gl.disable( 32926 );
24312
24313                 gl.blendEquation( 32774 );
24314                 gl.blendFunc( 1, 0 );
24315                 gl.blendFuncSeparate( 1, 0, 1, 0 );
24316
24317                 gl.colorMask( true, true, true, true );
24318                 gl.clearColor( 0, 0, 0, 0 );
24319
24320                 gl.depthMask( true );
24321                 gl.depthFunc( 513 );
24322                 gl.clearDepth( 1 );
24323
24324                 gl.stencilMask( 0xffffffff );
24325                 gl.stencilFunc( 519, 0, 0xffffffff );
24326                 gl.stencilOp( 7680, 7680, 7680 );
24327                 gl.clearStencil( 0 );
24328
24329                 gl.cullFace( 1029 );
24330                 gl.frontFace( 2305 );
24331
24332                 gl.polygonOffset( 0, 0 );
24333
24334                 gl.activeTexture( 33984 );
24335
24336                 gl.bindFramebuffer( 36160, null );
24337
24338                 if ( isWebGL2 === true ) {
24339
24340                         gl.bindFramebuffer( 36009, null );
24341                         gl.bindFramebuffer( 36008, null );
24342
24343                 }
24344
24345                 gl.useProgram( null );
24346
24347                 gl.lineWidth( 1 );
24348
24349                 gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height );
24350                 gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height );
24351
24352                 // reset internals
24353
24354                 enabledCapabilities = {};
24355
24356                 currentTextureSlot = null;
24357                 currentBoundTextures = {};
24358
24359                 xrFramebuffer = null;
24360                 currentBoundFramebuffers = {};
24361
24362                 currentProgram = null;
24363
24364                 currentBlendingEnabled = false;
24365                 currentBlending = null;
24366                 currentBlendEquation = null;
24367                 currentBlendSrc = null;
24368                 currentBlendDst = null;
24369                 currentBlendEquationAlpha = null;
24370                 currentBlendSrcAlpha = null;
24371                 currentBlendDstAlpha = null;
24372                 currentPremultipledAlpha = false;
24373
24374                 currentFlipSided = null;
24375                 currentCullFace = null;
24376
24377                 currentLineWidth = null;
24378
24379                 currentPolygonOffsetFactor = null;
24380                 currentPolygonOffsetUnits = null;
24381
24382                 currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height );
24383                 currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height );
24384
24385                 colorBuffer.reset();
24386                 depthBuffer.reset();
24387                 stencilBuffer.reset();
24388
24389         }
24390
24391         return {
24392
24393                 buffers: {
24394                         color: colorBuffer,
24395                         depth: depthBuffer,
24396                         stencil: stencilBuffer
24397                 },
24398
24399                 enable: enable,
24400                 disable: disable,
24401
24402                 bindFramebuffer: bindFramebuffer,
24403                 bindXRFramebuffer: bindXRFramebuffer,
24404
24405                 useProgram: useProgram,
24406
24407                 setBlending: setBlending,
24408                 setMaterial: setMaterial,
24409
24410                 setFlipSided: setFlipSided,
24411                 setCullFace: setCullFace,
24412
24413                 setLineWidth: setLineWidth,
24414                 setPolygonOffset: setPolygonOffset,
24415
24416                 setScissorTest: setScissorTest,
24417
24418                 activeTexture: activeTexture,
24419                 bindTexture: bindTexture,
24420                 unbindTexture: unbindTexture,
24421                 compressedTexImage2D: compressedTexImage2D,
24422                 texImage2D: texImage2D,
24423                 texImage3D: texImage3D,
24424
24425                 scissor: scissor,
24426                 viewport: viewport,
24427
24428                 reset: reset
24429
24430         };
24431
24432     }
24433
24434     function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
24435
24436         const isWebGL2 = capabilities.isWebGL2;
24437         const maxTextures = capabilities.maxTextures;
24438         const maxCubemapSize = capabilities.maxCubemapSize;
24439         const maxTextureSize = capabilities.maxTextureSize;
24440         const maxSamples = capabilities.maxSamples;
24441
24442         const _videoTextures = new WeakMap();
24443         let _canvas;
24444
24445         // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
24446         // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
24447         // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
24448
24449         let useOffscreenCanvas = false;
24450
24451         try {
24452
24453                 useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
24454                         && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null;
24455
24456         } catch ( err ) {
24457
24458                 // Ignore any errors
24459
24460         }
24461
24462         function createCanvas( width, height ) {
24463
24464                 // Use OffscreenCanvas when available. Specially needed in web workers
24465
24466                 return useOffscreenCanvas ?
24467                         new OffscreenCanvas( width, height ) : createElementNS( 'canvas' );
24468
24469         }
24470
24471         function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {
24472
24473                 let scale = 1;
24474
24475                 // handle case if texture exceeds max size
24476
24477                 if ( image.width > maxSize || image.height > maxSize ) {
24478
24479                         scale = maxSize / Math.max( image.width, image.height );
24480
24481                 }
24482
24483                 // only perform resize if necessary
24484
24485                 if ( scale < 1 || needsPowerOfTwo === true ) {
24486
24487                         // only perform resize for certain image types
24488
24489                         if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
24490                                 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
24491                                 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
24492
24493                                 const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor;
24494
24495                                 const width = floor( scale * image.width );
24496                                 const height = floor( scale * image.height );
24497
24498                                 if ( _canvas === undefined ) _canvas = createCanvas( width, height );
24499
24500                                 // cube textures can't reuse the same canvas
24501
24502                                 const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
24503
24504                                 canvas.width = width;
24505                                 canvas.height = height;
24506
24507                                 const context = canvas.getContext( '2d' );
24508                                 context.drawImage( image, 0, 0, width, height );
24509
24510                                 console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );
24511
24512                                 return canvas;
24513
24514                         } else {
24515
24516                                 if ( 'data' in image ) {
24517
24518                                         console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
24519
24520                                 }
24521
24522                                 return image;
24523
24524                         }
24525
24526                 }
24527
24528                 return image;
24529
24530         }
24531
24532         function isPowerOfTwo$1( image ) {
24533
24534                 return isPowerOfTwo( image.width ) && isPowerOfTwo( image.height );
24535
24536         }
24537
24538         function textureNeedsPowerOfTwo( texture ) {
24539
24540                 if ( isWebGL2 ) return false;
24541
24542                 return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
24543                         ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
24544
24545         }
24546
24547         function textureNeedsGenerateMipmaps( texture, supportsMips ) {
24548
24549                 return texture.generateMipmaps && supportsMips &&
24550                         texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
24551
24552         }
24553
24554         function generateMipmap( target, texture, width, height, depth = 1 ) {
24555
24556                 _gl.generateMipmap( target );
24557
24558                 const textureProperties = properties.get( texture );
24559
24560                 textureProperties.__maxMipLevel = Math.log2( Math.max( width, height, depth ) );
24561
24562         }
24563
24564         function getInternalFormat( internalFormatName, glFormat, glType, encoding ) {
24565
24566                 if ( isWebGL2 === false ) return glFormat;
24567
24568                 if ( internalFormatName !== null ) {
24569
24570                         if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
24571
24572                         console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
24573
24574                 }
24575
24576                 let internalFormat = glFormat;
24577
24578                 if ( glFormat === 6403 ) {
24579
24580                         if ( glType === 5126 ) internalFormat = 33326;
24581                         if ( glType === 5131 ) internalFormat = 33325;
24582                         if ( glType === 5121 ) internalFormat = 33321;
24583
24584                 }
24585
24586                 if ( glFormat === 6407 ) {
24587
24588                         if ( glType === 5126 ) internalFormat = 34837;
24589                         if ( glType === 5131 ) internalFormat = 34843;
24590                         if ( glType === 5121 ) internalFormat = 32849;
24591
24592                 }
24593
24594                 if ( glFormat === 6408 ) {
24595
24596                         if ( glType === 5126 ) internalFormat = 34836;
24597                         if ( glType === 5131 ) internalFormat = 34842;
24598                         if ( glType === 5121 ) internalFormat = ( encoding === sRGBEncoding ) ? 35907 : 32856;
24599
24600                 }
24601
24602                 if ( internalFormat === 33325 || internalFormat === 33326 ||
24603                         internalFormat === 34842 || internalFormat === 34836 ) {
24604
24605                         extensions.get( 'EXT_color_buffer_float' );
24606
24607                 }
24608
24609                 return internalFormat;
24610
24611         }
24612
24613         // Fallback filters for non-power-of-2 textures
24614
24615         function filterFallback( f ) {
24616
24617                 if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {
24618
24619                         return 9728;
24620
24621                 }
24622
24623                 return 9729;
24624
24625         }
24626
24627         //
24628
24629         function onTextureDispose( event ) {
24630
24631                 const texture = event.target;
24632
24633                 texture.removeEventListener( 'dispose', onTextureDispose );
24634
24635                 deallocateTexture( texture );
24636
24637                 if ( texture.isVideoTexture ) {
24638
24639                         _videoTextures.delete( texture );
24640
24641                 }
24642
24643                 info.memory.textures --;
24644
24645         }
24646
24647         function onRenderTargetDispose( event ) {
24648
24649                 const renderTarget = event.target;
24650
24651                 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
24652
24653                 deallocateRenderTarget( renderTarget );
24654
24655         }
24656
24657         //
24658
24659         function deallocateTexture( texture ) {
24660
24661                 const textureProperties = properties.get( texture );
24662
24663                 if ( textureProperties.__webglInit === undefined ) return;
24664
24665                 _gl.deleteTexture( textureProperties.__webglTexture );
24666
24667                 properties.remove( texture );
24668
24669         }
24670
24671         function deallocateRenderTarget( renderTarget ) {
24672
24673                 const texture = renderTarget.texture;
24674
24675                 const renderTargetProperties = properties.get( renderTarget );
24676                 const textureProperties = properties.get( texture );
24677
24678                 if ( ! renderTarget ) return;
24679
24680                 if ( textureProperties.__webglTexture !== undefined ) {
24681
24682                         _gl.deleteTexture( textureProperties.__webglTexture );
24683
24684                         info.memory.textures --;
24685
24686                 }
24687
24688                 if ( renderTarget.depthTexture ) {
24689
24690                         renderTarget.depthTexture.dispose();
24691
24692                 }
24693
24694                 if ( renderTarget.isWebGLCubeRenderTarget ) {
24695
24696                         for ( let i = 0; i < 6; i ++ ) {
24697
24698                                 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
24699                                 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
24700
24701                         }
24702
24703                 } else {
24704
24705                         _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
24706                         if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
24707                         if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
24708                         if ( renderTargetProperties.__webglColorRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer );
24709                         if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
24710
24711                 }
24712
24713                 if ( renderTarget.isWebGLMultipleRenderTargets ) {
24714
24715                         for ( let i = 0, il = texture.length; i < il; i ++ ) {
24716
24717                                 const attachmentProperties = properties.get( texture[ i ] );
24718
24719                                 if ( attachmentProperties.__webglTexture ) {
24720
24721                                         _gl.deleteTexture( attachmentProperties.__webglTexture );
24722
24723                                         info.memory.textures --;
24724
24725                                 }
24726
24727                                 properties.remove( texture[ i ] );
24728
24729                         }
24730
24731                 }
24732
24733                 properties.remove( texture );
24734                 properties.remove( renderTarget );
24735
24736         }
24737
24738         //
24739
24740         let textureUnits = 0;
24741
24742         function resetTextureUnits() {
24743
24744                 textureUnits = 0;
24745
24746         }
24747
24748         function allocateTextureUnit() {
24749
24750                 const textureUnit = textureUnits;
24751
24752                 if ( textureUnit >= maxTextures ) {
24753
24754                         console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );
24755
24756                 }
24757
24758                 textureUnits += 1;
24759
24760                 return textureUnit;
24761
24762         }
24763
24764         //
24765
24766         function setTexture2D( texture, slot ) {
24767
24768                 const textureProperties = properties.get( texture );
24769
24770                 if ( texture.isVideoTexture ) updateVideoTexture( texture );
24771
24772                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24773
24774                         const image = texture.image;
24775
24776                         if ( image === undefined ) {
24777
24778                                 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );
24779
24780                         } else if ( image.complete === false ) {
24781
24782                                 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
24783
24784                         } else {
24785
24786                                 uploadTexture( textureProperties, texture, slot );
24787                                 return;
24788
24789                         }
24790
24791                 }
24792
24793                 state.activeTexture( 33984 + slot );
24794                 state.bindTexture( 3553, textureProperties.__webglTexture );
24795
24796         }
24797
24798         function setTexture2DArray( texture, slot ) {
24799
24800                 const textureProperties = properties.get( texture );
24801
24802                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24803
24804                         uploadTexture( textureProperties, texture, slot );
24805                         return;
24806
24807                 }
24808
24809                 state.activeTexture( 33984 + slot );
24810                 state.bindTexture( 35866, textureProperties.__webglTexture );
24811
24812         }
24813
24814         function setTexture3D( texture, slot ) {
24815
24816                 const textureProperties = properties.get( texture );
24817
24818                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24819
24820                         uploadTexture( textureProperties, texture, slot );
24821                         return;
24822
24823                 }
24824
24825                 state.activeTexture( 33984 + slot );
24826                 state.bindTexture( 32879, textureProperties.__webglTexture );
24827
24828         }
24829
24830         function setTextureCube( texture, slot ) {
24831
24832                 const textureProperties = properties.get( texture );
24833
24834                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24835
24836                         uploadCubeTexture( textureProperties, texture, slot );
24837                         return;
24838
24839                 }
24840
24841                 state.activeTexture( 33984 + slot );
24842                 state.bindTexture( 34067, textureProperties.__webglTexture );
24843
24844         }
24845
24846         const wrappingToGL = {
24847                 [ RepeatWrapping ]: 10497,
24848                 [ ClampToEdgeWrapping ]: 33071,
24849                 [ MirroredRepeatWrapping ]: 33648
24850         };
24851
24852         const filterToGL = {
24853                 [ NearestFilter ]: 9728,
24854                 [ NearestMipmapNearestFilter ]: 9984,
24855                 [ NearestMipmapLinearFilter ]: 9986,
24856
24857                 [ LinearFilter ]: 9729,
24858                 [ LinearMipmapNearestFilter ]: 9985,
24859                 [ LinearMipmapLinearFilter ]: 9987
24860         };
24861
24862         function setTextureParameters( textureType, texture, supportsMips ) {
24863
24864                 if ( supportsMips ) {
24865
24866                         _gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] );
24867                         _gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] );
24868
24869                         if ( textureType === 32879 || textureType === 35866 ) {
24870
24871                                 _gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] );
24872
24873                         }
24874
24875                         _gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] );
24876                         _gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] );
24877
24878                 } else {
24879
24880                         _gl.texParameteri( textureType, 10242, 33071 );
24881                         _gl.texParameteri( textureType, 10243, 33071 );
24882
24883                         if ( textureType === 32879 || textureType === 35866 ) {
24884
24885                                 _gl.texParameteri( textureType, 32882, 33071 );
24886
24887                         }
24888
24889                         if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
24890
24891                                 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
24892
24893                         }
24894
24895                         _gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );
24896                         _gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );
24897
24898                         if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
24899
24900                                 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
24901
24902                         }
24903
24904                 }
24905
24906                 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) {
24907
24908                         const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
24909
24910                         if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension for WebGL 1 and WebGL 2
24911                         if ( isWebGL2 === false && ( texture.type === HalfFloatType && extensions.has( 'OES_texture_half_float_linear' ) === false ) ) return; // verify extension for WebGL 1 only
24912
24913                         if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
24914
24915                                 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
24916                                 properties.get( texture ).__currentAnisotropy = texture.anisotropy;
24917
24918                         }
24919
24920                 }
24921
24922         }
24923
24924         function initTexture( textureProperties, texture ) {
24925
24926                 if ( textureProperties.__webglInit === undefined ) {
24927
24928                         textureProperties.__webglInit = true;
24929
24930                         texture.addEventListener( 'dispose', onTextureDispose );
24931
24932                         textureProperties.__webglTexture = _gl.createTexture();
24933
24934                         info.memory.textures ++;
24935
24936                 }
24937
24938         }
24939
24940         function uploadTexture( textureProperties, texture, slot ) {
24941
24942                 let textureType = 3553;
24943
24944                 if ( texture.isDataTexture2DArray ) textureType = 35866;
24945                 if ( texture.isDataTexture3D ) textureType = 32879;
24946
24947                 initTexture( textureProperties, texture );
24948
24949                 state.activeTexture( 33984 + slot );
24950                 state.bindTexture( textureType, textureProperties.__webglTexture );
24951
24952                 _gl.pixelStorei( 37440, texture.flipY );
24953                 _gl.pixelStorei( 37441, texture.premultiplyAlpha );
24954                 _gl.pixelStorei( 3317, texture.unpackAlignment );
24955                 _gl.pixelStorei( 37443, 0 );
24956
24957                 const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo$1( texture.image ) === false;
24958                 const image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );
24959
24960                 const supportsMips = isPowerOfTwo$1( image ) || isWebGL2,
24961                         glFormat = utils.convert( texture.format );
24962
24963                 let glType = utils.convert( texture.type ),
24964                         glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
24965
24966                 setTextureParameters( textureType, texture, supportsMips );
24967
24968                 let mipmap;
24969                 const mipmaps = texture.mipmaps;
24970
24971                 if ( texture.isDepthTexture ) {
24972
24973                         // populate depth texture with dummy data
24974
24975                         glInternalFormat = 6402;
24976
24977                         if ( isWebGL2 ) {
24978
24979                                 if ( texture.type === FloatType ) {
24980
24981                                         glInternalFormat = 36012;
24982
24983                                 } else if ( texture.type === UnsignedIntType ) {
24984
24985                                         glInternalFormat = 33190;
24986
24987                                 } else if ( texture.type === UnsignedInt248Type ) {
24988
24989                                         glInternalFormat = 35056;
24990
24991                                 } else {
24992
24993                                         glInternalFormat = 33189; // WebGL2 requires sized internalformat for glTexImage2D
24994
24995                                 }
24996
24997                         } else {
24998
24999                                 if ( texture.type === FloatType ) {
25000
25001                                         console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );
25002
25003                                 }
25004
25005                         }
25006
25007                         // validation checks for WebGL 1
25008
25009                         if ( texture.format === DepthFormat && glInternalFormat === 6402 ) {
25010
25011                                 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
25012                                 // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
25013                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
25014                                 if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
25015
25016                                         console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
25017
25018                                         texture.type = UnsignedShortType;
25019                                         glType = utils.convert( texture.type );
25020
25021                                 }
25022
25023                         }
25024
25025                         if ( texture.format === DepthStencilFormat && glInternalFormat === 6402 ) {
25026
25027                                 // Depth stencil textures need the DEPTH_STENCIL internal format
25028                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
25029                                 glInternalFormat = 34041;
25030
25031                                 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
25032                                 // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
25033                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
25034                                 if ( texture.type !== UnsignedInt248Type ) {
25035
25036                                         console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
25037
25038                                         texture.type = UnsignedInt248Type;
25039                                         glType = utils.convert( texture.type );
25040
25041                                 }
25042
25043                         }
25044
25045                         //
25046
25047                         state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
25048
25049                 } else if ( texture.isDataTexture ) {
25050
25051                         // use manually created mipmaps if available
25052                         // if there are no manual mipmaps
25053                         // set 0 level mipmap and then use GL to generate other mipmap levels
25054
25055                         if ( mipmaps.length > 0 && supportsMips ) {
25056
25057                                 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
25058
25059                                         mipmap = mipmaps[ i ];
25060                                         state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
25061
25062                                 }
25063
25064                                 texture.generateMipmaps = false;
25065                                 textureProperties.__maxMipLevel = mipmaps.length - 1;
25066
25067                         } else {
25068
25069                                 state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
25070                                 textureProperties.__maxMipLevel = 0;
25071
25072                         }
25073
25074                 } else if ( texture.isCompressedTexture ) {
25075
25076                         for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
25077
25078                                 mipmap = mipmaps[ i ];
25079
25080                                 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
25081
25082                                         if ( glFormat !== null ) {
25083
25084                                                 state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
25085
25086                                         } else {
25087
25088                                                 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
25089
25090                                         }
25091
25092                                 } else {
25093
25094                                         state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
25095
25096                                 }
25097
25098                         }
25099
25100                         textureProperties.__maxMipLevel = mipmaps.length - 1;
25101
25102                 } else if ( texture.isDataTexture2DArray ) {
25103
25104                         state.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
25105                         textureProperties.__maxMipLevel = 0;
25106
25107                 } else if ( texture.isDataTexture3D ) {
25108
25109                         state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
25110                         textureProperties.__maxMipLevel = 0;
25111
25112                 } else {
25113
25114                         // regular Texture (image, video, canvas)
25115
25116                         // use manually created mipmaps if available
25117                         // if there are no manual mipmaps
25118                         // set 0 level mipmap and then use GL to generate other mipmap levels
25119
25120                         if ( mipmaps.length > 0 && supportsMips ) {
25121
25122                                 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
25123
25124                                         mipmap = mipmaps[ i ];
25125                                         state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );
25126
25127                                 }
25128
25129                                 texture.generateMipmaps = false;
25130                                 textureProperties.__maxMipLevel = mipmaps.length - 1;
25131
25132                         } else {
25133
25134                                 state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );
25135                                 textureProperties.__maxMipLevel = 0;
25136
25137                         }
25138
25139                 }
25140
25141                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25142
25143                         generateMipmap( textureType, texture, image.width, image.height );
25144
25145                 }
25146
25147                 textureProperties.__version = texture.version;
25148
25149                 if ( texture.onUpdate ) texture.onUpdate( texture );
25150
25151         }
25152
25153         function uploadCubeTexture( textureProperties, texture, slot ) {
25154
25155                 if ( texture.image.length !== 6 ) return;
25156
25157                 initTexture( textureProperties, texture );
25158
25159                 state.activeTexture( 33984 + slot );
25160                 state.bindTexture( 34067, textureProperties.__webglTexture );
25161
25162                 _gl.pixelStorei( 37440, texture.flipY );
25163                 _gl.pixelStorei( 37441, texture.premultiplyAlpha );
25164                 _gl.pixelStorei( 3317, texture.unpackAlignment );
25165                 _gl.pixelStorei( 37443, 0 );
25166
25167                 const isCompressed = ( texture && ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ) );
25168                 const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
25169
25170                 const cubeImage = [];
25171
25172                 for ( let i = 0; i < 6; i ++ ) {
25173
25174                         if ( ! isCompressed && ! isDataTexture ) {
25175
25176                                 cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );
25177
25178                         } else {
25179
25180                                 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
25181
25182                         }
25183
25184                 }
25185
25186                 const image = cubeImage[ 0 ],
25187                         supportsMips = isPowerOfTwo$1( image ) || isWebGL2,
25188                         glFormat = utils.convert( texture.format ),
25189                         glType = utils.convert( texture.type ),
25190                         glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
25191
25192                 setTextureParameters( 34067, texture, supportsMips );
25193
25194                 let mipmaps;
25195
25196                 if ( isCompressed ) {
25197
25198                         for ( let i = 0; i < 6; i ++ ) {
25199
25200                                 mipmaps = cubeImage[ i ].mipmaps;
25201
25202                                 for ( let j = 0; j < mipmaps.length; j ++ ) {
25203
25204                                         const mipmap = mipmaps[ j ];
25205
25206                                         if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
25207
25208                                                 if ( glFormat !== null ) {
25209
25210                                                         state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
25211
25212                                                 } else {
25213
25214                                                         console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
25215
25216                                                 }
25217
25218                                         } else {
25219
25220                                                 state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
25221
25222                                         }
25223
25224                                 }
25225
25226                         }
25227
25228                         textureProperties.__maxMipLevel = mipmaps.length - 1;
25229
25230                 } else {
25231
25232                         mipmaps = texture.mipmaps;
25233
25234                         for ( let i = 0; i < 6; i ++ ) {
25235
25236                                 if ( isDataTexture ) {
25237
25238                                         state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
25239
25240                                         for ( let j = 0; j < mipmaps.length; j ++ ) {
25241
25242                                                 const mipmap = mipmaps[ j ];
25243                                                 const mipmapImage = mipmap.image[ i ].image;
25244
25245                                                 state.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
25246
25247                                         }
25248
25249                                 } else {
25250
25251                                         state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
25252
25253                                         for ( let j = 0; j < mipmaps.length; j ++ ) {
25254
25255                                                 const mipmap = mipmaps[ j ];
25256
25257                                                 state.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
25258
25259                                         }
25260
25261                                 }
25262
25263                         }
25264
25265                         textureProperties.__maxMipLevel = mipmaps.length;
25266
25267                 }
25268
25269                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25270
25271                         // We assume images for cube map have the same size.
25272                         generateMipmap( 34067, texture, image.width, image.height );
25273
25274                 }
25275
25276                 textureProperties.__version = texture.version;
25277
25278                 if ( texture.onUpdate ) texture.onUpdate( texture );
25279
25280         }
25281
25282         // Render targets
25283
25284         // Setup storage for target texture and bind it to correct framebuffer
25285         function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) {
25286
25287                 const glFormat = utils.convert( texture.format );
25288                 const glType = utils.convert( texture.type );
25289                 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
25290
25291                 if ( textureTarget === 32879 || textureTarget === 35866 ) {
25292
25293                         state.texImage3D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null );
25294
25295                 } else {
25296
25297                         state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
25298
25299                 }
25300
25301                 state.bindFramebuffer( 36160, framebuffer );
25302                 _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 );
25303                 state.bindFramebuffer( 36160, null );
25304
25305         }
25306
25307         // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
25308         function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
25309
25310                 _gl.bindRenderbuffer( 36161, renderbuffer );
25311
25312                 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
25313
25314                         let glInternalFormat = 33189;
25315
25316                         if ( isMultisample ) {
25317
25318                                 const depthTexture = renderTarget.depthTexture;
25319
25320                                 if ( depthTexture && depthTexture.isDepthTexture ) {
25321
25322                                         if ( depthTexture.type === FloatType ) {
25323
25324                                                 glInternalFormat = 36012;
25325
25326                                         } else if ( depthTexture.type === UnsignedIntType ) {
25327
25328                                                 glInternalFormat = 33190;
25329
25330                                         }
25331
25332                                 }
25333
25334                                 const samples = getRenderTargetSamples( renderTarget );
25335
25336                                 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25337
25338                         } else {
25339
25340                                 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
25341
25342                         }
25343
25344                         _gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );
25345
25346                 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
25347
25348                         if ( isMultisample ) {
25349
25350                                 const samples = getRenderTargetSamples( renderTarget );
25351
25352                                 _gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height );
25353
25354                         } else {
25355
25356                                 _gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );
25357
25358                         }
25359
25360
25361                         _gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );
25362
25363                 } else {
25364
25365                         // Use the first texture for MRT so far
25366                         const texture = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture[ 0 ] : renderTarget.texture;
25367
25368                         const glFormat = utils.convert( texture.format );
25369                         const glType = utils.convert( texture.type );
25370                         const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
25371
25372                         if ( isMultisample ) {
25373
25374                                 const samples = getRenderTargetSamples( renderTarget );
25375
25376                                 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25377
25378                         } else {
25379
25380                                 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
25381
25382                         }
25383
25384                 }
25385
25386                 _gl.bindRenderbuffer( 36161, null );
25387
25388         }
25389
25390         // Setup resources for a Depth Texture for a FBO (needs an extension)
25391         function setupDepthTexture( framebuffer, renderTarget ) {
25392
25393                 const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
25394                 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
25395
25396                 state.bindFramebuffer( 36160, framebuffer );
25397
25398                 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
25399
25400                         throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
25401
25402                 }
25403
25404                 // upload an empty depth texture with framebuffer size
25405                 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
25406                                 renderTarget.depthTexture.image.width !== renderTarget.width ||
25407                                 renderTarget.depthTexture.image.height !== renderTarget.height ) {
25408
25409                         renderTarget.depthTexture.image.width = renderTarget.width;
25410                         renderTarget.depthTexture.image.height = renderTarget.height;
25411                         renderTarget.depthTexture.needsUpdate = true;
25412
25413                 }
25414
25415                 setTexture2D( renderTarget.depthTexture, 0 );
25416
25417                 const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
25418
25419                 if ( renderTarget.depthTexture.format === DepthFormat ) {
25420
25421                         _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );
25422
25423                 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
25424
25425                         _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );
25426
25427                 } else {
25428
25429                         throw new Error( 'Unknown depthTexture format' );
25430
25431                 }
25432
25433         }
25434
25435         // Setup GL resources for a non-texture depth buffer
25436         function setupDepthRenderbuffer( renderTarget ) {
25437
25438                 const renderTargetProperties = properties.get( renderTarget );
25439
25440                 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25441
25442                 if ( renderTarget.depthTexture ) {
25443
25444                         if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
25445
25446                         setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
25447
25448                 } else {
25449
25450                         if ( isCube ) {
25451
25452                                 renderTargetProperties.__webglDepthbuffer = [];
25453
25454                                 for ( let i = 0; i < 6; i ++ ) {
25455
25456                                         state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );
25457                                         renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
25458                                         setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );
25459
25460                                 }
25461
25462                         } else {
25463
25464                                 state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
25465                                 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
25466                                 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );
25467
25468                         }
25469
25470                 }
25471
25472                 state.bindFramebuffer( 36160, null );
25473
25474         }
25475
25476         // Set up GL resources for the render target
25477         function setupRenderTarget( renderTarget ) {
25478
25479                 const texture = renderTarget.texture;
25480
25481                 const renderTargetProperties = properties.get( renderTarget );
25482                 const textureProperties = properties.get( texture );
25483
25484                 renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
25485
25486                 if ( renderTarget.isWebGLMultipleRenderTargets !== true ) {
25487
25488                         textureProperties.__webglTexture = _gl.createTexture();
25489                         textureProperties.__version = texture.version;
25490                         info.memory.textures ++;
25491
25492                 }
25493
25494                 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25495                 const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true );
25496                 const isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );
25497                 const isRenderTarget3D = texture.isDataTexture3D || texture.isDataTexture2DArray;
25498                 const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2;
25499
25500                 // Handles WebGL2 RGBFormat fallback - #18858
25501
25502                 if ( isWebGL2 && texture.format === RGBFormat && ( texture.type === FloatType || texture.type === HalfFloatType ) ) {
25503
25504                         texture.format = RGBAFormat;
25505
25506                         console.warn( 'THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.' );
25507
25508                 }
25509
25510                 // Setup framebuffer
25511
25512                 if ( isCube ) {
25513
25514                         renderTargetProperties.__webglFramebuffer = [];
25515
25516                         for ( let i = 0; i < 6; i ++ ) {
25517
25518                                 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
25519
25520                         }
25521
25522                 } else {
25523
25524                         renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
25525
25526                         if ( isMultipleRenderTargets ) {
25527
25528                                 if ( capabilities.drawBuffers ) {
25529
25530                                         const textures = renderTarget.texture;
25531
25532                                         for ( let i = 0, il = textures.length; i < il; i ++ ) {
25533
25534                                                 const attachmentProperties = properties.get( textures[ i ] );
25535
25536                                                 if ( attachmentProperties.__webglTexture === undefined ) {
25537
25538                                                         attachmentProperties.__webglTexture = _gl.createTexture();
25539
25540                                                         info.memory.textures ++;
25541
25542                                                 }
25543
25544                                         }
25545
25546                                 } else {
25547
25548                                         console.warn( 'THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.' );
25549
25550                                 }
25551
25552                         } else if ( isMultisample ) {
25553
25554                                 if ( isWebGL2 ) {
25555
25556                                         renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
25557                                         renderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();
25558
25559                                         _gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer );
25560
25561                                         const glFormat = utils.convert( texture.format );
25562                                         const glType = utils.convert( texture.type );
25563                                         const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
25564                                         const samples = getRenderTargetSamples( renderTarget );
25565                                         _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25566
25567                                         state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
25568                                         _gl.framebufferRenderbuffer( 36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer );
25569                                         _gl.bindRenderbuffer( 36161, null );
25570
25571                                         if ( renderTarget.depthBuffer ) {
25572
25573                                                 renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
25574                                                 setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
25575
25576                                         }
25577
25578                                         state.bindFramebuffer( 36160, null );
25579
25580
25581                                 } else {
25582
25583                                         console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
25584
25585                                 }
25586
25587                         }
25588
25589                 }
25590
25591                 // Setup color buffer
25592
25593                 if ( isCube ) {
25594
25595                         state.bindTexture( 34067, textureProperties.__webglTexture );
25596                         setTextureParameters( 34067, texture, supportsMips );
25597
25598                         for ( let i = 0; i < 6; i ++ ) {
25599
25600                                 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, 36064, 34069 + i );
25601
25602                         }
25603
25604                         if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25605
25606                                 generateMipmap( 34067, texture, renderTarget.width, renderTarget.height );
25607
25608                         }
25609
25610                         state.unbindTexture();
25611
25612                 } else if ( isMultipleRenderTargets ) {
25613
25614                         const textures = renderTarget.texture;
25615
25616                         for ( let i = 0, il = textures.length; i < il; i ++ ) {
25617
25618                                 const attachment = textures[ i ];
25619                                 const attachmentProperties = properties.get( attachment );
25620
25621                                 state.bindTexture( 3553, attachmentProperties.__webglTexture );
25622                                 setTextureParameters( 3553, attachment, supportsMips );
25623                                 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, 36064 + i, 3553 );
25624
25625                                 if ( textureNeedsGenerateMipmaps( attachment, supportsMips ) ) {
25626
25627                                         generateMipmap( 3553, attachment, renderTarget.width, renderTarget.height );
25628
25629                                 }
25630
25631                         }
25632
25633                         state.unbindTexture();
25634
25635                 } else {
25636
25637                         let glTextureType = 3553;
25638
25639                         if ( isRenderTarget3D ) {
25640
25641                                 // Render targets containing layers, i.e: Texture 3D and 2d arrays
25642
25643                                 if ( isWebGL2 ) {
25644
25645                                         const isTexture3D = texture.isDataTexture3D;
25646                                         glTextureType = isTexture3D ? 32879 : 35866;
25647
25648                                 } else {
25649
25650                                         console.warn( 'THREE.DataTexture3D and THREE.DataTexture2DArray only supported with WebGL2.' );
25651
25652                                 }
25653
25654                         }
25655
25656                         state.bindTexture( glTextureType, textureProperties.__webglTexture );
25657                         setTextureParameters( glTextureType, texture, supportsMips );
25658                         setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, 36064, glTextureType );
25659
25660                         if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25661
25662                                 generateMipmap( glTextureType, texture, renderTarget.width, renderTarget.height, renderTarget.depth );
25663
25664                         }
25665
25666                         state.unbindTexture();
25667
25668                 }
25669
25670                 // Setup depth and stencil buffers
25671
25672                 if ( renderTarget.depthBuffer ) {
25673
25674                         setupDepthRenderbuffer( renderTarget );
25675
25676                 }
25677
25678         }
25679
25680         function updateRenderTargetMipmap( renderTarget ) {
25681
25682                 const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2;
25683
25684                 const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [ renderTarget.texture ];
25685
25686                 for ( let i = 0, il = textures.length; i < il; i ++ ) {
25687
25688                         const texture = textures[ i ];
25689
25690                         if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25691
25692                                 const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553;
25693                                 const webglTexture = properties.get( texture ).__webglTexture;
25694
25695                                 state.bindTexture( target, webglTexture );
25696                                 generateMipmap( target, texture, renderTarget.width, renderTarget.height );
25697                                 state.unbindTexture();
25698
25699                         }
25700
25701                 }
25702
25703         }
25704
25705         function updateMultisampleRenderTarget( renderTarget ) {
25706
25707                 if ( renderTarget.isWebGLMultisampleRenderTarget ) {
25708
25709                         if ( isWebGL2 ) {
25710
25711                                 const width = renderTarget.width;
25712                                 const height = renderTarget.height;
25713                                 let mask = 16384;
25714
25715                                 if ( renderTarget.depthBuffer ) mask |= 256;
25716                                 if ( renderTarget.stencilBuffer ) mask |= 1024;
25717
25718                                 const renderTargetProperties = properties.get( renderTarget );
25719
25720                                 state.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );
25721                                 state.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );
25722
25723                                 _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );
25724
25725                                 state.bindFramebuffer( 36008, null );
25726                                 state.bindFramebuffer( 36009, renderTargetProperties.__webglMultisampledFramebuffer );
25727
25728                         } else {
25729
25730                                 console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
25731
25732                         }
25733
25734                 }
25735
25736         }
25737
25738         function getRenderTargetSamples( renderTarget ) {
25739
25740                 return ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?
25741                         Math.min( maxSamples, renderTarget.samples ) : 0;
25742
25743         }
25744
25745         function updateVideoTexture( texture ) {
25746
25747                 const frame = info.render.frame;
25748
25749                 // Check the last frame we updated the VideoTexture
25750
25751                 if ( _videoTextures.get( texture ) !== frame ) {
25752
25753                         _videoTextures.set( texture, frame );
25754                         texture.update();
25755
25756                 }
25757
25758         }
25759
25760         // backwards compatibility
25761
25762         let warnedTexture2D = false;
25763         let warnedTextureCube = false;
25764
25765         function safeSetTexture2D( texture, slot ) {
25766
25767                 if ( texture && texture.isWebGLRenderTarget ) {
25768
25769                         if ( warnedTexture2D === false ) {
25770
25771                                 console.warn( 'THREE.WebGLTextures.safeSetTexture2D: don\'t use render targets as textures. Use their .texture property instead.' );
25772                                 warnedTexture2D = true;
25773
25774                         }
25775
25776                         texture = texture.texture;
25777
25778                 }
25779
25780                 setTexture2D( texture, slot );
25781
25782         }
25783
25784         function safeSetTextureCube( texture, slot ) {
25785
25786                 if ( texture && texture.isWebGLCubeRenderTarget ) {
25787
25788                         if ( warnedTextureCube === false ) {
25789
25790                                 console.warn( 'THREE.WebGLTextures.safeSetTextureCube: don\'t use cube render targets as textures. Use their .texture property instead.' );
25791                                 warnedTextureCube = true;
25792
25793                         }
25794
25795                         texture = texture.texture;
25796
25797                 }
25798
25799
25800                 setTextureCube( texture, slot );
25801
25802         }
25803
25804         //
25805
25806         this.allocateTextureUnit = allocateTextureUnit;
25807         this.resetTextureUnits = resetTextureUnits;
25808
25809         this.setTexture2D = setTexture2D;
25810         this.setTexture2DArray = setTexture2DArray;
25811         this.setTexture3D = setTexture3D;
25812         this.setTextureCube = setTextureCube;
25813         this.setupRenderTarget = setupRenderTarget;
25814         this.updateRenderTargetMipmap = updateRenderTargetMipmap;
25815         this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
25816
25817         this.safeSetTexture2D = safeSetTexture2D;
25818         this.safeSetTextureCube = safeSetTextureCube;
25819
25820     }
25821
25822     function WebGLUtils( gl, extensions, capabilities ) {
25823
25824         const isWebGL2 = capabilities.isWebGL2;
25825
25826         function convert( p ) {
25827
25828                 let extension;
25829
25830                 if ( p === UnsignedByteType ) return 5121;
25831                 if ( p === UnsignedShort4444Type ) return 32819;
25832                 if ( p === UnsignedShort5551Type ) return 32820;
25833                 if ( p === UnsignedShort565Type ) return 33635;
25834
25835                 if ( p === ByteType ) return 5120;
25836                 if ( p === ShortType ) return 5122;
25837                 if ( p === UnsignedShortType ) return 5123;
25838                 if ( p === IntType ) return 5124;
25839                 if ( p === UnsignedIntType ) return 5125;
25840                 if ( p === FloatType ) return 5126;
25841
25842                 if ( p === HalfFloatType ) {
25843
25844                         if ( isWebGL2 ) return 5131;
25845
25846                         extension = extensions.get( 'OES_texture_half_float' );
25847
25848                         if ( extension !== null ) {
25849
25850                                 return extension.HALF_FLOAT_OES;
25851
25852                         } else {
25853
25854                                 return null;
25855
25856                         }
25857
25858                 }
25859
25860                 if ( p === AlphaFormat ) return 6406;
25861                 if ( p === RGBFormat ) return 6407;
25862                 if ( p === RGBAFormat ) return 6408;
25863                 if ( p === LuminanceFormat ) return 6409;
25864                 if ( p === LuminanceAlphaFormat ) return 6410;
25865                 if ( p === DepthFormat ) return 6402;
25866                 if ( p === DepthStencilFormat ) return 34041;
25867                 if ( p === RedFormat ) return 6403;
25868
25869                 // WebGL2 formats.
25870
25871                 if ( p === RedIntegerFormat ) return 36244;
25872                 if ( p === RGFormat ) return 33319;
25873                 if ( p === RGIntegerFormat ) return 33320;
25874                 if ( p === RGBIntegerFormat ) return 36248;
25875                 if ( p === RGBAIntegerFormat ) return 36249;
25876
25877                 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
25878                         p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
25879
25880                         extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
25881
25882                         if ( extension !== null ) {
25883
25884                                 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
25885                                 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
25886                                 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
25887                                 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
25888
25889                         } else {
25890
25891                                 return null;
25892
25893                         }
25894
25895                 }
25896
25897                 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
25898                         p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
25899
25900                         extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
25901
25902                         if ( extension !== null ) {
25903
25904                                 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
25905                                 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
25906                                 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
25907                                 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
25908
25909                         } else {
25910
25911                                 return null;
25912
25913                         }
25914
25915                 }
25916
25917                 if ( p === RGB_ETC1_Format ) {
25918
25919                         extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
25920
25921                         if ( extension !== null ) {
25922
25923                                 return extension.COMPRESSED_RGB_ETC1_WEBGL;
25924
25925                         } else {
25926
25927                                 return null;
25928
25929                         }
25930
25931                 }
25932
25933                 if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {
25934
25935                         extension = extensions.get( 'WEBGL_compressed_texture_etc' );
25936
25937                         if ( extension !== null ) {
25938
25939                                 if ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2;
25940                                 if ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC;
25941
25942                         }
25943
25944                 }
25945
25946                 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
25947                         p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
25948                         p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
25949                         p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
25950                         p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ||
25951                         p === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format ||
25952                         p === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format ||
25953                         p === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format ||
25954                         p === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format ||
25955                         p === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) {
25956
25957                         extension = extensions.get( 'WEBGL_compressed_texture_astc' );
25958
25959                         if ( extension !== null ) {
25960
25961                                 // TODO Complete?
25962
25963                                 return p;
25964
25965                         } else {
25966
25967                                 return null;
25968
25969                         }
25970
25971                 }
25972
25973                 if ( p === RGBA_BPTC_Format ) {
25974
25975                         extension = extensions.get( 'EXT_texture_compression_bptc' );
25976
25977                         if ( extension !== null ) {
25978
25979                                 // TODO Complete?
25980
25981                                 return p;
25982
25983                         } else {
25984
25985                                 return null;
25986
25987                         }
25988
25989                 }
25990
25991                 if ( p === UnsignedInt248Type ) {
25992
25993                         if ( isWebGL2 ) return 34042;
25994
25995                         extension = extensions.get( 'WEBGL_depth_texture' );
25996
25997                         if ( extension !== null ) {
25998
25999                                 return extension.UNSIGNED_INT_24_8_WEBGL;
26000
26001                         } else {
26002
26003                                 return null;
26004
26005                         }
26006
26007                 }
26008
26009         }
26010
26011         return { convert: convert };
26012
26013     }
26014
26015     class ArrayCamera extends PerspectiveCamera {
26016
26017         constructor( array = [] ) {
26018
26019                 super();
26020
26021                 this.cameras = array;
26022
26023         }
26024
26025     }
26026
26027     ArrayCamera.prototype.isArrayCamera = true;
26028
26029     class Group extends Object3D {
26030
26031         constructor() {
26032
26033                 super();
26034
26035                 this.type = 'Group';
26036
26037         }
26038
26039     }
26040
26041     Group.prototype.isGroup = true;
26042
26043     const _moveEvent = { type: 'move' };
26044
26045     class WebXRController {
26046
26047         constructor() {
26048
26049                 this._targetRay = null;
26050                 this._grip = null;
26051                 this._hand = null;
26052
26053         }
26054
26055         getHandSpace() {
26056
26057                 if ( this._hand === null ) {
26058
26059                         this._hand = new Group();
26060                         this._hand.matrixAutoUpdate = false;
26061                         this._hand.visible = false;
26062
26063                         this._hand.joints = {};
26064                         this._hand.inputState = { pinching: false };
26065
26066                 }
26067
26068                 return this._hand;
26069
26070         }
26071
26072         getTargetRaySpace() {
26073
26074                 if ( this._targetRay === null ) {
26075
26076                         this._targetRay = new Group();
26077                         this._targetRay.matrixAutoUpdate = false;
26078                         this._targetRay.visible = false;
26079                         this._targetRay.hasLinearVelocity = false;
26080                         this._targetRay.linearVelocity = new Vector3();
26081                         this._targetRay.hasAngularVelocity = false;
26082                         this._targetRay.angularVelocity = new Vector3();
26083
26084                 }
26085
26086                 return this._targetRay;
26087
26088         }
26089
26090         getGripSpace() {
26091
26092                 if ( this._grip === null ) {
26093
26094                         this._grip = new Group();
26095                         this._grip.matrixAutoUpdate = false;
26096                         this._grip.visible = false;
26097                         this._grip.hasLinearVelocity = false;
26098                         this._grip.linearVelocity = new Vector3();
26099                         this._grip.hasAngularVelocity = false;
26100                         this._grip.angularVelocity = new Vector3();
26101
26102                 }
26103
26104                 return this._grip;
26105
26106         }
26107
26108         dispatchEvent( event ) {
26109
26110                 if ( this._targetRay !== null ) {
26111
26112                         this._targetRay.dispatchEvent( event );
26113
26114                 }
26115
26116                 if ( this._grip !== null ) {
26117
26118                         this._grip.dispatchEvent( event );
26119
26120                 }
26121
26122                 if ( this._hand !== null ) {
26123
26124                         this._hand.dispatchEvent( event );
26125
26126                 }
26127
26128                 return this;
26129
26130         }
26131
26132         disconnect( inputSource ) {
26133
26134                 this.dispatchEvent( { type: 'disconnected', data: inputSource } );
26135
26136                 if ( this._targetRay !== null ) {
26137
26138                         this._targetRay.visible = false;
26139
26140                 }
26141
26142                 if ( this._grip !== null ) {
26143
26144                         this._grip.visible = false;
26145
26146                 }
26147
26148                 if ( this._hand !== null ) {
26149
26150                         this._hand.visible = false;
26151
26152                 }
26153
26154                 return this;
26155
26156         }
26157
26158         update( inputSource, frame, referenceSpace ) {
26159
26160                 let inputPose = null;
26161                 let gripPose = null;
26162                 let handPose = null;
26163
26164                 const targetRay = this._targetRay;
26165                 const grip = this._grip;
26166                 const hand = this._hand;
26167
26168                 if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
26169
26170                         if ( targetRay !== null ) {
26171
26172                                 inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
26173
26174                                 if ( inputPose !== null ) {
26175
26176                                         targetRay.matrix.fromArray( inputPose.transform.matrix );
26177                                         targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
26178
26179                                         if ( inputPose.linearVelocity ) {
26180
26181                                                 targetRay.hasLinearVelocity = true;
26182                                                 targetRay.linearVelocity.copy( inputPose.linearVelocity );
26183
26184                                         } else {
26185
26186                                                 targetRay.hasLinearVelocity = false;
26187
26188                                         }
26189
26190                                         if ( inputPose.angularVelocity ) {
26191
26192                                                 targetRay.hasAngularVelocity = true;
26193                                                 targetRay.angularVelocity.copy( inputPose.angularVelocity );
26194
26195                                         } else {
26196
26197                                                 targetRay.hasAngularVelocity = false;
26198
26199                                         }
26200
26201                                         this.dispatchEvent( _moveEvent );
26202
26203                                 }
26204
26205                         }
26206
26207                         if ( hand && inputSource.hand ) {
26208
26209                                 handPose = true;
26210
26211                                 for ( const inputjoint of inputSource.hand.values() ) {
26212
26213                                         // Update the joints groups with the XRJoint poses
26214                                         const jointPose = frame.getJointPose( inputjoint, referenceSpace );
26215
26216                                         if ( hand.joints[ inputjoint.jointName ] === undefined ) {
26217
26218                                                 // The transform of this joint will be updated with the joint pose on each frame
26219                                                 const joint = new Group();
26220                                                 joint.matrixAutoUpdate = false;
26221                                                 joint.visible = false;
26222                                                 hand.joints[ inputjoint.jointName ] = joint;
26223                                                 // ??
26224                                                 hand.add( joint );
26225
26226                                         }
26227
26228                                         const joint = hand.joints[ inputjoint.jointName ];
26229
26230                                         if ( jointPose !== null ) {
26231
26232                                                 joint.matrix.fromArray( jointPose.transform.matrix );
26233                                                 joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
26234                                                 joint.jointRadius = jointPose.radius;
26235
26236                                         }
26237
26238                                         joint.visible = jointPose !== null;
26239
26240                                 }
26241
26242                                 // Custom events
26243
26244                                 // Check pinchz
26245                                 const indexTip = hand.joints[ 'index-finger-tip' ];
26246                                 const thumbTip = hand.joints[ 'thumb-tip' ];
26247                                 const distance = indexTip.position.distanceTo( thumbTip.position );
26248
26249                                 const distanceToPinch = 0.02;
26250                                 const threshold = 0.005;
26251
26252                                 if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
26253
26254                                         hand.inputState.pinching = false;
26255                                         this.dispatchEvent( {
26256                                                 type: 'pinchend',
26257                                                 handedness: inputSource.handedness,
26258                                                 target: this
26259                                         } );
26260
26261                                 } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
26262
26263                                         hand.inputState.pinching = true;
26264                                         this.dispatchEvent( {
26265                                                 type: 'pinchstart',
26266                                                 handedness: inputSource.handedness,
26267                                                 target: this
26268                                         } );
26269
26270                                 }
26271
26272                         } else {
26273
26274                                 if ( grip !== null && inputSource.gripSpace ) {
26275
26276                                         gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
26277
26278                                         if ( gripPose !== null ) {
26279
26280                                                 grip.matrix.fromArray( gripPose.transform.matrix );
26281                                                 grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
26282
26283                                                 if ( gripPose.linearVelocity ) {
26284
26285                                                         grip.hasLinearVelocity = true;
26286                                                         grip.linearVelocity.copy( gripPose.linearVelocity );
26287
26288                                                 } else {
26289
26290                                                         grip.hasLinearVelocity = false;
26291
26292                                                 }
26293
26294                                                 if ( gripPose.angularVelocity ) {
26295
26296                                                         grip.hasAngularVelocity = true;
26297                                                         grip.angularVelocity.copy( gripPose.angularVelocity );
26298
26299                                                 } else {
26300
26301                                                         grip.hasAngularVelocity = false;
26302
26303                                                 }
26304
26305                                         }
26306
26307                                 }
26308
26309                         }
26310
26311                 }
26312
26313                 if ( targetRay !== null ) {
26314
26315                         targetRay.visible = ( inputPose !== null );
26316
26317                 }
26318
26319                 if ( grip !== null ) {
26320
26321                         grip.visible = ( gripPose !== null );
26322
26323                 }
26324
26325                 if ( hand !== null ) {
26326
26327                         hand.visible = ( handPose !== null );
26328
26329                 }
26330
26331                 return this;
26332
26333         }
26334
26335     }
26336
26337     class WebXRManager extends EventDispatcher {
26338
26339         constructor( renderer, gl ) {
26340
26341                 super();
26342
26343                 const scope = this;
26344                 const state = renderer.state;
26345
26346                 let session = null;
26347                 let framebufferScaleFactor = 1.0;
26348
26349                 let referenceSpace = null;
26350                 let referenceSpaceType = 'local-floor';
26351
26352                 let pose = null;
26353                 let glBinding = null;
26354                 let glFramebuffer = null;
26355                 let glProjLayer = null;
26356                 let glBaseLayer = null;
26357                 let isMultisample = false;
26358                 let glMultisampledFramebuffer = null;
26359                 let glColorRenderbuffer = null;
26360                 let glDepthRenderbuffer = null;
26361                 let xrFrame = null;
26362                 let depthStyle = null;
26363                 let clearStyle = null;
26364
26365                 const controllers = [];
26366                 const inputSourcesMap = new Map();
26367
26368                 //
26369
26370                 const cameraL = new PerspectiveCamera();
26371                 cameraL.layers.enable( 1 );
26372                 cameraL.viewport = new Vector4();
26373
26374                 const cameraR = new PerspectiveCamera();
26375                 cameraR.layers.enable( 2 );
26376                 cameraR.viewport = new Vector4();
26377
26378                 const cameras = [ cameraL, cameraR ];
26379
26380                 const cameraVR = new ArrayCamera();
26381                 cameraVR.layers.enable( 1 );
26382                 cameraVR.layers.enable( 2 );
26383
26384                 let _currentDepthNear = null;
26385                 let _currentDepthFar = null;
26386
26387                 //
26388
26389                 this.cameraAutoUpdate = true;
26390                 this.enabled = false;
26391
26392                 this.isPresenting = false;
26393
26394                 this.getController = function ( index ) {
26395
26396                         let controller = controllers[ index ];
26397
26398                         if ( controller === undefined ) {
26399
26400                                 controller = new WebXRController();
26401                                 controllers[ index ] = controller;
26402
26403                         }
26404
26405                         return controller.getTargetRaySpace();
26406
26407                 };
26408
26409                 this.getControllerGrip = function ( index ) {
26410
26411                         let controller = controllers[ index ];
26412
26413                         if ( controller === undefined ) {
26414
26415                                 controller = new WebXRController();
26416                                 controllers[ index ] = controller;
26417
26418                         }
26419
26420                         return controller.getGripSpace();
26421
26422                 };
26423
26424                 this.getHand = function ( index ) {
26425
26426                         let controller = controllers[ index ];
26427
26428                         if ( controller === undefined ) {
26429
26430                                 controller = new WebXRController();
26431                                 controllers[ index ] = controller;
26432
26433                         }
26434
26435                         return controller.getHandSpace();
26436
26437                 };
26438
26439                 //
26440
26441                 function onSessionEvent( event ) {
26442
26443                         const controller = inputSourcesMap.get( event.inputSource );
26444
26445                         if ( controller ) {
26446
26447                                 controller.dispatchEvent( { type: event.type, data: event.inputSource } );
26448
26449                         }
26450
26451                 }
26452
26453                 function onSessionEnd() {
26454
26455                         inputSourcesMap.forEach( function ( controller, inputSource ) {
26456
26457                                 controller.disconnect( inputSource );
26458
26459                         } );
26460
26461                         inputSourcesMap.clear();
26462
26463                         _currentDepthNear = null;
26464                         _currentDepthFar = null;
26465
26466                         // restore framebuffer/rendering state
26467
26468                         state.bindXRFramebuffer( null );
26469                         renderer.setRenderTarget( renderer.getRenderTarget() );
26470
26471                         if ( glFramebuffer ) gl.deleteFramebuffer( glFramebuffer );
26472                         if ( glMultisampledFramebuffer ) gl.deleteFramebuffer( glMultisampledFramebuffer );
26473                         if ( glColorRenderbuffer ) gl.deleteRenderbuffer( glColorRenderbuffer );
26474                         if ( glDepthRenderbuffer ) gl.deleteRenderbuffer( glDepthRenderbuffer );
26475                         glFramebuffer = null;
26476                         glMultisampledFramebuffer = null;
26477                         glColorRenderbuffer = null;
26478                         glDepthRenderbuffer = null;
26479                         glBaseLayer = null;
26480                         glProjLayer = null;
26481                         glBinding = null;
26482                         session = null;
26483
26484                         //
26485
26486                         animation.stop();
26487
26488                         scope.isPresenting = false;
26489
26490                         scope.dispatchEvent( { type: 'sessionend' } );
26491
26492                 }
26493
26494                 this.setFramebufferScaleFactor = function ( value ) {
26495
26496                         framebufferScaleFactor = value;
26497
26498                         if ( scope.isPresenting === true ) {
26499
26500                                 console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
26501
26502                         }
26503
26504                 };
26505
26506                 this.setReferenceSpaceType = function ( value ) {
26507
26508                         referenceSpaceType = value;
26509
26510                         if ( scope.isPresenting === true ) {
26511
26512                                 console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
26513
26514                         }
26515
26516                 };
26517
26518                 this.getReferenceSpace = function () {
26519
26520                         return referenceSpace;
26521
26522                 };
26523
26524                 this.getBaseLayer = function () {
26525
26526                         return glProjLayer !== null ? glProjLayer : glBaseLayer;
26527
26528                 };
26529
26530                 this.getBinding = function () {
26531
26532                         return glBinding;
26533
26534                 };
26535
26536                 this.getFrame = function () {
26537
26538                         return xrFrame;
26539
26540                 };
26541
26542                 this.getSession = function () {
26543
26544                         return session;
26545
26546                 };
26547
26548                 this.setSession = async function ( value ) {
26549
26550                         session = value;
26551
26552                         if ( session !== null ) {
26553
26554                                 session.addEventListener( 'select', onSessionEvent );
26555                                 session.addEventListener( 'selectstart', onSessionEvent );
26556                                 session.addEventListener( 'selectend', onSessionEvent );
26557                                 session.addEventListener( 'squeeze', onSessionEvent );
26558                                 session.addEventListener( 'squeezestart', onSessionEvent );
26559                                 session.addEventListener( 'squeezeend', onSessionEvent );
26560                                 session.addEventListener( 'end', onSessionEnd );
26561                                 session.addEventListener( 'inputsourceschange', onInputSourcesChange );
26562
26563                                 const attributes = gl.getContextAttributes();
26564
26565                                 if ( attributes.xrCompatible !== true ) {
26566
26567                                         await gl.makeXRCompatible();
26568
26569                                 }
26570
26571                                 if ( session.renderState.layers === undefined ) {
26572
26573                                         const layerInit = {
26574                                                 antialias: attributes.antialias,
26575                                                 alpha: attributes.alpha,
26576                                                 depth: attributes.depth,
26577                                                 stencil: attributes.stencil,
26578                                                 framebufferScaleFactor: framebufferScaleFactor
26579                                         };
26580
26581                                         glBaseLayer = new XRWebGLLayer( session, gl, layerInit );
26582
26583                                         session.updateRenderState( { baseLayer: glBaseLayer } );
26584
26585                                 } else if ( gl instanceof WebGLRenderingContext ) {
26586
26587                                         // Use old style webgl layer because we can't use MSAA
26588                                         // WebGL2 support.
26589
26590                                         const layerInit = {
26591                                                 antialias: true,
26592                                                 alpha: attributes.alpha,
26593                                                 depth: attributes.depth,
26594                                                 stencil: attributes.stencil,
26595                                                 framebufferScaleFactor: framebufferScaleFactor
26596                                         };
26597
26598                                         glBaseLayer = new XRWebGLLayer( session, gl, layerInit );
26599
26600                                         session.updateRenderState( { layers: [ glBaseLayer ] } );
26601
26602                                 } else {
26603
26604                                         isMultisample = attributes.antialias;
26605                                         let depthFormat = null;
26606
26607
26608                                         if ( attributes.depth ) {
26609
26610                                                 clearStyle = 256;
26611
26612                                                 if ( attributes.stencil ) clearStyle |= 1024;
26613
26614                                                 depthStyle = attributes.stencil ? 33306 : 36096;
26615                                                 depthFormat = attributes.stencil ? 35056 : 33190;
26616
26617                                         }
26618
26619                                         const projectionlayerInit = {
26620                                                 colorFormat: attributes.alpha ? 32856 : 32849,
26621                                                 depthFormat: depthFormat,
26622                                                 scaleFactor: framebufferScaleFactor
26623                                         };
26624
26625                                         glBinding = new XRWebGLBinding( session, gl );
26626
26627                                         glProjLayer = glBinding.createProjectionLayer( projectionlayerInit );
26628
26629                                         glFramebuffer = gl.createFramebuffer();
26630
26631                                         session.updateRenderState( { layers: [ glProjLayer ] } );
26632
26633                                         if ( isMultisample ) {
26634
26635                                                 glMultisampledFramebuffer = gl.createFramebuffer();
26636                                                 glColorRenderbuffer = gl.createRenderbuffer();
26637                                                 gl.bindRenderbuffer( 36161, glColorRenderbuffer );
26638                                                 gl.renderbufferStorageMultisample(
26639                                                         36161,
26640                                                         4,
26641                                                         32856,
26642                                                         glProjLayer.textureWidth,
26643                                                         glProjLayer.textureHeight );
26644                                                 state.bindFramebuffer( 36160, glMultisampledFramebuffer );
26645                                                 gl.framebufferRenderbuffer( 36160, 36064, 36161, glColorRenderbuffer );
26646                                                 gl.bindRenderbuffer( 36161, null );
26647
26648                                                 if ( depthFormat !== null ) {
26649
26650                                                         glDepthRenderbuffer = gl.createRenderbuffer();
26651                                                         gl.bindRenderbuffer( 36161, glDepthRenderbuffer );
26652                                                         gl.renderbufferStorageMultisample( 36161, 4, depthFormat, glProjLayer.textureWidth, glProjLayer.textureHeight );
26653                                                         gl.framebufferRenderbuffer( 36160, depthStyle, 36161, glDepthRenderbuffer );
26654                                                         gl.bindRenderbuffer( 36161, null );
26655
26656                                                 }
26657
26658                                                 state.bindFramebuffer( 36160, null );
26659
26660                                         }
26661
26662                                 }
26663
26664                                 referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
26665
26666                                 animation.setContext( session );
26667                                 animation.start();
26668
26669                                 scope.isPresenting = true;
26670
26671                                 scope.dispatchEvent( { type: 'sessionstart' } );
26672
26673                         }
26674
26675                 };
26676
26677                 function onInputSourcesChange( event ) {
26678
26679                         const inputSources = session.inputSources;
26680
26681                         // Assign inputSources to available controllers
26682
26683                         for ( let i = 0; i < controllers.length; i ++ ) {
26684
26685                                 inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
26686
26687                         }
26688
26689                         // Notify disconnected
26690
26691                         for ( let i = 0; i < event.removed.length; i ++ ) {
26692
26693                                 const inputSource = event.removed[ i ];
26694                                 const controller = inputSourcesMap.get( inputSource );
26695
26696                                 if ( controller ) {
26697
26698                                         controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
26699                                         inputSourcesMap.delete( inputSource );
26700
26701                                 }
26702
26703                         }
26704
26705                         // Notify connected
26706
26707                         for ( let i = 0; i < event.added.length; i ++ ) {
26708
26709                                 const inputSource = event.added[ i ];
26710                                 const controller = inputSourcesMap.get( inputSource );
26711
26712                                 if ( controller ) {
26713
26714                                         controller.dispatchEvent( { type: 'connected', data: inputSource } );
26715
26716                                 }
26717
26718                         }
26719
26720                 }
26721
26722                 //
26723
26724                 const cameraLPos = new Vector3();
26725                 const cameraRPos = new Vector3();
26726
26727                 /**
26728                  * Assumes 2 cameras that are parallel and share an X-axis, and that
26729                  * the cameras' projection and world matrices have already been set.
26730                  * And that near and far planes are identical for both cameras.
26731                  * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
26732                  */
26733                 function setProjectionFromUnion( camera, cameraL, cameraR ) {
26734
26735                         cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
26736                         cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
26737
26738                         const ipd = cameraLPos.distanceTo( cameraRPos );
26739
26740                         const projL = cameraL.projectionMatrix.elements;
26741                         const projR = cameraR.projectionMatrix.elements;
26742
26743                         // VR systems will have identical far and near planes, and
26744                         // most likely identical top and bottom frustum extents.
26745                         // Use the left camera for these values.
26746                         const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
26747                         const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
26748                         const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
26749                         const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
26750
26751                         const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
26752                         const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
26753                         const left = near * leftFov;
26754                         const right = near * rightFov;
26755
26756                         // Calculate the new camera's position offset from the
26757                         // left camera. xOffset should be roughly half `ipd`.
26758                         const zOffset = ipd / ( - leftFov + rightFov );
26759                         const xOffset = zOffset * - leftFov;
26760
26761                         // TODO: Better way to apply this offset?
26762                         cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
26763                         camera.translateX( xOffset );
26764                         camera.translateZ( zOffset );
26765                         camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
26766                         camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
26767
26768                         // Find the union of the frustum values of the cameras and scale
26769                         // the values so that the near plane's position does not change in world space,
26770                         // although must now be relative to the new union camera.
26771                         const near2 = near + zOffset;
26772                         const far2 = far + zOffset;
26773                         const left2 = left - xOffset;
26774                         const right2 = right + ( ipd - xOffset );
26775                         const top2 = topFov * far / far2 * near2;
26776                         const bottom2 = bottomFov * far / far2 * near2;
26777
26778                         camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
26779
26780                 }
26781
26782                 function updateCamera( camera, parent ) {
26783
26784                         if ( parent === null ) {
26785
26786                                 camera.matrixWorld.copy( camera.matrix );
26787
26788                         } else {
26789
26790                                 camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
26791
26792                         }
26793
26794                         camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
26795
26796                 }
26797
26798                 this.updateCamera = function ( camera ) {
26799
26800                         if ( session === null ) return;
26801
26802                         cameraVR.near = cameraR.near = cameraL.near = camera.near;
26803                         cameraVR.far = cameraR.far = cameraL.far = camera.far;
26804
26805                         if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
26806
26807                                 // Note that the new renderState won't apply until the next frame. See #18320
26808
26809                                 session.updateRenderState( {
26810                                         depthNear: cameraVR.near,
26811                                         depthFar: cameraVR.far
26812                                 } );
26813
26814                                 _currentDepthNear = cameraVR.near;
26815                                 _currentDepthFar = cameraVR.far;
26816
26817                         }
26818
26819                         const parent = camera.parent;
26820                         const cameras = cameraVR.cameras;
26821
26822                         updateCamera( cameraVR, parent );
26823
26824                         for ( let i = 0; i < cameras.length; i ++ ) {
26825
26826                                 updateCamera( cameras[ i ], parent );
26827
26828                         }
26829
26830                         cameraVR.matrixWorld.decompose( cameraVR.position, cameraVR.quaternion, cameraVR.scale );
26831
26832                         // update user camera and its children
26833
26834                         camera.position.copy( cameraVR.position );
26835                         camera.quaternion.copy( cameraVR.quaternion );
26836                         camera.scale.copy( cameraVR.scale );
26837                         camera.matrix.copy( cameraVR.matrix );
26838                         camera.matrixWorld.copy( cameraVR.matrixWorld );
26839
26840                         const children = camera.children;
26841
26842                         for ( let i = 0, l = children.length; i < l; i ++ ) {
26843
26844                                 children[ i ].updateMatrixWorld( true );
26845
26846                         }
26847
26848                         // update projection matrix for proper view frustum culling
26849
26850                         if ( cameras.length === 2 ) {
26851
26852                                 setProjectionFromUnion( cameraVR, cameraL, cameraR );
26853
26854                         } else {
26855
26856                                 // assume single camera setup (AR)
26857
26858                                 cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
26859
26860                         }
26861
26862                 };
26863
26864                 this.getCamera = function () {
26865
26866                         return cameraVR;
26867
26868                 };
26869
26870                 this.getFoveation = function () {
26871
26872                         if ( glProjLayer !== null ) {
26873
26874                                 return glProjLayer.fixedFoveation;
26875
26876                         }
26877
26878                         if ( glBaseLayer !== null ) {
26879
26880                                 return glBaseLayer.fixedFoveation;
26881
26882                         }
26883
26884                         return undefined;
26885
26886                 };
26887
26888                 this.setFoveation = function ( foveation ) {
26889
26890                         // 0 = no foveation = full resolution
26891                         // 1 = maximum foveation = the edges render at lower resolution
26892
26893                         if ( glProjLayer !== null ) {
26894
26895                                 glProjLayer.fixedFoveation = foveation;
26896
26897                         }
26898
26899                         if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) {
26900
26901                                 glBaseLayer.fixedFoveation = foveation;
26902
26903                         }
26904
26905                 };
26906
26907                 // Animation Loop
26908
26909                 let onAnimationFrameCallback = null;
26910
26911                 function onAnimationFrame( time, frame ) {
26912
26913                         pose = frame.getViewerPose( referenceSpace );
26914                         xrFrame = frame;
26915
26916                         if ( pose !== null ) {
26917
26918                                 const views = pose.views;
26919
26920                                 if ( glBaseLayer !== null ) {
26921
26922                                         state.bindXRFramebuffer( glBaseLayer.framebuffer );
26923
26924                                 }
26925
26926                                 let cameraVRNeedsUpdate = false;
26927
26928                                 // check if it's necessary to rebuild cameraVR's camera list
26929
26930                                 if ( views.length !== cameraVR.cameras.length ) {
26931
26932                                         cameraVR.cameras.length = 0;
26933
26934                                         cameraVRNeedsUpdate = true;
26935
26936                                 }
26937
26938                                 for ( let i = 0; i < views.length; i ++ ) {
26939
26940                                         const view = views[ i ];
26941
26942                                         let viewport = null;
26943
26944                                         if ( glBaseLayer !== null ) {
26945
26946                                                 viewport = glBaseLayer.getViewport( view );
26947
26948                                         } else {
26949
26950                                                 const glSubImage = glBinding.getViewSubImage( glProjLayer, view );
26951
26952                                                 state.bindXRFramebuffer( glFramebuffer );
26953
26954                                                 if ( glSubImage.depthStencilTexture !== undefined ) {
26955
26956                                                         gl.framebufferTexture2D( 36160, depthStyle, 3553, glSubImage.depthStencilTexture, 0 );
26957
26958                                                 }
26959
26960                                                 gl.framebufferTexture2D( 36160, 36064, 3553, glSubImage.colorTexture, 0 );
26961
26962                                                 viewport = glSubImage.viewport;
26963
26964                                         }
26965
26966                                         const camera = cameras[ i ];
26967
26968                                         camera.matrix.fromArray( view.transform.matrix );
26969                                         camera.projectionMatrix.fromArray( view.projectionMatrix );
26970                                         camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
26971
26972                                         if ( i === 0 ) {
26973
26974                                                 cameraVR.matrix.copy( camera.matrix );
26975
26976                                         }
26977
26978                                         if ( cameraVRNeedsUpdate === true ) {
26979
26980                                                 cameraVR.cameras.push( camera );
26981
26982                                         }
26983
26984                                 }
26985
26986                                 if ( isMultisample ) {
26987
26988                                         state.bindXRFramebuffer( glMultisampledFramebuffer );
26989
26990                                         if ( clearStyle !== null ) gl.clear( clearStyle );
26991
26992                                 }
26993
26994                         }
26995
26996                         //
26997
26998                         const inputSources = session.inputSources;
26999
27000                         for ( let i = 0; i < controllers.length; i ++ ) {
27001
27002                                 const controller = controllers[ i ];
27003                                 const inputSource = inputSources[ i ];
27004
27005                                 controller.update( inputSource, frame, referenceSpace );
27006
27007                         }
27008
27009                         if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
27010
27011                         if ( isMultisample ) {
27012
27013                                 const width = glProjLayer.textureWidth;
27014                                 const height = glProjLayer.textureHeight;
27015
27016                                 state.bindFramebuffer( 36008, glMultisampledFramebuffer );
27017                                 state.bindFramebuffer( 36009, glFramebuffer );
27018                                 // Invalidate the depth here to avoid flush of the depth data to main memory.
27019                                 gl.invalidateFramebuffer( 36008, [ depthStyle ] );
27020                                 gl.invalidateFramebuffer( 36009, [ depthStyle ] );
27021                                 gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, 16384, 9728 );
27022                                 // Invalidate the MSAA buffer because it's not needed anymore.
27023                                 gl.invalidateFramebuffer( 36008, [ 36064 ] );
27024                                 state.bindFramebuffer( 36008, null );
27025                                 state.bindFramebuffer( 36009, null );
27026
27027                                 state.bindFramebuffer( 36160, glMultisampledFramebuffer );
27028
27029                         }
27030
27031                         xrFrame = null;
27032
27033                 }
27034
27035                 const animation = new WebGLAnimation();
27036
27037                 animation.setAnimationLoop( onAnimationFrame );
27038
27039                 this.setAnimationLoop = function ( callback ) {
27040
27041                         onAnimationFrameCallback = callback;
27042
27043                 };
27044
27045                 this.dispose = function () {};
27046
27047         }
27048
27049     }
27050
27051     function WebGLMaterials( properties ) {
27052
27053         function refreshFogUniforms( uniforms, fog ) {
27054
27055                 uniforms.fogColor.value.copy( fog.color );
27056
27057                 if ( fog.isFog ) {
27058
27059                         uniforms.fogNear.value = fog.near;
27060                         uniforms.fogFar.value = fog.far;
27061
27062                 } else if ( fog.isFogExp2 ) {
27063
27064                         uniforms.fogDensity.value = fog.density;
27065
27066                 }
27067
27068         }
27069
27070         function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) {
27071
27072                 if ( material.isMeshBasicMaterial ) {
27073
27074                         refreshUniformsCommon( uniforms, material );
27075
27076                 } else if ( material.isMeshLambertMaterial ) {
27077
27078                         refreshUniformsCommon( uniforms, material );
27079                         refreshUniformsLambert( uniforms, material );
27080
27081                 } else if ( material.isMeshToonMaterial ) {
27082
27083                         refreshUniformsCommon( uniforms, material );
27084                         refreshUniformsToon( uniforms, material );
27085
27086                 } else if ( material.isMeshPhongMaterial ) {
27087
27088                         refreshUniformsCommon( uniforms, material );
27089                         refreshUniformsPhong( uniforms, material );
27090
27091                 } else if ( material.isMeshStandardMaterial ) {
27092
27093                         refreshUniformsCommon( uniforms, material );
27094
27095                         if ( material.isMeshPhysicalMaterial ) {
27096
27097                                 refreshUniformsPhysical( uniforms, material, transmissionRenderTarget );
27098
27099                         } else {
27100
27101                                 refreshUniformsStandard( uniforms, material );
27102
27103                         }
27104
27105                 } else if ( material.isMeshMatcapMaterial ) {
27106
27107                         refreshUniformsCommon( uniforms, material );
27108                         refreshUniformsMatcap( uniforms, material );
27109
27110                 } else if ( material.isMeshDepthMaterial ) {
27111
27112                         refreshUniformsCommon( uniforms, material );
27113                         refreshUniformsDepth( uniforms, material );
27114
27115                 } else if ( material.isMeshDistanceMaterial ) {
27116
27117                         refreshUniformsCommon( uniforms, material );
27118                         refreshUniformsDistance( uniforms, material );
27119
27120                 } else if ( material.isMeshNormalMaterial ) {
27121
27122                         refreshUniformsCommon( uniforms, material );
27123                         refreshUniformsNormal( uniforms, material );
27124
27125                 } else if ( material.isLineBasicMaterial ) {
27126
27127                         refreshUniformsLine( uniforms, material );
27128
27129                         if ( material.isLineDashedMaterial ) {
27130
27131                                 refreshUniformsDash( uniforms, material );
27132
27133                         }
27134
27135                 } else if ( material.isPointsMaterial ) {
27136
27137                         refreshUniformsPoints( uniforms, material, pixelRatio, height );
27138
27139                 } else if ( material.isSpriteMaterial ) {
27140
27141                         refreshUniformsSprites( uniforms, material );
27142
27143                 } else if ( material.isShadowMaterial ) {
27144
27145                         uniforms.color.value.copy( material.color );
27146                         uniforms.opacity.value = material.opacity;
27147
27148                 } else if ( material.isShaderMaterial ) {
27149
27150                         material.uniformsNeedUpdate = false; // #15581
27151
27152                 }
27153
27154         }
27155
27156         function refreshUniformsCommon( uniforms, material ) {
27157
27158                 uniforms.opacity.value = material.opacity;
27159
27160                 if ( material.color ) {
27161
27162                         uniforms.diffuse.value.copy( material.color );
27163
27164                 }
27165
27166                 if ( material.emissive ) {
27167
27168                         uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
27169
27170                 }
27171
27172                 if ( material.map ) {
27173
27174                         uniforms.map.value = material.map;
27175
27176                 }
27177
27178                 if ( material.alphaMap ) {
27179
27180                         uniforms.alphaMap.value = material.alphaMap;
27181
27182                 }
27183
27184                 if ( material.specularMap ) {
27185
27186                         uniforms.specularMap.value = material.specularMap;
27187
27188                 }
27189
27190                 if ( material.alphaTest > 0 ) {
27191
27192                         uniforms.alphaTest.value = material.alphaTest;
27193
27194                 }
27195
27196                 const envMap = properties.get( material ).envMap;
27197
27198                 if ( envMap ) {
27199
27200                         uniforms.envMap.value = envMap;
27201
27202                         uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
27203
27204                         uniforms.reflectivity.value = material.reflectivity;
27205                         uniforms.ior.value = material.ior;
27206                         uniforms.refractionRatio.value = material.refractionRatio;
27207
27208                         const maxMipLevel = properties.get( envMap ).__maxMipLevel;
27209
27210                         if ( maxMipLevel !== undefined ) {
27211
27212                                 uniforms.maxMipLevel.value = maxMipLevel;
27213
27214                         }
27215
27216                 }
27217
27218                 if ( material.lightMap ) {
27219
27220                         uniforms.lightMap.value = material.lightMap;
27221                         uniforms.lightMapIntensity.value = material.lightMapIntensity;
27222
27223                 }
27224
27225                 if ( material.aoMap ) {
27226
27227                         uniforms.aoMap.value = material.aoMap;
27228                         uniforms.aoMapIntensity.value = material.aoMapIntensity;
27229
27230                 }
27231
27232                 // uv repeat and offset setting priorities
27233                 // 1. color map
27234                 // 2. specular map
27235                 // 3. displacementMap map
27236                 // 4. normal map
27237                 // 5. bump map
27238                 // 6. roughnessMap map
27239                 // 7. metalnessMap map
27240                 // 8. alphaMap map
27241                 // 9. emissiveMap map
27242                 // 10. clearcoat map
27243                 // 11. clearcoat normal map
27244                 // 12. clearcoat roughnessMap map
27245                 // 13. specular intensity map
27246                 // 14. specular tint map
27247                 // 15. transmission map
27248                 // 16. thickness map
27249
27250                 let uvScaleMap;
27251
27252                 if ( material.map ) {
27253
27254                         uvScaleMap = material.map;
27255
27256                 } else if ( material.specularMap ) {
27257
27258                         uvScaleMap = material.specularMap;
27259
27260                 } else if ( material.displacementMap ) {
27261
27262                         uvScaleMap = material.displacementMap;
27263
27264                 } else if ( material.normalMap ) {
27265
27266                         uvScaleMap = material.normalMap;
27267
27268                 } else if ( material.bumpMap ) {
27269
27270                         uvScaleMap = material.bumpMap;
27271
27272                 } else if ( material.roughnessMap ) {
27273
27274                         uvScaleMap = material.roughnessMap;
27275
27276                 } else if ( material.metalnessMap ) {
27277
27278                         uvScaleMap = material.metalnessMap;
27279
27280                 } else if ( material.alphaMap ) {
27281
27282                         uvScaleMap = material.alphaMap;
27283
27284                 } else if ( material.emissiveMap ) {
27285
27286                         uvScaleMap = material.emissiveMap;
27287
27288                 } else if ( material.clearcoatMap ) {
27289
27290                         uvScaleMap = material.clearcoatMap;
27291
27292                 } else if ( material.clearcoatNormalMap ) {
27293
27294                         uvScaleMap = material.clearcoatNormalMap;
27295
27296                 } else if ( material.clearcoatRoughnessMap ) {
27297
27298                         uvScaleMap = material.clearcoatRoughnessMap;
27299
27300                 } else if ( material.specularIntensityMap ) {
27301
27302                         uvScaleMap = material.specularIntensityMap;
27303
27304                 } else if ( material.specularColorMap ) {
27305
27306                         uvScaleMap = material.specularColorMap;
27307
27308                 } else if ( material.transmissionMap ) {
27309
27310                         uvScaleMap = material.transmissionMap;
27311
27312                 } else if ( material.thicknessMap ) {
27313
27314                         uvScaleMap = material.thicknessMap;
27315
27316                 } else if ( material.sheenColorMap ) {
27317
27318                         uvScaleMap = material.sheenColorMap;
27319
27320                 } else if ( material.sheenRoughnessMap ) {
27321
27322                         uvScaleMap = material.sheenRoughnessMap;
27323
27324                 }
27325
27326                 if ( uvScaleMap !== undefined ) {
27327
27328                         // backwards compatibility
27329                         if ( uvScaleMap.isWebGLRenderTarget ) {
27330
27331                                 uvScaleMap = uvScaleMap.texture;
27332
27333                         }
27334
27335                         if ( uvScaleMap.matrixAutoUpdate === true ) {
27336
27337                                 uvScaleMap.updateMatrix();
27338
27339                         }
27340
27341                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
27342
27343                 }
27344
27345                 // uv repeat and offset setting priorities for uv2
27346                 // 1. ao map
27347                 // 2. light map
27348
27349                 let uv2ScaleMap;
27350
27351                 if ( material.aoMap ) {
27352
27353                         uv2ScaleMap = material.aoMap;
27354
27355                 } else if ( material.lightMap ) {
27356
27357                         uv2ScaleMap = material.lightMap;
27358
27359                 }
27360
27361                 if ( uv2ScaleMap !== undefined ) {
27362
27363                         // backwards compatibility
27364                         if ( uv2ScaleMap.isWebGLRenderTarget ) {
27365
27366                                 uv2ScaleMap = uv2ScaleMap.texture;
27367
27368                         }
27369
27370                         if ( uv2ScaleMap.matrixAutoUpdate === true ) {
27371
27372                                 uv2ScaleMap.updateMatrix();
27373
27374                         }
27375
27376                         uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );
27377
27378                 }
27379
27380         }
27381
27382         function refreshUniformsLine( uniforms, material ) {
27383
27384                 uniforms.diffuse.value.copy( material.color );
27385                 uniforms.opacity.value = material.opacity;
27386
27387         }
27388
27389         function refreshUniformsDash( uniforms, material ) {
27390
27391                 uniforms.dashSize.value = material.dashSize;
27392                 uniforms.totalSize.value = material.dashSize + material.gapSize;
27393                 uniforms.scale.value = material.scale;
27394
27395         }
27396
27397         function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
27398
27399                 uniforms.diffuse.value.copy( material.color );
27400                 uniforms.opacity.value = material.opacity;
27401                 uniforms.size.value = material.size * pixelRatio;
27402                 uniforms.scale.value = height * 0.5;
27403
27404                 if ( material.map ) {
27405
27406                         uniforms.map.value = material.map;
27407
27408                 }
27409
27410                 if ( material.alphaMap ) {
27411
27412                         uniforms.alphaMap.value = material.alphaMap;
27413
27414                 }
27415
27416                 if ( material.alphaTest > 0 ) {
27417
27418                         uniforms.alphaTest.value = material.alphaTest;
27419
27420                 }
27421
27422                 // uv repeat and offset setting priorities
27423                 // 1. color map
27424                 // 2. alpha map
27425
27426                 let uvScaleMap;
27427
27428                 if ( material.map ) {
27429
27430                         uvScaleMap = material.map;
27431
27432                 } else if ( material.alphaMap ) {
27433
27434                         uvScaleMap = material.alphaMap;
27435
27436                 }
27437
27438                 if ( uvScaleMap !== undefined ) {
27439
27440                         if ( uvScaleMap.matrixAutoUpdate === true ) {
27441
27442                                 uvScaleMap.updateMatrix();
27443
27444                         }
27445
27446                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
27447
27448                 }
27449
27450         }
27451
27452         function refreshUniformsSprites( uniforms, material ) {
27453
27454                 uniforms.diffuse.value.copy( material.color );
27455                 uniforms.opacity.value = material.opacity;
27456                 uniforms.rotation.value = material.rotation;
27457
27458                 if ( material.map ) {
27459
27460                         uniforms.map.value = material.map;
27461
27462                 }
27463
27464                 if ( material.alphaMap ) {
27465
27466                         uniforms.alphaMap.value = material.alphaMap;
27467
27468                 }
27469
27470                 if ( material.alphaTest > 0 ) {
27471
27472                         uniforms.alphaTest.value = material.alphaTest;
27473
27474                 }
27475
27476                 // uv repeat and offset setting priorities
27477                 // 1. color map
27478                 // 2. alpha map
27479
27480                 let uvScaleMap;
27481
27482                 if ( material.map ) {
27483
27484                         uvScaleMap = material.map;
27485
27486                 } else if ( material.alphaMap ) {
27487
27488                         uvScaleMap = material.alphaMap;
27489
27490                 }
27491
27492                 if ( uvScaleMap !== undefined ) {
27493
27494                         if ( uvScaleMap.matrixAutoUpdate === true ) {
27495
27496                                 uvScaleMap.updateMatrix();
27497
27498                         }
27499
27500                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
27501
27502                 }
27503
27504         }
27505
27506         function refreshUniformsLambert( uniforms, material ) {
27507
27508                 if ( material.emissiveMap ) {
27509
27510                         uniforms.emissiveMap.value = material.emissiveMap;
27511
27512                 }
27513
27514         }
27515
27516         function refreshUniformsPhong( uniforms, material ) {
27517
27518                 uniforms.specular.value.copy( material.specular );
27519                 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
27520
27521                 if ( material.emissiveMap ) {
27522
27523                         uniforms.emissiveMap.value = material.emissiveMap;
27524
27525                 }
27526
27527                 if ( material.bumpMap ) {
27528
27529                         uniforms.bumpMap.value = material.bumpMap;
27530                         uniforms.bumpScale.value = material.bumpScale;
27531                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
27532
27533                 }
27534
27535                 if ( material.normalMap ) {
27536
27537                         uniforms.normalMap.value = material.normalMap;
27538                         uniforms.normalScale.value.copy( material.normalScale );
27539                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
27540
27541                 }
27542
27543                 if ( material.displacementMap ) {
27544
27545                         uniforms.displacementMap.value = material.displacementMap;
27546                         uniforms.displacementScale.value = material.displacementScale;
27547                         uniforms.displacementBias.value = material.displacementBias;
27548
27549                 }
27550
27551         }
27552
27553         function refreshUniformsToon( uniforms, material ) {
27554
27555                 if ( material.gradientMap ) {
27556
27557                         uniforms.gradientMap.value = material.gradientMap;
27558
27559                 }
27560
27561                 if ( material.emissiveMap ) {
27562
27563                         uniforms.emissiveMap.value = material.emissiveMap;
27564
27565                 }
27566
27567                 if ( material.bumpMap ) {
27568
27569                         uniforms.bumpMap.value = material.bumpMap;
27570                         uniforms.bumpScale.value = material.bumpScale;
27571                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
27572
27573                 }
27574
27575                 if ( material.normalMap ) {
27576
27577                         uniforms.normalMap.value = material.normalMap;
27578                         uniforms.normalScale.value.copy( material.normalScale );
27579                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
27580
27581                 }
27582
27583                 if ( material.displacementMap ) {
27584
27585                         uniforms.displacementMap.value = material.displacementMap;
27586                         uniforms.displacementScale.value = material.displacementScale;
27587                         uniforms.displacementBias.value = material.displacementBias;
27588
27589                 }
27590
27591         }
27592
27593         function refreshUniformsStandard( uniforms, material ) {
27594
27595                 uniforms.roughness.value = material.roughness;
27596                 uniforms.metalness.value = material.metalness;
27597
27598                 if ( material.roughnessMap ) {
27599
27600                         uniforms.roughnessMap.value = material.roughnessMap;
27601
27602                 }
27603
27604                 if ( material.metalnessMap ) {
27605
27606                         uniforms.metalnessMap.value = material.metalnessMap;
27607
27608                 }
27609
27610                 if ( material.emissiveMap ) {
27611
27612                         uniforms.emissiveMap.value = material.emissiveMap;
27613
27614                 }
27615
27616                 if ( material.bumpMap ) {
27617
27618                         uniforms.bumpMap.value = material.bumpMap;
27619                         uniforms.bumpScale.value = material.bumpScale;
27620                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
27621
27622                 }
27623
27624                 if ( material.normalMap ) {
27625
27626                         uniforms.normalMap.value = material.normalMap;
27627                         uniforms.normalScale.value.copy( material.normalScale );
27628                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
27629
27630                 }
27631
27632                 if ( material.displacementMap ) {
27633
27634                         uniforms.displacementMap.value = material.displacementMap;
27635                         uniforms.displacementScale.value = material.displacementScale;
27636                         uniforms.displacementBias.value = material.displacementBias;
27637
27638                 }
27639
27640                 const envMap = properties.get( material ).envMap;
27641
27642                 if ( envMap ) {
27643
27644                         //uniforms.envMap.value = material.envMap; // part of uniforms common
27645                         uniforms.envMapIntensity.value = material.envMapIntensity;
27646
27647                 }
27648
27649         }
27650
27651         function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) {
27652
27653                 refreshUniformsStandard( uniforms, material );
27654
27655                 uniforms.ior.value = material.ior; // also part of uniforms common
27656
27657                 if ( material.sheen > 0 ) {
27658
27659                         uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen );
27660
27661                         uniforms.sheenRoughness.value = material.sheenRoughness;
27662
27663                         if ( material.sheenColorMap ) {
27664
27665                                 uniforms.sheenColorMap.value = material.sheenColorMap;
27666
27667                         }
27668
27669                         if ( material.sheenRoughnessMap ) {
27670
27671                                 uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap;
27672
27673                         }
27674
27675                 }
27676
27677                 if ( material.clearcoat > 0 ) {
27678
27679                         uniforms.clearcoat.value = material.clearcoat;
27680                         uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
27681
27682                         if ( material.clearcoatMap ) {
27683
27684                                 uniforms.clearcoatMap.value = material.clearcoatMap;
27685
27686                         }
27687
27688                         if ( material.clearcoatRoughnessMap ) {
27689
27690                                 uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
27691
27692                         }
27693
27694                         if ( material.clearcoatNormalMap ) {
27695
27696                                 uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
27697                                 uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
27698
27699                                 if ( material.side === BackSide ) {
27700
27701                                         uniforms.clearcoatNormalScale.value.negate();
27702
27703                                 }
27704
27705                         }
27706
27707                 }
27708
27709                 if ( material.transmission > 0 ) {
27710
27711                         uniforms.transmission.value = material.transmission;
27712                         uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
27713                         uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height );
27714
27715                         if ( material.transmissionMap ) {
27716
27717                                 uniforms.transmissionMap.value = material.transmissionMap;
27718
27719                         }
27720
27721                         uniforms.thickness.value = material.thickness;
27722
27723                         if ( material.thicknessMap ) {
27724
27725                                 uniforms.thicknessMap.value = material.thicknessMap;
27726
27727                         }
27728
27729                         uniforms.attenuationDistance.value = material.attenuationDistance;
27730                         uniforms.attenuationColor.value.copy( material.attenuationColor );
27731
27732                 }
27733
27734                 uniforms.specularIntensity.value = material.specularIntensity;
27735                 uniforms.specularColor.value.copy( material.specularColor );
27736
27737                 if ( material.specularIntensityMap ) {
27738
27739                         uniforms.specularIntensityMap.value = material.specularIntensityMap;
27740
27741                 }
27742
27743                 if ( material.specularColorMap ) {
27744
27745                         uniforms.specularColorMap.value = material.specularColorMap;
27746
27747                 }
27748
27749         }
27750
27751         function refreshUniformsMatcap( uniforms, material ) {
27752
27753                 if ( material.matcap ) {
27754
27755                         uniforms.matcap.value = material.matcap;
27756
27757                 }
27758
27759                 if ( material.bumpMap ) {
27760
27761                         uniforms.bumpMap.value = material.bumpMap;
27762                         uniforms.bumpScale.value = material.bumpScale;
27763                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
27764
27765                 }
27766
27767                 if ( material.normalMap ) {
27768
27769                         uniforms.normalMap.value = material.normalMap;
27770                         uniforms.normalScale.value.copy( material.normalScale );
27771                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
27772
27773                 }
27774
27775                 if ( material.displacementMap ) {
27776
27777                         uniforms.displacementMap.value = material.displacementMap;
27778                         uniforms.displacementScale.value = material.displacementScale;
27779                         uniforms.displacementBias.value = material.displacementBias;
27780
27781                 }
27782
27783         }
27784
27785         function refreshUniformsDepth( uniforms, material ) {
27786
27787                 if ( material.displacementMap ) {
27788
27789                         uniforms.displacementMap.value = material.displacementMap;
27790                         uniforms.displacementScale.value = material.displacementScale;
27791                         uniforms.displacementBias.value = material.displacementBias;
27792
27793                 }
27794
27795         }
27796
27797         function refreshUniformsDistance( uniforms, material ) {
27798
27799                 if ( material.displacementMap ) {
27800
27801                         uniforms.displacementMap.value = material.displacementMap;
27802                         uniforms.displacementScale.value = material.displacementScale;
27803                         uniforms.displacementBias.value = material.displacementBias;
27804
27805                 }
27806
27807                 uniforms.referencePosition.value.copy( material.referencePosition );
27808                 uniforms.nearDistance.value = material.nearDistance;
27809                 uniforms.farDistance.value = material.farDistance;
27810
27811         }
27812
27813         function refreshUniformsNormal( uniforms, material ) {
27814
27815                 if ( material.bumpMap ) {
27816
27817                         uniforms.bumpMap.value = material.bumpMap;
27818                         uniforms.bumpScale.value = material.bumpScale;
27819                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
27820
27821                 }
27822
27823                 if ( material.normalMap ) {
27824
27825                         uniforms.normalMap.value = material.normalMap;
27826                         uniforms.normalScale.value.copy( material.normalScale );
27827                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
27828
27829                 }
27830
27831                 if ( material.displacementMap ) {
27832
27833                         uniforms.displacementMap.value = material.displacementMap;
27834                         uniforms.displacementScale.value = material.displacementScale;
27835                         uniforms.displacementBias.value = material.displacementBias;
27836
27837                 }
27838
27839         }
27840
27841         return {
27842                 refreshFogUniforms: refreshFogUniforms,
27843                 refreshMaterialUniforms: refreshMaterialUniforms
27844         };
27845
27846     }
27847
27848     function createCanvasElement() {
27849
27850         const canvas = createElementNS( 'canvas' );
27851         canvas.style.display = 'block';
27852         return canvas;
27853
27854     }
27855
27856     function WebGLRenderer( parameters = {} ) {
27857
27858         const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(),
27859                 _context = parameters.context !== undefined ? parameters.context : null,
27860
27861                 _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
27862                 _depth = parameters.depth !== undefined ? parameters.depth : true,
27863                 _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
27864                 _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
27865                 _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
27866                 _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
27867                 _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',
27868                 _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;
27869
27870         let currentRenderList = null;
27871         let currentRenderState = null;
27872
27873         // render() can be called from within a callback triggered by another render.
27874         // We track this so that the nested render call gets its list and state isolated from the parent render call.
27875
27876         const renderListStack = [];
27877         const renderStateStack = [];
27878
27879         // public properties
27880
27881         this.domElement = _canvas;
27882
27883         // Debug configuration container
27884         this.debug = {
27885
27886                 /**
27887                  * Enables error checking and reporting when shader programs are being compiled
27888                  * @type {boolean}
27889                  */
27890                 checkShaderErrors: true
27891         };
27892
27893         // clearing
27894
27895         this.autoClear = true;
27896         this.autoClearColor = true;
27897         this.autoClearDepth = true;
27898         this.autoClearStencil = true;
27899
27900         // scene graph
27901
27902         this.sortObjects = true;
27903
27904         // user-defined clipping
27905
27906         this.clippingPlanes = [];
27907         this.localClippingEnabled = false;
27908
27909         // physically based shading
27910
27911         this.gammaFactor = 2.0; // for backwards compatibility
27912         this.outputEncoding = LinearEncoding;
27913
27914         // physical lights
27915
27916         this.physicallyCorrectLights = false;
27917
27918         // tone mapping
27919
27920         this.toneMapping = NoToneMapping;
27921         this.toneMappingExposure = 1.0;
27922
27923         // internal properties
27924
27925         const _this = this;
27926
27927         let _isContextLost = false;
27928
27929         // internal state cache
27930
27931         let _currentActiveCubeFace = 0;
27932         let _currentActiveMipmapLevel = 0;
27933         let _currentRenderTarget = null;
27934         let _currentMaterialId = - 1;
27935
27936         let _currentCamera = null;
27937
27938         const _currentViewport = new Vector4();
27939         const _currentScissor = new Vector4();
27940         let _currentScissorTest = null;
27941
27942         //
27943
27944         let _width = _canvas.width;
27945         let _height = _canvas.height;
27946
27947         let _pixelRatio = 1;
27948         let _opaqueSort = null;
27949         let _transparentSort = null;
27950
27951         const _viewport = new Vector4( 0, 0, _width, _height );
27952         const _scissor = new Vector4( 0, 0, _width, _height );
27953         let _scissorTest = false;
27954
27955         //
27956
27957         const _currentDrawBuffers = [];
27958
27959         // frustum
27960
27961         const _frustum = new Frustum();
27962
27963         // clipping
27964
27965         let _clippingEnabled = false;
27966         let _localClippingEnabled = false;
27967
27968         // transmission
27969
27970         let _transmissionRenderTarget = null;
27971
27972         // camera matrices cache
27973
27974         const _projScreenMatrix = new Matrix4();
27975
27976         const _vector3 = new Vector3();
27977
27978         const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
27979
27980         function getTargetPixelRatio() {
27981
27982                 return _currentRenderTarget === null ? _pixelRatio : 1;
27983
27984         }
27985
27986         // initialize
27987
27988         let _gl = _context;
27989
27990         function getContext( contextNames, contextAttributes ) {
27991
27992                 for ( let i = 0; i < contextNames.length; i ++ ) {
27993
27994                         const contextName = contextNames[ i ];
27995                         const context = _canvas.getContext( contextName, contextAttributes );
27996                         if ( context !== null ) return context;
27997
27998                 }
27999
28000                 return null;
28001
28002         }
28003
28004         try {
28005
28006                 const contextAttributes = {
28007                         alpha: _alpha,
28008                         depth: _depth,
28009                         stencil: _stencil,
28010                         antialias: _antialias,
28011                         premultipliedAlpha: _premultipliedAlpha,
28012                         preserveDrawingBuffer: _preserveDrawingBuffer,
28013                         powerPreference: _powerPreference,
28014                         failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat
28015                 };
28016
28017                 // event listeners must be registered before WebGL context is created, see #12753
28018
28019                 _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
28020                 _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
28021
28022                 if ( _gl === null ) {
28023
28024                         const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ];
28025
28026                         if ( _this.isWebGL1Renderer === true ) {
28027
28028                                 contextNames.shift();
28029
28030                         }
28031
28032                         _gl = getContext( contextNames, contextAttributes );
28033
28034                         if ( _gl === null ) {
28035
28036                                 if ( getContext( contextNames ) ) {
28037
28038                                         throw new Error( 'Error creating WebGL context with your selected attributes.' );
28039
28040                                 } else {
28041
28042                                         throw new Error( 'Error creating WebGL context.' );
28043
28044                                 }
28045
28046                         }
28047
28048                 }
28049
28050                 // Some experimental-webgl implementations do not have getShaderPrecisionFormat
28051
28052                 if ( _gl.getShaderPrecisionFormat === undefined ) {
28053
28054                         _gl.getShaderPrecisionFormat = function () {
28055
28056                                 return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
28057
28058                         };
28059
28060                 }
28061
28062         } catch ( error ) {
28063
28064                 console.error( 'THREE.WebGLRenderer: ' + error.message );
28065                 throw error;
28066
28067         }
28068
28069         let extensions, capabilities, state, info;
28070         let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects;
28071         let programCache, materials, renderLists, renderStates, clipping, shadowMap;
28072
28073         let background, morphtargets, bufferRenderer, indexedBufferRenderer;
28074
28075         let utils, bindingStates;
28076
28077         function initGLContext() {
28078
28079                 extensions = new WebGLExtensions( _gl );
28080
28081                 capabilities = new WebGLCapabilities( _gl, extensions, parameters );
28082
28083                 extensions.init( capabilities );
28084
28085                 utils = new WebGLUtils( _gl, extensions, capabilities );
28086
28087                 state = new WebGLState( _gl, extensions, capabilities );
28088
28089                 _currentDrawBuffers[ 0 ] = 1029;
28090
28091                 info = new WebGLInfo( _gl );
28092                 properties = new WebGLProperties();
28093                 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
28094                 cubemaps = new WebGLCubeMaps( _this );
28095                 cubeuvmaps = new WebGLCubeUVMaps( _this );
28096                 attributes = new WebGLAttributes( _gl, capabilities );
28097                 bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities );
28098                 geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
28099                 objects = new WebGLObjects( _gl, geometries, attributes, info );
28100                 morphtargets = new WebGLMorphtargets( _gl, capabilities, textures );
28101                 clipping = new WebGLClipping( properties );
28102                 programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping );
28103                 materials = new WebGLMaterials( properties );
28104                 renderLists = new WebGLRenderLists( properties );
28105                 renderStates = new WebGLRenderStates( extensions, capabilities );
28106                 background = new WebGLBackground( _this, cubemaps, state, objects, _premultipliedAlpha );
28107                 shadowMap = new WebGLShadowMap( _this, objects, capabilities );
28108
28109                 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
28110                 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
28111
28112                 info.programs = programCache.programs;
28113
28114                 _this.capabilities = capabilities;
28115                 _this.extensions = extensions;
28116                 _this.properties = properties;
28117                 _this.renderLists = renderLists;
28118                 _this.shadowMap = shadowMap;
28119                 _this.state = state;
28120                 _this.info = info;
28121
28122         }
28123
28124         initGLContext();
28125
28126         // xr
28127
28128         const xr = new WebXRManager( _this, _gl );
28129
28130         this.xr = xr;
28131
28132         // API
28133
28134         this.getContext = function () {
28135
28136                 return _gl;
28137
28138         };
28139
28140         this.getContextAttributes = function () {
28141
28142                 return _gl.getContextAttributes();
28143
28144         };
28145
28146         this.forceContextLoss = function () {
28147
28148                 const extension = extensions.get( 'WEBGL_lose_context' );
28149                 if ( extension ) extension.loseContext();
28150
28151         };
28152
28153         this.forceContextRestore = function () {
28154
28155                 const extension = extensions.get( 'WEBGL_lose_context' );
28156                 if ( extension ) extension.restoreContext();
28157
28158         };
28159
28160         this.getPixelRatio = function () {
28161
28162                 return _pixelRatio;
28163
28164         };
28165
28166         this.setPixelRatio = function ( value ) {
28167
28168                 if ( value === undefined ) return;
28169
28170                 _pixelRatio = value;
28171
28172                 this.setSize( _width, _height, false );
28173
28174         };
28175
28176         this.getSize = function ( target ) {
28177
28178                 return target.set( _width, _height );
28179
28180         };
28181
28182         this.setSize = function ( width, height, updateStyle ) {
28183
28184                 if ( xr.isPresenting ) {
28185
28186                         console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
28187                         return;
28188
28189                 }
28190
28191                 _width = width;
28192                 _height = height;
28193
28194                 _canvas.width = Math.floor( width * _pixelRatio );
28195                 _canvas.height = Math.floor( height * _pixelRatio );
28196
28197                 if ( updateStyle !== false ) {
28198
28199                         _canvas.style.width = width + 'px';
28200                         _canvas.style.height = height + 'px';
28201
28202                 }
28203
28204                 this.setViewport( 0, 0, width, height );
28205
28206         };
28207
28208         this.getDrawingBufferSize = function ( target ) {
28209
28210                 return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
28211
28212         };
28213
28214         this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
28215
28216                 _width = width;
28217                 _height = height;
28218
28219                 _pixelRatio = pixelRatio;
28220
28221                 _canvas.width = Math.floor( width * pixelRatio );
28222                 _canvas.height = Math.floor( height * pixelRatio );
28223
28224                 this.setViewport( 0, 0, width, height );
28225
28226         };
28227
28228         this.getCurrentViewport = function ( target ) {
28229
28230                 return target.copy( _currentViewport );
28231
28232         };
28233
28234         this.getViewport = function ( target ) {
28235
28236                 return target.copy( _viewport );
28237
28238         };
28239
28240         this.setViewport = function ( x, y, width, height ) {
28241
28242                 if ( x.isVector4 ) {
28243
28244                         _viewport.set( x.x, x.y, x.z, x.w );
28245
28246                 } else {
28247
28248                         _viewport.set( x, y, width, height );
28249
28250                 }
28251
28252                 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
28253
28254         };
28255
28256         this.getScissor = function ( target ) {
28257
28258                 return target.copy( _scissor );
28259
28260         };
28261
28262         this.setScissor = function ( x, y, width, height ) {
28263
28264                 if ( x.isVector4 ) {
28265
28266                         _scissor.set( x.x, x.y, x.z, x.w );
28267
28268                 } else {
28269
28270                         _scissor.set( x, y, width, height );
28271
28272                 }
28273
28274                 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
28275
28276         };
28277
28278         this.getScissorTest = function () {
28279
28280                 return _scissorTest;
28281
28282         };
28283
28284         this.setScissorTest = function ( boolean ) {
28285
28286                 state.setScissorTest( _scissorTest = boolean );
28287
28288         };
28289
28290         this.setOpaqueSort = function ( method ) {
28291
28292                 _opaqueSort = method;
28293
28294         };
28295
28296         this.setTransparentSort = function ( method ) {
28297
28298                 _transparentSort = method;
28299
28300         };
28301
28302         // Clearing
28303
28304         this.getClearColor = function ( target ) {
28305
28306                 return target.copy( background.getClearColor() );
28307
28308         };
28309
28310         this.setClearColor = function () {
28311
28312                 background.setClearColor.apply( background, arguments );
28313
28314         };
28315
28316         this.getClearAlpha = function () {
28317
28318                 return background.getClearAlpha();
28319
28320         };
28321
28322         this.setClearAlpha = function () {
28323
28324                 background.setClearAlpha.apply( background, arguments );
28325
28326         };
28327
28328         this.clear = function ( color, depth, stencil ) {
28329
28330                 let bits = 0;
28331
28332                 if ( color === undefined || color ) bits |= 16384;
28333                 if ( depth === undefined || depth ) bits |= 256;
28334                 if ( stencil === undefined || stencil ) bits |= 1024;
28335
28336                 _gl.clear( bits );
28337
28338         };
28339
28340         this.clearColor = function () {
28341
28342                 this.clear( true, false, false );
28343
28344         };
28345
28346         this.clearDepth = function () {
28347
28348                 this.clear( false, true, false );
28349
28350         };
28351
28352         this.clearStencil = function () {
28353
28354                 this.clear( false, false, true );
28355
28356         };
28357
28358         //
28359
28360         this.dispose = function () {
28361
28362                 _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
28363                 _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
28364
28365                 renderLists.dispose();
28366                 renderStates.dispose();
28367                 properties.dispose();
28368                 cubemaps.dispose();
28369                 cubeuvmaps.dispose();
28370                 objects.dispose();
28371                 bindingStates.dispose();
28372
28373                 xr.dispose();
28374
28375                 xr.removeEventListener( 'sessionstart', onXRSessionStart );
28376                 xr.removeEventListener( 'sessionend', onXRSessionEnd );
28377
28378                 if ( _transmissionRenderTarget ) {
28379
28380                         _transmissionRenderTarget.dispose();
28381                         _transmissionRenderTarget = null;
28382
28383                 }
28384
28385                 animation.stop();
28386
28387         };
28388
28389         // Events
28390
28391         function onContextLost( event ) {
28392
28393                 event.preventDefault();
28394
28395                 console.log( 'THREE.WebGLRenderer: Context Lost.' );
28396
28397                 _isContextLost = true;
28398
28399         }
28400
28401         function onContextRestore( /* event */ ) {
28402
28403                 console.log( 'THREE.WebGLRenderer: Context Restored.' );
28404
28405                 _isContextLost = false;
28406
28407                 const infoAutoReset = info.autoReset;
28408                 const shadowMapEnabled = shadowMap.enabled;
28409                 const shadowMapAutoUpdate = shadowMap.autoUpdate;
28410                 const shadowMapNeedsUpdate = shadowMap.needsUpdate;
28411                 const shadowMapType = shadowMap.type;
28412
28413                 initGLContext();
28414
28415                 info.autoReset = infoAutoReset;
28416                 shadowMap.enabled = shadowMapEnabled;
28417                 shadowMap.autoUpdate = shadowMapAutoUpdate;
28418                 shadowMap.needsUpdate = shadowMapNeedsUpdate;
28419                 shadowMap.type = shadowMapType;
28420
28421         }
28422
28423         function onMaterialDispose( event ) {
28424
28425                 const material = event.target;
28426
28427                 material.removeEventListener( 'dispose', onMaterialDispose );
28428
28429                 deallocateMaterial( material );
28430
28431         }
28432
28433         // Buffer deallocation
28434
28435         function deallocateMaterial( material ) {
28436
28437                 releaseMaterialProgramReferences( material );
28438
28439                 properties.remove( material );
28440
28441         }
28442
28443
28444         function releaseMaterialProgramReferences( material ) {
28445
28446                 const programs = properties.get( material ).programs;
28447
28448                 if ( programs !== undefined ) {
28449
28450                         programs.forEach( function ( program ) {
28451
28452                                 programCache.releaseProgram( program );
28453
28454                         } );
28455
28456                 }
28457
28458         }
28459
28460         // Buffer rendering
28461
28462         this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {
28463
28464                 if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null)
28465
28466                 const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
28467
28468                 const program = setProgram( camera, scene, geometry, material, object );
28469
28470                 state.setMaterial( material, frontFaceCW );
28471
28472                 //
28473
28474                 let index = geometry.index;
28475                 const position = geometry.attributes.position;
28476
28477                 //
28478
28479                 if ( index === null ) {
28480
28481                         if ( position === undefined || position.count === 0 ) return;
28482
28483                 } else if ( index.count === 0 ) {
28484
28485                         return;
28486
28487                 }
28488
28489                 //
28490
28491                 let rangeFactor = 1;
28492
28493                 if ( material.wireframe === true ) {
28494
28495                         index = geometries.getWireframeAttribute( geometry );
28496                         rangeFactor = 2;
28497
28498                 }
28499
28500                 bindingStates.setup( object, material, program, geometry, index );
28501
28502                 let attribute;
28503                 let renderer = bufferRenderer;
28504
28505                 if ( index !== null ) {
28506
28507                         attribute = attributes.get( index );
28508
28509                         renderer = indexedBufferRenderer;
28510                         renderer.setIndex( attribute );
28511
28512                 }
28513
28514                 //
28515
28516                 const dataCount = ( index !== null ) ? index.count : position.count;
28517
28518                 const rangeStart = geometry.drawRange.start * rangeFactor;
28519                 const rangeCount = geometry.drawRange.count * rangeFactor;
28520
28521                 const groupStart = group !== null ? group.start * rangeFactor : 0;
28522                 const groupCount = group !== null ? group.count * rangeFactor : Infinity;
28523
28524                 const drawStart = Math.max( rangeStart, groupStart );
28525                 const drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
28526
28527                 const drawCount = Math.max( 0, drawEnd - drawStart + 1 );
28528
28529                 if ( drawCount === 0 ) return;
28530
28531                 //
28532
28533                 if ( object.isMesh ) {
28534
28535                         if ( material.wireframe === true ) {
28536
28537                                 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
28538                                 renderer.setMode( 1 );
28539
28540                         } else {
28541
28542                                 renderer.setMode( 4 );
28543
28544                         }
28545
28546                 } else if ( object.isLine ) {
28547
28548                         let lineWidth = material.linewidth;
28549
28550                         if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
28551
28552                         state.setLineWidth( lineWidth * getTargetPixelRatio() );
28553
28554                         if ( object.isLineSegments ) {
28555
28556                                 renderer.setMode( 1 );
28557
28558                         } else if ( object.isLineLoop ) {
28559
28560                                 renderer.setMode( 2 );
28561
28562                         } else {
28563
28564                                 renderer.setMode( 3 );
28565
28566                         }
28567
28568                 } else if ( object.isPoints ) {
28569
28570                         renderer.setMode( 0 );
28571
28572                 } else if ( object.isSprite ) {
28573
28574                         renderer.setMode( 4 );
28575
28576                 }
28577
28578                 if ( object.isInstancedMesh ) {
28579
28580                         renderer.renderInstances( drawStart, drawCount, object.count );
28581
28582                 } else if ( geometry.isInstancedBufferGeometry ) {
28583
28584                         const instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );
28585
28586                         renderer.renderInstances( drawStart, drawCount, instanceCount );
28587
28588                 } else {
28589
28590                         renderer.render( drawStart, drawCount );
28591
28592                 }
28593
28594         };
28595
28596         // Compile
28597
28598         this.compile = function ( scene, camera ) {
28599
28600                 currentRenderState = renderStates.get( scene );
28601                 currentRenderState.init();
28602
28603                 renderStateStack.push( currentRenderState );
28604
28605                 scene.traverseVisible( function ( object ) {
28606
28607                         if ( object.isLight && object.layers.test( camera.layers ) ) {
28608
28609                                 currentRenderState.pushLight( object );
28610
28611                                 if ( object.castShadow ) {
28612
28613                                         currentRenderState.pushShadow( object );
28614
28615                                 }
28616
28617                         }
28618
28619                 } );
28620
28621                 currentRenderState.setupLights( _this.physicallyCorrectLights );
28622
28623                 scene.traverse( function ( object ) {
28624
28625                         const material = object.material;
28626
28627                         if ( material ) {
28628
28629                                 if ( Array.isArray( material ) ) {
28630
28631                                         for ( let i = 0; i < material.length; i ++ ) {
28632
28633                                                 const material2 = material[ i ];
28634
28635                                                 getProgram( material2, scene, object );
28636
28637                                         }
28638
28639                                 } else {
28640
28641                                         getProgram( material, scene, object );
28642
28643                                 }
28644
28645                         }
28646
28647                 } );
28648
28649                 renderStateStack.pop();
28650                 currentRenderState = null;
28651
28652         };
28653
28654         // Animation Loop
28655
28656         let onAnimationFrameCallback = null;
28657
28658         function onAnimationFrame( time ) {
28659
28660                 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
28661
28662         }
28663
28664         function onXRSessionStart() {
28665
28666                 animation.stop();
28667
28668         }
28669
28670         function onXRSessionEnd() {
28671
28672                 animation.start();
28673
28674         }
28675
28676         const animation = new WebGLAnimation();
28677         animation.setAnimationLoop( onAnimationFrame );
28678
28679         if ( typeof window !== 'undefined' ) animation.setContext( window );
28680
28681         this.setAnimationLoop = function ( callback ) {
28682
28683                 onAnimationFrameCallback = callback;
28684                 xr.setAnimationLoop( callback );
28685
28686                 ( callback === null ) ? animation.stop() : animation.start();
28687
28688         };
28689
28690         xr.addEventListener( 'sessionstart', onXRSessionStart );
28691         xr.addEventListener( 'sessionend', onXRSessionEnd );
28692
28693         // Rendering
28694
28695         this.render = function ( scene, camera ) {
28696
28697                 if ( camera !== undefined && camera.isCamera !== true ) {
28698
28699                         console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
28700                         return;
28701
28702                 }
28703
28704                 if ( _isContextLost === true ) return;
28705
28706                 // update scene graph
28707
28708                 if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
28709
28710                 // update camera matrices and frustum
28711
28712                 if ( camera.parent === null ) camera.updateMatrixWorld();
28713
28714                 if ( xr.enabled === true && xr.isPresenting === true ) {
28715
28716                         if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera );
28717
28718                         camera = xr.getCamera(); // use XR camera for rendering
28719
28720                 }
28721
28722                 //
28723                 if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget );
28724
28725                 currentRenderState = renderStates.get( scene, renderStateStack.length );
28726                 currentRenderState.init();
28727
28728                 renderStateStack.push( currentRenderState );
28729
28730                 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
28731                 _frustum.setFromProjectionMatrix( _projScreenMatrix );
28732
28733                 _localClippingEnabled = this.localClippingEnabled;
28734                 _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
28735
28736                 currentRenderList = renderLists.get( scene, renderListStack.length );
28737                 currentRenderList.init();
28738
28739                 renderListStack.push( currentRenderList );
28740
28741                 projectObject( scene, camera, 0, _this.sortObjects );
28742
28743                 currentRenderList.finish();
28744
28745                 if ( _this.sortObjects === true ) {
28746
28747                         currentRenderList.sort( _opaqueSort, _transparentSort );
28748
28749                 }
28750
28751                 //
28752
28753                 if ( _clippingEnabled === true ) clipping.beginShadows();
28754
28755                 const shadowsArray = currentRenderState.state.shadowsArray;
28756
28757                 shadowMap.render( shadowsArray, scene, camera );
28758
28759                 if ( _clippingEnabled === true ) clipping.endShadows();
28760
28761                 //
28762
28763                 if ( this.info.autoReset === true ) this.info.reset();
28764
28765                 //
28766
28767                 background.render( currentRenderList, scene );
28768
28769                 // render scene
28770
28771                 currentRenderState.setupLights( _this.physicallyCorrectLights );
28772
28773                 if ( camera.isArrayCamera ) {
28774
28775                         const cameras = camera.cameras;
28776
28777                         for ( let i = 0, l = cameras.length; i < l; i ++ ) {
28778
28779                                 const camera2 = cameras[ i ];
28780
28781                                 renderScene( currentRenderList, scene, camera2, camera2.viewport );
28782
28783                         }
28784
28785                 } else {
28786
28787                         renderScene( currentRenderList, scene, camera );
28788
28789                 }
28790
28791                 //
28792
28793                 if ( _currentRenderTarget !== null ) {
28794
28795                         // resolve multisample renderbuffers to a single-sample texture if necessary
28796
28797                         textures.updateMultisampleRenderTarget( _currentRenderTarget );
28798
28799                         // Generate mipmap if we're using any kind of mipmap filtering
28800
28801                         textures.updateRenderTargetMipmap( _currentRenderTarget );
28802
28803                 }
28804
28805                 //
28806
28807                 if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );
28808
28809                 // Ensure depth buffer writing is enabled so it can be cleared on next render
28810
28811                 state.buffers.depth.setTest( true );
28812                 state.buffers.depth.setMask( true );
28813                 state.buffers.color.setMask( true );
28814
28815                 state.setPolygonOffset( false );
28816
28817                 // _gl.finish();
28818
28819                 bindingStates.resetDefaultState();
28820                 _currentMaterialId = - 1;
28821                 _currentCamera = null;
28822
28823                 renderStateStack.pop();
28824
28825                 if ( renderStateStack.length > 0 ) {
28826
28827                         currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
28828
28829                 } else {
28830
28831                         currentRenderState = null;
28832
28833                 }
28834
28835                 renderListStack.pop();
28836
28837                 if ( renderListStack.length > 0 ) {
28838
28839                         currentRenderList = renderListStack[ renderListStack.length - 1 ];
28840
28841                 } else {
28842
28843                         currentRenderList = null;
28844
28845                 }
28846
28847         };
28848
28849         function projectObject( object, camera, groupOrder, sortObjects ) {
28850
28851                 if ( object.visible === false ) return;
28852
28853                 const visible = object.layers.test( camera.layers );
28854
28855                 if ( visible ) {
28856
28857                         if ( object.isGroup ) {
28858
28859                                 groupOrder = object.renderOrder;
28860
28861                         } else if ( object.isLOD ) {
28862
28863                                 if ( object.autoUpdate === true ) object.update( camera );
28864
28865                         } else if ( object.isLight ) {
28866
28867                                 currentRenderState.pushLight( object );
28868
28869                                 if ( object.castShadow ) {
28870
28871                                         currentRenderState.pushShadow( object );
28872
28873                                 }
28874
28875                         } else if ( object.isSprite ) {
28876
28877                                 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
28878
28879                                         if ( sortObjects ) {
28880
28881                                                 _vector3.setFromMatrixPosition( object.matrixWorld )
28882                                                         .applyMatrix4( _projScreenMatrix );
28883
28884                                         }
28885
28886                                         const geometry = objects.update( object );
28887                                         const material = object.material;
28888
28889                                         if ( material.visible ) {
28890
28891                                                 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
28892
28893                                         }
28894
28895                                 }
28896
28897                         } else if ( object.isMesh || object.isLine || object.isPoints ) {
28898
28899                                 if ( object.isSkinnedMesh ) {
28900
28901                                         // update skeleton only once in a frame
28902
28903                                         if ( object.skeleton.frame !== info.render.frame ) {
28904
28905                                                 object.skeleton.update();
28906                                                 object.skeleton.frame = info.render.frame;
28907
28908                                         }
28909
28910                                 }
28911
28912                                 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
28913
28914                                         if ( sortObjects ) {
28915
28916                                                 _vector3.setFromMatrixPosition( object.matrixWorld )
28917                                                         .applyMatrix4( _projScreenMatrix );
28918
28919                                         }
28920
28921                                         const geometry = objects.update( object );
28922                                         const material = object.material;
28923
28924                                         if ( Array.isArray( material ) ) {
28925
28926                                                 const groups = geometry.groups;
28927
28928                                                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
28929
28930                                                         const group = groups[ i ];
28931                                                         const groupMaterial = material[ group.materialIndex ];
28932
28933                                                         if ( groupMaterial && groupMaterial.visible ) {
28934
28935                                                                 currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
28936
28937                                                         }
28938
28939                                                 }
28940
28941                                         } else if ( material.visible ) {
28942
28943                                                 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
28944
28945                                         }
28946
28947                                 }
28948
28949                         }
28950
28951                 }
28952
28953                 const children = object.children;
28954
28955                 for ( let i = 0, l = children.length; i < l; i ++ ) {
28956
28957                         projectObject( children[ i ], camera, groupOrder, sortObjects );
28958
28959                 }
28960
28961         }
28962
28963         function renderScene( currentRenderList, scene, camera, viewport ) {
28964
28965                 const opaqueObjects = currentRenderList.opaque;
28966                 const transmissiveObjects = currentRenderList.transmissive;
28967                 const transparentObjects = currentRenderList.transparent;
28968
28969                 currentRenderState.setupLightsView( camera );
28970
28971                 if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, scene, camera );
28972
28973                 if ( viewport ) state.viewport( _currentViewport.copy( viewport ) );
28974
28975                 if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
28976                 if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera );
28977                 if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
28978
28979         }
28980
28981         function renderTransmissionPass( opaqueObjects, scene, camera ) {
28982
28983                 if ( _transmissionRenderTarget === null ) {
28984
28985                         const needsAntialias = _antialias === true && capabilities.isWebGL2 === true;
28986                         const renderTargetType = needsAntialias ? WebGLMultisampleRenderTarget : WebGLRenderTarget;
28987
28988                         _transmissionRenderTarget = new renderTargetType( 1024, 1024, {
28989                                 generateMipmaps: true,
28990                                 type: utils.convert( HalfFloatType ) !== null ? HalfFloatType : UnsignedByteType,
28991                                 minFilter: LinearMipmapLinearFilter,
28992                                 magFilter: NearestFilter,
28993                                 wrapS: ClampToEdgeWrapping,
28994                                 wrapT: ClampToEdgeWrapping
28995                         } );
28996
28997                 }
28998
28999                 const currentRenderTarget = _this.getRenderTarget();
29000                 _this.setRenderTarget( _transmissionRenderTarget );
29001                 _this.clear();
29002
29003                 // Turn off the features which can affect the frag color for opaque objects pass.
29004                 // Otherwise they are applied twice in opaque objects pass and transmission objects pass.
29005                 const currentToneMapping = _this.toneMapping;
29006                 _this.toneMapping = NoToneMapping;
29007
29008                 renderObjects( opaqueObjects, scene, camera );
29009
29010                 _this.toneMapping = currentToneMapping;
29011
29012                 textures.updateMultisampleRenderTarget( _transmissionRenderTarget );
29013                 textures.updateRenderTargetMipmap( _transmissionRenderTarget );
29014
29015                 _this.setRenderTarget( currentRenderTarget );
29016
29017         }
29018
29019         function renderObjects( renderList, scene, camera ) {
29020
29021                 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
29022
29023                 for ( let i = 0, l = renderList.length; i < l; i ++ ) {
29024
29025                         const renderItem = renderList[ i ];
29026
29027                         const object = renderItem.object;
29028                         const geometry = renderItem.geometry;
29029                         const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
29030                         const group = renderItem.group;
29031
29032                         if ( object.layers.test( camera.layers ) ) {
29033
29034                                 renderObject( object, scene, camera, geometry, material, group );
29035
29036                         }
29037
29038                 }
29039
29040         }
29041
29042         function renderObject( object, scene, camera, geometry, material, group ) {
29043
29044                 object.onBeforeRender( _this, scene, camera, geometry, material, group );
29045
29046                 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
29047                 object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
29048
29049                 material.onBeforeRender( _this, scene, camera, geometry, object, group );
29050
29051                 if ( material.transparent === true && material.side === DoubleSide ) {
29052
29053                         material.side = BackSide;
29054                         material.needsUpdate = true;
29055                         _this.renderBufferDirect( camera, scene, geometry, material, object, group );
29056
29057                         material.side = FrontSide;
29058                         material.needsUpdate = true;
29059                         _this.renderBufferDirect( camera, scene, geometry, material, object, group );
29060
29061                         material.side = DoubleSide;
29062
29063                 } else {
29064
29065                         _this.renderBufferDirect( camera, scene, geometry, material, object, group );
29066
29067                 }
29068
29069                 object.onAfterRender( _this, scene, camera, geometry, material, group );
29070
29071         }
29072
29073         function getProgram( material, scene, object ) {
29074
29075                 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
29076
29077                 const materialProperties = properties.get( material );
29078
29079                 const lights = currentRenderState.state.lights;
29080                 const shadowsArray = currentRenderState.state.shadowsArray;
29081
29082                 const lightsStateVersion = lights.state.version;
29083
29084                 const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object );
29085                 const programCacheKey = programCache.getProgramCacheKey( parameters );
29086
29087                 let programs = materialProperties.programs;
29088
29089                 // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change
29090
29091                 materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
29092                 materialProperties.fog = scene.fog;
29093                 materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment );
29094
29095                 if ( programs === undefined ) {
29096
29097                         // new material
29098
29099                         material.addEventListener( 'dispose', onMaterialDispose );
29100
29101                         programs = new Map();
29102                         materialProperties.programs = programs;
29103
29104                 }
29105
29106                 let program = programs.get( programCacheKey );
29107
29108                 if ( program !== undefined ) {
29109
29110                         // early out if program and light state is identical
29111
29112                         if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) {
29113
29114                                 updateCommonMaterialProperties( material, parameters );
29115
29116                                 return program;
29117
29118                         }
29119
29120                 } else {
29121
29122                         parameters.uniforms = programCache.getUniforms( material );
29123
29124                         material.onBuild( object, parameters, _this );
29125
29126                         material.onBeforeCompile( parameters, _this );
29127
29128                         program = programCache.acquireProgram( parameters, programCacheKey );
29129                         programs.set( programCacheKey, program );
29130
29131                         materialProperties.uniforms = parameters.uniforms;
29132
29133                 }
29134
29135                 const uniforms = materialProperties.uniforms;
29136
29137                 if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) {
29138
29139                         uniforms.clippingPlanes = clipping.uniform;
29140
29141                 }
29142
29143                 updateCommonMaterialProperties( material, parameters );
29144
29145                 // store the light setup it was created for
29146
29147                 materialProperties.needsLights = materialNeedsLights( material );
29148                 materialProperties.lightsStateVersion = lightsStateVersion;
29149
29150                 if ( materialProperties.needsLights ) {
29151
29152                         // wire up the material to this renderer's lighting state
29153
29154                         uniforms.ambientLightColor.value = lights.state.ambient;
29155                         uniforms.lightProbe.value = lights.state.probe;
29156                         uniforms.directionalLights.value = lights.state.directional;
29157                         uniforms.directionalLightShadows.value = lights.state.directionalShadow;
29158                         uniforms.spotLights.value = lights.state.spot;
29159                         uniforms.spotLightShadows.value = lights.state.spotShadow;
29160                         uniforms.rectAreaLights.value = lights.state.rectArea;
29161                         uniforms.ltc_1.value = lights.state.rectAreaLTC1;
29162                         uniforms.ltc_2.value = lights.state.rectAreaLTC2;
29163                         uniforms.pointLights.value = lights.state.point;
29164                         uniforms.pointLightShadows.value = lights.state.pointShadow;
29165                         uniforms.hemisphereLights.value = lights.state.hemi;
29166
29167                         uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
29168                         uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
29169                         uniforms.spotShadowMap.value = lights.state.spotShadowMap;
29170                         uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
29171                         uniforms.pointShadowMap.value = lights.state.pointShadowMap;
29172                         uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
29173                         // TODO (abelnation): add area lights shadow info to uniforms
29174
29175                 }
29176
29177                 const progUniforms = program.getUniforms();
29178                 const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
29179
29180                 materialProperties.currentProgram = program;
29181                 materialProperties.uniformsList = uniformsList;
29182
29183                 return program;
29184
29185         }
29186
29187         function updateCommonMaterialProperties( material, parameters ) {
29188
29189                 const materialProperties = properties.get( material );
29190
29191                 materialProperties.outputEncoding = parameters.outputEncoding;
29192                 materialProperties.instancing = parameters.instancing;
29193                 materialProperties.skinning = parameters.skinning;
29194                 materialProperties.morphTargets = parameters.morphTargets;
29195                 materialProperties.morphNormals = parameters.morphNormals;
29196                 materialProperties.morphTargetsCount = parameters.morphTargetsCount;
29197                 materialProperties.numClippingPlanes = parameters.numClippingPlanes;
29198                 materialProperties.numIntersection = parameters.numClipIntersection;
29199                 materialProperties.vertexAlphas = parameters.vertexAlphas;
29200                 materialProperties.vertexTangents = parameters.vertexTangents;
29201
29202         }
29203
29204         function setProgram( camera, scene, geometry, material, object ) {
29205
29206                 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
29207
29208                 textures.resetTextureUnits();
29209
29210                 const fog = scene.fog;
29211                 const environment = material.isMeshStandardMaterial ? scene.environment : null;
29212                 const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding;
29213                 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
29214                 const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4;
29215                 const vertexTangents = !! material.normalMap && !! geometry.attributes.tangent;
29216                 const morphTargets = !! geometry.morphAttributes.position;
29217                 const morphNormals = !! geometry.morphAttributes.normal;
29218                 const morphTargetsCount = !! geometry.morphAttributes.position ? geometry.morphAttributes.position.length : 0;
29219
29220                 const materialProperties = properties.get( material );
29221                 const lights = currentRenderState.state.lights;
29222
29223                 if ( _clippingEnabled === true ) {
29224
29225                         if ( _localClippingEnabled === true || camera !== _currentCamera ) {
29226
29227                                 const useCache =
29228                                         camera === _currentCamera &&
29229                                         material.id === _currentMaterialId;
29230
29231                                 // we might want to call this function with some ClippingGroup
29232                                 // object instead of the material, once it becomes feasible
29233                                 // (#8465, #8379)
29234                                 clipping.setState( material, camera, useCache );
29235
29236                         }
29237
29238                 }
29239
29240                 //
29241
29242                 let needsProgramChange = false;
29243
29244                 if ( material.version === materialProperties.__version ) {
29245
29246                         if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
29247
29248                                 needsProgramChange = true;
29249
29250                         } else if ( materialProperties.outputEncoding !== encoding ) {
29251
29252                                 needsProgramChange = true;
29253
29254                         } else if ( object.isInstancedMesh && materialProperties.instancing === false ) {
29255
29256                                 needsProgramChange = true;
29257
29258                         } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) {
29259
29260                                 needsProgramChange = true;
29261
29262                         } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) {
29263
29264                                 needsProgramChange = true;
29265
29266                         } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) {
29267
29268                                 needsProgramChange = true;
29269
29270                         } else if ( materialProperties.envMap !== envMap ) {
29271
29272                                 needsProgramChange = true;
29273
29274                         } else if ( material.fog && materialProperties.fog !== fog ) {
29275
29276                                 needsProgramChange = true;
29277
29278                         } else if ( materialProperties.numClippingPlanes !== undefined &&
29279                                 ( materialProperties.numClippingPlanes !== clipping.numPlanes ||
29280                                 materialProperties.numIntersection !== clipping.numIntersection ) ) {
29281
29282                                 needsProgramChange = true;
29283
29284                         } else if ( materialProperties.vertexAlphas !== vertexAlphas ) {
29285
29286                                 needsProgramChange = true;
29287
29288                         } else if ( materialProperties.vertexTangents !== vertexTangents ) {
29289
29290                                 needsProgramChange = true;
29291
29292                         } else if ( materialProperties.morphTargets !== morphTargets ) {
29293
29294                                 needsProgramChange = true;
29295
29296                         } else if ( materialProperties.morphNormals !== morphNormals ) {
29297
29298                                 needsProgramChange = true;
29299
29300                         } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) {
29301
29302                                 needsProgramChange = true;
29303
29304                         }
29305
29306                 } else {
29307
29308                         needsProgramChange = true;
29309                         materialProperties.__version = material.version;
29310
29311                 }
29312
29313                 //
29314
29315                 let program = materialProperties.currentProgram;
29316
29317                 if ( needsProgramChange === true ) {
29318
29319                         program = getProgram( material, scene, object );
29320
29321                 }
29322
29323                 let refreshProgram = false;
29324                 let refreshMaterial = false;
29325                 let refreshLights = false;
29326
29327                 const p_uniforms = program.getUniforms(),
29328                         m_uniforms = materialProperties.uniforms;
29329
29330                 if ( state.useProgram( program.program ) ) {
29331
29332                         refreshProgram = true;
29333                         refreshMaterial = true;
29334                         refreshLights = true;
29335
29336                 }
29337
29338                 if ( material.id !== _currentMaterialId ) {
29339
29340                         _currentMaterialId = material.id;
29341
29342                         refreshMaterial = true;
29343
29344                 }
29345
29346                 if ( refreshProgram || _currentCamera !== camera ) {
29347
29348                         p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
29349
29350                         if ( capabilities.logarithmicDepthBuffer ) {
29351
29352                                 p_uniforms.setValue( _gl, 'logDepthBufFC',
29353                                         2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
29354
29355                         }
29356
29357                         if ( _currentCamera !== camera ) {
29358
29359                                 _currentCamera = camera;
29360
29361                                 // lighting uniforms depend on the camera so enforce an update
29362                                 // now, in case this material supports lights - or later, when
29363                                 // the next material that does gets activated:
29364
29365                                 refreshMaterial = true;         // set to true on material change
29366                                 refreshLights = true;           // remains set until update done
29367
29368                         }
29369
29370                         // load material specific uniforms
29371                         // (shader material also gets them for the sake of genericity)
29372
29373                         if ( material.isShaderMaterial ||
29374                                 material.isMeshPhongMaterial ||
29375                                 material.isMeshToonMaterial ||
29376                                 material.isMeshStandardMaterial ||
29377                                 material.envMap ) {
29378
29379                                 const uCamPos = p_uniforms.map.cameraPosition;
29380
29381                                 if ( uCamPos !== undefined ) {
29382
29383                                         uCamPos.setValue( _gl,
29384                                                 _vector3.setFromMatrixPosition( camera.matrixWorld ) );
29385
29386                                 }
29387
29388                         }
29389
29390                         if ( material.isMeshPhongMaterial ||
29391                                 material.isMeshToonMaterial ||
29392                                 material.isMeshLambertMaterial ||
29393                                 material.isMeshBasicMaterial ||
29394                                 material.isMeshStandardMaterial ||
29395                                 material.isShaderMaterial ) {
29396
29397                                 p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );
29398
29399                         }
29400
29401                         if ( material.isMeshPhongMaterial ||
29402                                 material.isMeshToonMaterial ||
29403                                 material.isMeshLambertMaterial ||
29404                                 material.isMeshBasicMaterial ||
29405                                 material.isMeshStandardMaterial ||
29406                                 material.isShaderMaterial ||
29407                                 material.isShadowMaterial ||
29408                                 object.isSkinnedMesh ) {
29409
29410                                 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
29411
29412                         }
29413
29414                 }
29415
29416                 // skinning and morph target uniforms must be set even if material didn't change
29417                 // auto-setting of texture unit for bone and morph texture must go before other textures
29418                 // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures
29419
29420                 if ( object.isSkinnedMesh ) {
29421
29422                         p_uniforms.setOptional( _gl, object, 'bindMatrix' );
29423                         p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
29424
29425                         const skeleton = object.skeleton;
29426
29427                         if ( skeleton ) {
29428
29429                                 if ( capabilities.floatVertexTextures ) {
29430
29431                                         if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture();
29432
29433                                         p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );
29434                                         p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
29435
29436                                 } else {
29437
29438                                         p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
29439
29440                                 }
29441
29442                         }
29443
29444                 }
29445
29446                 if ( !! geometry && ( geometry.morphAttributes.position !== undefined || geometry.morphAttributes.normal !== undefined ) ) {
29447
29448                         morphtargets.update( object, geometry, material, program );
29449
29450                 }
29451
29452
29453                 if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {
29454
29455                         materialProperties.receiveShadow = object.receiveShadow;
29456                         p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );
29457
29458                 }
29459
29460                 if ( refreshMaterial ) {
29461
29462                         p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
29463
29464                         if ( materialProperties.needsLights ) {
29465
29466                                 // the current material requires lighting info
29467
29468                                 // note: all lighting uniforms are always set correctly
29469                                 // they simply reference the renderer's state for their
29470                                 // values
29471                                 //
29472                                 // use the current material's .needsUpdate flags to set
29473                                 // the GL state when required
29474
29475                                 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
29476
29477                         }
29478
29479                         // refresh uniforms common to several materials
29480
29481                         if ( fog && material.fog ) {
29482
29483                                 materials.refreshFogUniforms( m_uniforms, fog );
29484
29485                         }
29486
29487                         materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget );
29488
29489                         WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
29490
29491                 }
29492
29493                 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
29494
29495                         WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
29496                         material.uniformsNeedUpdate = false;
29497
29498                 }
29499
29500                 if ( material.isSpriteMaterial ) {
29501
29502                         p_uniforms.setValue( _gl, 'center', object.center );
29503
29504                 }
29505
29506                 // common matrices
29507
29508                 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
29509                 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
29510                 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
29511
29512                 return program;
29513
29514         }
29515
29516         // If uniforms are marked as clean, they don't need to be loaded to the GPU.
29517
29518         function markUniformsLightsNeedsUpdate( uniforms, value ) {
29519
29520                 uniforms.ambientLightColor.needsUpdate = value;
29521                 uniforms.lightProbe.needsUpdate = value;
29522
29523                 uniforms.directionalLights.needsUpdate = value;
29524                 uniforms.directionalLightShadows.needsUpdate = value;
29525                 uniforms.pointLights.needsUpdate = value;
29526                 uniforms.pointLightShadows.needsUpdate = value;
29527                 uniforms.spotLights.needsUpdate = value;
29528                 uniforms.spotLightShadows.needsUpdate = value;
29529                 uniforms.rectAreaLights.needsUpdate = value;
29530                 uniforms.hemisphereLights.needsUpdate = value;
29531
29532         }
29533
29534         function materialNeedsLights( material ) {
29535
29536                 return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
29537                         material.isMeshStandardMaterial || material.isShadowMaterial ||
29538                         ( material.isShaderMaterial && material.lights === true );
29539
29540         }
29541
29542         this.getActiveCubeFace = function () {
29543
29544                 return _currentActiveCubeFace;
29545
29546         };
29547
29548         this.getActiveMipmapLevel = function () {
29549
29550                 return _currentActiveMipmapLevel;
29551
29552         };
29553
29554         this.getRenderTarget = function () {
29555
29556                 return _currentRenderTarget;
29557
29558         };
29559
29560         this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) {
29561
29562                 _currentRenderTarget = renderTarget;
29563                 _currentActiveCubeFace = activeCubeFace;
29564                 _currentActiveMipmapLevel = activeMipmapLevel;
29565
29566                 if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
29567
29568                         textures.setupRenderTarget( renderTarget );
29569
29570                 }
29571
29572                 let framebuffer = null;
29573                 let isCube = false;
29574                 let isRenderTarget3D = false;
29575
29576                 if ( renderTarget ) {
29577
29578                         const texture = renderTarget.texture;
29579
29580                         if ( texture.isDataTexture3D || texture.isDataTexture2DArray ) {
29581
29582                                 isRenderTarget3D = true;
29583
29584                         }
29585
29586                         const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
29587
29588                         if ( renderTarget.isWebGLCubeRenderTarget ) {
29589
29590                                 framebuffer = __webglFramebuffer[ activeCubeFace ];
29591                                 isCube = true;
29592
29593                         } else if ( renderTarget.isWebGLMultisampleRenderTarget ) {
29594
29595                                 framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
29596
29597                         } else {
29598
29599                                 framebuffer = __webglFramebuffer;
29600
29601                         }
29602
29603                         _currentViewport.copy( renderTarget.viewport );
29604                         _currentScissor.copy( renderTarget.scissor );
29605                         _currentScissorTest = renderTarget.scissorTest;
29606
29607                 } else {
29608
29609                         _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
29610                         _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
29611                         _currentScissorTest = _scissorTest;
29612
29613                 }
29614
29615                 const framebufferBound = state.bindFramebuffer( 36160, framebuffer );
29616
29617                 if ( framebufferBound && capabilities.drawBuffers ) {
29618
29619                         let needsUpdate = false;
29620
29621                         if ( renderTarget ) {
29622
29623                                 if ( renderTarget.isWebGLMultipleRenderTargets ) {
29624
29625                                         const textures = renderTarget.texture;
29626
29627                                         if ( _currentDrawBuffers.length !== textures.length || _currentDrawBuffers[ 0 ] !== 36064 ) {
29628
29629                                                 for ( let i = 0, il = textures.length; i < il; i ++ ) {
29630
29631                                                         _currentDrawBuffers[ i ] = 36064 + i;
29632
29633                                                 }
29634
29635                                                 _currentDrawBuffers.length = textures.length;
29636
29637                                                 needsUpdate = true;
29638
29639                                         }
29640
29641                                 } else {
29642
29643                                         if ( _currentDrawBuffers.length !== 1 || _currentDrawBuffers[ 0 ] !== 36064 ) {
29644
29645                                                 _currentDrawBuffers[ 0 ] = 36064;
29646                                                 _currentDrawBuffers.length = 1;
29647
29648                                                 needsUpdate = true;
29649
29650                                         }
29651
29652                                 }
29653
29654                         } else {
29655
29656                                 if ( _currentDrawBuffers.length !== 1 || _currentDrawBuffers[ 0 ] !== 1029 ) {
29657
29658                                         _currentDrawBuffers[ 0 ] = 1029;
29659                                         _currentDrawBuffers.length = 1;
29660
29661                                         needsUpdate = true;
29662
29663                                 }
29664
29665                         }
29666
29667                         if ( needsUpdate ) {
29668
29669                                 if ( capabilities.isWebGL2 ) {
29670
29671                                         _gl.drawBuffers( _currentDrawBuffers );
29672
29673                                 } else {
29674
29675                                         extensions.get( 'WEBGL_draw_buffers' ).drawBuffersWEBGL( _currentDrawBuffers );
29676
29677                                 }
29678
29679                         }
29680
29681                 }
29682
29683                 state.viewport( _currentViewport );
29684                 state.scissor( _currentScissor );
29685                 state.setScissorTest( _currentScissorTest );
29686
29687                 if ( isCube ) {
29688
29689                         const textureProperties = properties.get( renderTarget.texture );
29690                         _gl.framebufferTexture2D( 36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel );
29691
29692                 } else if ( isRenderTarget3D ) {
29693
29694                         const textureProperties = properties.get( renderTarget.texture );
29695                         const layer = activeCubeFace || 0;
29696                         _gl.framebufferTextureLayer( 36160, 36064, textureProperties.__webglTexture, activeMipmapLevel || 0, layer );
29697
29698                 }
29699
29700                 _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings
29701
29702         };
29703
29704         this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
29705
29706                 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
29707
29708                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
29709                         return;
29710
29711                 }
29712
29713                 let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
29714
29715                 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
29716
29717                         framebuffer = framebuffer[ activeCubeFaceIndex ];
29718
29719                 }
29720
29721                 if ( framebuffer ) {
29722
29723                         state.bindFramebuffer( 36160, framebuffer );
29724
29725                         try {
29726
29727                                 const texture = renderTarget.texture;
29728                                 const textureFormat = texture.format;
29729                                 const textureType = texture.type;
29730
29731                                 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {
29732
29733                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
29734                                         return;
29735
29736                                 }
29737
29738                                 const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) );
29739
29740                                 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // Edge and Chrome Mac < 52 (#9513)
29741                                         ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
29742                                         ! halfFloatSupportedByExt ) {
29743
29744                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
29745                                         return;
29746
29747                                 }
29748
29749                                 if ( _gl.checkFramebufferStatus( 36160 ) === 36053 ) {
29750
29751                                         // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
29752
29753                                         if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
29754
29755                                                 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
29756
29757                                         }
29758
29759                                 } else {
29760
29761                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
29762
29763                                 }
29764
29765                         } finally {
29766
29767                                 // restore framebuffer of current render target if necessary
29768
29769                                 const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null;
29770                                 state.bindFramebuffer( 36160, framebuffer );
29771
29772                         }
29773
29774                 }
29775
29776         };
29777
29778         this.copyFramebufferToTexture = function ( position, texture, level = 0 ) {
29779
29780                 const levelScale = Math.pow( 2, - level );
29781                 const width = Math.floor( texture.image.width * levelScale );
29782                 const height = Math.floor( texture.image.height * levelScale );
29783
29784                 let glFormat = utils.convert( texture.format );
29785
29786                 if ( capabilities.isWebGL2 ) {
29787
29788                         // Workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=1120100
29789                         // Not needed in Chrome 93+
29790
29791                         if ( glFormat === 6407 ) glFormat = 32849;
29792                         if ( glFormat === 6408 ) glFormat = 32856;
29793
29794                 }
29795
29796                 textures.setTexture2D( texture, 0 );
29797
29798                 _gl.copyTexImage2D( 3553, level, glFormat, position.x, position.y, width, height, 0 );
29799
29800                 state.unbindTexture();
29801
29802         };
29803
29804         this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) {
29805
29806                 const width = srcTexture.image.width;
29807                 const height = srcTexture.image.height;
29808                 const glFormat = utils.convert( dstTexture.format );
29809                 const glType = utils.convert( dstTexture.type );
29810
29811                 textures.setTexture2D( dstTexture, 0 );
29812
29813                 // As another texture upload may have changed pixelStorei
29814                 // parameters, make sure they are correct for the dstTexture
29815                 _gl.pixelStorei( 37440, dstTexture.flipY );
29816                 _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha );
29817                 _gl.pixelStorei( 3317, dstTexture.unpackAlignment );
29818
29819                 if ( srcTexture.isDataTexture ) {
29820
29821                         _gl.texSubImage2D( 3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
29822
29823                 } else {
29824
29825                         if ( srcTexture.isCompressedTexture ) {
29826
29827                                 _gl.compressedTexSubImage2D( 3553, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
29828
29829                         } else {
29830
29831                                 _gl.texSubImage2D( 3553, level, position.x, position.y, glFormat, glType, srcTexture.image );
29832
29833                         }
29834
29835                 }
29836
29837                 // Generate mipmaps only when copying level 0
29838                 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( 3553 );
29839
29840                 state.unbindTexture();
29841
29842         };
29843
29844         this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) {
29845
29846                 if ( _this.isWebGL1Renderer ) {
29847
29848                         console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' );
29849                         return;
29850
29851                 }
29852
29853                 const width = sourceBox.max.x - sourceBox.min.x + 1;
29854                 const height = sourceBox.max.y - sourceBox.min.y + 1;
29855                 const depth = sourceBox.max.z - sourceBox.min.z + 1;
29856                 const glFormat = utils.convert( dstTexture.format );
29857                 const glType = utils.convert( dstTexture.type );
29858                 let glTarget;
29859
29860                 if ( dstTexture.isDataTexture3D ) {
29861
29862                         textures.setTexture3D( dstTexture, 0 );
29863                         glTarget = 32879;
29864
29865                 } else if ( dstTexture.isDataTexture2DArray ) {
29866
29867                         textures.setTexture2DArray( dstTexture, 0 );
29868                         glTarget = 35866;
29869
29870                 } else {
29871
29872                         console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' );
29873                         return;
29874
29875                 }
29876
29877                 _gl.pixelStorei( 37440, dstTexture.flipY );
29878                 _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha );
29879                 _gl.pixelStorei( 3317, dstTexture.unpackAlignment );
29880
29881                 const unpackRowLen = _gl.getParameter( 3314 );
29882                 const unpackImageHeight = _gl.getParameter( 32878 );
29883                 const unpackSkipPixels = _gl.getParameter( 3316 );
29884                 const unpackSkipRows = _gl.getParameter( 3315 );
29885                 const unpackSkipImages = _gl.getParameter( 32877 );
29886
29887                 const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image;
29888
29889                 _gl.pixelStorei( 3314, image.width );
29890                 _gl.pixelStorei( 32878, image.height );
29891                 _gl.pixelStorei( 3316, sourceBox.min.x );
29892                 _gl.pixelStorei( 3315, sourceBox.min.y );
29893                 _gl.pixelStorei( 32877, sourceBox.min.z );
29894
29895                 if ( srcTexture.isDataTexture || srcTexture.isDataTexture3D ) {
29896
29897                         _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data );
29898
29899                 } else {
29900
29901                         if ( srcTexture.isCompressedTexture ) {
29902
29903                                 console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' );
29904                                 _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data );
29905
29906                         } else {
29907
29908                                 _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image );
29909
29910                         }
29911
29912                 }
29913
29914                 _gl.pixelStorei( 3314, unpackRowLen );
29915                 _gl.pixelStorei( 32878, unpackImageHeight );
29916                 _gl.pixelStorei( 3316, unpackSkipPixels );
29917                 _gl.pixelStorei( 3315, unpackSkipRows );
29918                 _gl.pixelStorei( 32877, unpackSkipImages );
29919
29920                 // Generate mipmaps only when copying level 0
29921                 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget );
29922
29923                 state.unbindTexture();
29924
29925         };
29926
29927         this.initTexture = function ( texture ) {
29928
29929                 textures.setTexture2D( texture, 0 );
29930
29931                 state.unbindTexture();
29932
29933         };
29934
29935         this.resetState = function () {
29936
29937                 _currentActiveCubeFace = 0;
29938                 _currentActiveMipmapLevel = 0;
29939                 _currentRenderTarget = null;
29940
29941                 state.reset();
29942                 bindingStates.reset();
29943
29944         };
29945
29946         if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
29947
29948                 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
29949
29950         }
29951
29952     }
29953
29954     WebGLRenderer.prototype.isWebGLRenderer = true;
29955
29956     class WebGL1Renderer extends WebGLRenderer {}
29957
29958     WebGL1Renderer.prototype.isWebGL1Renderer = true;
29959
29960     class Scene extends Object3D {
29961
29962         constructor() {
29963
29964                 super();
29965
29966                 this.type = 'Scene';
29967
29968                 this.background = null;
29969                 this.environment = null;
29970                 this.fog = null;
29971
29972                 this.overrideMaterial = null;
29973
29974                 this.autoUpdate = true; // checked by the renderer
29975
29976                 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
29977
29978                         __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
29979
29980                 }
29981
29982         }
29983
29984         copy( source, recursive ) {
29985
29986                 super.copy( source, recursive );
29987
29988                 if ( source.background !== null ) this.background = source.background.clone();
29989                 if ( source.environment !== null ) this.environment = source.environment.clone();
29990                 if ( source.fog !== null ) this.fog = source.fog.clone();
29991
29992                 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
29993
29994                 this.autoUpdate = source.autoUpdate;
29995                 this.matrixAutoUpdate = source.matrixAutoUpdate;
29996
29997                 return this;
29998
29999         }
30000
30001         toJSON( meta ) {
30002
30003                 const data = super.toJSON( meta );
30004
30005                 if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
30006
30007                 return data;
30008
30009         }
30010
30011     }
30012
30013     Scene.prototype.isScene = true;
30014
30015     class InterleavedBuffer {
30016
30017         constructor( array, stride ) {
30018
30019                 this.array = array;
30020                 this.stride = stride;
30021                 this.count = array !== undefined ? array.length / stride : 0;
30022
30023                 this.usage = StaticDrawUsage;
30024                 this.updateRange = { offset: 0, count: - 1 };
30025
30026                 this.version = 0;
30027
30028                 this.uuid = generateUUID();
30029
30030         }
30031
30032         onUploadCallback() {}
30033
30034         set needsUpdate( value ) {
30035
30036                 if ( value === true ) this.version ++;
30037
30038         }
30039
30040         setUsage( value ) {
30041
30042                 this.usage = value;
30043
30044                 return this;
30045
30046         }
30047
30048         copy( source ) {
30049
30050                 this.array = new source.array.constructor( source.array );
30051                 this.count = source.count;
30052                 this.stride = source.stride;
30053                 this.usage = source.usage;
30054
30055                 return this;
30056
30057         }
30058
30059         copyAt( index1, attribute, index2 ) {
30060
30061                 index1 *= this.stride;
30062                 index2 *= attribute.stride;
30063
30064                 for ( let i = 0, l = this.stride; i < l; i ++ ) {
30065
30066                         this.array[ index1 + i ] = attribute.array[ index2 + i ];
30067
30068                 }
30069
30070                 return this;
30071
30072         }
30073
30074         set( value, offset = 0 ) {
30075
30076                 this.array.set( value, offset );
30077
30078                 return this;
30079
30080         }
30081
30082         clone( data ) {
30083
30084                 if ( data.arrayBuffers === undefined ) {
30085
30086                         data.arrayBuffers = {};
30087
30088                 }
30089
30090                 if ( this.array.buffer._uuid === undefined ) {
30091
30092                         this.array.buffer._uuid = generateUUID();
30093
30094                 }
30095
30096                 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
30097
30098                         data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
30099
30100                 }
30101
30102                 const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
30103
30104                 const ib = new this.constructor( array, this.stride );
30105                 ib.setUsage( this.usage );
30106
30107                 return ib;
30108
30109         }
30110
30111         onUpload( callback ) {
30112
30113                 this.onUploadCallback = callback;
30114
30115                 return this;
30116
30117         }
30118
30119         toJSON( data ) {
30120
30121                 if ( data.arrayBuffers === undefined ) {
30122
30123                         data.arrayBuffers = {};
30124
30125                 }
30126
30127                 // generate UUID for array buffer if necessary
30128
30129                 if ( this.array.buffer._uuid === undefined ) {
30130
30131                         this.array.buffer._uuid = generateUUID();
30132
30133                 }
30134
30135                 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
30136
30137                         data.arrayBuffers[ this.array.buffer._uuid ] = Array.prototype.slice.call( new Uint32Array( this.array.buffer ) );
30138
30139                 }
30140
30141                 //
30142
30143                 return {
30144                         uuid: this.uuid,
30145                         buffer: this.array.buffer._uuid,
30146                         type: this.array.constructor.name,
30147                         stride: this.stride
30148                 };
30149
30150         }
30151
30152     }
30153
30154     InterleavedBuffer.prototype.isInterleavedBuffer = true;
30155
30156     const _vector$6 = /*@__PURE__*/ new Vector3();
30157
30158     class InterleavedBufferAttribute {
30159
30160         constructor( interleavedBuffer, itemSize, offset, normalized = false ) {
30161
30162                 this.name = '';
30163
30164                 this.data = interleavedBuffer;
30165                 this.itemSize = itemSize;
30166                 this.offset = offset;
30167
30168                 this.normalized = normalized === true;
30169
30170         }
30171
30172         get count() {
30173
30174                 return this.data.count;
30175
30176         }
30177
30178         get array() {
30179
30180                 return this.data.array;
30181
30182         }
30183
30184         set needsUpdate( value ) {
30185
30186                 this.data.needsUpdate = value;
30187
30188         }
30189
30190         applyMatrix4( m ) {
30191
30192                 for ( let i = 0, l = this.data.count; i < l; i ++ ) {
30193
30194                         _vector$6.x = this.getX( i );
30195                         _vector$6.y = this.getY( i );
30196                         _vector$6.z = this.getZ( i );
30197
30198                         _vector$6.applyMatrix4( m );
30199
30200                         this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
30201
30202                 }
30203
30204                 return this;
30205
30206         }
30207
30208         applyNormalMatrix( m ) {
30209
30210                 for ( let i = 0, l = this.count; i < l; i ++ ) {
30211
30212                         _vector$6.x = this.getX( i );
30213                         _vector$6.y = this.getY( i );
30214                         _vector$6.z = this.getZ( i );
30215
30216                         _vector$6.applyNormalMatrix( m );
30217
30218                         this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
30219
30220                 }
30221
30222                 return this;
30223
30224         }
30225
30226         transformDirection( m ) {
30227
30228                 for ( let i = 0, l = this.count; i < l; i ++ ) {
30229
30230                         _vector$6.x = this.getX( i );
30231                         _vector$6.y = this.getY( i );
30232                         _vector$6.z = this.getZ( i );
30233
30234                         _vector$6.transformDirection( m );
30235
30236                         this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
30237
30238                 }
30239
30240                 return this;
30241
30242         }
30243
30244         setX( index, x ) {
30245
30246                 this.data.array[ index * this.data.stride + this.offset ] = x;
30247
30248                 return this;
30249
30250         }
30251
30252         setY( index, y ) {
30253
30254                 this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
30255
30256                 return this;
30257
30258         }
30259
30260         setZ( index, z ) {
30261
30262                 this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
30263
30264                 return this;
30265
30266         }
30267
30268         setW( index, w ) {
30269
30270                 this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
30271
30272                 return this;
30273
30274         }
30275
30276         getX( index ) {
30277
30278                 return this.data.array[ index * this.data.stride + this.offset ];
30279
30280         }
30281
30282         getY( index ) {
30283
30284                 return this.data.array[ index * this.data.stride + this.offset + 1 ];
30285
30286         }
30287
30288         getZ( index ) {
30289
30290                 return this.data.array[ index * this.data.stride + this.offset + 2 ];
30291
30292         }
30293
30294         getW( index ) {
30295
30296                 return this.data.array[ index * this.data.stride + this.offset + 3 ];
30297
30298         }
30299
30300         setXY( index, x, y ) {
30301
30302                 index = index * this.data.stride + this.offset;
30303
30304                 this.data.array[ index + 0 ] = x;
30305                 this.data.array[ index + 1 ] = y;
30306
30307                 return this;
30308
30309         }
30310
30311         setXYZ( index, x, y, z ) {
30312
30313                 index = index * this.data.stride + this.offset;
30314
30315                 this.data.array[ index + 0 ] = x;
30316                 this.data.array[ index + 1 ] = y;
30317                 this.data.array[ index + 2 ] = z;
30318
30319                 return this;
30320
30321         }
30322
30323         setXYZW( index, x, y, z, w ) {
30324
30325                 index = index * this.data.stride + this.offset;
30326
30327                 this.data.array[ index + 0 ] = x;
30328                 this.data.array[ index + 1 ] = y;
30329                 this.data.array[ index + 2 ] = z;
30330                 this.data.array[ index + 3 ] = w;
30331
30332                 return this;
30333
30334         }
30335
30336         clone( data ) {
30337
30338                 if ( data === undefined ) {
30339
30340                         console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interlaved buffer attribute will deinterleave buffer data.' );
30341
30342                         const array = [];
30343
30344                         for ( let i = 0; i < this.count; i ++ ) {
30345
30346                                 const index = i * this.data.stride + this.offset;
30347
30348                                 for ( let j = 0; j < this.itemSize; j ++ ) {
30349
30350                                         array.push( this.data.array[ index + j ] );
30351
30352                                 }
30353
30354                         }
30355
30356                         return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
30357
30358                 } else {
30359
30360                         if ( data.interleavedBuffers === undefined ) {
30361
30362                                 data.interleavedBuffers = {};
30363
30364                         }
30365
30366                         if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
30367
30368                                 data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
30369
30370                         }
30371
30372                         return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
30373
30374                 }
30375
30376         }
30377
30378         toJSON( data ) {
30379
30380                 if ( data === undefined ) {
30381
30382                         console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.' );
30383
30384                         const array = [];
30385
30386                         for ( let i = 0; i < this.count; i ++ ) {
30387
30388                                 const index = i * this.data.stride + this.offset;
30389
30390                                 for ( let j = 0; j < this.itemSize; j ++ ) {
30391
30392                                         array.push( this.data.array[ index + j ] );
30393
30394                                 }
30395
30396                         }
30397
30398                         // deinterleave data and save it as an ordinary buffer attribute for now
30399
30400                         return {
30401                                 itemSize: this.itemSize,
30402                                 type: this.array.constructor.name,
30403                                 array: array,
30404                                 normalized: this.normalized
30405                         };
30406
30407                 } else {
30408
30409                         // save as true interlaved attribtue
30410
30411                         if ( data.interleavedBuffers === undefined ) {
30412
30413                                 data.interleavedBuffers = {};
30414
30415                         }
30416
30417                         if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
30418
30419                                 data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
30420
30421                         }
30422
30423                         return {
30424                                 isInterleavedBufferAttribute: true,
30425                                 itemSize: this.itemSize,
30426                                 data: this.data.uuid,
30427                                 offset: this.offset,
30428                                 normalized: this.normalized
30429                         };
30430
30431                 }
30432
30433         }
30434
30435     }
30436
30437     InterleavedBufferAttribute.prototype.isInterleavedBufferAttribute = true;
30438
30439     /**
30440      * parameters = {
30441      *  color: <hex>,
30442      *  map: new THREE.Texture( <Image> ),
30443      *  alphaMap: new THREE.Texture( <Image> ),
30444      *  rotation: <float>,
30445      *  sizeAttenuation: <bool>
30446      * }
30447      */
30448
30449     class SpriteMaterial extends Material {
30450
30451         constructor( parameters ) {
30452
30453                 super();
30454
30455                 this.type = 'SpriteMaterial';
30456
30457                 this.color = new Color( 0xffffff );
30458
30459                 this.map = null;
30460
30461                 this.alphaMap = null;
30462
30463                 this.rotation = 0;
30464
30465                 this.sizeAttenuation = true;
30466
30467                 this.transparent = true;
30468
30469                 this.setValues( parameters );
30470
30471         }
30472
30473         copy( source ) {
30474
30475                 super.copy( source );
30476
30477                 this.color.copy( source.color );
30478
30479                 this.map = source.map;
30480
30481                 this.alphaMap = source.alphaMap;
30482
30483                 this.rotation = source.rotation;
30484
30485                 this.sizeAttenuation = source.sizeAttenuation;
30486
30487                 return this;
30488
30489         }
30490
30491     }
30492
30493     SpriteMaterial.prototype.isSpriteMaterial = true;
30494
30495     let _geometry;
30496
30497     const _intersectPoint = /*@__PURE__*/ new Vector3();
30498     const _worldScale = /*@__PURE__*/ new Vector3();
30499     const _mvPosition = /*@__PURE__*/ new Vector3();
30500
30501     const _alignedPosition = /*@__PURE__*/ new Vector2();
30502     const _rotatedPosition = /*@__PURE__*/ new Vector2();
30503     const _viewWorldMatrix = /*@__PURE__*/ new Matrix4();
30504
30505     const _vA = /*@__PURE__*/ new Vector3();
30506     const _vB = /*@__PURE__*/ new Vector3();
30507     const _vC = /*@__PURE__*/ new Vector3();
30508
30509     const _uvA = /*@__PURE__*/ new Vector2();
30510     const _uvB = /*@__PURE__*/ new Vector2();
30511     const _uvC = /*@__PURE__*/ new Vector2();
30512
30513     class Sprite extends Object3D {
30514
30515         constructor( material ) {
30516
30517                 super();
30518
30519                 this.type = 'Sprite';
30520
30521                 if ( _geometry === undefined ) {
30522
30523                         _geometry = new BufferGeometry();
30524
30525                         const float32Array = new Float32Array( [
30526                                 - 0.5, - 0.5, 0, 0, 0,
30527                                 0.5, - 0.5, 0, 1, 0,
30528                                 0.5, 0.5, 0, 1, 1,
30529                                 - 0.5, 0.5, 0, 0, 1
30530                         ] );
30531
30532                         const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
30533
30534                         _geometry.setIndex( [ 0, 1, 2,  0, 2, 3 ] );
30535                         _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
30536                         _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
30537
30538                 }
30539
30540                 this.geometry = _geometry;
30541                 this.material = ( material !== undefined ) ? material : new SpriteMaterial();
30542
30543                 this.center = new Vector2( 0.5, 0.5 );
30544
30545         }
30546
30547         raycast( raycaster, intersects ) {
30548
30549                 if ( raycaster.camera === null ) {
30550
30551                         console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
30552
30553                 }
30554
30555                 _worldScale.setFromMatrixScale( this.matrixWorld );
30556
30557                 _viewWorldMatrix.copy( raycaster.camera.matrixWorld );
30558                 this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
30559
30560                 _mvPosition.setFromMatrixPosition( this.modelViewMatrix );
30561
30562                 if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
30563
30564                         _worldScale.multiplyScalar( - _mvPosition.z );
30565
30566                 }
30567
30568                 const rotation = this.material.rotation;
30569                 let sin, cos;
30570
30571                 if ( rotation !== 0 ) {
30572
30573                         cos = Math.cos( rotation );
30574                         sin = Math.sin( rotation );
30575
30576                 }
30577
30578                 const center = this.center;
30579
30580                 transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
30581                 transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
30582                 transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
30583
30584                 _uvA.set( 0, 0 );
30585                 _uvB.set( 1, 0 );
30586                 _uvC.set( 1, 1 );
30587
30588                 // check first triangle
30589                 let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint );
30590
30591                 if ( intersect === null ) {
30592
30593                         // check second triangle
30594                         transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
30595                         _uvB.set( 0, 1 );
30596
30597                         intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint );
30598                         if ( intersect === null ) {
30599
30600                                 return;
30601
30602                         }
30603
30604                 }
30605
30606                 const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
30607
30608                 if ( distance < raycaster.near || distance > raycaster.far ) return;
30609
30610                 intersects.push( {
30611
30612                         distance: distance,
30613                         point: _intersectPoint.clone(),
30614                         uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ),
30615                         face: null,
30616                         object: this
30617
30618                 } );
30619
30620         }
30621
30622         copy( source ) {
30623
30624                 super.copy( source );
30625
30626                 if ( source.center !== undefined ) this.center.copy( source.center );
30627
30628                 this.material = source.material;
30629
30630                 return this;
30631
30632         }
30633
30634     }
30635
30636     Sprite.prototype.isSprite = true;
30637
30638     function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
30639
30640         // compute position in camera space
30641         _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
30642
30643         // to check if rotation is not zero
30644         if ( sin !== undefined ) {
30645
30646                 _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
30647                 _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
30648
30649         } else {
30650
30651                 _rotatedPosition.copy( _alignedPosition );
30652
30653         }
30654
30655
30656         vertexPosition.copy( mvPosition );
30657         vertexPosition.x += _rotatedPosition.x;
30658         vertexPosition.y += _rotatedPosition.y;
30659
30660         // transform to world space
30661         vertexPosition.applyMatrix4( _viewWorldMatrix );
30662
30663     }
30664
30665     const _basePosition = /*@__PURE__*/ new Vector3();
30666
30667     const _skinIndex = /*@__PURE__*/ new Vector4();
30668     const _skinWeight = /*@__PURE__*/ new Vector4();
30669
30670     const _vector$5 = /*@__PURE__*/ new Vector3();
30671     const _matrix = /*@__PURE__*/ new Matrix4();
30672
30673     class SkinnedMesh extends Mesh {
30674
30675         constructor( geometry, material ) {
30676
30677                 super( geometry, material );
30678
30679                 this.type = 'SkinnedMesh';
30680
30681                 this.bindMode = 'attached';
30682                 this.bindMatrix = new Matrix4();
30683                 this.bindMatrixInverse = new Matrix4();
30684
30685         }
30686
30687         copy( source ) {
30688
30689                 super.copy( source );
30690
30691                 this.bindMode = source.bindMode;
30692                 this.bindMatrix.copy( source.bindMatrix );
30693                 this.bindMatrixInverse.copy( source.bindMatrixInverse );
30694
30695                 this.skeleton = source.skeleton;
30696
30697                 return this;
30698
30699         }
30700
30701         bind( skeleton, bindMatrix ) {
30702
30703                 this.skeleton = skeleton;
30704
30705                 if ( bindMatrix === undefined ) {
30706
30707                         this.updateMatrixWorld( true );
30708
30709                         this.skeleton.calculateInverses();
30710
30711                         bindMatrix = this.matrixWorld;
30712
30713                 }
30714
30715                 this.bindMatrix.copy( bindMatrix );
30716                 this.bindMatrixInverse.copy( bindMatrix ).invert();
30717
30718         }
30719
30720         pose() {
30721
30722                 this.skeleton.pose();
30723
30724         }
30725
30726         normalizeSkinWeights() {
30727
30728                 const vector = new Vector4();
30729
30730                 const skinWeight = this.geometry.attributes.skinWeight;
30731
30732                 for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
30733
30734                         vector.x = skinWeight.getX( i );
30735                         vector.y = skinWeight.getY( i );
30736                         vector.z = skinWeight.getZ( i );
30737                         vector.w = skinWeight.getW( i );
30738
30739                         const scale = 1.0 / vector.manhattanLength();
30740
30741                         if ( scale !== Infinity ) {
30742
30743                                 vector.multiplyScalar( scale );
30744
30745                         } else {
30746
30747                                 vector.set( 1, 0, 0, 0 ); // do something reasonable
30748
30749                         }
30750
30751                         skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
30752
30753                 }
30754
30755         }
30756
30757         updateMatrixWorld( force ) {
30758
30759                 super.updateMatrixWorld( force );
30760
30761                 if ( this.bindMode === 'attached' ) {
30762
30763                         this.bindMatrixInverse.copy( this.matrixWorld ).invert();
30764
30765                 } else if ( this.bindMode === 'detached' ) {
30766
30767                         this.bindMatrixInverse.copy( this.bindMatrix ).invert();
30768
30769                 } else {
30770
30771                         console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
30772
30773                 }
30774
30775         }
30776
30777         boneTransform( index, target ) {
30778
30779                 const skeleton = this.skeleton;
30780                 const geometry = this.geometry;
30781
30782                 _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
30783                 _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
30784
30785                 _basePosition.copy( target ).applyMatrix4( this.bindMatrix );
30786
30787                 target.set( 0, 0, 0 );
30788
30789                 for ( let i = 0; i < 4; i ++ ) {
30790
30791                         const weight = _skinWeight.getComponent( i );
30792
30793                         if ( weight !== 0 ) {
30794
30795                                 const boneIndex = _skinIndex.getComponent( i );
30796
30797                                 _matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
30798
30799                                 target.addScaledVector( _vector$5.copy( _basePosition ).applyMatrix4( _matrix ), weight );
30800
30801                         }
30802
30803                 }
30804
30805                 return target.applyMatrix4( this.bindMatrixInverse );
30806
30807         }
30808
30809     }
30810
30811     SkinnedMesh.prototype.isSkinnedMesh = true;
30812
30813     class Bone extends Object3D {
30814
30815         constructor() {
30816
30817                 super();
30818
30819                 this.type = 'Bone';
30820
30821         }
30822
30823     }
30824
30825     Bone.prototype.isBone = true;
30826
30827     class DataTexture extends Texture {
30828
30829         constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, encoding ) {
30830
30831                 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
30832
30833                 this.image = { data: data, width: width, height: height };
30834
30835                 this.magFilter = magFilter;
30836                 this.minFilter = minFilter;
30837
30838                 this.generateMipmaps = false;
30839                 this.flipY = false;
30840                 this.unpackAlignment = 1;
30841
30842                 this.needsUpdate = true;
30843
30844         }
30845
30846     }
30847
30848     DataTexture.prototype.isDataTexture = true;
30849
30850     class InstancedBufferAttribute extends BufferAttribute {
30851
30852         constructor( array, itemSize, normalized, meshPerAttribute = 1 ) {
30853
30854                 if ( typeof normalized === 'number' ) {
30855
30856                         meshPerAttribute = normalized;
30857
30858                         normalized = false;
30859
30860                         console.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );
30861
30862                 }
30863
30864                 super( array, itemSize, normalized );
30865
30866                 this.meshPerAttribute = meshPerAttribute;
30867
30868         }
30869
30870         copy( source ) {
30871
30872                 super.copy( source );
30873
30874                 this.meshPerAttribute = source.meshPerAttribute;
30875
30876                 return this;
30877
30878         }
30879
30880         toJSON() {
30881
30882                 const data = super.toJSON();
30883
30884                 data.meshPerAttribute = this.meshPerAttribute;
30885
30886                 data.isInstancedBufferAttribute = true;
30887
30888                 return data;
30889
30890         }
30891
30892     }
30893
30894     InstancedBufferAttribute.prototype.isInstancedBufferAttribute = true;
30895
30896     const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4();
30897     const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4();
30898
30899     const _instanceIntersects = [];
30900
30901     const _mesh = /*@__PURE__*/ new Mesh();
30902
30903     class InstancedMesh extends Mesh {
30904
30905         constructor( geometry, material, count ) {
30906
30907                 super( geometry, material );
30908
30909                 this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 );
30910                 this.instanceColor = null;
30911
30912                 this.count = count;
30913
30914                 this.frustumCulled = false;
30915
30916         }
30917
30918         copy( source ) {
30919
30920                 super.copy( source );
30921
30922                 this.instanceMatrix.copy( source.instanceMatrix );
30923
30924                 if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
30925
30926                 this.count = source.count;
30927
30928                 return this;
30929
30930         }
30931
30932         getColorAt( index, color ) {
30933
30934                 color.fromArray( this.instanceColor.array, index * 3 );
30935
30936         }
30937
30938         getMatrixAt( index, matrix ) {
30939
30940                 matrix.fromArray( this.instanceMatrix.array, index * 16 );
30941
30942         }
30943
30944         raycast( raycaster, intersects ) {
30945
30946                 const matrixWorld = this.matrixWorld;
30947                 const raycastTimes = this.count;
30948
30949                 _mesh.geometry = this.geometry;
30950                 _mesh.material = this.material;
30951
30952                 if ( _mesh.material === undefined ) return;
30953
30954                 for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
30955
30956                         // calculate the world matrix for each instance
30957
30958                         this.getMatrixAt( instanceId, _instanceLocalMatrix );
30959
30960                         _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
30961
30962                         // the mesh represents this single instance
30963
30964                         _mesh.matrixWorld = _instanceWorldMatrix;
30965
30966                         _mesh.raycast( raycaster, _instanceIntersects );
30967
30968                         // process the result of raycast
30969
30970                         for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
30971
30972                                 const intersect = _instanceIntersects[ i ];
30973                                 intersect.instanceId = instanceId;
30974                                 intersect.object = this;
30975                                 intersects.push( intersect );
30976
30977                         }
30978
30979                         _instanceIntersects.length = 0;
30980
30981                 }
30982
30983         }
30984
30985         setColorAt( index, color ) {
30986
30987                 if ( this.instanceColor === null ) {
30988
30989                         this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 );
30990
30991                 }
30992
30993                 color.toArray( this.instanceColor.array, index * 3 );
30994
30995         }
30996
30997         setMatrixAt( index, matrix ) {
30998
30999                 matrix.toArray( this.instanceMatrix.array, index * 16 );
31000
31001         }
31002
31003         updateMorphTargets() {
31004
31005         }
31006
31007         dispose() {
31008
31009                 this.dispatchEvent( { type: 'dispose' } );
31010
31011         }
31012
31013     }
31014
31015     InstancedMesh.prototype.isInstancedMesh = true;
31016
31017     /**
31018      * parameters = {
31019      *  color: <hex>,
31020      *  opacity: <float>,
31021      *
31022      *  linewidth: <float>,
31023      *  linecap: "round",
31024      *  linejoin: "round"
31025      * }
31026      */
31027
31028     class LineBasicMaterial extends Material {
31029
31030         constructor( parameters ) {
31031
31032                 super();
31033
31034                 this.type = 'LineBasicMaterial';
31035
31036                 this.color = new Color( 0xffffff );
31037
31038                 this.linewidth = 1;
31039                 this.linecap = 'round';
31040                 this.linejoin = 'round';
31041
31042                 this.setValues( parameters );
31043
31044         }
31045
31046
31047         copy( source ) {
31048
31049                 super.copy( source );
31050
31051                 this.color.copy( source.color );
31052
31053                 this.linewidth = source.linewidth;
31054                 this.linecap = source.linecap;
31055                 this.linejoin = source.linejoin;
31056
31057                 return this;
31058
31059         }
31060
31061     }
31062
31063     LineBasicMaterial.prototype.isLineBasicMaterial = true;
31064
31065     const _start$1 = /*@__PURE__*/ new Vector3();
31066     const _end$1 = /*@__PURE__*/ new Vector3();
31067     const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4();
31068     const _ray$1 = /*@__PURE__*/ new Ray();
31069     const _sphere$1 = /*@__PURE__*/ new Sphere();
31070
31071     class Line extends Object3D {
31072
31073         constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
31074
31075                 super();
31076
31077                 this.type = 'Line';
31078
31079                 this.geometry = geometry;
31080                 this.material = material;
31081
31082                 this.updateMorphTargets();
31083
31084         }
31085
31086         copy( source ) {
31087
31088                 super.copy( source );
31089
31090                 this.material = source.material;
31091                 this.geometry = source.geometry;
31092
31093                 return this;
31094
31095         }
31096
31097         computeLineDistances() {
31098
31099                 const geometry = this.geometry;
31100
31101                 if ( geometry.isBufferGeometry ) {
31102
31103                         // we assume non-indexed geometry
31104
31105                         if ( geometry.index === null ) {
31106
31107                                 const positionAttribute = geometry.attributes.position;
31108                                 const lineDistances = [ 0 ];
31109
31110                                 for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
31111
31112                                         _start$1.fromBufferAttribute( positionAttribute, i - 1 );
31113                                         _end$1.fromBufferAttribute( positionAttribute, i );
31114
31115                                         lineDistances[ i ] = lineDistances[ i - 1 ];
31116                                         lineDistances[ i ] += _start$1.distanceTo( _end$1 );
31117
31118                                 }
31119
31120                                 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
31121
31122                         } else {
31123
31124                                 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
31125
31126                         }
31127
31128                 } else if ( geometry.isGeometry ) {
31129
31130                         console.error( 'THREE.Line.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
31131
31132                 }
31133
31134                 return this;
31135
31136         }
31137
31138         raycast( raycaster, intersects ) {
31139
31140                 const geometry = this.geometry;
31141                 const matrixWorld = this.matrixWorld;
31142                 const threshold = raycaster.params.Line.threshold;
31143                 const drawRange = geometry.drawRange;
31144
31145                 // Checking boundingSphere distance to ray
31146
31147                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
31148
31149                 _sphere$1.copy( geometry.boundingSphere );
31150                 _sphere$1.applyMatrix4( matrixWorld );
31151                 _sphere$1.radius += threshold;
31152
31153                 if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return;
31154
31155                 //
31156
31157                 _inverseMatrix$1.copy( matrixWorld ).invert();
31158                 _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
31159
31160                 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
31161                 const localThresholdSq = localThreshold * localThreshold;
31162
31163                 const vStart = new Vector3();
31164                 const vEnd = new Vector3();
31165                 const interSegment = new Vector3();
31166                 const interRay = new Vector3();
31167                 const step = this.isLineSegments ? 2 : 1;
31168
31169                 if ( geometry.isBufferGeometry ) {
31170
31171                         const index = geometry.index;
31172                         const attributes = geometry.attributes;
31173                         const positionAttribute = attributes.position;
31174
31175                         if ( index !== null ) {
31176
31177                                 const start = Math.max( 0, drawRange.start );
31178                                 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
31179
31180                                 for ( let i = start, l = end - 1; i < l; i += step ) {
31181
31182                                         const a = index.getX( i );
31183                                         const b = index.getX( i + 1 );
31184
31185                                         vStart.fromBufferAttribute( positionAttribute, a );
31186                                         vEnd.fromBufferAttribute( positionAttribute, b );
31187
31188                                         const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
31189
31190                                         if ( distSq > localThresholdSq ) continue;
31191
31192                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
31193
31194                                         const distance = raycaster.ray.origin.distanceTo( interRay );
31195
31196                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
31197
31198                                         intersects.push( {
31199
31200                                                 distance: distance,
31201                                                 // What do we want? intersection point on the ray or on the segment??
31202                                                 // point: raycaster.ray.at( distance ),
31203                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
31204                                                 index: i,
31205                                                 face: null,
31206                                                 faceIndex: null,
31207                                                 object: this
31208
31209                                         } );
31210
31211                                 }
31212
31213                         } else {
31214
31215                                 const start = Math.max( 0, drawRange.start );
31216                                 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
31217
31218                                 for ( let i = start, l = end - 1; i < l; i += step ) {
31219
31220                                         vStart.fromBufferAttribute( positionAttribute, i );
31221                                         vEnd.fromBufferAttribute( positionAttribute, i + 1 );
31222
31223                                         const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
31224
31225                                         if ( distSq > localThresholdSq ) continue;
31226
31227                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
31228
31229                                         const distance = raycaster.ray.origin.distanceTo( interRay );
31230
31231                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
31232
31233                                         intersects.push( {
31234
31235                                                 distance: distance,
31236                                                 // What do we want? intersection point on the ray or on the segment??
31237                                                 // point: raycaster.ray.at( distance ),
31238                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
31239                                                 index: i,
31240                                                 face: null,
31241                                                 faceIndex: null,
31242                                                 object: this
31243
31244                                         } );
31245
31246                                 }
31247
31248                         }
31249
31250                 } else if ( geometry.isGeometry ) {
31251
31252                         console.error( 'THREE.Line.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
31253
31254                 }
31255
31256         }
31257
31258         updateMorphTargets() {
31259
31260                 const geometry = this.geometry;
31261
31262                 if ( geometry.isBufferGeometry ) {
31263
31264                         const morphAttributes = geometry.morphAttributes;
31265                         const keys = Object.keys( morphAttributes );
31266
31267                         if ( keys.length > 0 ) {
31268
31269                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
31270
31271                                 if ( morphAttribute !== undefined ) {
31272
31273                                         this.morphTargetInfluences = [];
31274                                         this.morphTargetDictionary = {};
31275
31276                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
31277
31278                                                 const name = morphAttribute[ m ].name || String( m );
31279
31280                                                 this.morphTargetInfluences.push( 0 );
31281                                                 this.morphTargetDictionary[ name ] = m;
31282
31283                                         }
31284
31285                                 }
31286
31287                         }
31288
31289                 } else {
31290
31291                         const morphTargets = geometry.morphTargets;
31292
31293                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
31294
31295                                 console.error( 'THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
31296
31297                         }
31298
31299                 }
31300
31301         }
31302
31303     }
31304
31305     Line.prototype.isLine = true;
31306
31307     const _start = /*@__PURE__*/ new Vector3();
31308     const _end = /*@__PURE__*/ new Vector3();
31309
31310     class LineSegments extends Line {
31311
31312         constructor( geometry, material ) {
31313
31314                 super( geometry, material );
31315
31316                 this.type = 'LineSegments';
31317
31318         }
31319
31320         computeLineDistances() {
31321
31322                 const geometry = this.geometry;
31323
31324                 if ( geometry.isBufferGeometry ) {
31325
31326                         // we assume non-indexed geometry
31327
31328                         if ( geometry.index === null ) {
31329
31330                                 const positionAttribute = geometry.attributes.position;
31331                                 const lineDistances = [];
31332
31333                                 for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
31334
31335                                         _start.fromBufferAttribute( positionAttribute, i );
31336                                         _end.fromBufferAttribute( positionAttribute, i + 1 );
31337
31338                                         lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
31339                                         lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end );
31340
31341                                 }
31342
31343                                 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
31344
31345                         } else {
31346
31347                                 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
31348
31349                         }
31350
31351                 } else if ( geometry.isGeometry ) {
31352
31353                         console.error( 'THREE.LineSegments.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
31354
31355                 }
31356
31357                 return this;
31358
31359         }
31360
31361     }
31362
31363     LineSegments.prototype.isLineSegments = true;
31364
31365     class LineLoop extends Line {
31366
31367         constructor( geometry, material ) {
31368
31369                 super( geometry, material );
31370
31371                 this.type = 'LineLoop';
31372
31373         }
31374
31375     }
31376
31377     LineLoop.prototype.isLineLoop = true;
31378
31379     /**
31380      * parameters = {
31381      *  color: <hex>,
31382      *  opacity: <float>,
31383      *  map: new THREE.Texture( <Image> ),
31384      *  alphaMap: new THREE.Texture( <Image> ),
31385      *
31386      *  size: <float>,
31387      *  sizeAttenuation: <bool>
31388      *
31389      * }
31390      */
31391
31392     class PointsMaterial extends Material {
31393
31394         constructor( parameters ) {
31395
31396                 super();
31397
31398                 this.type = 'PointsMaterial';
31399
31400                 this.color = new Color( 0xffffff );
31401
31402                 this.map = null;
31403
31404                 this.alphaMap = null;
31405
31406                 this.size = 1;
31407                 this.sizeAttenuation = true;
31408
31409                 this.setValues( parameters );
31410
31411         }
31412
31413         copy( source ) {
31414
31415                 super.copy( source );
31416
31417                 this.color.copy( source.color );
31418
31419                 this.map = source.map;
31420
31421                 this.alphaMap = source.alphaMap;
31422
31423                 this.size = source.size;
31424                 this.sizeAttenuation = source.sizeAttenuation;
31425
31426                 return this;
31427
31428         }
31429
31430     }
31431
31432     PointsMaterial.prototype.isPointsMaterial = true;
31433
31434     const _inverseMatrix = /*@__PURE__*/ new Matrix4();
31435     const _ray = /*@__PURE__*/ new Ray();
31436     const _sphere = /*@__PURE__*/ new Sphere();
31437     const _position$2 = /*@__PURE__*/ new Vector3();
31438
31439     class Points extends Object3D {
31440
31441         constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
31442
31443                 super();
31444
31445                 this.type = 'Points';
31446
31447                 this.geometry = geometry;
31448                 this.material = material;
31449
31450                 this.updateMorphTargets();
31451
31452         }
31453
31454         copy( source ) {
31455
31456                 super.copy( source );
31457
31458                 this.material = source.material;
31459                 this.geometry = source.geometry;
31460
31461                 return this;
31462
31463         }
31464
31465         raycast( raycaster, intersects ) {
31466
31467                 const geometry = this.geometry;
31468                 const matrixWorld = this.matrixWorld;
31469                 const threshold = raycaster.params.Points.threshold;
31470                 const drawRange = geometry.drawRange;
31471
31472                 // Checking boundingSphere distance to ray
31473
31474                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
31475
31476                 _sphere.copy( geometry.boundingSphere );
31477                 _sphere.applyMatrix4( matrixWorld );
31478                 _sphere.radius += threshold;
31479
31480                 if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
31481
31482                 //
31483
31484                 _inverseMatrix.copy( matrixWorld ).invert();
31485                 _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
31486
31487                 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
31488                 const localThresholdSq = localThreshold * localThreshold;
31489
31490                 if ( geometry.isBufferGeometry ) {
31491
31492                         const index = geometry.index;
31493                         const attributes = geometry.attributes;
31494                         const positionAttribute = attributes.position;
31495
31496                         if ( index !== null ) {
31497
31498                                 const start = Math.max( 0, drawRange.start );
31499                                 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
31500
31501                                 for ( let i = start, il = end; i < il; i ++ ) {
31502
31503                                         const a = index.getX( i );
31504
31505                                         _position$2.fromBufferAttribute( positionAttribute, a );
31506
31507                                         testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
31508
31509                                 }
31510
31511                         } else {
31512
31513                                 const start = Math.max( 0, drawRange.start );
31514                                 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
31515
31516                                 for ( let i = start, l = end; i < l; i ++ ) {
31517
31518                                         _position$2.fromBufferAttribute( positionAttribute, i );
31519
31520                                         testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
31521
31522                                 }
31523
31524                         }
31525
31526                 } else {
31527
31528                         console.error( 'THREE.Points.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
31529
31530                 }
31531
31532         }
31533
31534         updateMorphTargets() {
31535
31536                 const geometry = this.geometry;
31537
31538                 if ( geometry.isBufferGeometry ) {
31539
31540                         const morphAttributes = geometry.morphAttributes;
31541                         const keys = Object.keys( morphAttributes );
31542
31543                         if ( keys.length > 0 ) {
31544
31545                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
31546
31547                                 if ( morphAttribute !== undefined ) {
31548
31549                                         this.morphTargetInfluences = [];
31550                                         this.morphTargetDictionary = {};
31551
31552                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
31553
31554                                                 const name = morphAttribute[ m ].name || String( m );
31555
31556                                                 this.morphTargetInfluences.push( 0 );
31557                                                 this.morphTargetDictionary[ name ] = m;
31558
31559                                         }
31560
31561                                 }
31562
31563                         }
31564
31565                 } else {
31566
31567                         const morphTargets = geometry.morphTargets;
31568
31569                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
31570
31571                                 console.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
31572
31573                         }
31574
31575                 }
31576
31577         }
31578
31579     }
31580
31581     Points.prototype.isPoints = true;
31582
31583     function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
31584
31585         const rayPointDistanceSq = _ray.distanceSqToPoint( point );
31586
31587         if ( rayPointDistanceSq < localThresholdSq ) {
31588
31589                 const intersectPoint = new Vector3();
31590
31591                 _ray.closestPointToPoint( point, intersectPoint );
31592                 intersectPoint.applyMatrix4( matrixWorld );
31593
31594                 const distance = raycaster.ray.origin.distanceTo( intersectPoint );
31595
31596                 if ( distance < raycaster.near || distance > raycaster.far ) return;
31597
31598                 intersects.push( {
31599
31600                         distance: distance,
31601                         distanceToRay: Math.sqrt( rayPointDistanceSq ),
31602                         point: intersectPoint,
31603                         index: index,
31604                         face: null,
31605                         object: object
31606
31607                 } );
31608
31609         }
31610
31611     }
31612
31613     class VideoTexture extends Texture {
31614
31615         constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
31616
31617                 super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
31618
31619                 this.format = format !== undefined ? format : RGBFormat;
31620
31621                 this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
31622                 this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
31623
31624                 this.generateMipmaps = false;
31625
31626                 const scope = this;
31627
31628                 function updateVideo() {
31629
31630                         scope.needsUpdate = true;
31631                         video.requestVideoFrameCallback( updateVideo );
31632
31633                 }
31634
31635                 if ( 'requestVideoFrameCallback' in video ) {
31636
31637                         video.requestVideoFrameCallback( updateVideo );
31638
31639                 }
31640
31641         }
31642
31643         clone() {
31644
31645                 return new this.constructor( this.image ).copy( this );
31646
31647         }
31648
31649         update() {
31650
31651                 const video = this.image;
31652                 const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
31653
31654                 if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
31655
31656                         this.needsUpdate = true;
31657
31658                 }
31659
31660         }
31661
31662     }
31663
31664     VideoTexture.prototype.isVideoTexture = true;
31665
31666     class CompressedTexture extends Texture {
31667
31668         constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
31669
31670                 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
31671
31672                 this.image = { width: width, height: height };
31673                 this.mipmaps = mipmaps;
31674
31675                 // no flipping for cube textures
31676                 // (also flipping doesn't work for compressed textures )
31677
31678                 this.flipY = false;
31679
31680                 // can't generate mipmaps for compressed textures
31681                 // mips must be embedded in DDS files
31682
31683                 this.generateMipmaps = false;
31684
31685         }
31686
31687     }
31688
31689     CompressedTexture.prototype.isCompressedTexture = true;
31690
31691     class CanvasTexture extends Texture {
31692
31693         constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
31694
31695                 super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
31696
31697                 this.needsUpdate = true;
31698
31699         }
31700
31701     }
31702
31703     CanvasTexture.prototype.isCanvasTexture = true;
31704
31705     class DepthTexture extends Texture {
31706
31707         constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
31708
31709                 format = format !== undefined ? format : DepthFormat;
31710
31711                 if ( format !== DepthFormat && format !== DepthStencilFormat ) {
31712
31713                         throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
31714
31715                 }
31716
31717                 if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
31718                 if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
31719
31720                 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
31721
31722                 this.image = { width: width, height: height };
31723
31724                 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
31725                 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
31726
31727                 this.flipY = false;
31728                 this.generateMipmaps    = false;
31729
31730         }
31731
31732
31733     }
31734
31735     DepthTexture.prototype.isDepthTexture = true;
31736
31737     class CircleGeometry extends BufferGeometry {
31738
31739         constructor( radius = 1, segments = 8, thetaStart = 0, thetaLength = Math.PI * 2 ) {
31740
31741                 super();
31742
31743                 this.type = 'CircleGeometry';
31744
31745                 this.parameters = {
31746                         radius: radius,
31747                         segments: segments,
31748                         thetaStart: thetaStart,
31749                         thetaLength: thetaLength
31750                 };
31751
31752                 segments = Math.max( 3, segments );
31753
31754                 // buffers
31755
31756                 const indices = [];
31757                 const vertices = [];
31758                 const normals = [];
31759                 const uvs = [];
31760
31761                 // helper variables
31762
31763                 const vertex = new Vector3();
31764                 const uv = new Vector2();
31765
31766                 // center point
31767
31768                 vertices.push( 0, 0, 0 );
31769                 normals.push( 0, 0, 1 );
31770                 uvs.push( 0.5, 0.5 );
31771
31772                 for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
31773
31774                         const segment = thetaStart + s / segments * thetaLength;
31775
31776                         // vertex
31777
31778                         vertex.x = radius * Math.cos( segment );
31779                         vertex.y = radius * Math.sin( segment );
31780
31781                         vertices.push( vertex.x, vertex.y, vertex.z );
31782
31783                         // normal
31784
31785                         normals.push( 0, 0, 1 );
31786
31787                         // uvs
31788
31789                         uv.x = ( vertices[ i ] / radius + 1 ) / 2;
31790                         uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
31791
31792                         uvs.push( uv.x, uv.y );
31793
31794                 }
31795
31796                 // indices
31797
31798                 for ( let i = 1; i <= segments; i ++ ) {
31799
31800                         indices.push( i, i + 1, 0 );
31801
31802                 }
31803
31804                 // build geometry
31805
31806                 this.setIndex( indices );
31807                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31808                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
31809                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
31810
31811         }
31812
31813         static fromJSON( data ) {
31814
31815                 return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength );
31816
31817         }
31818
31819     }
31820
31821     new Vector3();
31822     new Vector3();
31823     new Vector3();
31824     new Triangle();
31825
31826     /**
31827      * Extensible curve object.
31828      *
31829      * Some common of curve methods:
31830      * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
31831      * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
31832      * .getPoints(), .getSpacedPoints()
31833      * .getLength()
31834      * .updateArcLengths()
31835      *
31836      * This following curves inherit from THREE.Curve:
31837      *
31838      * -- 2D curves --
31839      * THREE.ArcCurve
31840      * THREE.CubicBezierCurve
31841      * THREE.EllipseCurve
31842      * THREE.LineCurve
31843      * THREE.QuadraticBezierCurve
31844      * THREE.SplineCurve
31845      *
31846      * -- 3D curves --
31847      * THREE.CatmullRomCurve3
31848      * THREE.CubicBezierCurve3
31849      * THREE.LineCurve3
31850      * THREE.QuadraticBezierCurve3
31851      *
31852      * A series of curves can be represented as a THREE.CurvePath.
31853      *
31854      **/
31855
31856     class Curve {
31857
31858         constructor() {
31859
31860                 this.type = 'Curve';
31861
31862                 this.arcLengthDivisions = 200;
31863
31864         }
31865
31866         // Virtual base class method to overwrite and implement in subclasses
31867         //      - t [0 .. 1]
31868
31869         getPoint( /* t, optionalTarget */ ) {
31870
31871                 console.warn( 'THREE.Curve: .getPoint() not implemented.' );
31872                 return null;
31873
31874         }
31875
31876         // Get point at relative position in curve according to arc length
31877         // - u [0 .. 1]
31878
31879         getPointAt( u, optionalTarget ) {
31880
31881                 const t = this.getUtoTmapping( u );
31882                 return this.getPoint( t, optionalTarget );
31883
31884         }
31885
31886         // Get sequence of points using getPoint( t )
31887
31888         getPoints( divisions = 5 ) {
31889
31890                 const points = [];
31891
31892                 for ( let d = 0; d <= divisions; d ++ ) {
31893
31894                         points.push( this.getPoint( d / divisions ) );
31895
31896                 }
31897
31898                 return points;
31899
31900         }
31901
31902         // Get sequence of points using getPointAt( u )
31903
31904         getSpacedPoints( divisions = 5 ) {
31905
31906                 const points = [];
31907
31908                 for ( let d = 0; d <= divisions; d ++ ) {
31909
31910                         points.push( this.getPointAt( d / divisions ) );
31911
31912                 }
31913
31914                 return points;
31915
31916         }
31917
31918         // Get total curve arc length
31919
31920         getLength() {
31921
31922                 const lengths = this.getLengths();
31923                 return lengths[ lengths.length - 1 ];
31924
31925         }
31926
31927         // Get list of cumulative segment lengths
31928
31929         getLengths( divisions = this.arcLengthDivisions ) {
31930
31931                 if ( this.cacheArcLengths &&
31932                         ( this.cacheArcLengths.length === divisions + 1 ) &&
31933                         ! this.needsUpdate ) {
31934
31935                         return this.cacheArcLengths;
31936
31937                 }
31938
31939                 this.needsUpdate = false;
31940
31941                 const cache = [];
31942                 let current, last = this.getPoint( 0 );
31943                 let sum = 0;
31944
31945                 cache.push( 0 );
31946
31947                 for ( let p = 1; p <= divisions; p ++ ) {
31948
31949                         current = this.getPoint( p / divisions );
31950                         sum += current.distanceTo( last );
31951                         cache.push( sum );
31952                         last = current;
31953
31954                 }
31955
31956                 this.cacheArcLengths = cache;
31957
31958                 return cache; // { sums: cache, sum: sum }; Sum is in the last element.
31959
31960         }
31961
31962         updateArcLengths() {
31963
31964                 this.needsUpdate = true;
31965                 this.getLengths();
31966
31967         }
31968
31969         // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
31970
31971         getUtoTmapping( u, distance ) {
31972
31973                 const arcLengths = this.getLengths();
31974
31975                 let i = 0;
31976                 const il = arcLengths.length;
31977
31978                 let targetArcLength; // The targeted u distance value to get
31979
31980                 if ( distance ) {
31981
31982                         targetArcLength = distance;
31983
31984                 } else {
31985
31986                         targetArcLength = u * arcLengths[ il - 1 ];
31987
31988                 }
31989
31990                 // binary search for the index with largest value smaller than target u distance
31991
31992                 let low = 0, high = il - 1, comparison;
31993
31994                 while ( low <= high ) {
31995
31996                         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
31997
31998                         comparison = arcLengths[ i ] - targetArcLength;
31999
32000                         if ( comparison < 0 ) {
32001
32002                                 low = i + 1;
32003
32004                         } else if ( comparison > 0 ) {
32005
32006                                 high = i - 1;
32007
32008                         } else {
32009
32010                                 high = i;
32011                                 break;
32012
32013                                 // DONE
32014
32015                         }
32016
32017                 }
32018
32019                 i = high;
32020
32021                 if ( arcLengths[ i ] === targetArcLength ) {
32022
32023                         return i / ( il - 1 );
32024
32025                 }
32026
32027                 // we could get finer grain at lengths, or use simple interpolation between two points
32028
32029                 const lengthBefore = arcLengths[ i ];
32030                 const lengthAfter = arcLengths[ i + 1 ];
32031
32032                 const segmentLength = lengthAfter - lengthBefore;
32033
32034                 // determine where we are between the 'before' and 'after' points
32035
32036                 const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
32037
32038                 // add that fractional amount to t
32039
32040                 const t = ( i + segmentFraction ) / ( il - 1 );
32041
32042                 return t;
32043
32044         }
32045
32046         // Returns a unit vector tangent at t
32047         // In case any sub curve does not implement its tangent derivation,
32048         // 2 points a small delta apart will be used to find its gradient
32049         // which seems to give a reasonable approximation
32050
32051         getTangent( t, optionalTarget ) {
32052
32053                 const delta = 0.0001;
32054                 let t1 = t - delta;
32055                 let t2 = t + delta;
32056
32057                 // Capping in case of danger
32058
32059                 if ( t1 < 0 ) t1 = 0;
32060                 if ( t2 > 1 ) t2 = 1;
32061
32062                 const pt1 = this.getPoint( t1 );
32063                 const pt2 = this.getPoint( t2 );
32064
32065                 const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
32066
32067                 tangent.copy( pt2 ).sub( pt1 ).normalize();
32068
32069                 return tangent;
32070
32071         }
32072
32073         getTangentAt( u, optionalTarget ) {
32074
32075                 const t = this.getUtoTmapping( u );
32076                 return this.getTangent( t, optionalTarget );
32077
32078         }
32079
32080         computeFrenetFrames( segments, closed ) {
32081
32082                 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
32083
32084                 const normal = new Vector3();
32085
32086                 const tangents = [];
32087                 const normals = [];
32088                 const binormals = [];
32089
32090                 const vec = new Vector3();
32091                 const mat = new Matrix4();
32092
32093                 // compute the tangent vectors for each segment on the curve
32094
32095                 for ( let i = 0; i <= segments; i ++ ) {
32096
32097                         const u = i / segments;
32098
32099                         tangents[ i ] = this.getTangentAt( u, new Vector3() );
32100
32101                 }
32102
32103                 // select an initial normal vector perpendicular to the first tangent vector,
32104                 // and in the direction of the minimum tangent xyz component
32105
32106                 normals[ 0 ] = new Vector3();
32107                 binormals[ 0 ] = new Vector3();
32108                 let min = Number.MAX_VALUE;
32109                 const tx = Math.abs( tangents[ 0 ].x );
32110                 const ty = Math.abs( tangents[ 0 ].y );
32111                 const tz = Math.abs( tangents[ 0 ].z );
32112
32113                 if ( tx <= min ) {
32114
32115                         min = tx;
32116                         normal.set( 1, 0, 0 );
32117
32118                 }
32119
32120                 if ( ty <= min ) {
32121
32122                         min = ty;
32123                         normal.set( 0, 1, 0 );
32124
32125                 }
32126
32127                 if ( tz <= min ) {
32128
32129                         normal.set( 0, 0, 1 );
32130
32131                 }
32132
32133                 vec.crossVectors( tangents[ 0 ], normal ).normalize();
32134
32135                 normals[ 0 ].crossVectors( tangents[ 0 ], vec );
32136                 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
32137
32138
32139                 // compute the slowly-varying normal and binormal vectors for each segment on the curve
32140
32141                 for ( let i = 1; i <= segments; i ++ ) {
32142
32143                         normals[ i ] = normals[ i - 1 ].clone();
32144
32145                         binormals[ i ] = binormals[ i - 1 ].clone();
32146
32147                         vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
32148
32149                         if ( vec.length() > Number.EPSILON ) {
32150
32151                                 vec.normalize();
32152
32153                                 const theta = Math.acos( clamp$1( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
32154
32155                                 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
32156
32157                         }
32158
32159                         binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
32160
32161                 }
32162
32163                 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
32164
32165                 if ( closed === true ) {
32166
32167                         let theta = Math.acos( clamp$1( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
32168                         theta /= segments;
32169
32170                         if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
32171
32172                                 theta = - theta;
32173
32174                         }
32175
32176                         for ( let i = 1; i <= segments; i ++ ) {
32177
32178                                 // twist a little...
32179                                 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
32180                                 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
32181
32182                         }
32183
32184                 }
32185
32186                 return {
32187                         tangents: tangents,
32188                         normals: normals,
32189                         binormals: binormals
32190                 };
32191
32192         }
32193
32194         clone() {
32195
32196                 return new this.constructor().copy( this );
32197
32198         }
32199
32200         copy( source ) {
32201
32202                 this.arcLengthDivisions = source.arcLengthDivisions;
32203
32204                 return this;
32205
32206         }
32207
32208         toJSON() {
32209
32210                 const data = {
32211                         metadata: {
32212                                 version: 4.5,
32213                                 type: 'Curve',
32214                                 generator: 'Curve.toJSON'
32215                         }
32216                 };
32217
32218                 data.arcLengthDivisions = this.arcLengthDivisions;
32219                 data.type = this.type;
32220
32221                 return data;
32222
32223         }
32224
32225         fromJSON( json ) {
32226
32227                 this.arcLengthDivisions = json.arcLengthDivisions;
32228
32229                 return this;
32230
32231         }
32232
32233     }
32234
32235     class EllipseCurve extends Curve {
32236
32237         constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) {
32238
32239                 super();
32240
32241                 this.type = 'EllipseCurve';
32242
32243                 this.aX = aX;
32244                 this.aY = aY;
32245
32246                 this.xRadius = xRadius;
32247                 this.yRadius = yRadius;
32248
32249                 this.aStartAngle = aStartAngle;
32250                 this.aEndAngle = aEndAngle;
32251
32252                 this.aClockwise = aClockwise;
32253
32254                 this.aRotation = aRotation;
32255
32256         }
32257
32258         getPoint( t, optionalTarget ) {
32259
32260                 const point = optionalTarget || new Vector2();
32261
32262                 const twoPi = Math.PI * 2;
32263                 let deltaAngle = this.aEndAngle - this.aStartAngle;
32264                 const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
32265
32266                 // ensures that deltaAngle is 0 .. 2 PI
32267                 while ( deltaAngle < 0 ) deltaAngle += twoPi;
32268                 while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
32269
32270                 if ( deltaAngle < Number.EPSILON ) {
32271
32272                         if ( samePoints ) {
32273
32274                                 deltaAngle = 0;
32275
32276                         } else {
32277
32278                                 deltaAngle = twoPi;
32279
32280                         }
32281
32282                 }
32283
32284                 if ( this.aClockwise === true && ! samePoints ) {
32285
32286                         if ( deltaAngle === twoPi ) {
32287
32288                                 deltaAngle = - twoPi;
32289
32290                         } else {
32291
32292                                 deltaAngle = deltaAngle - twoPi;
32293
32294                         }
32295
32296                 }
32297
32298                 const angle = this.aStartAngle + t * deltaAngle;
32299                 let x = this.aX + this.xRadius * Math.cos( angle );
32300                 let y = this.aY + this.yRadius * Math.sin( angle );
32301
32302                 if ( this.aRotation !== 0 ) {
32303
32304                         const cos = Math.cos( this.aRotation );
32305                         const sin = Math.sin( this.aRotation );
32306
32307                         const tx = x - this.aX;
32308                         const ty = y - this.aY;
32309
32310                         // Rotate the point about the center of the ellipse.
32311                         x = tx * cos - ty * sin + this.aX;
32312                         y = tx * sin + ty * cos + this.aY;
32313
32314                 }
32315
32316                 return point.set( x, y );
32317
32318         }
32319
32320         copy( source ) {
32321
32322                 super.copy( source );
32323
32324                 this.aX = source.aX;
32325                 this.aY = source.aY;
32326
32327                 this.xRadius = source.xRadius;
32328                 this.yRadius = source.yRadius;
32329
32330                 this.aStartAngle = source.aStartAngle;
32331                 this.aEndAngle = source.aEndAngle;
32332
32333                 this.aClockwise = source.aClockwise;
32334
32335                 this.aRotation = source.aRotation;
32336
32337                 return this;
32338
32339         }
32340
32341         toJSON() {
32342
32343                 const data = super.toJSON();
32344
32345                 data.aX = this.aX;
32346                 data.aY = this.aY;
32347
32348                 data.xRadius = this.xRadius;
32349                 data.yRadius = this.yRadius;
32350
32351                 data.aStartAngle = this.aStartAngle;
32352                 data.aEndAngle = this.aEndAngle;
32353
32354                 data.aClockwise = this.aClockwise;
32355
32356                 data.aRotation = this.aRotation;
32357
32358                 return data;
32359
32360         }
32361
32362         fromJSON( json ) {
32363
32364                 super.fromJSON( json );
32365
32366                 this.aX = json.aX;
32367                 this.aY = json.aY;
32368
32369                 this.xRadius = json.xRadius;
32370                 this.yRadius = json.yRadius;
32371
32372                 this.aStartAngle = json.aStartAngle;
32373                 this.aEndAngle = json.aEndAngle;
32374
32375                 this.aClockwise = json.aClockwise;
32376
32377                 this.aRotation = json.aRotation;
32378
32379                 return this;
32380
32381         }
32382
32383     }
32384
32385     EllipseCurve.prototype.isEllipseCurve = true;
32386
32387     class ArcCurve extends EllipseCurve {
32388
32389         constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
32390
32391                 super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
32392
32393                 this.type = 'ArcCurve';
32394
32395         }
32396
32397     }
32398
32399     ArcCurve.prototype.isArcCurve = true;
32400
32401     /**
32402      * Centripetal CatmullRom Curve - which is useful for avoiding
32403      * cusps and self-intersections in non-uniform catmull rom curves.
32404      * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
32405      *
32406      * curve.type accepts centripetal(default), chordal and catmullrom
32407      * curve.tension is used for catmullrom which defaults to 0.5
32408      */
32409
32410
32411     /*
32412     Based on an optimized c++ solution in
32413      - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
32414      - http://ideone.com/NoEbVM
32415
32416     This CubicPoly class could be used for reusing some variables and calculations,
32417     but for three.js curve use, it could be possible inlined and flatten into a single function call
32418     which can be placed in CurveUtils.
32419     */
32420
32421     function CubicPoly() {
32422
32423         let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
32424
32425         /*
32426          * Compute coefficients for a cubic polynomial
32427          *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
32428          * such that
32429          *   p(0) = x0, p(1) = x1
32430          *  and
32431          *   p'(0) = t0, p'(1) = t1.
32432          */
32433         function init( x0, x1, t0, t1 ) {
32434
32435                 c0 = x0;
32436                 c1 = t0;
32437                 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
32438                 c3 = 2 * x0 - 2 * x1 + t0 + t1;
32439
32440         }
32441
32442         return {
32443
32444                 initCatmullRom: function ( x0, x1, x2, x3, tension ) {
32445
32446                         init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
32447
32448                 },
32449
32450                 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
32451
32452                         // compute tangents when parameterized in [t1,t2]
32453                         let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
32454                         let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
32455
32456                         // rescale tangents for parametrization in [0,1]
32457                         t1 *= dt1;
32458                         t2 *= dt1;
32459
32460                         init( x1, x2, t1, t2 );
32461
32462                 },
32463
32464                 calc: function ( t ) {
32465
32466                         const t2 = t * t;
32467                         const t3 = t2 * t;
32468                         return c0 + c1 * t + c2 * t2 + c3 * t3;
32469
32470                 }
32471
32472         };
32473
32474     }
32475
32476     //
32477
32478     const tmp = new Vector3();
32479     const px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();
32480
32481     class CatmullRomCurve3 extends Curve {
32482
32483         constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
32484
32485                 super();
32486
32487                 this.type = 'CatmullRomCurve3';
32488
32489                 this.points = points;
32490                 this.closed = closed;
32491                 this.curveType = curveType;
32492                 this.tension = tension;
32493
32494         }
32495
32496         getPoint( t, optionalTarget = new Vector3() ) {
32497
32498                 const point = optionalTarget;
32499
32500                 const points = this.points;
32501                 const l = points.length;
32502
32503                 const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
32504                 let intPoint = Math.floor( p );
32505                 let weight = p - intPoint;
32506
32507                 if ( this.closed ) {
32508
32509                         intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
32510
32511                 } else if ( weight === 0 && intPoint === l - 1 ) {
32512
32513                         intPoint = l - 2;
32514                         weight = 1;
32515
32516                 }
32517
32518                 let p0, p3; // 4 points (p1 & p2 defined below)
32519
32520                 if ( this.closed || intPoint > 0 ) {
32521
32522                         p0 = points[ ( intPoint - 1 ) % l ];
32523
32524                 } else {
32525
32526                         // extrapolate first point
32527                         tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
32528                         p0 = tmp;
32529
32530                 }
32531
32532                 const p1 = points[ intPoint % l ];
32533                 const p2 = points[ ( intPoint + 1 ) % l ];
32534
32535                 if ( this.closed || intPoint + 2 < l ) {
32536
32537                         p3 = points[ ( intPoint + 2 ) % l ];
32538
32539                 } else {
32540
32541                         // extrapolate last point
32542                         tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
32543                         p3 = tmp;
32544
32545                 }
32546
32547                 if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
32548
32549                         // init Centripetal / Chordal Catmull-Rom
32550                         const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
32551                         let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
32552                         let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
32553                         let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
32554
32555                         // safety check for repeated points
32556                         if ( dt1 < 1e-4 ) dt1 = 1.0;
32557                         if ( dt0 < 1e-4 ) dt0 = dt1;
32558                         if ( dt2 < 1e-4 ) dt2 = dt1;
32559
32560                         px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
32561                         py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
32562                         pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
32563
32564                 } else if ( this.curveType === 'catmullrom' ) {
32565
32566                         px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
32567                         py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
32568                         pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
32569
32570                 }
32571
32572                 point.set(
32573                         px.calc( weight ),
32574                         py.calc( weight ),
32575                         pz.calc( weight )
32576                 );
32577
32578                 return point;
32579
32580         }
32581
32582         copy( source ) {
32583
32584                 super.copy( source );
32585
32586                 this.points = [];
32587
32588                 for ( let i = 0, l = source.points.length; i < l; i ++ ) {
32589
32590                         const point = source.points[ i ];
32591
32592                         this.points.push( point.clone() );
32593
32594                 }
32595
32596                 this.closed = source.closed;
32597                 this.curveType = source.curveType;
32598                 this.tension = source.tension;
32599
32600                 return this;
32601
32602         }
32603
32604         toJSON() {
32605
32606                 const data = super.toJSON();
32607
32608                 data.points = [];
32609
32610                 for ( let i = 0, l = this.points.length; i < l; i ++ ) {
32611
32612                         const point = this.points[ i ];
32613                         data.points.push( point.toArray() );
32614
32615                 }
32616
32617                 data.closed = this.closed;
32618                 data.curveType = this.curveType;
32619                 data.tension = this.tension;
32620
32621                 return data;
32622
32623         }
32624
32625         fromJSON( json ) {
32626
32627                 super.fromJSON( json );
32628
32629                 this.points = [];
32630
32631                 for ( let i = 0, l = json.points.length; i < l; i ++ ) {
32632
32633                         const point = json.points[ i ];
32634                         this.points.push( new Vector3().fromArray( point ) );
32635
32636                 }
32637
32638                 this.closed = json.closed;
32639                 this.curveType = json.curveType;
32640                 this.tension = json.tension;
32641
32642                 return this;
32643
32644         }
32645
32646     }
32647
32648     CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
32649
32650     /**
32651      * Bezier Curves formulas obtained from
32652      * http://en.wikipedia.org/wiki/Bézier_curve
32653      */
32654
32655     function CatmullRom( t, p0, p1, p2, p3 ) {
32656
32657         const v0 = ( p2 - p0 ) * 0.5;
32658         const v1 = ( p3 - p1 ) * 0.5;
32659         const t2 = t * t;
32660         const t3 = t * t2;
32661         return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
32662
32663     }
32664
32665     //
32666
32667     function QuadraticBezierP0( t, p ) {
32668
32669         const k = 1 - t;
32670         return k * k * p;
32671
32672     }
32673
32674     function QuadraticBezierP1( t, p ) {
32675
32676         return 2 * ( 1 - t ) * t * p;
32677
32678     }
32679
32680     function QuadraticBezierP2( t, p ) {
32681
32682         return t * t * p;
32683
32684     }
32685
32686     function QuadraticBezier( t, p0, p1, p2 ) {
32687
32688         return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
32689                 QuadraticBezierP2( t, p2 );
32690
32691     }
32692
32693     //
32694
32695     function CubicBezierP0( t, p ) {
32696
32697         const k = 1 - t;
32698         return k * k * k * p;
32699
32700     }
32701
32702     function CubicBezierP1( t, p ) {
32703
32704         const k = 1 - t;
32705         return 3 * k * k * t * p;
32706
32707     }
32708
32709     function CubicBezierP2( t, p ) {
32710
32711         return 3 * ( 1 - t ) * t * t * p;
32712
32713     }
32714
32715     function CubicBezierP3( t, p ) {
32716
32717         return t * t * t * p;
32718
32719     }
32720
32721     function CubicBezier( t, p0, p1, p2, p3 ) {
32722
32723         return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
32724                 CubicBezierP3( t, p3 );
32725
32726     }
32727
32728     class CubicBezierCurve extends Curve {
32729
32730         constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
32731
32732                 super();
32733
32734                 this.type = 'CubicBezierCurve';
32735
32736                 this.v0 = v0;
32737                 this.v1 = v1;
32738                 this.v2 = v2;
32739                 this.v3 = v3;
32740
32741         }
32742
32743         getPoint( t, optionalTarget = new Vector2() ) {
32744
32745                 const point = optionalTarget;
32746
32747                 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32748
32749                 point.set(
32750                         CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32751                         CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
32752                 );
32753
32754                 return point;
32755
32756         }
32757
32758         copy( source ) {
32759
32760                 super.copy( source );
32761
32762                 this.v0.copy( source.v0 );
32763                 this.v1.copy( source.v1 );
32764                 this.v2.copy( source.v2 );
32765                 this.v3.copy( source.v3 );
32766
32767                 return this;
32768
32769         }
32770
32771         toJSON() {
32772
32773                 const data = super.toJSON();
32774
32775                 data.v0 = this.v0.toArray();
32776                 data.v1 = this.v1.toArray();
32777                 data.v2 = this.v2.toArray();
32778                 data.v3 = this.v3.toArray();
32779
32780                 return data;
32781
32782         }
32783
32784         fromJSON( json ) {
32785
32786                 super.fromJSON( json );
32787
32788                 this.v0.fromArray( json.v0 );
32789                 this.v1.fromArray( json.v1 );
32790                 this.v2.fromArray( json.v2 );
32791                 this.v3.fromArray( json.v3 );
32792
32793                 return this;
32794
32795         }
32796
32797     }
32798
32799     CubicBezierCurve.prototype.isCubicBezierCurve = true;
32800
32801     class CubicBezierCurve3 extends Curve {
32802
32803         constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
32804
32805                 super();
32806
32807                 this.type = 'CubicBezierCurve3';
32808
32809                 this.v0 = v0;
32810                 this.v1 = v1;
32811                 this.v2 = v2;
32812                 this.v3 = v3;
32813
32814         }
32815
32816         getPoint( t, optionalTarget = new Vector3() ) {
32817
32818                 const point = optionalTarget;
32819
32820                 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32821
32822                 point.set(
32823                         CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32824                         CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
32825                         CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
32826                 );
32827
32828                 return point;
32829
32830         }
32831
32832         copy( source ) {
32833
32834                 super.copy( source );
32835
32836                 this.v0.copy( source.v0 );
32837                 this.v1.copy( source.v1 );
32838                 this.v2.copy( source.v2 );
32839                 this.v3.copy( source.v3 );
32840
32841                 return this;
32842
32843         }
32844
32845         toJSON() {
32846
32847                 const data = super.toJSON();
32848
32849                 data.v0 = this.v0.toArray();
32850                 data.v1 = this.v1.toArray();
32851                 data.v2 = this.v2.toArray();
32852                 data.v3 = this.v3.toArray();
32853
32854                 return data;
32855
32856         }
32857
32858         fromJSON( json ) {
32859
32860                 super.fromJSON( json );
32861
32862                 this.v0.fromArray( json.v0 );
32863                 this.v1.fromArray( json.v1 );
32864                 this.v2.fromArray( json.v2 );
32865                 this.v3.fromArray( json.v3 );
32866
32867                 return this;
32868
32869         }
32870
32871     }
32872
32873     CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
32874
32875     class LineCurve extends Curve {
32876
32877         constructor( v1 = new Vector2(), v2 = new Vector2() ) {
32878
32879                 super();
32880
32881                 this.type = 'LineCurve';
32882
32883                 this.v1 = v1;
32884                 this.v2 = v2;
32885
32886         }
32887
32888         getPoint( t, optionalTarget = new Vector2() ) {
32889
32890                 const point = optionalTarget;
32891
32892                 if ( t === 1 ) {
32893
32894                         point.copy( this.v2 );
32895
32896                 } else {
32897
32898                         point.copy( this.v2 ).sub( this.v1 );
32899                         point.multiplyScalar( t ).add( this.v1 );
32900
32901                 }
32902
32903                 return point;
32904
32905         }
32906
32907         // Line curve is linear, so we can overwrite default getPointAt
32908         getPointAt( u, optionalTarget ) {
32909
32910                 return this.getPoint( u, optionalTarget );
32911
32912         }
32913
32914         getTangent( t, optionalTarget ) {
32915
32916                 const tangent = optionalTarget || new Vector2();
32917
32918                 tangent.copy( this.v2 ).sub( this.v1 ).normalize();
32919
32920                 return tangent;
32921
32922         }
32923
32924         copy( source ) {
32925
32926                 super.copy( source );
32927
32928                 this.v1.copy( source.v1 );
32929                 this.v2.copy( source.v2 );
32930
32931                 return this;
32932
32933         }
32934
32935         toJSON() {
32936
32937                 const data = super.toJSON();
32938
32939                 data.v1 = this.v1.toArray();
32940                 data.v2 = this.v2.toArray();
32941
32942                 return data;
32943
32944         }
32945
32946         fromJSON( json ) {
32947
32948                 super.fromJSON( json );
32949
32950                 this.v1.fromArray( json.v1 );
32951                 this.v2.fromArray( json.v2 );
32952
32953                 return this;
32954
32955         }
32956
32957     }
32958
32959     LineCurve.prototype.isLineCurve = true;
32960
32961     class LineCurve3 extends Curve {
32962
32963         constructor( v1 = new Vector3(), v2 = new Vector3() ) {
32964
32965                 super();
32966
32967                 this.type = 'LineCurve3';
32968                 this.isLineCurve3 = true;
32969
32970                 this.v1 = v1;
32971                 this.v2 = v2;
32972
32973         }
32974         getPoint( t, optionalTarget = new Vector3() ) {
32975
32976                 const point = optionalTarget;
32977
32978                 if ( t === 1 ) {
32979
32980                         point.copy( this.v2 );
32981
32982                 } else {
32983
32984                         point.copy( this.v2 ).sub( this.v1 );
32985                         point.multiplyScalar( t ).add( this.v1 );
32986
32987                 }
32988
32989                 return point;
32990
32991         }
32992         // Line curve is linear, so we can overwrite default getPointAt
32993         getPointAt( u, optionalTarget ) {
32994
32995                 return this.getPoint( u, optionalTarget );
32996
32997         }
32998         copy( source ) {
32999
33000                 super.copy( source );
33001
33002                 this.v1.copy( source.v1 );
33003                 this.v2.copy( source.v2 );
33004
33005                 return this;
33006
33007         }
33008         toJSON() {
33009
33010                 const data = super.toJSON();
33011
33012                 data.v1 = this.v1.toArray();
33013                 data.v2 = this.v2.toArray();
33014
33015                 return data;
33016
33017         }
33018         fromJSON( json ) {
33019
33020                 super.fromJSON( json );
33021
33022                 this.v1.fromArray( json.v1 );
33023                 this.v2.fromArray( json.v2 );
33024
33025                 return this;
33026
33027         }
33028
33029     }
33030
33031     class QuadraticBezierCurve extends Curve {
33032
33033         constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
33034
33035                 super();
33036
33037                 this.type = 'QuadraticBezierCurve';
33038
33039                 this.v0 = v0;
33040                 this.v1 = v1;
33041                 this.v2 = v2;
33042
33043         }
33044
33045         getPoint( t, optionalTarget = new Vector2() ) {
33046
33047                 const point = optionalTarget;
33048
33049                 const v0 = this.v0, v1 = this.v1, v2 = this.v2;
33050
33051                 point.set(
33052                         QuadraticBezier( t, v0.x, v1.x, v2.x ),
33053                         QuadraticBezier( t, v0.y, v1.y, v2.y )
33054                 );
33055
33056                 return point;
33057
33058         }
33059
33060         copy( source ) {
33061
33062                 super.copy( source );
33063
33064                 this.v0.copy( source.v0 );
33065                 this.v1.copy( source.v1 );
33066                 this.v2.copy( source.v2 );
33067
33068                 return this;
33069
33070         }
33071
33072         toJSON() {
33073
33074                 const data = super.toJSON();
33075
33076                 data.v0 = this.v0.toArray();
33077                 data.v1 = this.v1.toArray();
33078                 data.v2 = this.v2.toArray();
33079
33080                 return data;
33081
33082         }
33083
33084         fromJSON( json ) {
33085
33086                 super.fromJSON( json );
33087
33088                 this.v0.fromArray( json.v0 );
33089                 this.v1.fromArray( json.v1 );
33090                 this.v2.fromArray( json.v2 );
33091
33092                 return this;
33093
33094         }
33095
33096     }
33097
33098     QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
33099
33100     class QuadraticBezierCurve3 extends Curve {
33101
33102         constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
33103
33104                 super();
33105
33106                 this.type = 'QuadraticBezierCurve3';
33107
33108                 this.v0 = v0;
33109                 this.v1 = v1;
33110                 this.v2 = v2;
33111
33112         }
33113
33114         getPoint( t, optionalTarget = new Vector3() ) {
33115
33116                 const point = optionalTarget;
33117
33118                 const v0 = this.v0, v1 = this.v1, v2 = this.v2;
33119
33120                 point.set(
33121                         QuadraticBezier( t, v0.x, v1.x, v2.x ),
33122                         QuadraticBezier( t, v0.y, v1.y, v2.y ),
33123                         QuadraticBezier( t, v0.z, v1.z, v2.z )
33124                 );
33125
33126                 return point;
33127
33128         }
33129
33130         copy( source ) {
33131
33132                 super.copy( source );
33133
33134                 this.v0.copy( source.v0 );
33135                 this.v1.copy( source.v1 );
33136                 this.v2.copy( source.v2 );
33137
33138                 return this;
33139
33140         }
33141
33142         toJSON() {
33143
33144                 const data = super.toJSON();
33145
33146                 data.v0 = this.v0.toArray();
33147                 data.v1 = this.v1.toArray();
33148                 data.v2 = this.v2.toArray();
33149
33150                 return data;
33151
33152         }
33153
33154         fromJSON( json ) {
33155
33156                 super.fromJSON( json );
33157
33158                 this.v0.fromArray( json.v0 );
33159                 this.v1.fromArray( json.v1 );
33160                 this.v2.fromArray( json.v2 );
33161
33162                 return this;
33163
33164         }
33165
33166     }
33167
33168     QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
33169
33170     class SplineCurve extends Curve {
33171
33172         constructor( points = [] ) {
33173
33174                 super();
33175
33176                 this.type = 'SplineCurve';
33177
33178                 this.points = points;
33179
33180         }
33181
33182         getPoint( t, optionalTarget = new Vector2() ) {
33183
33184                 const point = optionalTarget;
33185
33186                 const points = this.points;
33187                 const p = ( points.length - 1 ) * t;
33188
33189                 const intPoint = Math.floor( p );
33190                 const weight = p - intPoint;
33191
33192                 const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
33193                 const p1 = points[ intPoint ];
33194                 const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
33195                 const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
33196
33197                 point.set(
33198                         CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
33199                         CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
33200                 );
33201
33202                 return point;
33203
33204         }
33205
33206         copy( source ) {
33207
33208                 super.copy( source );
33209
33210                 this.points = [];
33211
33212                 for ( let i = 0, l = source.points.length; i < l; i ++ ) {
33213
33214                         const point = source.points[ i ];
33215
33216                         this.points.push( point.clone() );
33217
33218                 }
33219
33220                 return this;
33221
33222         }
33223
33224         toJSON() {
33225
33226                 const data = super.toJSON();
33227
33228                 data.points = [];
33229
33230                 for ( let i = 0, l = this.points.length; i < l; i ++ ) {
33231
33232                         const point = this.points[ i ];
33233                         data.points.push( point.toArray() );
33234
33235                 }
33236
33237                 return data;
33238
33239         }
33240
33241         fromJSON( json ) {
33242
33243                 super.fromJSON( json );
33244
33245                 this.points = [];
33246
33247                 for ( let i = 0, l = json.points.length; i < l; i ++ ) {
33248
33249                         const point = json.points[ i ];
33250                         this.points.push( new Vector2().fromArray( point ) );
33251
33252                 }
33253
33254                 return this;
33255
33256         }
33257
33258     }
33259
33260     SplineCurve.prototype.isSplineCurve = true;
33261
33262     var Curves = /*#__PURE__*/Object.freeze({
33263         __proto__: null,
33264         ArcCurve: ArcCurve,
33265         CatmullRomCurve3: CatmullRomCurve3,
33266         CubicBezierCurve: CubicBezierCurve,
33267         CubicBezierCurve3: CubicBezierCurve3,
33268         EllipseCurve: EllipseCurve,
33269         LineCurve: LineCurve,
33270         LineCurve3: LineCurve3,
33271         QuadraticBezierCurve: QuadraticBezierCurve,
33272         QuadraticBezierCurve3: QuadraticBezierCurve3,
33273         SplineCurve: SplineCurve
33274     });
33275
33276     /**************************************************************
33277      *  Curved Path - a curve path is simply a array of connected
33278      *  curves, but retains the api of a curve
33279      **************************************************************/
33280
33281     class CurvePath extends Curve {
33282
33283         constructor() {
33284
33285                 super();
33286
33287                 this.type = 'CurvePath';
33288
33289                 this.curves = [];
33290                 this.autoClose = false; // Automatically closes the path
33291
33292         }
33293
33294         add( curve ) {
33295
33296                 this.curves.push( curve );
33297
33298         }
33299
33300         closePath() {
33301
33302                 // Add a line curve if start and end of lines are not connected
33303                 const startPoint = this.curves[ 0 ].getPoint( 0 );
33304                 const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
33305
33306                 if ( ! startPoint.equals( endPoint ) ) {
33307
33308                         this.curves.push( new LineCurve( endPoint, startPoint ) );
33309
33310                 }
33311
33312         }
33313
33314         // To get accurate point with reference to
33315         // entire path distance at time t,
33316         // following has to be done:
33317
33318         // 1. Length of each sub path have to be known
33319         // 2. Locate and identify type of curve
33320         // 3. Get t for the curve
33321         // 4. Return curve.getPointAt(t')
33322
33323         getPoint( t, optionalTarget ) {
33324
33325                 const d = t * this.getLength();
33326                 const curveLengths = this.getCurveLengths();
33327                 let i = 0;
33328
33329                 // To think about boundaries points.
33330
33331                 while ( i < curveLengths.length ) {
33332
33333                         if ( curveLengths[ i ] >= d ) {
33334
33335                                 const diff = curveLengths[ i ] - d;
33336                                 const curve = this.curves[ i ];
33337
33338                                 const segmentLength = curve.getLength();
33339                                 const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
33340
33341                                 return curve.getPointAt( u, optionalTarget );
33342
33343                         }
33344
33345                         i ++;
33346
33347                 }
33348
33349                 return null;
33350
33351                 // loop where sum != 0, sum > d , sum+1 <d
33352
33353         }
33354
33355         // We cannot use the default THREE.Curve getPoint() with getLength() because in
33356         // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
33357         // getPoint() depends on getLength
33358
33359         getLength() {
33360
33361                 const lens = this.getCurveLengths();
33362                 return lens[ lens.length - 1 ];
33363
33364         }
33365
33366         // cacheLengths must be recalculated.
33367         updateArcLengths() {
33368
33369                 this.needsUpdate = true;
33370                 this.cacheLengths = null;
33371                 this.getCurveLengths();
33372
33373         }
33374
33375         // Compute lengths and cache them
33376         // We cannot overwrite getLengths() because UtoT mapping uses it.
33377
33378         getCurveLengths() {
33379
33380                 // We use cache values if curves and cache array are same length
33381
33382                 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
33383
33384                         return this.cacheLengths;
33385
33386                 }
33387
33388                 // Get length of sub-curve
33389                 // Push sums into cached array
33390
33391                 const lengths = [];
33392                 let sums = 0;
33393
33394                 for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
33395
33396                         sums += this.curves[ i ].getLength();
33397                         lengths.push( sums );
33398
33399                 }
33400
33401                 this.cacheLengths = lengths;
33402
33403                 return lengths;
33404
33405         }
33406
33407         getSpacedPoints( divisions = 40 ) {
33408
33409                 const points = [];
33410
33411                 for ( let i = 0; i <= divisions; i ++ ) {
33412
33413                         points.push( this.getPoint( i / divisions ) );
33414
33415                 }
33416
33417                 if ( this.autoClose ) {
33418
33419                         points.push( points[ 0 ] );
33420
33421                 }
33422
33423                 return points;
33424
33425         }
33426
33427         getPoints( divisions = 12 ) {
33428
33429                 const points = [];
33430                 let last;
33431
33432                 for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
33433
33434                         const curve = curves[ i ];
33435                         const resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
33436                                 : ( curve && ( curve.isLineCurve || curve.isLineCurve3 ) ) ? 1
33437                                         : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
33438                                                 : divisions;
33439
33440                         const pts = curve.getPoints( resolution );
33441
33442                         for ( let j = 0; j < pts.length; j ++ ) {
33443
33444                                 const point = pts[ j ];
33445
33446                                 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
33447
33448                                 points.push( point );
33449                                 last = point;
33450
33451                         }
33452
33453                 }
33454
33455                 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
33456
33457                         points.push( points[ 0 ] );
33458
33459                 }
33460
33461                 return points;
33462
33463         }
33464
33465         copy( source ) {
33466
33467                 super.copy( source );
33468
33469                 this.curves = [];
33470
33471                 for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
33472
33473                         const curve = source.curves[ i ];
33474
33475                         this.curves.push( curve.clone() );
33476
33477                 }
33478
33479                 this.autoClose = source.autoClose;
33480
33481                 return this;
33482
33483         }
33484
33485         toJSON() {
33486
33487                 const data = super.toJSON();
33488
33489                 data.autoClose = this.autoClose;
33490                 data.curves = [];
33491
33492                 for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
33493
33494                         const curve = this.curves[ i ];
33495                         data.curves.push( curve.toJSON() );
33496
33497                 }
33498
33499                 return data;
33500
33501         }
33502
33503         fromJSON( json ) {
33504
33505                 super.fromJSON( json );
33506
33507                 this.autoClose = json.autoClose;
33508                 this.curves = [];
33509
33510                 for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
33511
33512                         const curve = json.curves[ i ];
33513                         this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
33514
33515                 }
33516
33517                 return this;
33518
33519         }
33520
33521     }
33522
33523     class Path extends CurvePath {
33524
33525         constructor( points ) {
33526
33527                 super();
33528                 this.type = 'Path';
33529
33530                 this.currentPoint = new Vector2();
33531
33532                 if ( points ) {
33533
33534                         this.setFromPoints( points );
33535
33536                 }
33537
33538         }
33539
33540         setFromPoints( points ) {
33541
33542                 this.moveTo( points[ 0 ].x, points[ 0 ].y );
33543
33544                 for ( let i = 1, l = points.length; i < l; i ++ ) {
33545
33546                         this.lineTo( points[ i ].x, points[ i ].y );
33547
33548                 }
33549
33550                 return this;
33551
33552         }
33553
33554         moveTo( x, y ) {
33555
33556                 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
33557
33558                 return this;
33559
33560         }
33561
33562         lineTo( x, y ) {
33563
33564                 const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
33565                 this.curves.push( curve );
33566
33567                 this.currentPoint.set( x, y );
33568
33569                 return this;
33570
33571         }
33572
33573         quadraticCurveTo( aCPx, aCPy, aX, aY ) {
33574
33575                 const curve = new QuadraticBezierCurve(
33576                         this.currentPoint.clone(),
33577                         new Vector2( aCPx, aCPy ),
33578                         new Vector2( aX, aY )
33579                 );
33580
33581                 this.curves.push( curve );
33582
33583                 this.currentPoint.set( aX, aY );
33584
33585                 return this;
33586
33587         }
33588
33589         bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
33590
33591                 const curve = new CubicBezierCurve(
33592                         this.currentPoint.clone(),
33593                         new Vector2( aCP1x, aCP1y ),
33594                         new Vector2( aCP2x, aCP2y ),
33595                         new Vector2( aX, aY )
33596                 );
33597
33598                 this.curves.push( curve );
33599
33600                 this.currentPoint.set( aX, aY );
33601
33602                 return this;
33603
33604         }
33605
33606         splineThru( pts /*Array of Vector*/ ) {
33607
33608                 const npts = [ this.currentPoint.clone() ].concat( pts );
33609
33610                 const curve = new SplineCurve( npts );
33611                 this.curves.push( curve );
33612
33613                 this.currentPoint.copy( pts[ pts.length - 1 ] );
33614
33615                 return this;
33616
33617         }
33618
33619         arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33620
33621                 const x0 = this.currentPoint.x;
33622                 const y0 = this.currentPoint.y;
33623
33624                 this.absarc( aX + x0, aY + y0, aRadius,
33625                         aStartAngle, aEndAngle, aClockwise );
33626
33627                 return this;
33628
33629         }
33630
33631         absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33632
33633                 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
33634
33635                 return this;
33636
33637         }
33638
33639         ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33640
33641                 const x0 = this.currentPoint.x;
33642                 const y0 = this.currentPoint.y;
33643
33644                 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33645
33646                 return this;
33647
33648         }
33649
33650         absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33651
33652                 const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33653
33654                 if ( this.curves.length > 0 ) {
33655
33656                         // if a previous curve is present, attempt to join
33657                         const firstPoint = curve.getPoint( 0 );
33658
33659                         if ( ! firstPoint.equals( this.currentPoint ) ) {
33660
33661                                 this.lineTo( firstPoint.x, firstPoint.y );
33662
33663                         }
33664
33665                 }
33666
33667                 this.curves.push( curve );
33668
33669                 const lastPoint = curve.getPoint( 1 );
33670                 this.currentPoint.copy( lastPoint );
33671
33672                 return this;
33673
33674         }
33675
33676         copy( source ) {
33677
33678                 super.copy( source );
33679
33680                 this.currentPoint.copy( source.currentPoint );
33681
33682                 return this;
33683
33684         }
33685
33686         toJSON() {
33687
33688                 const data = super.toJSON();
33689
33690                 data.currentPoint = this.currentPoint.toArray();
33691
33692                 return data;
33693
33694         }
33695
33696         fromJSON( json ) {
33697
33698                 super.fromJSON( json );
33699
33700                 this.currentPoint.fromArray( json.currentPoint );
33701
33702                 return this;
33703
33704         }
33705
33706     }
33707
33708     class Shape extends Path {
33709
33710         constructor( points ) {
33711
33712                 super( points );
33713
33714                 this.uuid = generateUUID();
33715
33716                 this.type = 'Shape';
33717
33718                 this.holes = [];
33719
33720         }
33721
33722         getPointsHoles( divisions ) {
33723
33724                 const holesPts = [];
33725
33726                 for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
33727
33728                         holesPts[ i ] = this.holes[ i ].getPoints( divisions );
33729
33730                 }
33731
33732                 return holesPts;
33733
33734         }
33735
33736         // get points of shape and holes (keypoints based on segments parameter)
33737
33738         extractPoints( divisions ) {
33739
33740                 return {
33741
33742                         shape: this.getPoints( divisions ),
33743                         holes: this.getPointsHoles( divisions )
33744
33745                 };
33746
33747         }
33748
33749         copy( source ) {
33750
33751                 super.copy( source );
33752
33753                 this.holes = [];
33754
33755                 for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
33756
33757                         const hole = source.holes[ i ];
33758
33759                         this.holes.push( hole.clone() );
33760
33761                 }
33762
33763                 return this;
33764
33765         }
33766
33767         toJSON() {
33768
33769                 const data = super.toJSON();
33770
33771                 data.uuid = this.uuid;
33772                 data.holes = [];
33773
33774                 for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
33775
33776                         const hole = this.holes[ i ];
33777                         data.holes.push( hole.toJSON() );
33778
33779                 }
33780
33781                 return data;
33782
33783         }
33784
33785         fromJSON( json ) {
33786
33787                 super.fromJSON( json );
33788
33789                 this.uuid = json.uuid;
33790                 this.holes = [];
33791
33792                 for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
33793
33794                         const hole = json.holes[ i ];
33795                         this.holes.push( new Path().fromJSON( hole ) );
33796
33797                 }
33798
33799                 return this;
33800
33801         }
33802
33803     }
33804
33805     /**
33806      * Port from https://github.com/mapbox/earcut (v2.2.2)
33807      */
33808
33809     const Earcut = {
33810
33811         triangulate: function ( data, holeIndices, dim = 2 ) {
33812
33813                 const hasHoles = holeIndices && holeIndices.length;
33814                 const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
33815                 let outerNode = linkedList$1( data, 0, outerLen, dim, true );
33816                 const triangles = [];
33817
33818                 if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
33819
33820                 let minX, minY, maxX, maxY, x, y, invSize;
33821
33822                 if ( hasHoles ) outerNode = eliminateHoles$1( data, holeIndices, outerNode, dim );
33823
33824                 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
33825                 if ( data.length > 80 * dim ) {
33826
33827                         minX = maxX = data[ 0 ];
33828                         minY = maxY = data[ 1 ];
33829
33830                         for ( let i = dim; i < outerLen; i += dim ) {
33831
33832                                 x = data[ i ];
33833                                 y = data[ i + 1 ];
33834                                 if ( x < minX ) minX = x;
33835                                 if ( y < minY ) minY = y;
33836                                 if ( x > maxX ) maxX = x;
33837                                 if ( y > maxY ) maxY = y;
33838
33839                         }
33840
33841                         // minX, minY and invSize are later used to transform coords into integers for z-order calculation
33842                         invSize = Math.max( maxX - minX, maxY - minY );
33843                         invSize = invSize !== 0 ? 1 / invSize : 0;
33844
33845                 }
33846
33847                 earcutLinked$1( outerNode, triangles, dim, minX, minY, invSize );
33848
33849                 return triangles;
33850
33851         }
33852
33853     };
33854
33855     // create a circular doubly linked list from polygon points in the specified winding order
33856     function linkedList$1( data, start, end, dim, clockwise ) {
33857
33858         let i, last;
33859
33860         if ( clockwise === ( signedArea$2( data, start, end, dim ) > 0 ) ) {
33861
33862                 for ( i = start; i < end; i += dim ) last = insertNode$2( i, data[ i ], data[ i + 1 ], last );
33863
33864         } else {
33865
33866                 for ( i = end - dim; i >= start; i -= dim ) last = insertNode$2( i, data[ i ], data[ i + 1 ], last );
33867
33868         }
33869
33870         if ( last && equals$2( last, last.next ) ) {
33871
33872                 removeNode$2( last );
33873                 last = last.next;
33874
33875         }
33876
33877         return last;
33878
33879     }
33880
33881     // eliminate colinear or duplicate points
33882     function filterPoints$1( start, end ) {
33883
33884         if ( ! start ) return start;
33885         if ( ! end ) end = start;
33886
33887         let p = start,
33888                 again;
33889         do {
33890
33891                 again = false;
33892
33893                 if ( ! p.steiner && ( equals$2( p, p.next ) || area$1( p.prev, p, p.next ) === 0 ) ) {
33894
33895                         removeNode$2( p );
33896                         p = end = p.prev;
33897                         if ( p === p.next ) break;
33898                         again = true;
33899
33900                 } else {
33901
33902                         p = p.next;
33903
33904                 }
33905
33906         } while ( again || p !== end );
33907
33908         return end;
33909
33910     }
33911
33912     // main ear slicing loop which triangulates a polygon (given as a linked list)
33913     function earcutLinked$1( ear, triangles, dim, minX, minY, invSize, pass ) {
33914
33915         if ( ! ear ) return;
33916
33917         // interlink polygon nodes in z-order
33918         if ( ! pass && invSize ) indexCurve$1( ear, minX, minY, invSize );
33919
33920         let stop = ear,
33921                 prev, next;
33922
33923         // iterate through ears, slicing them one by one
33924         while ( ear.prev !== ear.next ) {
33925
33926                 prev = ear.prev;
33927                 next = ear.next;
33928
33929                 if ( invSize ? isEarHashed$1( ear, minX, minY, invSize ) : isEar$1( ear ) ) {
33930
33931                         // cut off the triangle
33932                         triangles.push( prev.i / dim );
33933                         triangles.push( ear.i / dim );
33934                         triangles.push( next.i / dim );
33935
33936                         removeNode$2( ear );
33937
33938                         // skipping the next vertex leads to less sliver triangles
33939                         ear = next.next;
33940                         stop = next.next;
33941
33942                         continue;
33943
33944                 }
33945
33946                 ear = next;
33947
33948                 // if we looped through the whole remaining polygon and can't find any more ears
33949                 if ( ear === stop ) {
33950
33951                         // try filtering points and slicing again
33952                         if ( ! pass ) {
33953
33954                                 earcutLinked$1( filterPoints$1( ear ), triangles, dim, minX, minY, invSize, 1 );
33955
33956                                 // if this didn't work, try curing all small self-intersections locally
33957
33958                         } else if ( pass === 1 ) {
33959
33960                                 ear = cureLocalIntersections$1( filterPoints$1( ear ), triangles, dim );
33961                                 earcutLinked$1( ear, triangles, dim, minX, minY, invSize, 2 );
33962
33963                                 // as a last resort, try splitting the remaining polygon into two
33964
33965                         } else if ( pass === 2 ) {
33966
33967                                 splitEarcut$1( ear, triangles, dim, minX, minY, invSize );
33968
33969                         }
33970
33971                         break;
33972
33973                 }
33974
33975         }
33976
33977     }
33978
33979     // check whether a polygon node forms a valid ear with adjacent nodes
33980     function isEar$1( ear ) {
33981
33982         const a = ear.prev,
33983                 b = ear,
33984                 c = ear.next;
33985
33986         if ( area$1( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
33987
33988         // now make sure we don't have other points inside the potential ear
33989         let p = ear.next.next;
33990
33991         while ( p !== ear.prev ) {
33992
33993                 if ( pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
33994                         area$1( p.prev, p, p.next ) >= 0 ) return false;
33995                 p = p.next;
33996
33997         }
33998
33999         return true;
34000
34001     }
34002
34003     function isEarHashed$1( ear, minX, minY, invSize ) {
34004
34005         const a = ear.prev,
34006                 b = ear,
34007                 c = ear.next;
34008
34009         if ( area$1( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
34010
34011         // triangle bbox; min & max are calculated like this for speed
34012         const minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
34013                 minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
34014                 maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
34015                 maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
34016
34017         // z-order range for the current triangle bbox;
34018         const minZ = zOrder$1( minTX, minTY, minX, minY, invSize ),
34019                 maxZ = zOrder$1( maxTX, maxTY, minX, minY, invSize );
34020
34021         let p = ear.prevZ,
34022                 n = ear.nextZ;
34023
34024         // look for points inside the triangle in both directions
34025         while ( p && p.z >= minZ && n && n.z <= maxZ ) {
34026
34027                 if ( p !== ear.prev && p !== ear.next &&
34028                         pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
34029                         area$1( p.prev, p, p.next ) >= 0 ) return false;
34030                 p = p.prevZ;
34031
34032                 if ( n !== ear.prev && n !== ear.next &&
34033                         pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
34034                         area$1( n.prev, n, n.next ) >= 0 ) return false;
34035                 n = n.nextZ;
34036
34037         }
34038
34039         // look for remaining points in decreasing z-order
34040         while ( p && p.z >= minZ ) {
34041
34042                 if ( p !== ear.prev && p !== ear.next &&
34043                         pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
34044                         area$1( p.prev, p, p.next ) >= 0 ) return false;
34045                 p = p.prevZ;
34046
34047         }
34048
34049         // look for remaining points in increasing z-order
34050         while ( n && n.z <= maxZ ) {
34051
34052                 if ( n !== ear.prev && n !== ear.next &&
34053                         pointInTriangle$1( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
34054                         area$1( n.prev, n, n.next ) >= 0 ) return false;
34055                 n = n.nextZ;
34056
34057         }
34058
34059         return true;
34060
34061     }
34062
34063     // go through all polygon nodes and cure small local self-intersections
34064     function cureLocalIntersections$1( start, triangles, dim ) {
34065
34066         let p = start;
34067         do {
34068
34069                 const a = p.prev,
34070                         b = p.next.next;
34071
34072                 if ( ! equals$2( a, b ) && intersects$2( a, p, p.next, b ) && locallyInside$1( a, b ) && locallyInside$1( b, a ) ) {
34073
34074                         triangles.push( a.i / dim );
34075                         triangles.push( p.i / dim );
34076                         triangles.push( b.i / dim );
34077
34078                         // remove two nodes involved
34079                         removeNode$2( p );
34080                         removeNode$2( p.next );
34081
34082                         p = start = b;
34083
34084                 }
34085
34086                 p = p.next;
34087
34088         } while ( p !== start );
34089
34090         return filterPoints$1( p );
34091
34092     }
34093
34094     // try splitting polygon into two and triangulate them independently
34095     function splitEarcut$1( start, triangles, dim, minX, minY, invSize ) {
34096
34097         // look for a valid diagonal that divides the polygon into two
34098         let a = start;
34099         do {
34100
34101                 let b = a.next.next;
34102                 while ( b !== a.prev ) {
34103
34104                         if ( a.i !== b.i && isValidDiagonal$1( a, b ) ) {
34105
34106                                 // split the polygon in two by the diagonal
34107                                 let c = splitPolygon$1( a, b );
34108
34109                                 // filter colinear points around the cuts
34110                                 a = filterPoints$1( a, a.next );
34111                                 c = filterPoints$1( c, c.next );
34112
34113                                 // run earcut on each half
34114                                 earcutLinked$1( a, triangles, dim, minX, minY, invSize );
34115                                 earcutLinked$1( c, triangles, dim, minX, minY, invSize );
34116                                 return;
34117
34118                         }
34119
34120                         b = b.next;
34121
34122                 }
34123
34124                 a = a.next;
34125
34126         } while ( a !== start );
34127
34128     }
34129
34130     // link every hole into the outer loop, producing a single-ring polygon without holes
34131     function eliminateHoles$1( data, holeIndices, outerNode, dim ) {
34132
34133         const queue = [];
34134         let i, len, start, end, list;
34135
34136         for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
34137
34138                 start = holeIndices[ i ] * dim;
34139                 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
34140                 list = linkedList$1( data, start, end, dim, false );
34141                 if ( list === list.next ) list.steiner = true;
34142                 queue.push( getLeftmost$1( list ) );
34143
34144         }
34145
34146         queue.sort( compareX$1 );
34147
34148         // process holes from left to right
34149         for ( i = 0; i < queue.length; i ++ ) {
34150
34151                 eliminateHole$1( queue[ i ], outerNode );
34152                 outerNode = filterPoints$1( outerNode, outerNode.next );
34153
34154         }
34155
34156         return outerNode;
34157
34158     }
34159
34160     function compareX$1( a, b ) {
34161
34162         return a.x - b.x;
34163
34164     }
34165
34166     // find a bridge between vertices that connects hole with an outer ring and and link it
34167     function eliminateHole$1( hole, outerNode ) {
34168
34169         outerNode = findHoleBridge$1( hole, outerNode );
34170         if ( outerNode ) {
34171
34172                 const b = splitPolygon$1( outerNode, hole );
34173
34174                 // filter collinear points around the cuts
34175                 filterPoints$1( outerNode, outerNode.next );
34176                 filterPoints$1( b, b.next );
34177
34178         }
34179
34180     }
34181
34182     // David Eberly's algorithm for finding a bridge between hole and outer polygon
34183     function findHoleBridge$1( hole, outerNode ) {
34184
34185         let p = outerNode;
34186         const hx = hole.x;
34187         const hy = hole.y;
34188         let qx = - Infinity, m;
34189
34190         // find a segment intersected by a ray from the hole's leftmost point to the left;
34191         // segment's endpoint with lesser x will be potential connection point
34192         do {
34193
34194                 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
34195
34196                         const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
34197                         if ( x <= hx && x > qx ) {
34198
34199                                 qx = x;
34200                                 if ( x === hx ) {
34201
34202                                         if ( hy === p.y ) return p;
34203                                         if ( hy === p.next.y ) return p.next;
34204
34205                                 }
34206
34207                                 m = p.x < p.next.x ? p : p.next;
34208
34209                         }
34210
34211                 }
34212
34213                 p = p.next;
34214
34215         } while ( p !== outerNode );
34216
34217         if ( ! m ) return null;
34218
34219         if ( hx === qx ) return m; // hole touches outer segment; pick leftmost endpoint
34220
34221         // look for points inside the triangle of hole point, segment intersection and endpoint;
34222         // if there are no points found, we have a valid connection;
34223         // otherwise choose the point of the minimum angle with the ray as connection point
34224
34225         const stop = m,
34226                 mx = m.x,
34227                 my = m.y;
34228         let tanMin = Infinity, tan;
34229
34230         p = m;
34231
34232         do {
34233
34234                 if ( hx >= p.x && p.x >= mx && hx !== p.x &&
34235                                 pointInTriangle$1( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
34236
34237                         tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
34238
34239                         if ( locallyInside$1( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector$1( m, p ) ) ) ) ) ) {
34240
34241                                 m = p;
34242                                 tanMin = tan;
34243
34244                         }
34245
34246                 }
34247
34248                 p = p.next;
34249
34250         } while ( p !== stop );
34251
34252         return m;
34253
34254     }
34255
34256     // whether sector in vertex m contains sector in vertex p in the same coordinates
34257     function sectorContainsSector$1( m, p ) {
34258
34259         return area$1( m.prev, m, p.prev ) < 0 && area$1( p.next, m, m.next ) < 0;
34260
34261     }
34262
34263     // interlink polygon nodes in z-order
34264     function indexCurve$1( start, minX, minY, invSize ) {
34265
34266         let p = start;
34267         do {
34268
34269                 if ( p.z === null ) p.z = zOrder$1( p.x, p.y, minX, minY, invSize );
34270                 p.prevZ = p.prev;
34271                 p.nextZ = p.next;
34272                 p = p.next;
34273
34274         } while ( p !== start );
34275
34276         p.prevZ.nextZ = null;
34277         p.prevZ = null;
34278
34279         sortLinked$1( p );
34280
34281     }
34282
34283     // Simon Tatham's linked list merge sort algorithm
34284     // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
34285     function sortLinked$1( list ) {
34286
34287         let i, p, q, e, tail, numMerges, pSize, qSize,
34288                 inSize = 1;
34289
34290         do {
34291
34292                 p = list;
34293                 list = null;
34294                 tail = null;
34295                 numMerges = 0;
34296
34297                 while ( p ) {
34298
34299                         numMerges ++;
34300                         q = p;
34301                         pSize = 0;
34302                         for ( i = 0; i < inSize; i ++ ) {
34303
34304                                 pSize ++;
34305                                 q = q.nextZ;
34306                                 if ( ! q ) break;
34307
34308                         }
34309
34310                         qSize = inSize;
34311
34312                         while ( pSize > 0 || ( qSize > 0 && q ) ) {
34313
34314                                 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
34315
34316                                         e = p;
34317                                         p = p.nextZ;
34318                                         pSize --;
34319
34320                                 } else {
34321
34322                                         e = q;
34323                                         q = q.nextZ;
34324                                         qSize --;
34325
34326                                 }
34327
34328                                 if ( tail ) tail.nextZ = e;
34329                                 else list = e;
34330
34331                                 e.prevZ = tail;
34332                                 tail = e;
34333
34334                         }
34335
34336                         p = q;
34337
34338                 }
34339
34340                 tail.nextZ = null;
34341                 inSize *= 2;
34342
34343         } while ( numMerges > 1 );
34344
34345         return list;
34346
34347     }
34348
34349     // z-order of a point given coords and inverse of the longer side of data bbox
34350     function zOrder$1( x, y, minX, minY, invSize ) {
34351
34352         // coords are transformed into non-negative 15-bit integer range
34353         x = 32767 * ( x - minX ) * invSize;
34354         y = 32767 * ( y - minY ) * invSize;
34355
34356         x = ( x | ( x << 8 ) ) & 0x00FF00FF;
34357         x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
34358         x = ( x | ( x << 2 ) ) & 0x33333333;
34359         x = ( x | ( x << 1 ) ) & 0x55555555;
34360
34361         y = ( y | ( y << 8 ) ) & 0x00FF00FF;
34362         y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
34363         y = ( y | ( y << 2 ) ) & 0x33333333;
34364         y = ( y | ( y << 1 ) ) & 0x55555555;
34365
34366         return x | ( y << 1 );
34367
34368     }
34369
34370     // find the leftmost node of a polygon ring
34371     function getLeftmost$1( start ) {
34372
34373         let p = start,
34374                 leftmost = start;
34375         do {
34376
34377                 if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
34378                 p = p.next;
34379
34380         } while ( p !== start );
34381
34382         return leftmost;
34383
34384     }
34385
34386     // check if a point lies within a convex triangle
34387     function pointInTriangle$1( ax, ay, bx, by, cx, cy, px, py ) {
34388
34389         return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
34390                         ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
34391                         ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
34392
34393     }
34394
34395     // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
34396     function isValidDiagonal$1( a, b ) {
34397
34398         return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon$1( a, b ) && // dones't intersect other edges
34399                 ( locallyInside$1( a, b ) && locallyInside$1( b, a ) && middleInside$1( a, b ) && // locally visible
34400                 ( area$1( a.prev, a, b.prev ) || area$1( a, b.prev, b ) ) || // does not create opposite-facing sectors
34401                 equals$2( a, b ) && area$1( a.prev, a, a.next ) > 0 && area$1( b.prev, b, b.next ) > 0 ); // special zero-length case
34402
34403     }
34404
34405     // signed area of a triangle
34406     function area$1( p, q, r ) {
34407
34408         return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
34409
34410     }
34411
34412     // check if two points are equal
34413     function equals$2( p1, p2 ) {
34414
34415         return p1.x === p2.x && p1.y === p2.y;
34416
34417     }
34418
34419     // check if two segments intersect
34420     function intersects$2( p1, q1, p2, q2 ) {
34421
34422         const o1 = sign$2( area$1( p1, q1, p2 ) );
34423         const o2 = sign$2( area$1( p1, q1, q2 ) );
34424         const o3 = sign$2( area$1( p2, q2, p1 ) );
34425         const o4 = sign$2( area$1( p2, q2, q1 ) );
34426
34427         if ( o1 !== o2 && o3 !== o4 ) return true; // general case
34428
34429         if ( o1 === 0 && onSegment$1( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
34430         if ( o2 === 0 && onSegment$1( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
34431         if ( o3 === 0 && onSegment$1( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
34432         if ( o4 === 0 && onSegment$1( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
34433
34434         return false;
34435
34436     }
34437
34438     // for collinear points p, q, r, check if point q lies on segment pr
34439     function onSegment$1( p, q, r ) {
34440
34441         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 );
34442
34443     }
34444
34445     function sign$2( num ) {
34446
34447         return num > 0 ? 1 : num < 0 ? - 1 : 0;
34448
34449     }
34450
34451     // check if a polygon diagonal intersects any polygon segments
34452     function intersectsPolygon$1( a, b ) {
34453
34454         let p = a;
34455         do {
34456
34457                 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
34458                                 intersects$2( p, p.next, a, b ) ) return true;
34459                 p = p.next;
34460
34461         } while ( p !== a );
34462
34463         return false;
34464
34465     }
34466
34467     // check if a polygon diagonal is locally inside the polygon
34468     function locallyInside$1( a, b ) {
34469
34470         return area$1( a.prev, a, a.next ) < 0 ?
34471                 area$1( a, b, a.next ) >= 0 && area$1( a, a.prev, b ) >= 0 :
34472                 area$1( a, b, a.prev ) < 0 || area$1( a, a.next, b ) < 0;
34473
34474     }
34475
34476     // check if the middle point of a polygon diagonal is inside the polygon
34477     function middleInside$1( a, b ) {
34478
34479         let p = a,
34480                 inside = false;
34481         const px = ( a.x + b.x ) / 2,
34482                 py = ( a.y + b.y ) / 2;
34483         do {
34484
34485                 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
34486                                 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
34487                         inside = ! inside;
34488                 p = p.next;
34489
34490         } while ( p !== a );
34491
34492         return inside;
34493
34494     }
34495
34496     // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
34497     // if one belongs to the outer ring and another to a hole, it merges it into a single ring
34498     function splitPolygon$1( a, b ) {
34499
34500         const a2 = new Node$1( a.i, a.x, a.y ),
34501                 b2 = new Node$1( b.i, b.x, b.y ),
34502                 an = a.next,
34503                 bp = b.prev;
34504
34505         a.next = b;
34506         b.prev = a;
34507
34508         a2.next = an;
34509         an.prev = a2;
34510
34511         b2.next = a2;
34512         a2.prev = b2;
34513
34514         bp.next = b2;
34515         b2.prev = bp;
34516
34517         return b2;
34518
34519     }
34520
34521     // create a node and optionally link it with previous one (in a circular doubly linked list)
34522     function insertNode$2( i, x, y, last ) {
34523
34524         const p = new Node$1( i, x, y );
34525
34526         if ( ! last ) {
34527
34528                 p.prev = p;
34529                 p.next = p;
34530
34531         } else {
34532
34533                 p.next = last.next;
34534                 p.prev = last;
34535                 last.next.prev = p;
34536                 last.next = p;
34537
34538         }
34539
34540         return p;
34541
34542     }
34543
34544     function removeNode$2( p ) {
34545
34546         p.next.prev = p.prev;
34547         p.prev.next = p.next;
34548
34549         if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
34550         if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
34551
34552     }
34553
34554     function Node$1( i, x, y ) {
34555
34556         // vertex index in coordinates array
34557         this.i = i;
34558
34559         // vertex coordinates
34560         this.x = x;
34561         this.y = y;
34562
34563         // previous and next vertex nodes in a polygon ring
34564         this.prev = null;
34565         this.next = null;
34566
34567         // z-order curve value
34568         this.z = null;
34569
34570         // previous and next nodes in z-order
34571         this.prevZ = null;
34572         this.nextZ = null;
34573
34574         // indicates whether this is a steiner point
34575         this.steiner = false;
34576
34577     }
34578
34579     function signedArea$2( data, start, end, dim ) {
34580
34581         let sum = 0;
34582         for ( let i = start, j = end - dim; i < end; i += dim ) {
34583
34584                 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
34585                 j = i;
34586
34587         }
34588
34589         return sum;
34590
34591     }
34592
34593     class ShapeUtils {
34594
34595         // calculate area of the contour polygon
34596
34597         static area( contour ) {
34598
34599                 const n = contour.length;
34600                 let a = 0.0;
34601
34602                 for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
34603
34604                         a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
34605
34606                 }
34607
34608                 return a * 0.5;
34609
34610         }
34611
34612         static isClockWise( pts ) {
34613
34614                 return ShapeUtils.area( pts ) < 0;
34615
34616         }
34617
34618         static triangulateShape( contour, holes ) {
34619
34620                 const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
34621                 const holeIndices = []; // array of hole indices
34622                 const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
34623
34624                 removeDupEndPts( contour );
34625                 addContour( vertices, contour );
34626
34627                 //
34628
34629                 let holeIndex = contour.length;
34630
34631                 holes.forEach( removeDupEndPts );
34632
34633                 for ( let i = 0; i < holes.length; i ++ ) {
34634
34635                         holeIndices.push( holeIndex );
34636                         holeIndex += holes[ i ].length;
34637                         addContour( vertices, holes[ i ] );
34638
34639                 }
34640
34641                 //
34642
34643                 const triangles = Earcut.triangulate( vertices, holeIndices );
34644
34645                 //
34646
34647                 for ( let i = 0; i < triangles.length; i += 3 ) {
34648
34649                         faces.push( triangles.slice( i, i + 3 ) );
34650
34651                 }
34652
34653                 return faces;
34654
34655         }
34656
34657     }
34658
34659     function removeDupEndPts( points ) {
34660
34661         const l = points.length;
34662
34663         if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
34664
34665                 points.pop();
34666
34667         }
34668
34669     }
34670
34671     function addContour( vertices, contour ) {
34672
34673         for ( let i = 0; i < contour.length; i ++ ) {
34674
34675                 vertices.push( contour[ i ].x );
34676                 vertices.push( contour[ i ].y );
34677
34678         }
34679
34680     }
34681
34682     /**
34683      * Creates extruded geometry from a path shape.
34684      *
34685      * parameters = {
34686      *
34687      *  curveSegments: <int>, // number of points on the curves
34688      *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
34689      *  depth: <float>, // Depth to extrude the shape
34690      *
34691      *  bevelEnabled: <bool>, // turn on bevel
34692      *  bevelThickness: <float>, // how deep into the original shape bevel goes
34693      *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
34694      *  bevelOffset: <float>, // how far from shape outline does bevel start
34695      *  bevelSegments: <int>, // number of bevel layers
34696      *
34697      *  extrudePath: <THREE.Curve> // curve to extrude shape along
34698      *
34699      *  UVGenerator: <Object> // object that provides UV generator functions
34700      *
34701      * }
34702      */
34703
34704     class ExtrudeGeometry extends BufferGeometry {
34705
34706         constructor( shapes = new Shape( [ new Vector2( 0.5, 0.5 ), new Vector2( - 0.5, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), options = {} ) {
34707
34708                 super();
34709
34710                 this.type = 'ExtrudeGeometry';
34711
34712                 this.parameters = {
34713                         shapes: shapes,
34714                         options: options
34715                 };
34716
34717                 shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
34718
34719                 const scope = this;
34720
34721                 const verticesArray = [];
34722                 const uvArray = [];
34723
34724                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
34725
34726                         const shape = shapes[ i ];
34727                         addShape( shape );
34728
34729                 }
34730
34731                 // build geometry
34732
34733                 this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
34734                 this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
34735
34736                 this.computeVertexNormals();
34737
34738                 // functions
34739
34740                 function addShape( shape ) {
34741
34742                         const placeholder = [];
34743
34744                         // options
34745
34746                         const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
34747                         const steps = options.steps !== undefined ? options.steps : 1;
34748                         let depth = options.depth !== undefined ? options.depth : 1;
34749
34750                         let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
34751                         let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2;
34752                         let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1;
34753                         let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
34754                         let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
34755
34756                         const extrudePath = options.extrudePath;
34757
34758                         const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
34759
34760                         // deprecated options
34761
34762                         if ( options.amount !== undefined ) {
34763
34764                                 console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );
34765                                 depth = options.amount;
34766
34767                         }
34768
34769                         //
34770
34771                         let extrudePts, extrudeByPath = false;
34772                         let splineTube, binormal, normal, position2;
34773
34774                         if ( extrudePath ) {
34775
34776                                 extrudePts = extrudePath.getSpacedPoints( steps );
34777
34778                                 extrudeByPath = true;
34779                                 bevelEnabled = false; // bevels not supported for path extrusion
34780
34781                                 // SETUP TNB variables
34782
34783                                 // TODO1 - have a .isClosed in spline?
34784
34785                                 splineTube = extrudePath.computeFrenetFrames( steps, false );
34786
34787                                 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
34788
34789                                 binormal = new Vector3();
34790                                 normal = new Vector3();
34791                                 position2 = new Vector3();
34792
34793                         }
34794
34795                         // Safeguards if bevels are not enabled
34796
34797                         if ( ! bevelEnabled ) {
34798
34799                                 bevelSegments = 0;
34800                                 bevelThickness = 0;
34801                                 bevelSize = 0;
34802                                 bevelOffset = 0;
34803
34804                         }
34805
34806                         // Variables initialization
34807
34808                         const shapePoints = shape.extractPoints( curveSegments );
34809
34810                         let vertices = shapePoints.shape;
34811                         const holes = shapePoints.holes;
34812
34813                         const reverse = ! ShapeUtils.isClockWise( vertices );
34814
34815                         if ( reverse ) {
34816
34817                                 vertices = vertices.reverse();
34818
34819                                 // Maybe we should also check if holes are in the opposite direction, just to be safe ...
34820
34821                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
34822
34823                                         const ahole = holes[ h ];
34824
34825                                         if ( ShapeUtils.isClockWise( ahole ) ) {
34826
34827                                                 holes[ h ] = ahole.reverse();
34828
34829                                         }
34830
34831                                 }
34832
34833                         }
34834
34835
34836                         const faces = ShapeUtils.triangulateShape( vertices, holes );
34837
34838                         /* Vertices */
34839
34840                         const contour = vertices; // vertices has all points but contour has only points of circumference
34841
34842                         for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
34843
34844                                 const ahole = holes[ h ];
34845
34846                                 vertices = vertices.concat( ahole );
34847
34848                         }
34849
34850
34851                         function scalePt2( pt, vec, size ) {
34852
34853                                 if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' );
34854
34855                                 return vec.clone().multiplyScalar( size ).add( pt );
34856
34857                         }
34858
34859                         const vlen = vertices.length, flen = faces.length;
34860
34861
34862                         // Find directions for point movement
34863
34864
34865                         function getBevelVec( inPt, inPrev, inNext ) {
34866
34867                                 // computes for inPt the corresponding point inPt' on a new contour
34868                                 //   shifted by 1 unit (length of normalized vector) to the left
34869                                 // if we walk along contour clockwise, this new contour is outside the old one
34870                                 //
34871                                 // inPt' is the intersection of the two lines parallel to the two
34872                                 //  adjacent edges of inPt at a distance of 1 unit on the left side.
34873
34874                                 let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
34875
34876                                 // good reading for geometry algorithms (here: line-line intersection)
34877                                 // http://geomalgorithms.com/a05-_intersect-1.html
34878
34879                                 const v_prev_x = inPt.x - inPrev.x,
34880                                         v_prev_y = inPt.y - inPrev.y;
34881                                 const v_next_x = inNext.x - inPt.x,
34882                                         v_next_y = inNext.y - inPt.y;
34883
34884                                 const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
34885
34886                                 // check for collinear edges
34887                                 const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
34888
34889                                 if ( Math.abs( collinear0 ) > Number.EPSILON ) {
34890
34891                                         // not collinear
34892
34893                                         // length of vectors for normalizing
34894
34895                                         const v_prev_len = Math.sqrt( v_prev_lensq );
34896                                         const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
34897
34898                                         // shift adjacent points by unit vectors to the left
34899
34900                                         const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
34901                                         const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
34902
34903                                         const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
34904                                         const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
34905
34906                                         // scaling factor for v_prev to intersection point
34907
34908                                         const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
34909                                                         ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
34910                                                 ( v_prev_x * v_next_y - v_prev_y * v_next_x );
34911
34912                                         // vector from inPt to intersection point
34913
34914                                         v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
34915                                         v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
34916
34917                                         // Don't normalize!, otherwise sharp corners become ugly
34918                                         //  but prevent crazy spikes
34919                                         const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
34920                                         if ( v_trans_lensq <= 2 ) {
34921
34922                                                 return new Vector2( v_trans_x, v_trans_y );
34923
34924                                         } else {
34925
34926                                                 shrink_by = Math.sqrt( v_trans_lensq / 2 );
34927
34928                                         }
34929
34930                                 } else {
34931
34932                                         // handle special case of collinear edges
34933
34934                                         let direction_eq = false; // assumes: opposite
34935
34936                                         if ( v_prev_x > Number.EPSILON ) {
34937
34938                                                 if ( v_next_x > Number.EPSILON ) {
34939
34940                                                         direction_eq = true;
34941
34942                                                 }
34943
34944                                         } else {
34945
34946                                                 if ( v_prev_x < - Number.EPSILON ) {
34947
34948                                                         if ( v_next_x < - Number.EPSILON ) {
34949
34950                                                                 direction_eq = true;
34951
34952                                                         }
34953
34954                                                 } else {
34955
34956                                                         if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
34957
34958                                                                 direction_eq = true;
34959
34960                                                         }
34961
34962                                                 }
34963
34964                                         }
34965
34966                                         if ( direction_eq ) {
34967
34968                                                 // console.log("Warning: lines are a straight sequence");
34969                                                 v_trans_x = - v_prev_y;
34970                                                 v_trans_y = v_prev_x;
34971                                                 shrink_by = Math.sqrt( v_prev_lensq );
34972
34973                                         } else {
34974
34975                                                 // console.log("Warning: lines are a straight spike");
34976                                                 v_trans_x = v_prev_x;
34977                                                 v_trans_y = v_prev_y;
34978                                                 shrink_by = Math.sqrt( v_prev_lensq / 2 );
34979
34980                                         }
34981
34982                                 }
34983
34984                                 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
34985
34986                         }
34987
34988
34989                         const contourMovements = [];
34990
34991                         for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
34992
34993                                 if ( j === il ) j = 0;
34994                                 if ( k === il ) k = 0;
34995
34996                                 //  (j)---(i)---(k)
34997                                 // console.log('i,j,k', i, j , k)
34998
34999                                 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
35000
35001                         }
35002
35003                         const holesMovements = [];
35004                         let oneHoleMovements, verticesMovements = contourMovements.concat();
35005
35006                         for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35007
35008                                 const ahole = holes[ h ];
35009
35010                                 oneHoleMovements = [];
35011
35012                                 for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
35013
35014                                         if ( j === il ) j = 0;
35015                                         if ( k === il ) k = 0;
35016
35017                                         //  (j)---(i)---(k)
35018                                         oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
35019
35020                                 }
35021
35022                                 holesMovements.push( oneHoleMovements );
35023                                 verticesMovements = verticesMovements.concat( oneHoleMovements );
35024
35025                         }
35026
35027
35028                         // Loop bevelSegments, 1 for the front, 1 for the back
35029
35030                         for ( let b = 0; b < bevelSegments; b ++ ) {
35031
35032                                 //for ( b = bevelSegments; b > 0; b -- ) {
35033
35034                                 const t = b / bevelSegments;
35035                                 const z = bevelThickness * Math.cos( t * Math.PI / 2 );
35036                                 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
35037
35038                                 // contract shape
35039
35040                                 for ( let i = 0, il = contour.length; i < il; i ++ ) {
35041
35042                                         const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
35043
35044                                         v( vert.x, vert.y, - z );
35045
35046                                 }
35047
35048                                 // expand holes
35049
35050                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35051
35052                                         const ahole = holes[ h ];
35053                                         oneHoleMovements = holesMovements[ h ];
35054
35055                                         for ( let i = 0, il = ahole.length; i < il; i ++ ) {
35056
35057                                                 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
35058
35059                                                 v( vert.x, vert.y, - z );
35060
35061                                         }
35062
35063                                 }
35064
35065                         }
35066
35067                         const bs = bevelSize + bevelOffset;
35068
35069                         // Back facing vertices
35070
35071                         for ( let i = 0; i < vlen; i ++ ) {
35072
35073                                 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
35074
35075                                 if ( ! extrudeByPath ) {
35076
35077                                         v( vert.x, vert.y, 0 );
35078
35079                                 } else {
35080
35081                                         // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
35082
35083                                         normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
35084                                         binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
35085
35086                                         position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
35087
35088                                         v( position2.x, position2.y, position2.z );
35089
35090                                 }
35091
35092                         }
35093
35094                         // Add stepped vertices...
35095                         // Including front facing vertices
35096
35097                         for ( let s = 1; s <= steps; s ++ ) {
35098
35099                                 for ( let i = 0; i < vlen; i ++ ) {
35100
35101                                         const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
35102
35103                                         if ( ! extrudeByPath ) {
35104
35105                                                 v( vert.x, vert.y, depth / steps * s );
35106
35107                                         } else {
35108
35109                                                 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
35110
35111                                                 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
35112                                                 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
35113
35114                                                 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
35115
35116                                                 v( position2.x, position2.y, position2.z );
35117
35118                                         }
35119
35120                                 }
35121
35122                         }
35123
35124
35125                         // Add bevel segments planes
35126
35127                         //for ( b = 1; b <= bevelSegments; b ++ ) {
35128                         for ( let b = bevelSegments - 1; b >= 0; b -- ) {
35129
35130                                 const t = b / bevelSegments;
35131                                 const z = bevelThickness * Math.cos( t * Math.PI / 2 );
35132                                 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
35133
35134                                 // contract shape
35135
35136                                 for ( let i = 0, il = contour.length; i < il; i ++ ) {
35137
35138                                         const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
35139                                         v( vert.x, vert.y, depth + z );
35140
35141                                 }
35142
35143                                 // expand holes
35144
35145                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35146
35147                                         const ahole = holes[ h ];
35148                                         oneHoleMovements = holesMovements[ h ];
35149
35150                                         for ( let i = 0, il = ahole.length; i < il; i ++ ) {
35151
35152                                                 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
35153
35154                                                 if ( ! extrudeByPath ) {
35155
35156                                                         v( vert.x, vert.y, depth + z );
35157
35158                                                 } else {
35159
35160                                                         v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
35161
35162                                                 }
35163
35164                                         }
35165
35166                                 }
35167
35168                         }
35169
35170                         /* Faces */
35171
35172                         // Top and bottom faces
35173
35174                         buildLidFaces();
35175
35176                         // Sides faces
35177
35178                         buildSideFaces();
35179
35180
35181                         /////  Internal functions
35182
35183                         function buildLidFaces() {
35184
35185                                 const start = verticesArray.length / 3;
35186
35187                                 if ( bevelEnabled ) {
35188
35189                                         let layer = 0; // steps + 1
35190                                         let offset = vlen * layer;
35191
35192                                         // Bottom faces
35193
35194                                         for ( let i = 0; i < flen; i ++ ) {
35195
35196                                                 const face = faces[ i ];
35197                                                 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
35198
35199                                         }
35200
35201                                         layer = steps + bevelSegments * 2;
35202                                         offset = vlen * layer;
35203
35204                                         // Top faces
35205
35206                                         for ( let i = 0; i < flen; i ++ ) {
35207
35208                                                 const face = faces[ i ];
35209                                                 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
35210
35211                                         }
35212
35213                                 } else {
35214
35215                                         // Bottom faces
35216
35217                                         for ( let i = 0; i < flen; i ++ ) {
35218
35219                                                 const face = faces[ i ];
35220                                                 f3( face[ 2 ], face[ 1 ], face[ 0 ] );
35221
35222                                         }
35223
35224                                         // Top faces
35225
35226                                         for ( let i = 0; i < flen; i ++ ) {
35227
35228                                                 const face = faces[ i ];
35229                                                 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
35230
35231                                         }
35232
35233                                 }
35234
35235                                 scope.addGroup( start, verticesArray.length / 3 - start, 0 );
35236
35237                         }
35238
35239                         // Create faces for the z-sides of the shape
35240
35241                         function buildSideFaces() {
35242
35243                                 const start = verticesArray.length / 3;
35244                                 let layeroffset = 0;
35245                                 sidewalls( contour, layeroffset );
35246                                 layeroffset += contour.length;
35247
35248                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35249
35250                                         const ahole = holes[ h ];
35251                                         sidewalls( ahole, layeroffset );
35252
35253                                         //, true
35254                                         layeroffset += ahole.length;
35255
35256                                 }
35257
35258
35259                                 scope.addGroup( start, verticesArray.length / 3 - start, 1 );
35260
35261
35262                         }
35263
35264                         function sidewalls( contour, layeroffset ) {
35265
35266                                 let i = contour.length;
35267
35268                                 while ( -- i >= 0 ) {
35269
35270                                         const j = i;
35271                                         let k = i - 1;
35272                                         if ( k < 0 ) k = contour.length - 1;
35273
35274                                         //console.log('b', i,j, i-1, k,vertices.length);
35275
35276                                         for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
35277
35278                                                 const slen1 = vlen * s;
35279                                                 const slen2 = vlen * ( s + 1 );
35280
35281                                                 const a = layeroffset + j + slen1,
35282                                                         b = layeroffset + k + slen1,
35283                                                         c = layeroffset + k + slen2,
35284                                                         d = layeroffset + j + slen2;
35285
35286                                                 f4( a, b, c, d );
35287
35288                                         }
35289
35290                                 }
35291
35292                         }
35293
35294                         function v( x, y, z ) {
35295
35296                                 placeholder.push( x );
35297                                 placeholder.push( y );
35298                                 placeholder.push( z );
35299
35300                         }
35301
35302
35303                         function f3( a, b, c ) {
35304
35305                                 addVertex( a );
35306                                 addVertex( b );
35307                                 addVertex( c );
35308
35309                                 const nextIndex = verticesArray.length / 3;
35310                                 const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
35311
35312                                 addUV( uvs[ 0 ] );
35313                                 addUV( uvs[ 1 ] );
35314                                 addUV( uvs[ 2 ] );
35315
35316                         }
35317
35318                         function f4( a, b, c, d ) {
35319
35320                                 addVertex( a );
35321                                 addVertex( b );
35322                                 addVertex( d );
35323
35324                                 addVertex( b );
35325                                 addVertex( c );
35326                                 addVertex( d );
35327
35328
35329                                 const nextIndex = verticesArray.length / 3;
35330                                 const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
35331
35332                                 addUV( uvs[ 0 ] );
35333                                 addUV( uvs[ 1 ] );
35334                                 addUV( uvs[ 3 ] );
35335
35336                                 addUV( uvs[ 1 ] );
35337                                 addUV( uvs[ 2 ] );
35338                                 addUV( uvs[ 3 ] );
35339
35340                         }
35341
35342                         function addVertex( index ) {
35343
35344                                 verticesArray.push( placeholder[ index * 3 + 0 ] );
35345                                 verticesArray.push( placeholder[ index * 3 + 1 ] );
35346                                 verticesArray.push( placeholder[ index * 3 + 2 ] );
35347
35348                         }
35349
35350
35351                         function addUV( vector2 ) {
35352
35353                                 uvArray.push( vector2.x );
35354                                 uvArray.push( vector2.y );
35355
35356                         }
35357
35358                 }
35359
35360         }
35361
35362         toJSON() {
35363
35364                 const data = super.toJSON();
35365
35366                 const shapes = this.parameters.shapes;
35367                 const options = this.parameters.options;
35368
35369                 return toJSON$1( shapes, options, data );
35370
35371         }
35372
35373         static fromJSON( data, shapes ) {
35374
35375                 const geometryShapes = [];
35376
35377                 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
35378
35379                         const shape = shapes[ data.shapes[ j ] ];
35380
35381                         geometryShapes.push( shape );
35382
35383                 }
35384
35385                 const extrudePath = data.options.extrudePath;
35386
35387                 if ( extrudePath !== undefined ) {
35388
35389                         data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
35390
35391                 }
35392
35393                 return new ExtrudeGeometry( geometryShapes, data.options );
35394
35395         }
35396
35397     }
35398
35399     const WorldUVGenerator = {
35400
35401         generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
35402
35403                 const a_x = vertices[ indexA * 3 ];
35404                 const a_y = vertices[ indexA * 3 + 1 ];
35405                 const b_x = vertices[ indexB * 3 ];
35406                 const b_y = vertices[ indexB * 3 + 1 ];
35407                 const c_x = vertices[ indexC * 3 ];
35408                 const c_y = vertices[ indexC * 3 + 1 ];
35409
35410                 return [
35411                         new Vector2( a_x, a_y ),
35412                         new Vector2( b_x, b_y ),
35413                         new Vector2( c_x, c_y )
35414                 ];
35415
35416         },
35417
35418         generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
35419
35420                 const a_x = vertices[ indexA * 3 ];
35421                 const a_y = vertices[ indexA * 3 + 1 ];
35422                 const a_z = vertices[ indexA * 3 + 2 ];
35423                 const b_x = vertices[ indexB * 3 ];
35424                 const b_y = vertices[ indexB * 3 + 1 ];
35425                 const b_z = vertices[ indexB * 3 + 2 ];
35426                 const c_x = vertices[ indexC * 3 ];
35427                 const c_y = vertices[ indexC * 3 + 1 ];
35428                 const c_z = vertices[ indexC * 3 + 2 ];
35429                 const d_x = vertices[ indexD * 3 ];
35430                 const d_y = vertices[ indexD * 3 + 1 ];
35431                 const d_z = vertices[ indexD * 3 + 2 ];
35432
35433                 if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) {
35434
35435                         return [
35436                                 new Vector2( a_x, 1 - a_z ),
35437                                 new Vector2( b_x, 1 - b_z ),
35438                                 new Vector2( c_x, 1 - c_z ),
35439                                 new Vector2( d_x, 1 - d_z )
35440                         ];
35441
35442                 } else {
35443
35444                         return [
35445                                 new Vector2( a_y, 1 - a_z ),
35446                                 new Vector2( b_y, 1 - b_z ),
35447                                 new Vector2( c_y, 1 - c_z ),
35448                                 new Vector2( d_y, 1 - d_z )
35449                         ];
35450
35451                 }
35452
35453         }
35454
35455     };
35456
35457     function toJSON$1( shapes, options, data ) {
35458
35459         data.shapes = [];
35460
35461         if ( Array.isArray( shapes ) ) {
35462
35463                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
35464
35465                         const shape = shapes[ i ];
35466
35467                         data.shapes.push( shape.uuid );
35468
35469                 }
35470
35471         } else {
35472
35473                 data.shapes.push( shapes.uuid );
35474
35475         }
35476
35477         if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
35478
35479         return data;
35480
35481     }
35482
35483     class ShapeGeometry extends BufferGeometry {
35484
35485         constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) {
35486
35487                 super();
35488                 this.type = 'ShapeGeometry';
35489
35490                 this.parameters = {
35491                         shapes: shapes,
35492                         curveSegments: curveSegments
35493                 };
35494
35495                 // buffers
35496
35497                 const indices = [];
35498                 const vertices = [];
35499                 const normals = [];
35500                 const uvs = [];
35501
35502                 // helper variables
35503
35504                 let groupStart = 0;
35505                 let groupCount = 0;
35506
35507                 // allow single and array values for "shapes" parameter
35508
35509                 if ( Array.isArray( shapes ) === false ) {
35510
35511                         addShape( shapes );
35512
35513                 } else {
35514
35515                         for ( let i = 0; i < shapes.length; i ++ ) {
35516
35517                                 addShape( shapes[ i ] );
35518
35519                                 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
35520
35521                                 groupStart += groupCount;
35522                                 groupCount = 0;
35523
35524                         }
35525
35526                 }
35527
35528                 // build geometry
35529
35530                 this.setIndex( indices );
35531                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
35532                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
35533                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
35534
35535
35536                 // helper functions
35537
35538                 function addShape( shape ) {
35539
35540                         const indexOffset = vertices.length / 3;
35541                         const points = shape.extractPoints( curveSegments );
35542
35543                         let shapeVertices = points.shape;
35544                         const shapeHoles = points.holes;
35545
35546                         // check direction of vertices
35547
35548                         if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
35549
35550                                 shapeVertices = shapeVertices.reverse();
35551
35552                         }
35553
35554                         for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
35555
35556                                 const shapeHole = shapeHoles[ i ];
35557
35558                                 if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
35559
35560                                         shapeHoles[ i ] = shapeHole.reverse();
35561
35562                                 }
35563
35564                         }
35565
35566                         const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
35567
35568                         // join vertices of inner and outer paths to a single array
35569
35570                         for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
35571
35572                                 const shapeHole = shapeHoles[ i ];
35573                                 shapeVertices = shapeVertices.concat( shapeHole );
35574
35575                         }
35576
35577                         // vertices, normals, uvs
35578
35579                         for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
35580
35581                                 const vertex = shapeVertices[ i ];
35582
35583                                 vertices.push( vertex.x, vertex.y, 0 );
35584                                 normals.push( 0, 0, 1 );
35585                                 uvs.push( vertex.x, vertex.y ); // world uvs
35586
35587                         }
35588
35589                         // incides
35590
35591                         for ( let i = 0, l = faces.length; i < l; i ++ ) {
35592
35593                                 const face = faces[ i ];
35594
35595                                 const a = face[ 0 ] + indexOffset;
35596                                 const b = face[ 1 ] + indexOffset;
35597                                 const c = face[ 2 ] + indexOffset;
35598
35599                                 indices.push( a, b, c );
35600                                 groupCount += 3;
35601
35602                         }
35603
35604                 }
35605
35606         }
35607
35608         toJSON() {
35609
35610                 const data = super.toJSON();
35611
35612                 const shapes = this.parameters.shapes;
35613
35614                 return toJSON( shapes, data );
35615
35616         }
35617
35618         static fromJSON( data, shapes ) {
35619
35620                 const geometryShapes = [];
35621
35622                 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
35623
35624                         const shape = shapes[ data.shapes[ j ] ];
35625
35626                         geometryShapes.push( shape );
35627
35628                 }
35629
35630                 return new ShapeGeometry( geometryShapes, data.curveSegments );
35631
35632         }
35633
35634     }
35635
35636     function toJSON( shapes, data ) {
35637
35638         data.shapes = [];
35639
35640         if ( Array.isArray( shapes ) ) {
35641
35642                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
35643
35644                         const shape = shapes[ i ];
35645
35646                         data.shapes.push( shape.uuid );
35647
35648                 }
35649
35650         } else {
35651
35652                 data.shapes.push( shapes.uuid );
35653
35654         }
35655
35656         return data;
35657
35658     }
35659
35660     class SphereGeometry extends BufferGeometry {
35661
35662         constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
35663
35664                 super();
35665                 this.type = 'SphereGeometry';
35666
35667                 this.parameters = {
35668                         radius: radius,
35669                         widthSegments: widthSegments,
35670                         heightSegments: heightSegments,
35671                         phiStart: phiStart,
35672                         phiLength: phiLength,
35673                         thetaStart: thetaStart,
35674                         thetaLength: thetaLength
35675                 };
35676
35677                 widthSegments = Math.max( 3, Math.floor( widthSegments ) );
35678                 heightSegments = Math.max( 2, Math.floor( heightSegments ) );
35679
35680                 const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
35681
35682                 let index = 0;
35683                 const grid = [];
35684
35685                 const vertex = new Vector3();
35686                 const normal = new Vector3();
35687
35688                 // buffers
35689
35690                 const indices = [];
35691                 const vertices = [];
35692                 const normals = [];
35693                 const uvs = [];
35694
35695                 // generate vertices, normals and uvs
35696
35697                 for ( let iy = 0; iy <= heightSegments; iy ++ ) {
35698
35699                         const verticesRow = [];
35700
35701                         const v = iy / heightSegments;
35702
35703                         // special case for the poles
35704
35705                         let uOffset = 0;
35706
35707                         if ( iy == 0 && thetaStart == 0 ) {
35708
35709                                 uOffset = 0.5 / widthSegments;
35710
35711                         } else if ( iy == heightSegments && thetaEnd == Math.PI ) {
35712
35713                                 uOffset = - 0.5 / widthSegments;
35714
35715                         }
35716
35717                         for ( let ix = 0; ix <= widthSegments; ix ++ ) {
35718
35719                                 const u = ix / widthSegments;
35720
35721                                 // vertex
35722
35723                                 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
35724                                 vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
35725                                 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
35726
35727                                 vertices.push( vertex.x, vertex.y, vertex.z );
35728
35729                                 // normal
35730
35731                                 normal.copy( vertex ).normalize();
35732                                 normals.push( normal.x, normal.y, normal.z );
35733
35734                                 // uv
35735
35736                                 uvs.push( u + uOffset, 1 - v );
35737
35738                                 verticesRow.push( index ++ );
35739
35740                         }
35741
35742                         grid.push( verticesRow );
35743
35744                 }
35745
35746                 // indices
35747
35748                 for ( let iy = 0; iy < heightSegments; iy ++ ) {
35749
35750                         for ( let ix = 0; ix < widthSegments; ix ++ ) {
35751
35752                                 const a = grid[ iy ][ ix + 1 ];
35753                                 const b = grid[ iy ][ ix ];
35754                                 const c = grid[ iy + 1 ][ ix ];
35755                                 const d = grid[ iy + 1 ][ ix + 1 ];
35756
35757                                 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
35758                                 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
35759
35760                         }
35761
35762                 }
35763
35764                 // build geometry
35765
35766                 this.setIndex( indices );
35767                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
35768                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
35769                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
35770
35771         }
35772
35773         static fromJSON( data ) {
35774
35775                 return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength );
35776
35777         }
35778
35779     }
35780
35781     /**
35782      * parameters = {
35783      *  color: <THREE.Color>
35784      * }
35785      */
35786
35787     class ShadowMaterial extends Material {
35788
35789         constructor( parameters ) {
35790
35791                 super();
35792
35793                 this.type = 'ShadowMaterial';
35794
35795                 this.color = new Color( 0x000000 );
35796                 this.transparent = true;
35797
35798                 this.setValues( parameters );
35799
35800         }
35801
35802         copy( source ) {
35803
35804                 super.copy( source );
35805
35806                 this.color.copy( source.color );
35807
35808                 return this;
35809
35810         }
35811
35812     }
35813
35814     ShadowMaterial.prototype.isShadowMaterial = true;
35815
35816     /**
35817      * parameters = {
35818      *  color: <hex>,
35819      *  roughness: <float>,
35820      *  metalness: <float>,
35821      *  opacity: <float>,
35822      *
35823      *  map: new THREE.Texture( <Image> ),
35824      *
35825      *  lightMap: new THREE.Texture( <Image> ),
35826      *  lightMapIntensity: <float>
35827      *
35828      *  aoMap: new THREE.Texture( <Image> ),
35829      *  aoMapIntensity: <float>
35830      *
35831      *  emissive: <hex>,
35832      *  emissiveIntensity: <float>
35833      *  emissiveMap: new THREE.Texture( <Image> ),
35834      *
35835      *  bumpMap: new THREE.Texture( <Image> ),
35836      *  bumpScale: <float>,
35837      *
35838      *  normalMap: new THREE.Texture( <Image> ),
35839      *  normalMapType: THREE.TangentSpaceNormalMap,
35840      *  normalScale: <Vector2>,
35841      *
35842      *  displacementMap: new THREE.Texture( <Image> ),
35843      *  displacementScale: <float>,
35844      *  displacementBias: <float>,
35845      *
35846      *  roughnessMap: new THREE.Texture( <Image> ),
35847      *
35848      *  metalnessMap: new THREE.Texture( <Image> ),
35849      *
35850      *  alphaMap: new THREE.Texture( <Image> ),
35851      *
35852      *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
35853      *  envMapIntensity: <float>
35854      *
35855      *  refractionRatio: <float>,
35856      *
35857      *  wireframe: <boolean>,
35858      *  wireframeLinewidth: <float>,
35859      *
35860      *  flatShading: <bool>
35861      * }
35862      */
35863
35864     class MeshStandardMaterial extends Material {
35865
35866         constructor( parameters ) {
35867
35868                 super();
35869
35870                 this.defines = { 'STANDARD': '' };
35871
35872                 this.type = 'MeshStandardMaterial';
35873
35874                 this.color = new Color( 0xffffff ); // diffuse
35875                 this.roughness = 1.0;
35876                 this.metalness = 0.0;
35877
35878                 this.map = null;
35879
35880                 this.lightMap = null;
35881                 this.lightMapIntensity = 1.0;
35882
35883                 this.aoMap = null;
35884                 this.aoMapIntensity = 1.0;
35885
35886                 this.emissive = new Color( 0x000000 );
35887                 this.emissiveIntensity = 1.0;
35888                 this.emissiveMap = null;
35889
35890                 this.bumpMap = null;
35891                 this.bumpScale = 1;
35892
35893                 this.normalMap = null;
35894                 this.normalMapType = TangentSpaceNormalMap;
35895                 this.normalScale = new Vector2( 1, 1 );
35896
35897                 this.displacementMap = null;
35898                 this.displacementScale = 1;
35899                 this.displacementBias = 0;
35900
35901                 this.roughnessMap = null;
35902
35903                 this.metalnessMap = null;
35904
35905                 this.alphaMap = null;
35906
35907                 this.envMap = null;
35908                 this.envMapIntensity = 1.0;
35909
35910                 this.refractionRatio = 0.98;
35911
35912                 this.wireframe = false;
35913                 this.wireframeLinewidth = 1;
35914                 this.wireframeLinecap = 'round';
35915                 this.wireframeLinejoin = 'round';
35916
35917                 this.flatShading = false;
35918
35919                 this.setValues( parameters );
35920
35921         }
35922
35923         copy( source ) {
35924
35925                 super.copy( source );
35926
35927                 this.defines = { 'STANDARD': '' };
35928
35929                 this.color.copy( source.color );
35930                 this.roughness = source.roughness;
35931                 this.metalness = source.metalness;
35932
35933                 this.map = source.map;
35934
35935                 this.lightMap = source.lightMap;
35936                 this.lightMapIntensity = source.lightMapIntensity;
35937
35938                 this.aoMap = source.aoMap;
35939                 this.aoMapIntensity = source.aoMapIntensity;
35940
35941                 this.emissive.copy( source.emissive );
35942                 this.emissiveMap = source.emissiveMap;
35943                 this.emissiveIntensity = source.emissiveIntensity;
35944
35945                 this.bumpMap = source.bumpMap;
35946                 this.bumpScale = source.bumpScale;
35947
35948                 this.normalMap = source.normalMap;
35949                 this.normalMapType = source.normalMapType;
35950                 this.normalScale.copy( source.normalScale );
35951
35952                 this.displacementMap = source.displacementMap;
35953                 this.displacementScale = source.displacementScale;
35954                 this.displacementBias = source.displacementBias;
35955
35956                 this.roughnessMap = source.roughnessMap;
35957
35958                 this.metalnessMap = source.metalnessMap;
35959
35960                 this.alphaMap = source.alphaMap;
35961
35962                 this.envMap = source.envMap;
35963                 this.envMapIntensity = source.envMapIntensity;
35964
35965                 this.refractionRatio = source.refractionRatio;
35966
35967                 this.wireframe = source.wireframe;
35968                 this.wireframeLinewidth = source.wireframeLinewidth;
35969                 this.wireframeLinecap = source.wireframeLinecap;
35970                 this.wireframeLinejoin = source.wireframeLinejoin;
35971
35972                 this.flatShading = source.flatShading;
35973
35974                 return this;
35975
35976         }
35977
35978     }
35979
35980     MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
35981
35982     /**
35983      * parameters = {
35984      *  clearcoat: <float>,
35985      *  clearcoatMap: new THREE.Texture( <Image> ),
35986      *  clearcoatRoughness: <float>,
35987      *  clearcoatRoughnessMap: new THREE.Texture( <Image> ),
35988      *  clearcoatNormalScale: <Vector2>,
35989      *  clearcoatNormalMap: new THREE.Texture( <Image> ),
35990      *
35991      *  ior: <float>,
35992      *  reflectivity: <float>,
35993      *
35994      *  sheen: <float>,
35995      *  sheenColor: <Color>,
35996      *  sheenColorMap: new THREE.Texture( <Image> ),
35997      *  sheenRoughness: <float>,
35998      *  sheenRoughnessMap: new THREE.Texture( <Image> ),
35999      *
36000      *  transmission: <float>,
36001      *  transmissionMap: new THREE.Texture( <Image> ),
36002      *
36003      *  thickness: <float>,
36004      *  thicknessMap: new THREE.Texture( <Image> ),
36005      *  attenuationDistance: <float>,
36006      *  attenuationColor: <Color>,
36007      *
36008      *  specularIntensity: <float>,
36009      *  specularIntensityMap: new THREE.Texture( <Image> ),
36010      *  specularColor: <Color>,
36011      *  specularColorMap: new THREE.Texture( <Image> )
36012      * }
36013      */
36014
36015     class MeshPhysicalMaterial extends MeshStandardMaterial {
36016
36017         constructor( parameters ) {
36018
36019                 super();
36020
36021                 this.defines = {
36022
36023                         'STANDARD': '',
36024                         'PHYSICAL': ''
36025
36026                 };
36027
36028                 this.type = 'MeshPhysicalMaterial';
36029
36030                 this.clearcoatMap = null;
36031                 this.clearcoatRoughness = 0.0;
36032                 this.clearcoatRoughnessMap = null;
36033                 this.clearcoatNormalScale = new Vector2( 1, 1 );
36034                 this.clearcoatNormalMap = null;
36035
36036                 this.ior = 1.5;
36037
36038                 Object.defineProperty( this, 'reflectivity', {
36039                         get: function () {
36040
36041                                 return ( clamp$1( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) );
36042
36043                         },
36044                         set: function ( reflectivity ) {
36045
36046                                 this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity );
36047
36048                         }
36049                 } );
36050
36051                 this.sheenColor = new Color( 0x000000 );
36052                 this.sheenColorMap = null;
36053                 this.sheenRoughness = 1.0;
36054                 this.sheenRoughnessMap = null;
36055
36056                 this.transmissionMap = null;
36057
36058                 this.thickness = 0.01;
36059                 this.thicknessMap = null;
36060                 this.attenuationDistance = 0.0;
36061                 this.attenuationColor = new Color( 1, 1, 1 );
36062
36063                 this.specularIntensity = 1.0;
36064                 this.specularIntensityMap = null;
36065                 this.specularColor = new Color( 1, 1, 1 );
36066                 this.specularColorMap = null;
36067
36068                 this._sheen = 0.0;
36069                 this._clearcoat = 0;
36070                 this._transmission = 0;
36071
36072                 this.setValues( parameters );
36073
36074         }
36075
36076         get sheen() {
36077
36078                 return this._sheen;
36079
36080         }
36081
36082         set sheen( value ) {
36083
36084                 if ( this._sheen > 0 !== value > 0 ) {
36085
36086                         this.version ++;
36087
36088                 }
36089
36090                 this._sheen = value;
36091
36092         }
36093
36094         get clearcoat() {
36095
36096                 return this._clearcoat;
36097
36098         }
36099
36100         set clearcoat( value ) {
36101
36102                 if ( this._clearcoat > 0 !== value > 0 ) {
36103
36104                         this.version ++;
36105
36106                 }
36107
36108                 this._clearcoat = value;
36109
36110         }
36111
36112         get transmission() {
36113
36114                 return this._transmission;
36115
36116         }
36117
36118         set transmission( value ) {
36119
36120                 if ( this._transmission > 0 !== value > 0 ) {
36121
36122                         this.version ++;
36123
36124                 }
36125
36126                 this._transmission = value;
36127
36128         }
36129
36130         copy( source ) {
36131
36132                 super.copy( source );
36133
36134                 this.defines = {
36135
36136                         'STANDARD': '',
36137                         'PHYSICAL': ''
36138
36139                 };
36140
36141                 this.clearcoat = source.clearcoat;
36142                 this.clearcoatMap = source.clearcoatMap;
36143                 this.clearcoatRoughness = source.clearcoatRoughness;
36144                 this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
36145                 this.clearcoatNormalMap = source.clearcoatNormalMap;
36146                 this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
36147
36148                 this.ior = source.ior;
36149
36150                 this.sheen = source.sheen;
36151                 this.sheenColor.copy( source.sheenColor );
36152                 this.sheenColorMap = source.sheenColorMap;
36153                 this.sheenRoughness = source.sheenRoughness;
36154                 this.sheenRoughnessMap = source.sheenRoughnessMap;
36155
36156                 this.transmission = source.transmission;
36157                 this.transmissionMap = source.transmissionMap;
36158
36159                 this.thickness = source.thickness;
36160                 this.thicknessMap = source.thicknessMap;
36161                 this.attenuationDistance = source.attenuationDistance;
36162                 this.attenuationColor.copy( source.attenuationColor );
36163
36164                 this.specularIntensity = source.specularIntensity;
36165                 this.specularIntensityMap = source.specularIntensityMap;
36166                 this.specularColor.copy( source.specularColor );
36167                 this.specularColorMap = source.specularColorMap;
36168
36169                 return this;
36170
36171         }
36172
36173     }
36174
36175     MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
36176
36177     /**
36178      * parameters = {
36179      *  color: <hex>,
36180      *  specular: <hex>,
36181      *  shininess: <float>,
36182      *  opacity: <float>,
36183      *
36184      *  map: new THREE.Texture( <Image> ),
36185      *
36186      *  lightMap: new THREE.Texture( <Image> ),
36187      *  lightMapIntensity: <float>
36188      *
36189      *  aoMap: new THREE.Texture( <Image> ),
36190      *  aoMapIntensity: <float>
36191      *
36192      *  emissive: <hex>,
36193      *  emissiveIntensity: <float>
36194      *  emissiveMap: new THREE.Texture( <Image> ),
36195      *
36196      *  bumpMap: new THREE.Texture( <Image> ),
36197      *  bumpScale: <float>,
36198      *
36199      *  normalMap: new THREE.Texture( <Image> ),
36200      *  normalMapType: THREE.TangentSpaceNormalMap,
36201      *  normalScale: <Vector2>,
36202      *
36203      *  displacementMap: new THREE.Texture( <Image> ),
36204      *  displacementScale: <float>,
36205      *  displacementBias: <float>,
36206      *
36207      *  specularMap: new THREE.Texture( <Image> ),
36208      *
36209      *  alphaMap: new THREE.Texture( <Image> ),
36210      *
36211      *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
36212      *  combine: THREE.MultiplyOperation,
36213      *  reflectivity: <float>,
36214      *  refractionRatio: <float>,
36215      *
36216      *  wireframe: <boolean>,
36217      *  wireframeLinewidth: <float>,
36218      *
36219      *  flatShading: <bool>
36220      * }
36221      */
36222
36223     class MeshPhongMaterial extends Material {
36224
36225         constructor( parameters ) {
36226
36227                 super();
36228
36229                 this.type = 'MeshPhongMaterial';
36230
36231                 this.color = new Color( 0xffffff ); // diffuse
36232                 this.specular = new Color( 0x111111 );
36233                 this.shininess = 30;
36234
36235                 this.map = null;
36236
36237                 this.lightMap = null;
36238                 this.lightMapIntensity = 1.0;
36239
36240                 this.aoMap = null;
36241                 this.aoMapIntensity = 1.0;
36242
36243                 this.emissive = new Color( 0x000000 );
36244                 this.emissiveIntensity = 1.0;
36245                 this.emissiveMap = null;
36246
36247                 this.bumpMap = null;
36248                 this.bumpScale = 1;
36249
36250                 this.normalMap = null;
36251                 this.normalMapType = TangentSpaceNormalMap;
36252                 this.normalScale = new Vector2( 1, 1 );
36253
36254                 this.displacementMap = null;
36255                 this.displacementScale = 1;
36256                 this.displacementBias = 0;
36257
36258                 this.specularMap = null;
36259
36260                 this.alphaMap = null;
36261
36262                 this.envMap = null;
36263                 this.combine = MultiplyOperation;
36264                 this.reflectivity = 1;
36265                 this.refractionRatio = 0.98;
36266
36267                 this.wireframe = false;
36268                 this.wireframeLinewidth = 1;
36269                 this.wireframeLinecap = 'round';
36270                 this.wireframeLinejoin = 'round';
36271
36272                 this.flatShading = false;
36273
36274                 this.setValues( parameters );
36275
36276         }
36277
36278         copy( source ) {
36279
36280                 super.copy( source );
36281
36282                 this.color.copy( source.color );
36283                 this.specular.copy( source.specular );
36284                 this.shininess = source.shininess;
36285
36286                 this.map = source.map;
36287
36288                 this.lightMap = source.lightMap;
36289                 this.lightMapIntensity = source.lightMapIntensity;
36290
36291                 this.aoMap = source.aoMap;
36292                 this.aoMapIntensity = source.aoMapIntensity;
36293
36294                 this.emissive.copy( source.emissive );
36295                 this.emissiveMap = source.emissiveMap;
36296                 this.emissiveIntensity = source.emissiveIntensity;
36297
36298                 this.bumpMap = source.bumpMap;
36299                 this.bumpScale = source.bumpScale;
36300
36301                 this.normalMap = source.normalMap;
36302                 this.normalMapType = source.normalMapType;
36303                 this.normalScale.copy( source.normalScale );
36304
36305                 this.displacementMap = source.displacementMap;
36306                 this.displacementScale = source.displacementScale;
36307                 this.displacementBias = source.displacementBias;
36308
36309                 this.specularMap = source.specularMap;
36310
36311                 this.alphaMap = source.alphaMap;
36312
36313                 this.envMap = source.envMap;
36314                 this.combine = source.combine;
36315                 this.reflectivity = source.reflectivity;
36316                 this.refractionRatio = source.refractionRatio;
36317
36318                 this.wireframe = source.wireframe;
36319                 this.wireframeLinewidth = source.wireframeLinewidth;
36320                 this.wireframeLinecap = source.wireframeLinecap;
36321                 this.wireframeLinejoin = source.wireframeLinejoin;
36322
36323                 this.flatShading = source.flatShading;
36324
36325                 return this;
36326
36327         }
36328
36329     }
36330
36331     MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
36332
36333     /**
36334      * parameters = {
36335      *  color: <hex>,
36336      *
36337      *  map: new THREE.Texture( <Image> ),
36338      *  gradientMap: new THREE.Texture( <Image> ),
36339      *
36340      *  lightMap: new THREE.Texture( <Image> ),
36341      *  lightMapIntensity: <float>
36342      *
36343      *  aoMap: new THREE.Texture( <Image> ),
36344      *  aoMapIntensity: <float>
36345      *
36346      *  emissive: <hex>,
36347      *  emissiveIntensity: <float>
36348      *  emissiveMap: new THREE.Texture( <Image> ),
36349      *
36350      *  bumpMap: new THREE.Texture( <Image> ),
36351      *  bumpScale: <float>,
36352      *
36353      *  normalMap: new THREE.Texture( <Image> ),
36354      *  normalMapType: THREE.TangentSpaceNormalMap,
36355      *  normalScale: <Vector2>,
36356      *
36357      *  displacementMap: new THREE.Texture( <Image> ),
36358      *  displacementScale: <float>,
36359      *  displacementBias: <float>,
36360      *
36361      *  alphaMap: new THREE.Texture( <Image> ),
36362      *
36363      *  wireframe: <boolean>,
36364      *  wireframeLinewidth: <float>,
36365      *
36366      * }
36367      */
36368
36369     class MeshToonMaterial extends Material {
36370
36371         constructor( parameters ) {
36372
36373                 super();
36374
36375                 this.defines = { 'TOON': '' };
36376
36377                 this.type = 'MeshToonMaterial';
36378
36379                 this.color = new Color( 0xffffff );
36380
36381                 this.map = null;
36382                 this.gradientMap = null;
36383
36384                 this.lightMap = null;
36385                 this.lightMapIntensity = 1.0;
36386
36387                 this.aoMap = null;
36388                 this.aoMapIntensity = 1.0;
36389
36390                 this.emissive = new Color( 0x000000 );
36391                 this.emissiveIntensity = 1.0;
36392                 this.emissiveMap = null;
36393
36394                 this.bumpMap = null;
36395                 this.bumpScale = 1;
36396
36397                 this.normalMap = null;
36398                 this.normalMapType = TangentSpaceNormalMap;
36399                 this.normalScale = new Vector2( 1, 1 );
36400
36401                 this.displacementMap = null;
36402                 this.displacementScale = 1;
36403                 this.displacementBias = 0;
36404
36405                 this.alphaMap = null;
36406
36407                 this.wireframe = false;
36408                 this.wireframeLinewidth = 1;
36409                 this.wireframeLinecap = 'round';
36410                 this.wireframeLinejoin = 'round';
36411
36412                 this.setValues( parameters );
36413
36414         }
36415
36416         copy( source ) {
36417
36418                 super.copy( source );
36419
36420                 this.color.copy( source.color );
36421
36422                 this.map = source.map;
36423                 this.gradientMap = source.gradientMap;
36424
36425                 this.lightMap = source.lightMap;
36426                 this.lightMapIntensity = source.lightMapIntensity;
36427
36428                 this.aoMap = source.aoMap;
36429                 this.aoMapIntensity = source.aoMapIntensity;
36430
36431                 this.emissive.copy( source.emissive );
36432                 this.emissiveMap = source.emissiveMap;
36433                 this.emissiveIntensity = source.emissiveIntensity;
36434
36435                 this.bumpMap = source.bumpMap;
36436                 this.bumpScale = source.bumpScale;
36437
36438                 this.normalMap = source.normalMap;
36439                 this.normalMapType = source.normalMapType;
36440                 this.normalScale.copy( source.normalScale );
36441
36442                 this.displacementMap = source.displacementMap;
36443                 this.displacementScale = source.displacementScale;
36444                 this.displacementBias = source.displacementBias;
36445
36446                 this.alphaMap = source.alphaMap;
36447
36448                 this.wireframe = source.wireframe;
36449                 this.wireframeLinewidth = source.wireframeLinewidth;
36450                 this.wireframeLinecap = source.wireframeLinecap;
36451                 this.wireframeLinejoin = source.wireframeLinejoin;
36452
36453                 return this;
36454
36455         }
36456
36457     }
36458
36459     MeshToonMaterial.prototype.isMeshToonMaterial = true;
36460
36461     /**
36462      * parameters = {
36463      *  opacity: <float>,
36464      *
36465      *  bumpMap: new THREE.Texture( <Image> ),
36466      *  bumpScale: <float>,
36467      *
36468      *  normalMap: new THREE.Texture( <Image> ),
36469      *  normalMapType: THREE.TangentSpaceNormalMap,
36470      *  normalScale: <Vector2>,
36471      *
36472      *  displacementMap: new THREE.Texture( <Image> ),
36473      *  displacementScale: <float>,
36474      *  displacementBias: <float>,
36475      *
36476      *  wireframe: <boolean>,
36477      *  wireframeLinewidth: <float>
36478      *
36479      *  flatShading: <bool>
36480      * }
36481      */
36482
36483     class MeshNormalMaterial extends Material {
36484
36485         constructor( parameters ) {
36486
36487                 super();
36488
36489                 this.type = 'MeshNormalMaterial';
36490
36491                 this.bumpMap = null;
36492                 this.bumpScale = 1;
36493
36494                 this.normalMap = null;
36495                 this.normalMapType = TangentSpaceNormalMap;
36496                 this.normalScale = new Vector2( 1, 1 );
36497
36498                 this.displacementMap = null;
36499                 this.displacementScale = 1;
36500                 this.displacementBias = 0;
36501
36502                 this.wireframe = false;
36503                 this.wireframeLinewidth = 1;
36504
36505                 this.fog = false;
36506
36507                 this.flatShading = false;
36508
36509                 this.setValues( parameters );
36510
36511         }
36512
36513         copy( source ) {
36514
36515                 super.copy( source );
36516
36517                 this.bumpMap = source.bumpMap;
36518                 this.bumpScale = source.bumpScale;
36519
36520                 this.normalMap = source.normalMap;
36521                 this.normalMapType = source.normalMapType;
36522                 this.normalScale.copy( source.normalScale );
36523
36524                 this.displacementMap = source.displacementMap;
36525                 this.displacementScale = source.displacementScale;
36526                 this.displacementBias = source.displacementBias;
36527
36528                 this.wireframe = source.wireframe;
36529                 this.wireframeLinewidth = source.wireframeLinewidth;
36530
36531                 this.flatShading = source.flatShading;
36532
36533                 return this;
36534
36535         }
36536
36537     }
36538
36539     MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
36540
36541     /**
36542      * parameters = {
36543      *  color: <hex>,
36544      *  opacity: <float>,
36545      *
36546      *  map: new THREE.Texture( <Image> ),
36547      *
36548      *  lightMap: new THREE.Texture( <Image> ),
36549      *  lightMapIntensity: <float>
36550      *
36551      *  aoMap: new THREE.Texture( <Image> ),
36552      *  aoMapIntensity: <float>
36553      *
36554      *  emissive: <hex>,
36555      *  emissiveIntensity: <float>
36556      *  emissiveMap: new THREE.Texture( <Image> ),
36557      *
36558      *  specularMap: new THREE.Texture( <Image> ),
36559      *
36560      *  alphaMap: new THREE.Texture( <Image> ),
36561      *
36562      *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
36563      *  combine: THREE.Multiply,
36564      *  reflectivity: <float>,
36565      *  refractionRatio: <float>,
36566      *
36567      *  wireframe: <boolean>,
36568      *  wireframeLinewidth: <float>,
36569      *
36570      * }
36571      */
36572
36573     class MeshLambertMaterial extends Material {
36574
36575         constructor( parameters ) {
36576
36577                 super();
36578
36579                 this.type = 'MeshLambertMaterial';
36580
36581                 this.color = new Color( 0xffffff ); // diffuse
36582
36583                 this.map = null;
36584
36585                 this.lightMap = null;
36586                 this.lightMapIntensity = 1.0;
36587
36588                 this.aoMap = null;
36589                 this.aoMapIntensity = 1.0;
36590
36591                 this.emissive = new Color( 0x000000 );
36592                 this.emissiveIntensity = 1.0;
36593                 this.emissiveMap = null;
36594
36595                 this.specularMap = null;
36596
36597                 this.alphaMap = null;
36598
36599                 this.envMap = null;
36600                 this.combine = MultiplyOperation;
36601                 this.reflectivity = 1;
36602                 this.refractionRatio = 0.98;
36603
36604                 this.wireframe = false;
36605                 this.wireframeLinewidth = 1;
36606                 this.wireframeLinecap = 'round';
36607                 this.wireframeLinejoin = 'round';
36608
36609                 this.setValues( parameters );
36610
36611         }
36612
36613         copy( source ) {
36614
36615                 super.copy( source );
36616
36617                 this.color.copy( source.color );
36618
36619                 this.map = source.map;
36620
36621                 this.lightMap = source.lightMap;
36622                 this.lightMapIntensity = source.lightMapIntensity;
36623
36624                 this.aoMap = source.aoMap;
36625                 this.aoMapIntensity = source.aoMapIntensity;
36626
36627                 this.emissive.copy( source.emissive );
36628                 this.emissiveMap = source.emissiveMap;
36629                 this.emissiveIntensity = source.emissiveIntensity;
36630
36631                 this.specularMap = source.specularMap;
36632
36633                 this.alphaMap = source.alphaMap;
36634
36635                 this.envMap = source.envMap;
36636                 this.combine = source.combine;
36637                 this.reflectivity = source.reflectivity;
36638                 this.refractionRatio = source.refractionRatio;
36639
36640                 this.wireframe = source.wireframe;
36641                 this.wireframeLinewidth = source.wireframeLinewidth;
36642                 this.wireframeLinecap = source.wireframeLinecap;
36643                 this.wireframeLinejoin = source.wireframeLinejoin;
36644
36645                 return this;
36646
36647         }
36648
36649     }
36650
36651     MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
36652
36653     /**
36654      * parameters = {
36655      *  color: <hex>,
36656      *  opacity: <float>,
36657      *
36658      *  matcap: new THREE.Texture( <Image> ),
36659      *
36660      *  map: new THREE.Texture( <Image> ),
36661      *
36662      *  bumpMap: new THREE.Texture( <Image> ),
36663      *  bumpScale: <float>,
36664      *
36665      *  normalMap: new THREE.Texture( <Image> ),
36666      *  normalMapType: THREE.TangentSpaceNormalMap,
36667      *  normalScale: <Vector2>,
36668      *
36669      *  displacementMap: new THREE.Texture( <Image> ),
36670      *  displacementScale: <float>,
36671      *  displacementBias: <float>,
36672      *
36673      *  alphaMap: new THREE.Texture( <Image> ),
36674      *
36675      *  flatShading: <bool>
36676      * }
36677      */
36678
36679     class MeshMatcapMaterial extends Material {
36680
36681         constructor( parameters ) {
36682
36683                 super();
36684
36685                 this.defines = { 'MATCAP': '' };
36686
36687                 this.type = 'MeshMatcapMaterial';
36688
36689                 this.color = new Color( 0xffffff ); // diffuse
36690
36691                 this.matcap = null;
36692
36693                 this.map = null;
36694
36695                 this.bumpMap = null;
36696                 this.bumpScale = 1;
36697
36698                 this.normalMap = null;
36699                 this.normalMapType = TangentSpaceNormalMap;
36700                 this.normalScale = new Vector2( 1, 1 );
36701
36702                 this.displacementMap = null;
36703                 this.displacementScale = 1;
36704                 this.displacementBias = 0;
36705
36706                 this.alphaMap = null;
36707
36708                 this.flatShading = false;
36709
36710                 this.setValues( parameters );
36711
36712         }
36713
36714
36715         copy( source ) {
36716
36717                 super.copy( source );
36718
36719                 this.defines = { 'MATCAP': '' };
36720
36721                 this.color.copy( source.color );
36722
36723                 this.matcap = source.matcap;
36724
36725                 this.map = source.map;
36726
36727                 this.bumpMap = source.bumpMap;
36728                 this.bumpScale = source.bumpScale;
36729
36730                 this.normalMap = source.normalMap;
36731                 this.normalMapType = source.normalMapType;
36732                 this.normalScale.copy( source.normalScale );
36733
36734                 this.displacementMap = source.displacementMap;
36735                 this.displacementScale = source.displacementScale;
36736                 this.displacementBias = source.displacementBias;
36737
36738                 this.alphaMap = source.alphaMap;
36739
36740                 this.flatShading = source.flatShading;
36741
36742                 return this;
36743
36744         }
36745
36746     }
36747
36748     MeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;
36749
36750     /**
36751      * parameters = {
36752      *  color: <hex>,
36753      *  opacity: <float>,
36754      *
36755      *  linewidth: <float>,
36756      *
36757      *  scale: <float>,
36758      *  dashSize: <float>,
36759      *  gapSize: <float>
36760      * }
36761      */
36762
36763     class LineDashedMaterial extends LineBasicMaterial {
36764
36765         constructor( parameters ) {
36766
36767                 super();
36768
36769                 this.type = 'LineDashedMaterial';
36770
36771                 this.scale = 1;
36772                 this.dashSize = 3;
36773                 this.gapSize = 1;
36774
36775                 this.setValues( parameters );
36776
36777         }
36778
36779         copy( source ) {
36780
36781                 super.copy( source );
36782
36783                 this.scale = source.scale;
36784                 this.dashSize = source.dashSize;
36785                 this.gapSize = source.gapSize;
36786
36787                 return this;
36788
36789         }
36790
36791     }
36792
36793     LineDashedMaterial.prototype.isLineDashedMaterial = true;
36794
36795     const AnimationUtils = {
36796
36797         // same as Array.prototype.slice, but also works on typed arrays
36798         arraySlice: function ( array, from, to ) {
36799
36800                 if ( AnimationUtils.isTypedArray( array ) ) {
36801
36802                         // in ios9 array.subarray(from, undefined) will return empty array
36803                         // but array.subarray(from) or array.subarray(from, len) is correct
36804                         return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
36805
36806                 }
36807
36808                 return array.slice( from, to );
36809
36810         },
36811
36812         // converts an array to a specific type
36813         convertArray: function ( array, type, forceClone ) {
36814
36815                 if ( ! array || // let 'undefined' and 'null' pass
36816                         ! forceClone && array.constructor === type ) return array;
36817
36818                 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
36819
36820                         return new type( array ); // create typed array
36821
36822                 }
36823
36824                 return Array.prototype.slice.call( array ); // create Array
36825
36826         },
36827
36828         isTypedArray: function ( object ) {
36829
36830                 return ArrayBuffer.isView( object ) &&
36831                         ! ( object instanceof DataView );
36832
36833         },
36834
36835         // returns an array by which times and values can be sorted
36836         getKeyframeOrder: function ( times ) {
36837
36838                 function compareTime( i, j ) {
36839
36840                         return times[ i ] - times[ j ];
36841
36842                 }
36843
36844                 const n = times.length;
36845                 const result = new Array( n );
36846                 for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
36847
36848                 result.sort( compareTime );
36849
36850                 return result;
36851
36852         },
36853
36854         // uses the array previously returned by 'getKeyframeOrder' to sort data
36855         sortedArray: function ( values, stride, order ) {
36856
36857                 const nValues = values.length;
36858                 const result = new values.constructor( nValues );
36859
36860                 for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
36861
36862                         const srcOffset = order[ i ] * stride;
36863
36864                         for ( let j = 0; j !== stride; ++ j ) {
36865
36866                                 result[ dstOffset ++ ] = values[ srcOffset + j ];
36867
36868                         }
36869
36870                 }
36871
36872                 return result;
36873
36874         },
36875
36876         // function for parsing AOS keyframe formats
36877         flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
36878
36879                 let i = 1, key = jsonKeys[ 0 ];
36880
36881                 while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
36882
36883                         key = jsonKeys[ i ++ ];
36884
36885                 }
36886
36887                 if ( key === undefined ) return; // no data
36888
36889                 let value = key[ valuePropertyName ];
36890                 if ( value === undefined ) return; // no data
36891
36892                 if ( Array.isArray( value ) ) {
36893
36894                         do {
36895
36896                                 value = key[ valuePropertyName ];
36897
36898                                 if ( value !== undefined ) {
36899
36900                                         times.push( key.time );
36901                                         values.push.apply( values, value ); // push all elements
36902
36903                                 }
36904
36905                                 key = jsonKeys[ i ++ ];
36906
36907                         } while ( key !== undefined );
36908
36909                 } else if ( value.toArray !== undefined ) {
36910
36911                         // ...assume THREE.Math-ish
36912
36913                         do {
36914
36915                                 value = key[ valuePropertyName ];
36916
36917                                 if ( value !== undefined ) {
36918
36919                                         times.push( key.time );
36920                                         value.toArray( values, values.length );
36921
36922                                 }
36923
36924                                 key = jsonKeys[ i ++ ];
36925
36926                         } while ( key !== undefined );
36927
36928                 } else {
36929
36930                         // otherwise push as-is
36931
36932                         do {
36933
36934                                 value = key[ valuePropertyName ];
36935
36936                                 if ( value !== undefined ) {
36937
36938                                         times.push( key.time );
36939                                         values.push( value );
36940
36941                                 }
36942
36943                                 key = jsonKeys[ i ++ ];
36944
36945                         } while ( key !== undefined );
36946
36947                 }
36948
36949         },
36950
36951         subclip: function ( sourceClip, name, startFrame, endFrame, fps = 30 ) {
36952
36953                 const clip = sourceClip.clone();
36954
36955                 clip.name = name;
36956
36957                 const tracks = [];
36958
36959                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
36960
36961                         const track = clip.tracks[ i ];
36962                         const valueSize = track.getValueSize();
36963
36964                         const times = [];
36965                         const values = [];
36966
36967                         for ( let j = 0; j < track.times.length; ++ j ) {
36968
36969                                 const frame = track.times[ j ] * fps;
36970
36971                                 if ( frame < startFrame || frame >= endFrame ) continue;
36972
36973                                 times.push( track.times[ j ] );
36974
36975                                 for ( let k = 0; k < valueSize; ++ k ) {
36976
36977                                         values.push( track.values[ j * valueSize + k ] );
36978
36979                                 }
36980
36981                         }
36982
36983                         if ( times.length === 0 ) continue;
36984
36985                         track.times = AnimationUtils.convertArray( times, track.times.constructor );
36986                         track.values = AnimationUtils.convertArray( values, track.values.constructor );
36987
36988                         tracks.push( track );
36989
36990                 }
36991
36992                 clip.tracks = tracks;
36993
36994                 // find minimum .times value across all tracks in the trimmed clip
36995
36996                 let minStartTime = Infinity;
36997
36998                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
36999
37000                         if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
37001
37002                                 minStartTime = clip.tracks[ i ].times[ 0 ];
37003
37004                         }
37005
37006                 }
37007
37008                 // shift all tracks such that clip begins at t=0
37009
37010                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
37011
37012                         clip.tracks[ i ].shift( - 1 * minStartTime );
37013
37014                 }
37015
37016                 clip.resetDuration();
37017
37018                 return clip;
37019
37020         },
37021
37022         makeClipAdditive: function ( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
37023
37024                 if ( fps <= 0 ) fps = 30;
37025
37026                 const numTracks = referenceClip.tracks.length;
37027                 const referenceTime = referenceFrame / fps;
37028
37029                 // Make each track's values relative to the values at the reference frame
37030                 for ( let i = 0; i < numTracks; ++ i ) {
37031
37032                         const referenceTrack = referenceClip.tracks[ i ];
37033                         const referenceTrackType = referenceTrack.ValueTypeName;
37034
37035                         // Skip this track if it's non-numeric
37036                         if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
37037
37038                         // Find the track in the target clip whose name and type matches the reference track
37039                         const targetTrack = targetClip.tracks.find( function ( track ) {
37040
37041                                 return track.name === referenceTrack.name
37042                                         && track.ValueTypeName === referenceTrackType;
37043
37044                         } );
37045
37046                         if ( targetTrack === undefined ) continue;
37047
37048                         let referenceOffset = 0;
37049                         const referenceValueSize = referenceTrack.getValueSize();
37050
37051                         if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
37052
37053                                 referenceOffset = referenceValueSize / 3;
37054
37055                         }
37056
37057                         let targetOffset = 0;
37058                         const targetValueSize = targetTrack.getValueSize();
37059
37060                         if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
37061
37062                                 targetOffset = targetValueSize / 3;
37063
37064                         }
37065
37066                         const lastIndex = referenceTrack.times.length - 1;
37067                         let referenceValue;
37068
37069                         // Find the value to subtract out of the track
37070                         if ( referenceTime <= referenceTrack.times[ 0 ] ) {
37071
37072                                 // Reference frame is earlier than the first keyframe, so just use the first keyframe
37073                                 const startIndex = referenceOffset;
37074                                 const endIndex = referenceValueSize - referenceOffset;
37075                                 referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
37076
37077                         } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
37078
37079                                 // Reference frame is after the last keyframe, so just use the last keyframe
37080                                 const startIndex = lastIndex * referenceValueSize + referenceOffset;
37081                                 const endIndex = startIndex + referenceValueSize - referenceOffset;
37082                                 referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
37083
37084                         } else {
37085
37086                                 // Interpolate to the reference value
37087                                 const interpolant = referenceTrack.createInterpolant();
37088                                 const startIndex = referenceOffset;
37089                                 const endIndex = referenceValueSize - referenceOffset;
37090                                 interpolant.evaluate( referenceTime );
37091                                 referenceValue = AnimationUtils.arraySlice( interpolant.resultBuffer, startIndex, endIndex );
37092
37093                         }
37094
37095                         // Conjugate the quaternion
37096                         if ( referenceTrackType === 'quaternion' ) {
37097
37098                                 const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
37099                                 referenceQuat.toArray( referenceValue );
37100
37101                         }
37102
37103                         // Subtract the reference value from all of the track values
37104
37105                         const numTimes = targetTrack.times.length;
37106                         for ( let j = 0; j < numTimes; ++ j ) {
37107
37108                                 const valueStart = j * targetValueSize + targetOffset;
37109
37110                                 if ( referenceTrackType === 'quaternion' ) {
37111
37112                                         // Multiply the conjugate for quaternion track types
37113                                         Quaternion.multiplyQuaternionsFlat(
37114                                                 targetTrack.values,
37115                                                 valueStart,
37116                                                 referenceValue,
37117                                                 0,
37118                                                 targetTrack.values,
37119                                                 valueStart
37120                                         );
37121
37122                                 } else {
37123
37124                                         const valueEnd = targetValueSize - targetOffset * 2;
37125
37126                                         // Subtract each value for all other numeric track types
37127                                         for ( let k = 0; k < valueEnd; ++ k ) {
37128
37129                                                 targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
37130
37131                                         }
37132
37133                                 }
37134
37135                         }
37136
37137                 }
37138
37139                 targetClip.blendMode = AdditiveAnimationBlendMode;
37140
37141                 return targetClip;
37142
37143         }
37144
37145     };
37146
37147     /**
37148      * Abstract base class of interpolants over parametric samples.
37149      *
37150      * The parameter domain is one dimensional, typically the time or a path
37151      * along a curve defined by the data.
37152      *
37153      * The sample values can have any dimensionality and derived classes may
37154      * apply special interpretations to the data.
37155      *
37156      * This class provides the interval seek in a Template Method, deferring
37157      * the actual interpolation to derived classes.
37158      *
37159      * Time complexity is O(1) for linear access crossing at most two points
37160      * and O(log N) for random access, where N is the number of positions.
37161      *
37162      * References:
37163      *
37164      *          http://www.oodesign.com/template-method-pattern.html
37165      *
37166      */
37167
37168     class Interpolant {
37169
37170         constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
37171
37172                 this.parameterPositions = parameterPositions;
37173                 this._cachedIndex = 0;
37174
37175                 this.resultBuffer = resultBuffer !== undefined ?
37176                         resultBuffer : new sampleValues.constructor( sampleSize );
37177                 this.sampleValues = sampleValues;
37178                 this.valueSize = sampleSize;
37179
37180                 this.settings = null;
37181                 this.DefaultSettings_ = {};
37182
37183         }
37184
37185         evaluate( t ) {
37186
37187                 const pp = this.parameterPositions;
37188                 let i1 = this._cachedIndex,
37189                         t1 = pp[ i1 ],
37190                         t0 = pp[ i1 - 1 ];
37191
37192                 validate_interval: {
37193
37194                         seek: {
37195
37196                                 let right;
37197
37198                                 linear_scan: {
37199
37200                                         //- See http://jsperf.com/comparison-to-undefined/3
37201                                         //- slower code:
37202                                         //-
37203                                         //-                             if ( t >= t1 || t1 === undefined ) {
37204                                         forward_scan: if ( ! ( t < t1 ) ) {
37205
37206                                                 for ( let giveUpAt = i1 + 2; ; ) {
37207
37208                                                         if ( t1 === undefined ) {
37209
37210                                                                 if ( t < t0 ) break forward_scan;
37211
37212                                                                 // after end
37213
37214                                                                 i1 = pp.length;
37215                                                                 this._cachedIndex = i1;
37216                                                                 return this.afterEnd_( i1 - 1, t, t0 );
37217
37218                                                         }
37219
37220                                                         if ( i1 === giveUpAt ) break; // this loop
37221
37222                                                         t0 = t1;
37223                                                         t1 = pp[ ++ i1 ];
37224
37225                                                         if ( t < t1 ) {
37226
37227                                                                 // we have arrived at the sought interval
37228                                                                 break seek;
37229
37230                                                         }
37231
37232                                                 }
37233
37234                                                 // prepare binary search on the right side of the index
37235                                                 right = pp.length;
37236                                                 break linear_scan;
37237
37238                                         }
37239
37240                                         //- slower code:
37241                                         //-                                     if ( t < t0 || t0 === undefined ) {
37242                                         if ( ! ( t >= t0 ) ) {
37243
37244                                                 // looping?
37245
37246                                                 const t1global = pp[ 1 ];
37247
37248                                                 if ( t < t1global ) {
37249
37250                                                         i1 = 2; // + 1, using the scan for the details
37251                                                         t0 = t1global;
37252
37253                                                 }
37254
37255                                                 // linear reverse scan
37256
37257                                                 for ( let giveUpAt = i1 - 2; ; ) {
37258
37259                                                         if ( t0 === undefined ) {
37260
37261                                                                 // before start
37262
37263                                                                 this._cachedIndex = 0;
37264                                                                 return this.beforeStart_( 0, t, t1 );
37265
37266                                                         }
37267
37268                                                         if ( i1 === giveUpAt ) break; // this loop
37269
37270                                                         t1 = t0;
37271                                                         t0 = pp[ -- i1 - 1 ];
37272
37273                                                         if ( t >= t0 ) {
37274
37275                                                                 // we have arrived at the sought interval
37276                                                                 break seek;
37277
37278                                                         }
37279
37280                                                 }
37281
37282                                                 // prepare binary search on the left side of the index
37283                                                 right = i1;
37284                                                 i1 = 0;
37285                                                 break linear_scan;
37286
37287                                         }
37288
37289                                         // the interval is valid
37290
37291                                         break validate_interval;
37292
37293                                 } // linear scan
37294
37295                                 // binary search
37296
37297                                 while ( i1 < right ) {
37298
37299                                         const mid = ( i1 + right ) >>> 1;
37300
37301                                         if ( t < pp[ mid ] ) {
37302
37303                                                 right = mid;
37304
37305                                         } else {
37306
37307                                                 i1 = mid + 1;
37308
37309                                         }
37310
37311                                 }
37312
37313                                 t1 = pp[ i1 ];
37314                                 t0 = pp[ i1 - 1 ];
37315
37316                                 // check boundary cases, again
37317
37318                                 if ( t0 === undefined ) {
37319
37320                                         this._cachedIndex = 0;
37321                                         return this.beforeStart_( 0, t, t1 );
37322
37323                                 }
37324
37325                                 if ( t1 === undefined ) {
37326
37327                                         i1 = pp.length;
37328                                         this._cachedIndex = i1;
37329                                         return this.afterEnd_( i1 - 1, t0, t );
37330
37331                                 }
37332
37333                         } // seek
37334
37335                         this._cachedIndex = i1;
37336
37337                         this.intervalChanged_( i1, t0, t1 );
37338
37339                 } // validate_interval
37340
37341                 return this.interpolate_( i1, t0, t, t1 );
37342
37343         }
37344
37345         getSettings_() {
37346
37347                 return this.settings || this.DefaultSettings_;
37348
37349         }
37350
37351         copySampleValue_( index ) {
37352
37353                 // copies a sample value to the result buffer
37354
37355                 const result = this.resultBuffer,
37356                         values = this.sampleValues,
37357                         stride = this.valueSize,
37358                         offset = index * stride;
37359
37360                 for ( let i = 0; i !== stride; ++ i ) {
37361
37362                         result[ i ] = values[ offset + i ];
37363
37364                 }
37365
37366                 return result;
37367
37368         }
37369
37370         // Template methods for derived classes:
37371
37372         interpolate_( /* i1, t0, t, t1 */ ) {
37373
37374                 throw new Error( 'call to abstract method' );
37375                 // implementations shall return this.resultBuffer
37376
37377         }
37378
37379         intervalChanged_( /* i1, t0, t1 */ ) {
37380
37381                 // empty
37382
37383         }
37384
37385     }
37386
37387     // ALIAS DEFINITIONS
37388
37389     Interpolant.prototype.beforeStart_ = Interpolant.prototype.copySampleValue_;
37390     Interpolant.prototype.afterEnd_ = Interpolant.prototype.copySampleValue_;
37391
37392     /**
37393      * Fast and simple cubic spline interpolant.
37394      *
37395      * It was derived from a Hermitian construction setting the first derivative
37396      * at each sample position to the linear slope between neighboring positions
37397      * over their parameter interval.
37398      */
37399
37400     class CubicInterpolant extends Interpolant {
37401
37402         constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
37403
37404                 super( parameterPositions, sampleValues, sampleSize, resultBuffer );
37405
37406                 this._weightPrev = - 0;
37407                 this._offsetPrev = - 0;
37408                 this._weightNext = - 0;
37409                 this._offsetNext = - 0;
37410
37411                 this.DefaultSettings_ = {
37412
37413                         endingStart: ZeroCurvatureEnding,
37414                         endingEnd: ZeroCurvatureEnding
37415
37416                 };
37417
37418         }
37419
37420         intervalChanged_( i1, t0, t1 ) {
37421
37422                 const pp = this.parameterPositions;
37423                 let iPrev = i1 - 2,
37424                         iNext = i1 + 1,
37425
37426                         tPrev = pp[ iPrev ],
37427                         tNext = pp[ iNext ];
37428
37429                 if ( tPrev === undefined ) {
37430
37431                         switch ( this.getSettings_().endingStart ) {
37432
37433                                 case ZeroSlopeEnding:
37434
37435                                         // f'(t0) = 0
37436                                         iPrev = i1;
37437                                         tPrev = 2 * t0 - t1;
37438
37439                                         break;
37440
37441                                 case WrapAroundEnding:
37442
37443                                         // use the other end of the curve
37444                                         iPrev = pp.length - 2;
37445                                         tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
37446
37447                                         break;
37448
37449                                 default: // ZeroCurvatureEnding
37450
37451                                         // f''(t0) = 0 a.k.a. Natural Spline
37452                                         iPrev = i1;
37453                                         tPrev = t1;
37454
37455                         }
37456
37457                 }
37458
37459                 if ( tNext === undefined ) {
37460
37461                         switch ( this.getSettings_().endingEnd ) {
37462
37463                                 case ZeroSlopeEnding:
37464
37465                                         // f'(tN) = 0
37466                                         iNext = i1;
37467                                         tNext = 2 * t1 - t0;
37468
37469                                         break;
37470
37471                                 case WrapAroundEnding:
37472
37473                                         // use the other end of the curve
37474                                         iNext = 1;
37475                                         tNext = t1 + pp[ 1 ] - pp[ 0 ];
37476
37477                                         break;
37478
37479                                 default: // ZeroCurvatureEnding
37480
37481                                         // f''(tN) = 0, a.k.a. Natural Spline
37482                                         iNext = i1 - 1;
37483                                         tNext = t0;
37484
37485                         }
37486
37487                 }
37488
37489                 const halfDt = ( t1 - t0 ) * 0.5,
37490                         stride = this.valueSize;
37491
37492                 this._weightPrev = halfDt / ( t0 - tPrev );
37493                 this._weightNext = halfDt / ( tNext - t1 );
37494                 this._offsetPrev = iPrev * stride;
37495                 this._offsetNext = iNext * stride;
37496
37497         }
37498
37499         interpolate_( i1, t0, t, t1 ) {
37500
37501                 const result = this.resultBuffer,
37502                         values = this.sampleValues,
37503                         stride = this.valueSize,
37504
37505                         o1 = i1 * stride,               o0 = o1 - stride,
37506                         oP = this._offsetPrev,  oN = this._offsetNext,
37507                         wP = this._weightPrev,  wN = this._weightNext,
37508
37509                         p = ( t - t0 ) / ( t1 - t0 ),
37510                         pp = p * p,
37511                         ppp = pp * p;
37512
37513                 // evaluate polynomials
37514
37515                 const sP = - wP * ppp + 2 * wP * pp - wP * p;
37516                 const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
37517                 const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
37518                 const sN = wN * ppp - wN * pp;
37519
37520                 // combine data linearly
37521
37522                 for ( let i = 0; i !== stride; ++ i ) {
37523
37524                         result[ i ] =
37525                                         sP * values[ oP + i ] +
37526                                         s0 * values[ o0 + i ] +
37527                                         s1 * values[ o1 + i ] +
37528                                         sN * values[ oN + i ];
37529
37530                 }
37531
37532                 return result;
37533
37534         }
37535
37536     }
37537
37538     class LinearInterpolant extends Interpolant {
37539
37540         constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
37541
37542                 super( parameterPositions, sampleValues, sampleSize, resultBuffer );
37543
37544         }
37545
37546         interpolate_( i1, t0, t, t1 ) {
37547
37548                 const result = this.resultBuffer,
37549                         values = this.sampleValues,
37550                         stride = this.valueSize,
37551
37552                         offset1 = i1 * stride,
37553                         offset0 = offset1 - stride,
37554
37555                         weight1 = ( t - t0 ) / ( t1 - t0 ),
37556                         weight0 = 1 - weight1;
37557
37558                 for ( let i = 0; i !== stride; ++ i ) {
37559
37560                         result[ i ] =
37561                                         values[ offset0 + i ] * weight0 +
37562                                         values[ offset1 + i ] * weight1;
37563
37564                 }
37565
37566                 return result;
37567
37568         }
37569
37570     }
37571
37572     /**
37573      *
37574      * Interpolant that evaluates to the sample value at the position preceeding
37575      * the parameter.
37576      */
37577
37578     class DiscreteInterpolant extends Interpolant {
37579
37580         constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
37581
37582                 super( parameterPositions, sampleValues, sampleSize, resultBuffer );
37583
37584         }
37585
37586         interpolate_( i1 /*, t0, t, t1 */ ) {
37587
37588                 return this.copySampleValue_( i1 - 1 );
37589
37590         }
37591
37592     }
37593
37594     class KeyframeTrack {
37595
37596         constructor( name, times, values, interpolation ) {
37597
37598                 if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
37599                 if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
37600
37601                 this.name = name;
37602
37603                 this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
37604                 this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
37605
37606                 this.setInterpolation( interpolation || this.DefaultInterpolation );
37607
37608         }
37609
37610         // Serialization (in static context, because of constructor invocation
37611         // and automatic invocation of .toJSON):
37612
37613         static toJSON( track ) {
37614
37615                 const trackType = track.constructor;
37616
37617                 let json;
37618
37619                 // derived classes can define a static toJSON method
37620                 if ( trackType.toJSON !== this.toJSON ) {
37621
37622                         json = trackType.toJSON( track );
37623
37624                 } else {
37625
37626                         // by default, we assume the data can be serialized as-is
37627                         json = {
37628
37629                                 'name': track.name,
37630                                 'times': AnimationUtils.convertArray( track.times, Array ),
37631                                 'values': AnimationUtils.convertArray( track.values, Array )
37632
37633                         };
37634
37635                         const interpolation = track.getInterpolation();
37636
37637                         if ( interpolation !== track.DefaultInterpolation ) {
37638
37639                                 json.interpolation = interpolation;
37640
37641                         }
37642
37643                 }
37644
37645                 json.type = track.ValueTypeName; // mandatory
37646
37647                 return json;
37648
37649         }
37650
37651         InterpolantFactoryMethodDiscrete( result ) {
37652
37653                 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
37654
37655         }
37656
37657         InterpolantFactoryMethodLinear( result ) {
37658
37659                 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
37660
37661         }
37662
37663         InterpolantFactoryMethodSmooth( result ) {
37664
37665                 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
37666
37667         }
37668
37669         setInterpolation( interpolation ) {
37670
37671                 let factoryMethod;
37672
37673                 switch ( interpolation ) {
37674
37675                         case InterpolateDiscrete:
37676
37677                                 factoryMethod = this.InterpolantFactoryMethodDiscrete;
37678
37679                                 break;
37680
37681                         case InterpolateLinear:
37682
37683                                 factoryMethod = this.InterpolantFactoryMethodLinear;
37684
37685                                 break;
37686
37687                         case InterpolateSmooth:
37688
37689                                 factoryMethod = this.InterpolantFactoryMethodSmooth;
37690
37691                                 break;
37692
37693                 }
37694
37695                 if ( factoryMethod === undefined ) {
37696
37697                         const message = 'unsupported interpolation for ' +
37698                                 this.ValueTypeName + ' keyframe track named ' + this.name;
37699
37700                         if ( this.createInterpolant === undefined ) {
37701
37702                                 // fall back to default, unless the default itself is messed up
37703                                 if ( interpolation !== this.DefaultInterpolation ) {
37704
37705                                         this.setInterpolation( this.DefaultInterpolation );
37706
37707                                 } else {
37708
37709                                         throw new Error( message ); // fatal, in this case
37710
37711                                 }
37712
37713                         }
37714
37715                         console.warn( 'THREE.KeyframeTrack:', message );
37716                         return this;
37717
37718                 }
37719
37720                 this.createInterpolant = factoryMethod;
37721
37722                 return this;
37723
37724         }
37725
37726         getInterpolation() {
37727
37728                 switch ( this.createInterpolant ) {
37729
37730                         case this.InterpolantFactoryMethodDiscrete:
37731
37732                                 return InterpolateDiscrete;
37733
37734                         case this.InterpolantFactoryMethodLinear:
37735
37736                                 return InterpolateLinear;
37737
37738                         case this.InterpolantFactoryMethodSmooth:
37739
37740                                 return InterpolateSmooth;
37741
37742                 }
37743
37744         }
37745
37746         getValueSize() {
37747
37748                 return this.values.length / this.times.length;
37749
37750         }
37751
37752         // move all keyframes either forwards or backwards in time
37753         shift( timeOffset ) {
37754
37755                 if ( timeOffset !== 0.0 ) {
37756
37757                         const times = this.times;
37758
37759                         for ( let i = 0, n = times.length; i !== n; ++ i ) {
37760
37761                                 times[ i ] += timeOffset;
37762
37763                         }
37764
37765                 }
37766
37767                 return this;
37768
37769         }
37770
37771         // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
37772         scale( timeScale ) {
37773
37774                 if ( timeScale !== 1.0 ) {
37775
37776                         const times = this.times;
37777
37778                         for ( let i = 0, n = times.length; i !== n; ++ i ) {
37779
37780                                 times[ i ] *= timeScale;
37781
37782                         }
37783
37784                 }
37785
37786                 return this;
37787
37788         }
37789
37790         // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
37791         // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
37792         trim( startTime, endTime ) {
37793
37794                 const times = this.times,
37795                         nKeys = times.length;
37796
37797                 let from = 0,
37798                         to = nKeys - 1;
37799
37800                 while ( from !== nKeys && times[ from ] < startTime ) {
37801
37802                         ++ from;
37803
37804                 }
37805
37806                 while ( to !== - 1 && times[ to ] > endTime ) {
37807
37808                         -- to;
37809
37810                 }
37811
37812                 ++ to; // inclusive -> exclusive bound
37813
37814                 if ( from !== 0 || to !== nKeys ) {
37815
37816                         // empty tracks are forbidden, so keep at least one keyframe
37817                         if ( from >= to ) {
37818
37819                                 to = Math.max( to, 1 );
37820                                 from = to - 1;
37821
37822                         }
37823
37824                         const stride = this.getValueSize();
37825                         this.times = AnimationUtils.arraySlice( times, from, to );
37826                         this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
37827
37828                 }
37829
37830                 return this;
37831
37832         }
37833
37834         // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
37835         validate() {
37836
37837                 let valid = true;
37838
37839                 const valueSize = this.getValueSize();
37840                 if ( valueSize - Math.floor( valueSize ) !== 0 ) {
37841
37842                         console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
37843                         valid = false;
37844
37845                 }
37846
37847                 const times = this.times,
37848                         values = this.values,
37849
37850                         nKeys = times.length;
37851
37852                 if ( nKeys === 0 ) {
37853
37854                         console.error( 'THREE.KeyframeTrack: Track is empty.', this );
37855                         valid = false;
37856
37857                 }
37858
37859                 let prevTime = null;
37860
37861                 for ( let i = 0; i !== nKeys; i ++ ) {
37862
37863                         const currTime = times[ i ];
37864
37865                         if ( typeof currTime === 'number' && isNaN( currTime ) ) {
37866
37867                                 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
37868                                 valid = false;
37869                                 break;
37870
37871                         }
37872
37873                         if ( prevTime !== null && prevTime > currTime ) {
37874
37875                                 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
37876                                 valid = false;
37877                                 break;
37878
37879                         }
37880
37881                         prevTime = currTime;
37882
37883                 }
37884
37885                 if ( values !== undefined ) {
37886
37887                         if ( AnimationUtils.isTypedArray( values ) ) {
37888
37889                                 for ( let i = 0, n = values.length; i !== n; ++ i ) {
37890
37891                                         const value = values[ i ];
37892
37893                                         if ( isNaN( value ) ) {
37894
37895                                                 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
37896                                                 valid = false;
37897                                                 break;
37898
37899                                         }
37900
37901                                 }
37902
37903                         }
37904
37905                 }
37906
37907                 return valid;
37908
37909         }
37910
37911         // removes equivalent sequential keys as common in morph target sequences
37912         // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
37913         optimize() {
37914
37915                 // times or values may be shared with other tracks, so overwriting is unsafe
37916                 const times = AnimationUtils.arraySlice( this.times ),
37917                         values = AnimationUtils.arraySlice( this.values ),
37918                         stride = this.getValueSize(),
37919
37920                         smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
37921
37922                         lastIndex = times.length - 1;
37923
37924                 let writeIndex = 1;
37925
37926                 for ( let i = 1; i < lastIndex; ++ i ) {
37927
37928                         let keep = false;
37929
37930                         const time = times[ i ];
37931                         const timeNext = times[ i + 1 ];
37932
37933                         // remove adjacent keyframes scheduled at the same time
37934
37935                         if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {
37936
37937                                 if ( ! smoothInterpolation ) {
37938
37939                                         // remove unnecessary keyframes same as their neighbors
37940
37941                                         const offset = i * stride,
37942                                                 offsetP = offset - stride,
37943                                                 offsetN = offset + stride;
37944
37945                                         for ( let j = 0; j !== stride; ++ j ) {
37946
37947                                                 const value = values[ offset + j ];
37948
37949                                                 if ( value !== values[ offsetP + j ] ||
37950                                                         value !== values[ offsetN + j ] ) {
37951
37952                                                         keep = true;
37953                                                         break;
37954
37955                                                 }
37956
37957                                         }
37958
37959                                 } else {
37960
37961                                         keep = true;
37962
37963                                 }
37964
37965                         }
37966
37967                         // in-place compaction
37968
37969                         if ( keep ) {
37970
37971                                 if ( i !== writeIndex ) {
37972
37973                                         times[ writeIndex ] = times[ i ];
37974
37975                                         const readOffset = i * stride,
37976                                                 writeOffset = writeIndex * stride;
37977
37978                                         for ( let j = 0; j !== stride; ++ j ) {
37979
37980                                                 values[ writeOffset + j ] = values[ readOffset + j ];
37981
37982                                         }
37983
37984                                 }
37985
37986                                 ++ writeIndex;
37987
37988                         }
37989
37990                 }
37991
37992                 // flush last keyframe (compaction looks ahead)
37993
37994                 if ( lastIndex > 0 ) {
37995
37996                         times[ writeIndex ] = times[ lastIndex ];
37997
37998                         for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
37999
38000                                 values[ writeOffset + j ] = values[ readOffset + j ];
38001
38002                         }
38003
38004                         ++ writeIndex;
38005
38006                 }
38007
38008                 if ( writeIndex !== times.length ) {
38009
38010                         this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
38011                         this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
38012
38013                 } else {
38014
38015                         this.times = times;
38016                         this.values = values;
38017
38018                 }
38019
38020                 return this;
38021
38022         }
38023
38024         clone() {
38025
38026                 const times = AnimationUtils.arraySlice( this.times, 0 );
38027                 const values = AnimationUtils.arraySlice( this.values, 0 );
38028
38029                 const TypedKeyframeTrack = this.constructor;
38030                 const track = new TypedKeyframeTrack( this.name, times, values );
38031
38032                 // Interpolant argument to constructor is not saved, so copy the factory method directly.
38033                 track.createInterpolant = this.createInterpolant;
38034
38035                 return track;
38036
38037         }
38038
38039     }
38040
38041     KeyframeTrack.prototype.TimeBufferType = Float32Array;
38042     KeyframeTrack.prototype.ValueBufferType = Float32Array;
38043     KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
38044
38045     /**
38046      * A Track of Boolean keyframe values.
38047      */
38048     class BooleanKeyframeTrack extends KeyframeTrack {}
38049
38050     BooleanKeyframeTrack.prototype.ValueTypeName = 'bool';
38051     BooleanKeyframeTrack.prototype.ValueBufferType = Array;
38052     BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
38053     BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
38054     BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
38055
38056     /**
38057      * A Track of keyframe values that represent color.
38058      */
38059     class ColorKeyframeTrack extends KeyframeTrack {}
38060
38061     ColorKeyframeTrack.prototype.ValueTypeName = 'color';
38062
38063     /**
38064      * A Track of numeric keyframe values.
38065      */
38066     class NumberKeyframeTrack extends KeyframeTrack {}
38067
38068     NumberKeyframeTrack.prototype.ValueTypeName = 'number';
38069
38070     /**
38071      * Spherical linear unit quaternion interpolant.
38072      */
38073
38074     class QuaternionLinearInterpolant extends Interpolant {
38075
38076         constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
38077
38078                 super( parameterPositions, sampleValues, sampleSize, resultBuffer );
38079
38080         }
38081
38082         interpolate_( i1, t0, t, t1 ) {
38083
38084                 const result = this.resultBuffer,
38085                         values = this.sampleValues,
38086                         stride = this.valueSize,
38087
38088                         alpha = ( t - t0 ) / ( t1 - t0 );
38089
38090                 let offset = i1 * stride;
38091
38092                 for ( let end = offset + stride; offset !== end; offset += 4 ) {
38093
38094                         Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
38095
38096                 }
38097
38098                 return result;
38099
38100         }
38101
38102     }
38103
38104     /**
38105      * A Track of quaternion keyframe values.
38106      */
38107     class QuaternionKeyframeTrack extends KeyframeTrack {
38108
38109         InterpolantFactoryMethodLinear( result ) {
38110
38111                 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
38112
38113         }
38114
38115     }
38116
38117     QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';
38118     // ValueBufferType is inherited
38119     QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
38120     QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
38121
38122     /**
38123      * A Track that interpolates Strings
38124      */
38125     class StringKeyframeTrack extends KeyframeTrack {}
38126
38127     StringKeyframeTrack.prototype.ValueTypeName = 'string';
38128     StringKeyframeTrack.prototype.ValueBufferType = Array;
38129     StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
38130     StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
38131     StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
38132
38133     /**
38134      * A Track of vectored keyframe values.
38135      */
38136     class VectorKeyframeTrack extends KeyframeTrack {}
38137
38138     VectorKeyframeTrack.prototype.ValueTypeName = 'vector';
38139
38140     class AnimationClip {
38141
38142         constructor( name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode ) {
38143
38144                 this.name = name;
38145                 this.tracks = tracks;
38146                 this.duration = duration;
38147                 this.blendMode = blendMode;
38148
38149                 this.uuid = generateUUID();
38150
38151                 // this means it should figure out its duration by scanning the tracks
38152                 if ( this.duration < 0 ) {
38153
38154                         this.resetDuration();
38155
38156                 }
38157
38158         }
38159
38160
38161         static parse( json ) {
38162
38163                 const tracks = [],
38164                         jsonTracks = json.tracks,
38165                         frameTime = 1.0 / ( json.fps || 1.0 );
38166
38167                 for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
38168
38169                         tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
38170
38171                 }
38172
38173                 const clip = new this( json.name, json.duration, tracks, json.blendMode );
38174                 clip.uuid = json.uuid;
38175
38176                 return clip;
38177
38178         }
38179
38180         static toJSON( clip ) {
38181
38182                 const tracks = [],
38183                         clipTracks = clip.tracks;
38184
38185                 const json = {
38186
38187                         'name': clip.name,
38188                         'duration': clip.duration,
38189                         'tracks': tracks,
38190                         'uuid': clip.uuid,
38191                         'blendMode': clip.blendMode
38192
38193                 };
38194
38195                 for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
38196
38197                         tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
38198
38199                 }
38200
38201                 return json;
38202
38203         }
38204
38205         static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) {
38206
38207                 const numMorphTargets = morphTargetSequence.length;
38208                 const tracks = [];
38209
38210                 for ( let i = 0; i < numMorphTargets; i ++ ) {
38211
38212                         let times = [];
38213                         let values = [];
38214
38215                         times.push(
38216                                 ( i + numMorphTargets - 1 ) % numMorphTargets,
38217                                 i,
38218                                 ( i + 1 ) % numMorphTargets );
38219
38220                         values.push( 0, 1, 0 );
38221
38222                         const order = AnimationUtils.getKeyframeOrder( times );
38223                         times = AnimationUtils.sortedArray( times, 1, order );
38224                         values = AnimationUtils.sortedArray( values, 1, order );
38225
38226                         // if there is a key at the first frame, duplicate it as the
38227                         // last frame as well for perfect loop.
38228                         if ( ! noLoop && times[ 0 ] === 0 ) {
38229
38230                                 times.push( numMorphTargets );
38231                                 values.push( values[ 0 ] );
38232
38233                         }
38234
38235                         tracks.push(
38236                                 new NumberKeyframeTrack(
38237                                         '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
38238                                         times, values
38239                                 ).scale( 1.0 / fps ) );
38240
38241                 }
38242
38243                 return new this( name, - 1, tracks );
38244
38245         }
38246
38247         static findByName( objectOrClipArray, name ) {
38248
38249                 let clipArray = objectOrClipArray;
38250
38251                 if ( ! Array.isArray( objectOrClipArray ) ) {
38252
38253                         const o = objectOrClipArray;
38254                         clipArray = o.geometry && o.geometry.animations || o.animations;
38255
38256                 }
38257
38258                 for ( let i = 0; i < clipArray.length; i ++ ) {
38259
38260                         if ( clipArray[ i ].name === name ) {
38261
38262                                 return clipArray[ i ];
38263
38264                         }
38265
38266                 }
38267
38268                 return null;
38269
38270         }
38271
38272         static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {
38273
38274                 const animationToMorphTargets = {};
38275
38276                 // tested with https://regex101.com/ on trick sequences
38277                 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
38278                 const pattern = /^([\w-]*?)([\d]+)$/;
38279
38280                 // sort morph target names into animation groups based
38281                 // patterns like Walk_001, Walk_002, Run_001, Run_002
38282                 for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
38283
38284                         const morphTarget = morphTargets[ i ];
38285                         const parts = morphTarget.name.match( pattern );
38286
38287                         if ( parts && parts.length > 1 ) {
38288
38289                                 const name = parts[ 1 ];
38290
38291                                 let animationMorphTargets = animationToMorphTargets[ name ];
38292
38293                                 if ( ! animationMorphTargets ) {
38294
38295                                         animationToMorphTargets[ name ] = animationMorphTargets = [];
38296
38297                                 }
38298
38299                                 animationMorphTargets.push( morphTarget );
38300
38301                         }
38302
38303                 }
38304
38305                 const clips = [];
38306
38307                 for ( const name in animationToMorphTargets ) {
38308
38309                         clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
38310
38311                 }
38312
38313                 return clips;
38314
38315         }
38316
38317         // parse the animation.hierarchy format
38318         static parseAnimation( animation, bones ) {
38319
38320                 if ( ! animation ) {
38321
38322                         console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
38323                         return null;
38324
38325                 }
38326
38327                 const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
38328
38329                         // only return track if there are actually keys.
38330                         if ( animationKeys.length !== 0 ) {
38331
38332                                 const times = [];
38333                                 const values = [];
38334
38335                                 AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
38336
38337                                 // empty keys are filtered out, so check again
38338                                 if ( times.length !== 0 ) {
38339
38340                                         destTracks.push( new trackType( trackName, times, values ) );
38341
38342                                 }
38343
38344                         }
38345
38346                 };
38347
38348                 const tracks = [];
38349
38350                 const clipName = animation.name || 'default';
38351                 const fps = animation.fps || 30;
38352                 const blendMode = animation.blendMode;
38353
38354                 // automatic length determination in AnimationClip.
38355                 let duration = animation.length || - 1;
38356
38357                 const hierarchyTracks = animation.hierarchy || [];
38358
38359                 for ( let h = 0; h < hierarchyTracks.length; h ++ ) {
38360
38361                         const animationKeys = hierarchyTracks[ h ].keys;
38362
38363                         // skip empty tracks
38364                         if ( ! animationKeys || animationKeys.length === 0 ) continue;
38365
38366                         // process morph targets
38367                         if ( animationKeys[ 0 ].morphTargets ) {
38368
38369                                 // figure out all morph targets used in this track
38370                                 const morphTargetNames = {};
38371
38372                                 let k;
38373
38374                                 for ( k = 0; k < animationKeys.length; k ++ ) {
38375
38376                                         if ( animationKeys[ k ].morphTargets ) {
38377
38378                                                 for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
38379
38380                                                         morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
38381
38382                                                 }
38383
38384                                         }
38385
38386                                 }
38387
38388                                 // create a track for each morph target with all zero
38389                                 // morphTargetInfluences except for the keys in which
38390                                 // the morphTarget is named.
38391                                 for ( const morphTargetName in morphTargetNames ) {
38392
38393                                         const times = [];
38394                                         const values = [];
38395
38396                                         for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
38397
38398                                                 const animationKey = animationKeys[ k ];
38399
38400                                                 times.push( animationKey.time );
38401                                                 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
38402
38403                                         }
38404
38405                                         tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
38406
38407                                 }
38408
38409                                 duration = morphTargetNames.length * ( fps || 1.0 );
38410
38411                         } else {
38412
38413                                 // ...assume skeletal animation
38414
38415                                 const boneName = '.bones[' + bones[ h ].name + ']';
38416
38417                                 addNonemptyTrack(
38418                                         VectorKeyframeTrack, boneName + '.position',
38419                                         animationKeys, 'pos', tracks );
38420
38421                                 addNonemptyTrack(
38422                                         QuaternionKeyframeTrack, boneName + '.quaternion',
38423                                         animationKeys, 'rot', tracks );
38424
38425                                 addNonemptyTrack(
38426                                         VectorKeyframeTrack, boneName + '.scale',
38427                                         animationKeys, 'scl', tracks );
38428
38429                         }
38430
38431                 }
38432
38433                 if ( tracks.length === 0 ) {
38434
38435                         return null;
38436
38437                 }
38438
38439                 const clip = new this( clipName, duration, tracks, blendMode );
38440
38441                 return clip;
38442
38443         }
38444
38445         resetDuration() {
38446
38447                 const tracks = this.tracks;
38448                 let duration = 0;
38449
38450                 for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
38451
38452                         const track = this.tracks[ i ];
38453
38454                         duration = Math.max( duration, track.times[ track.times.length - 1 ] );
38455
38456                 }
38457
38458                 this.duration = duration;
38459
38460                 return this;
38461
38462         }
38463
38464         trim() {
38465
38466                 for ( let i = 0; i < this.tracks.length; i ++ ) {
38467
38468                         this.tracks[ i ].trim( 0, this.duration );
38469
38470                 }
38471
38472                 return this;
38473
38474         }
38475
38476         validate() {
38477
38478                 let valid = true;
38479
38480                 for ( let i = 0; i < this.tracks.length; i ++ ) {
38481
38482                         valid = valid && this.tracks[ i ].validate();
38483
38484                 }
38485
38486                 return valid;
38487
38488         }
38489
38490         optimize() {
38491
38492                 for ( let i = 0; i < this.tracks.length; i ++ ) {
38493
38494                         this.tracks[ i ].optimize();
38495
38496                 }
38497
38498                 return this;
38499
38500         }
38501
38502         clone() {
38503
38504                 const tracks = [];
38505
38506                 for ( let i = 0; i < this.tracks.length; i ++ ) {
38507
38508                         tracks.push( this.tracks[ i ].clone() );
38509
38510                 }
38511
38512                 return new this.constructor( this.name, this.duration, tracks, this.blendMode );
38513
38514         }
38515
38516         toJSON() {
38517
38518                 return this.constructor.toJSON( this );
38519
38520         }
38521
38522     }
38523
38524     function getTrackTypeForValueTypeName( typeName ) {
38525
38526         switch ( typeName.toLowerCase() ) {
38527
38528                 case 'scalar':
38529                 case 'double':
38530                 case 'float':
38531                 case 'number':
38532                 case 'integer':
38533
38534                         return NumberKeyframeTrack;
38535
38536                 case 'vector':
38537                 case 'vector2':
38538                 case 'vector3':
38539                 case 'vector4':
38540
38541                         return VectorKeyframeTrack;
38542
38543                 case 'color':
38544
38545                         return ColorKeyframeTrack;
38546
38547                 case 'quaternion':
38548
38549                         return QuaternionKeyframeTrack;
38550
38551                 case 'bool':
38552                 case 'boolean':
38553
38554                         return BooleanKeyframeTrack;
38555
38556                 case 'string':
38557
38558                         return StringKeyframeTrack;
38559
38560         }
38561
38562         throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
38563
38564     }
38565
38566     function parseKeyframeTrack( json ) {
38567
38568         if ( json.type === undefined ) {
38569
38570                 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
38571
38572         }
38573
38574         const trackType = getTrackTypeForValueTypeName( json.type );
38575
38576         if ( json.times === undefined ) {
38577
38578                 const times = [], values = [];
38579
38580                 AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
38581
38582                 json.times = times;
38583                 json.values = values;
38584
38585         }
38586
38587         // derived classes can define a static parse method
38588         if ( trackType.parse !== undefined ) {
38589
38590                 return trackType.parse( json );
38591
38592         } else {
38593
38594                 // by default, we assume a constructor compatible with the base
38595                 return new trackType( json.name, json.times, json.values, json.interpolation );
38596
38597         }
38598
38599     }
38600
38601     const Cache = {
38602
38603         enabled: false,
38604
38605         files: {},
38606
38607         add: function ( key, file ) {
38608
38609                 if ( this.enabled === false ) return;
38610
38611                 // console.log( 'THREE.Cache', 'Adding key:', key );
38612
38613                 this.files[ key ] = file;
38614
38615         },
38616
38617         get: function ( key ) {
38618
38619                 if ( this.enabled === false ) return;
38620
38621                 // console.log( 'THREE.Cache', 'Checking key:', key );
38622
38623                 return this.files[ key ];
38624
38625         },
38626
38627         remove: function ( key ) {
38628
38629                 delete this.files[ key ];
38630
38631         },
38632
38633         clear: function () {
38634
38635                 this.files = {};
38636
38637         }
38638
38639     };
38640
38641     class LoadingManager {
38642
38643         constructor( onLoad, onProgress, onError ) {
38644
38645                 const scope = this;
38646
38647                 let isLoading = false;
38648                 let itemsLoaded = 0;
38649                 let itemsTotal = 0;
38650                 let urlModifier = undefined;
38651                 const handlers = [];
38652
38653                 // Refer to #5689 for the reason why we don't set .onStart
38654                 // in the constructor
38655
38656                 this.onStart = undefined;
38657                 this.onLoad = onLoad;
38658                 this.onProgress = onProgress;
38659                 this.onError = onError;
38660
38661                 this.itemStart = function ( url ) {
38662
38663                         itemsTotal ++;
38664
38665                         if ( isLoading === false ) {
38666
38667                                 if ( scope.onStart !== undefined ) {
38668
38669                                         scope.onStart( url, itemsLoaded, itemsTotal );
38670
38671                                 }
38672
38673                         }
38674
38675                         isLoading = true;
38676
38677                 };
38678
38679                 this.itemEnd = function ( url ) {
38680
38681                         itemsLoaded ++;
38682
38683                         if ( scope.onProgress !== undefined ) {
38684
38685                                 scope.onProgress( url, itemsLoaded, itemsTotal );
38686
38687                         }
38688
38689                         if ( itemsLoaded === itemsTotal ) {
38690
38691                                 isLoading = false;
38692
38693                                 if ( scope.onLoad !== undefined ) {
38694
38695                                         scope.onLoad();
38696
38697                                 }
38698
38699                         }
38700
38701                 };
38702
38703                 this.itemError = function ( url ) {
38704
38705                         if ( scope.onError !== undefined ) {
38706
38707                                 scope.onError( url );
38708
38709                         }
38710
38711                 };
38712
38713                 this.resolveURL = function ( url ) {
38714
38715                         if ( urlModifier ) {
38716
38717                                 return urlModifier( url );
38718
38719                         }
38720
38721                         return url;
38722
38723                 };
38724
38725                 this.setURLModifier = function ( transform ) {
38726
38727                         urlModifier = transform;
38728
38729                         return this;
38730
38731                 };
38732
38733                 this.addHandler = function ( regex, loader ) {
38734
38735                         handlers.push( regex, loader );
38736
38737                         return this;
38738
38739                 };
38740
38741                 this.removeHandler = function ( regex ) {
38742
38743                         const index = handlers.indexOf( regex );
38744
38745                         if ( index !== - 1 ) {
38746
38747                                 handlers.splice( index, 2 );
38748
38749                         }
38750
38751                         return this;
38752
38753                 };
38754
38755                 this.getHandler = function ( file ) {
38756
38757                         for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
38758
38759                                 const regex = handlers[ i ];
38760                                 const loader = handlers[ i + 1 ];
38761
38762                                 if ( regex.global ) regex.lastIndex = 0; // see #17920
38763
38764                                 if ( regex.test( file ) ) {
38765
38766                                         return loader;
38767
38768                                 }
38769
38770                         }
38771
38772                         return null;
38773
38774                 };
38775
38776         }
38777
38778     }
38779
38780     const DefaultLoadingManager = new LoadingManager();
38781
38782     class Loader {
38783
38784         constructor( manager ) {
38785
38786                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
38787
38788                 this.crossOrigin = 'anonymous';
38789                 this.withCredentials = false;
38790                 this.path = '';
38791                 this.resourcePath = '';
38792                 this.requestHeader = {};
38793
38794         }
38795
38796         load( /* url, onLoad, onProgress, onError */ ) {}
38797
38798         loadAsync( url, onProgress ) {
38799
38800                 const scope = this;
38801
38802                 return new Promise( function ( resolve, reject ) {
38803
38804                         scope.load( url, resolve, onProgress, reject );
38805
38806                 } );
38807
38808         }
38809
38810         parse( /* data */ ) {}
38811
38812         setCrossOrigin( crossOrigin ) {
38813
38814                 this.crossOrigin = crossOrigin;
38815                 return this;
38816
38817         }
38818
38819         setWithCredentials( value ) {
38820
38821                 this.withCredentials = value;
38822                 return this;
38823
38824         }
38825
38826         setPath( path ) {
38827
38828                 this.path = path;
38829                 return this;
38830
38831         }
38832
38833         setResourcePath( resourcePath ) {
38834
38835                 this.resourcePath = resourcePath;
38836                 return this;
38837
38838         }
38839
38840         setRequestHeader( requestHeader ) {
38841
38842                 this.requestHeader = requestHeader;
38843                 return this;
38844
38845         }
38846
38847     }
38848
38849     const loading = {};
38850
38851     class FileLoader extends Loader {
38852
38853         constructor( manager ) {
38854
38855                 super( manager );
38856
38857         }
38858
38859         load( url, onLoad, onProgress, onError ) {
38860
38861                 if ( url === undefined ) url = '';
38862
38863                 if ( this.path !== undefined ) url = this.path + url;
38864
38865                 url = this.manager.resolveURL( url );
38866
38867                 const cached = Cache.get( url );
38868
38869                 if ( cached !== undefined ) {
38870
38871                         this.manager.itemStart( url );
38872
38873                         setTimeout( () => {
38874
38875                                 if ( onLoad ) onLoad( cached );
38876
38877                                 this.manager.itemEnd( url );
38878
38879                         }, 0 );
38880
38881                         return cached;
38882
38883                 }
38884
38885                 // Check if request is duplicate
38886
38887                 if ( loading[ url ] !== undefined ) {
38888
38889                         loading[ url ].push( {
38890
38891                                 onLoad: onLoad,
38892                                 onProgress: onProgress,
38893                                 onError: onError
38894
38895                         } );
38896
38897                         return;
38898
38899                 }
38900
38901                 // Initialise array for duplicate requests
38902                 loading[ url ] = [];
38903
38904                 loading[ url ].push( {
38905                         onLoad: onLoad,
38906                         onProgress: onProgress,
38907                         onError: onError,
38908                 } );
38909
38910                 // create request
38911                 const req = new Request( url, {
38912                         headers: new Headers( this.requestHeader ),
38913                         credentials: this.withCredentials ? 'include' : 'same-origin',
38914                         // An abort controller could be added within a future PR
38915                 } );
38916
38917                 // start the fetch
38918                 fetch( req )
38919                         .then( response => {
38920
38921                                 if ( response.status === 200 || response.status === 0 ) {
38922
38923                                         // Some browsers return HTTP Status 0 when using non-http protocol
38924                                         // e.g. 'file://' or 'data://'. Handle as success.
38925
38926                                         if ( response.status === 0 ) {
38927
38928                                                 console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
38929
38930                                         }
38931
38932                                         const callbacks = loading[ url ];
38933                                         const reader = response.body.getReader();
38934                                         const contentLength = response.headers.get( 'Content-Length' );
38935                                         const total = contentLength ? parseInt( contentLength ) : 0;
38936                                         const lengthComputable = total !== 0;
38937                                         let loaded = 0;
38938
38939                                         // periodically read data into the new stream tracking while download progress
38940                                         return new ReadableStream( {
38941                                                 start( controller ) {
38942
38943                                                         readData();
38944
38945                                                         function readData() {
38946
38947                                                                 reader.read().then( ( { done, value } ) => {
38948
38949                                                                         if ( done ) {
38950
38951                                                                                 controller.close();
38952
38953                                                                         } else {
38954
38955                                                                                 loaded += value.byteLength;
38956
38957                                                                                 const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } );
38958                                                                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
38959
38960                                                                                         const callback = callbacks[ i ];
38961                                                                                         if ( callback.onProgress ) callback.onProgress( event );
38962
38963                                                                                 }
38964
38965                                                                                 controller.enqueue( value );
38966                                                                                 readData();
38967
38968                                                                         }
38969
38970                                                                 } );
38971
38972                                                         }
38973
38974                                                 }
38975
38976                                         } );
38977
38978                                 } else {
38979
38980                                         throw Error( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}` );
38981
38982                                 }
38983
38984                         } )
38985                         .then( stream => {
38986
38987                                 const response = new Response( stream );
38988
38989                                 switch ( this.responseType ) {
38990
38991                                         case 'arraybuffer':
38992
38993                                                 return response.arrayBuffer();
38994
38995                                         case 'blob':
38996
38997                                                 return response.blob();
38998
38999                                         case 'document':
39000
39001                                                 return response.text()
39002                                                         .then( text => {
39003
39004                                                                 const parser = new DOMParser();
39005                                                                 return parser.parseFromString( text, this.mimeType );
39006
39007                                                         } );
39008
39009                                         case 'json':
39010
39011                                                 return response.json();
39012
39013                                         default:
39014
39015                                                 return response.text();
39016
39017                                 }
39018
39019                         } )
39020                         .then( data => {
39021
39022                                 // Add to cache only on HTTP success, so that we do not cache
39023                                 // error response bodies as proper responses to requests.
39024                                 Cache.add( url, data );
39025
39026                                 const callbacks = loading[ url ];
39027                                 delete loading[ url ];
39028
39029                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
39030
39031                                         const callback = callbacks[ i ];
39032                                         if ( callback.onLoad ) callback.onLoad( data );
39033
39034                                 }
39035
39036                                 this.manager.itemEnd( url );
39037
39038                         } )
39039                         .catch( err => {
39040
39041                                 // Abort errors and other errors are handled the same
39042
39043                                 const callbacks = loading[ url ];
39044                                 delete loading[ url ];
39045
39046                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
39047
39048                                         const callback = callbacks[ i ];
39049                                         if ( callback.onError ) callback.onError( err );
39050
39051                                 }
39052
39053                                 this.manager.itemError( url );
39054                                 this.manager.itemEnd( url );
39055
39056                         } );
39057
39058                 this.manager.itemStart( url );
39059
39060         }
39061
39062         setResponseType( value ) {
39063
39064                 this.responseType = value;
39065                 return this;
39066
39067         }
39068
39069         setMimeType( value ) {
39070
39071                 this.mimeType = value;
39072                 return this;
39073
39074         }
39075
39076     }
39077
39078     class ImageLoader extends Loader {
39079
39080         constructor( manager ) {
39081
39082                 super( manager );
39083
39084         }
39085
39086         load( url, onLoad, onProgress, onError ) {
39087
39088                 if ( this.path !== undefined ) url = this.path + url;
39089
39090                 url = this.manager.resolveURL( url );
39091
39092                 const scope = this;
39093
39094                 const cached = Cache.get( url );
39095
39096                 if ( cached !== undefined ) {
39097
39098                         scope.manager.itemStart( url );
39099
39100                         setTimeout( function () {
39101
39102                                 if ( onLoad ) onLoad( cached );
39103
39104                                 scope.manager.itemEnd( url );
39105
39106                         }, 0 );
39107
39108                         return cached;
39109
39110                 }
39111
39112                 const image = createElementNS( 'img' );
39113
39114                 function onImageLoad() {
39115
39116                         removeEventListeners();
39117
39118                         Cache.add( url, this );
39119
39120                         if ( onLoad ) onLoad( this );
39121
39122                         scope.manager.itemEnd( url );
39123
39124                 }
39125
39126                 function onImageError( event ) {
39127
39128                         removeEventListeners();
39129
39130                         if ( onError ) onError( event );
39131
39132                         scope.manager.itemError( url );
39133                         scope.manager.itemEnd( url );
39134
39135                 }
39136
39137                 function removeEventListeners() {
39138
39139                         image.removeEventListener( 'load', onImageLoad, false );
39140                         image.removeEventListener( 'error', onImageError, false );
39141
39142                 }
39143
39144                 image.addEventListener( 'load', onImageLoad, false );
39145                 image.addEventListener( 'error', onImageError, false );
39146
39147                 if ( url.substr( 0, 5 ) !== 'data:' ) {
39148
39149                         if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
39150
39151                 }
39152
39153                 scope.manager.itemStart( url );
39154
39155                 image.src = url;
39156
39157                 return image;
39158
39159         }
39160
39161     }
39162
39163     class CubeTextureLoader extends Loader {
39164
39165         constructor( manager ) {
39166
39167                 super( manager );
39168
39169         }
39170
39171         load( urls, onLoad, onProgress, onError ) {
39172
39173                 const texture = new CubeTexture();
39174
39175                 const loader = new ImageLoader( this.manager );
39176                 loader.setCrossOrigin( this.crossOrigin );
39177                 loader.setPath( this.path );
39178
39179                 let loaded = 0;
39180
39181                 function loadTexture( i ) {
39182
39183                         loader.load( urls[ i ], function ( image ) {
39184
39185                                 texture.images[ i ] = image;
39186
39187                                 loaded ++;
39188
39189                                 if ( loaded === 6 ) {
39190
39191                                         texture.needsUpdate = true;
39192
39193                                         if ( onLoad ) onLoad( texture );
39194
39195                                 }
39196
39197                         }, undefined, onError );
39198
39199                 }
39200
39201                 for ( let i = 0; i < urls.length; ++ i ) {
39202
39203                         loadTexture( i );
39204
39205                 }
39206
39207                 return texture;
39208
39209         }
39210
39211     }
39212
39213     class TextureLoader extends Loader {
39214
39215         constructor( manager ) {
39216
39217                 super( manager );
39218
39219         }
39220
39221         load( url, onLoad, onProgress, onError ) {
39222
39223                 const texture = new Texture();
39224
39225                 const loader = new ImageLoader( this.manager );
39226                 loader.setCrossOrigin( this.crossOrigin );
39227                 loader.setPath( this.path );
39228
39229                 loader.load( url, function ( image ) {
39230
39231                         texture.image = image;
39232                         texture.needsUpdate = true;
39233
39234                         if ( onLoad !== undefined ) {
39235
39236                                 onLoad( texture );
39237
39238                         }
39239
39240                 }, onProgress, onError );
39241
39242                 return texture;
39243
39244         }
39245
39246     }
39247
39248     class Light extends Object3D {
39249
39250         constructor( color, intensity = 1 ) {
39251
39252                 super();
39253
39254                 this.type = 'Light';
39255
39256                 this.color = new Color( color );
39257                 this.intensity = intensity;
39258
39259         }
39260
39261         dispose() {
39262
39263                 // Empty here in base class; some subclasses override.
39264
39265         }
39266
39267         copy( source ) {
39268
39269                 super.copy( source );
39270
39271                 this.color.copy( source.color );
39272                 this.intensity = source.intensity;
39273
39274                 return this;
39275
39276         }
39277
39278         toJSON( meta ) {
39279
39280                 const data = super.toJSON( meta );
39281
39282                 data.object.color = this.color.getHex();
39283                 data.object.intensity = this.intensity;
39284
39285                 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
39286
39287                 if ( this.distance !== undefined ) data.object.distance = this.distance;
39288                 if ( this.angle !== undefined ) data.object.angle = this.angle;
39289                 if ( this.decay !== undefined ) data.object.decay = this.decay;
39290                 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
39291
39292                 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
39293
39294                 return data;
39295
39296         }
39297
39298     }
39299
39300     Light.prototype.isLight = true;
39301
39302     class HemisphereLight extends Light {
39303
39304         constructor( skyColor, groundColor, intensity ) {
39305
39306                 super( skyColor, intensity );
39307
39308                 this.type = 'HemisphereLight';
39309
39310                 this.position.copy( Object3D.DefaultUp );
39311                 this.updateMatrix();
39312
39313                 this.groundColor = new Color( groundColor );
39314
39315         }
39316
39317         copy( source ) {
39318
39319                 Light.prototype.copy.call( this, source );
39320
39321                 this.groundColor.copy( source.groundColor );
39322
39323                 return this;
39324
39325         }
39326
39327     }
39328
39329     HemisphereLight.prototype.isHemisphereLight = true;
39330
39331     const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4();
39332     const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3();
39333     const _lookTarget$1 = /*@__PURE__*/ new Vector3();
39334
39335     class LightShadow {
39336
39337         constructor( camera ) {
39338
39339                 this.camera = camera;
39340
39341                 this.bias = 0;
39342                 this.normalBias = 0;
39343                 this.radius = 1;
39344                 this.blurSamples = 8;
39345
39346                 this.mapSize = new Vector2( 512, 512 );
39347
39348                 this.map = null;
39349                 this.mapPass = null;
39350                 this.matrix = new Matrix4();
39351
39352                 this.autoUpdate = true;
39353                 this.needsUpdate = false;
39354
39355                 this._frustum = new Frustum();
39356                 this._frameExtents = new Vector2( 1, 1 );
39357
39358                 this._viewportCount = 1;
39359
39360                 this._viewports = [
39361
39362                         new Vector4( 0, 0, 1, 1 )
39363
39364                 ];
39365
39366         }
39367
39368         getViewportCount() {
39369
39370                 return this._viewportCount;
39371
39372         }
39373
39374         getFrustum() {
39375
39376                 return this._frustum;
39377
39378         }
39379
39380         updateMatrices( light ) {
39381
39382                 const shadowCamera = this.camera;
39383                 const shadowMatrix = this.matrix;
39384
39385                 _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld );
39386                 shadowCamera.position.copy( _lightPositionWorld$1 );
39387
39388                 _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld );
39389                 shadowCamera.lookAt( _lookTarget$1 );
39390                 shadowCamera.updateMatrixWorld();
39391
39392                 _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
39393                 this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 );
39394
39395                 shadowMatrix.set(
39396                         0.5, 0.0, 0.0, 0.5,
39397                         0.0, 0.5, 0.0, 0.5,
39398                         0.0, 0.0, 0.5, 0.5,
39399                         0.0, 0.0, 0.0, 1.0
39400                 );
39401
39402                 shadowMatrix.multiply( shadowCamera.projectionMatrix );
39403                 shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
39404
39405         }
39406
39407         getViewport( viewportIndex ) {
39408
39409                 return this._viewports[ viewportIndex ];
39410
39411         }
39412
39413         getFrameExtents() {
39414
39415                 return this._frameExtents;
39416
39417         }
39418
39419         dispose() {
39420
39421                 if ( this.map ) {
39422
39423                         this.map.dispose();
39424
39425                 }
39426
39427                 if ( this.mapPass ) {
39428
39429                         this.mapPass.dispose();
39430
39431                 }
39432
39433         }
39434
39435         copy( source ) {
39436
39437                 this.camera = source.camera.clone();
39438
39439                 this.bias = source.bias;
39440                 this.radius = source.radius;
39441
39442                 this.mapSize.copy( source.mapSize );
39443
39444                 return this;
39445
39446         }
39447
39448         clone() {
39449
39450                 return new this.constructor().copy( this );
39451
39452         }
39453
39454         toJSON() {
39455
39456                 const object = {};
39457
39458                 if ( this.bias !== 0 ) object.bias = this.bias;
39459                 if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
39460                 if ( this.radius !== 1 ) object.radius = this.radius;
39461                 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
39462
39463                 object.camera = this.camera.toJSON( false ).object;
39464                 delete object.camera.matrix;
39465
39466                 return object;
39467
39468         }
39469
39470     }
39471
39472     class SpotLightShadow extends LightShadow {
39473
39474         constructor() {
39475
39476                 super( new PerspectiveCamera( 50, 1, 0.5, 500 ) );
39477
39478                 this.focus = 1;
39479
39480         }
39481
39482         updateMatrices( light ) {
39483
39484                 const camera = this.camera;
39485
39486                 const fov = RAD2DEG$1 * 2 * light.angle * this.focus;
39487                 const aspect = this.mapSize.width / this.mapSize.height;
39488                 const far = light.distance || camera.far;
39489
39490                 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
39491
39492                         camera.fov = fov;
39493                         camera.aspect = aspect;
39494                         camera.far = far;
39495                         camera.updateProjectionMatrix();
39496
39497                 }
39498
39499                 super.updateMatrices( light );
39500
39501         }
39502
39503         copy( source ) {
39504
39505                 super.copy( source );
39506
39507                 this.focus = source.focus;
39508
39509                 return this;
39510
39511         }
39512
39513     }
39514
39515     SpotLightShadow.prototype.isSpotLightShadow = true;
39516
39517     class SpotLight extends Light {
39518
39519         constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 1 ) {
39520
39521                 super( color, intensity );
39522
39523                 this.type = 'SpotLight';
39524
39525                 this.position.copy( Object3D.DefaultUp );
39526                 this.updateMatrix();
39527
39528                 this.target = new Object3D();
39529
39530                 this.distance = distance;
39531                 this.angle = angle;
39532                 this.penumbra = penumbra;
39533                 this.decay = decay; // for physically correct lights, should be 2.
39534
39535                 this.shadow = new SpotLightShadow();
39536
39537         }
39538
39539         get power() {
39540
39541                 // compute the light's luminous power (in lumens) from its intensity (in candela)
39542                 // by convention for a spotlight, luminous power (lm) = Ï€ * luminous intensity (cd)
39543                 return this.intensity * Math.PI;
39544
39545         }
39546
39547         set power( power ) {
39548
39549                 // set the light's intensity (in candela) from the desired luminous power (in lumens)
39550                 this.intensity = power / Math.PI;
39551
39552         }
39553
39554         dispose() {
39555
39556                 this.shadow.dispose();
39557
39558         }
39559
39560         copy( source ) {
39561
39562                 super.copy( source );
39563
39564                 this.distance = source.distance;
39565                 this.angle = source.angle;
39566                 this.penumbra = source.penumbra;
39567                 this.decay = source.decay;
39568
39569                 this.target = source.target.clone();
39570
39571                 this.shadow = source.shadow.clone();
39572
39573                 return this;
39574
39575         }
39576
39577     }
39578
39579     SpotLight.prototype.isSpotLight = true;
39580
39581     const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
39582     const _lightPositionWorld = /*@__PURE__*/ new Vector3();
39583     const _lookTarget = /*@__PURE__*/ new Vector3();
39584
39585     class PointLightShadow extends LightShadow {
39586
39587         constructor() {
39588
39589                 super( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
39590
39591                 this._frameExtents = new Vector2( 4, 2 );
39592
39593                 this._viewportCount = 6;
39594
39595                 this._viewports = [
39596                         // These viewports map a cube-map onto a 2D texture with the
39597                         // following orientation:
39598                         //
39599                         //  xzXZ
39600                         //   y Y
39601                         //
39602                         // X - Positive x direction
39603                         // x - Negative x direction
39604                         // Y - Positive y direction
39605                         // y - Negative y direction
39606                         // Z - Positive z direction
39607                         // z - Negative z direction
39608
39609                         // positive X
39610                         new Vector4( 2, 1, 1, 1 ),
39611                         // negative X
39612                         new Vector4( 0, 1, 1, 1 ),
39613                         // positive Z
39614                         new Vector4( 3, 1, 1, 1 ),
39615                         // negative Z
39616                         new Vector4( 1, 1, 1, 1 ),
39617                         // positive Y
39618                         new Vector4( 3, 0, 1, 1 ),
39619                         // negative Y
39620                         new Vector4( 1, 0, 1, 1 )
39621                 ];
39622
39623                 this._cubeDirections = [
39624                         new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
39625                         new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
39626                 ];
39627
39628                 this._cubeUps = [
39629                         new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
39630                         new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
39631                 ];
39632
39633         }
39634
39635         updateMatrices( light, viewportIndex = 0 ) {
39636
39637                 const camera = this.camera;
39638                 const shadowMatrix = this.matrix;
39639
39640                 const far = light.distance || camera.far;
39641
39642                 if ( far !== camera.far ) {
39643
39644                         camera.far = far;
39645                         camera.updateProjectionMatrix();
39646
39647                 }
39648
39649                 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
39650                 camera.position.copy( _lightPositionWorld );
39651
39652                 _lookTarget.copy( camera.position );
39653                 _lookTarget.add( this._cubeDirections[ viewportIndex ] );
39654                 camera.up.copy( this._cubeUps[ viewportIndex ] );
39655                 camera.lookAt( _lookTarget );
39656                 camera.updateMatrixWorld();
39657
39658                 shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
39659
39660                 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
39661                 this._frustum.setFromProjectionMatrix( _projScreenMatrix );
39662
39663         }
39664
39665     }
39666
39667     PointLightShadow.prototype.isPointLightShadow = true;
39668
39669     class PointLight extends Light {
39670
39671         constructor( color, intensity, distance = 0, decay = 1 ) {
39672
39673                 super( color, intensity );
39674
39675                 this.type = 'PointLight';
39676
39677                 this.distance = distance;
39678                 this.decay = decay; // for physically correct lights, should be 2.
39679
39680                 this.shadow = new PointLightShadow();
39681
39682         }
39683
39684         get power() {
39685
39686                 // compute the light's luminous power (in lumens) from its intensity (in candela)
39687                 // for an isotropic light source, luminous power (lm) = 4 Ï€ luminous intensity (cd)
39688                 return this.intensity * 4 * Math.PI;
39689
39690         }
39691
39692         set power( power ) {
39693
39694                 // set the light's intensity (in candela) from the desired luminous power (in lumens)
39695                 this.intensity = power / ( 4 * Math.PI );
39696
39697         }
39698
39699         dispose() {
39700
39701                 this.shadow.dispose();
39702
39703         }
39704
39705         copy( source ) {
39706
39707                 super.copy( source );
39708
39709                 this.distance = source.distance;
39710                 this.decay = source.decay;
39711
39712                 this.shadow = source.shadow.clone();
39713
39714                 return this;
39715
39716         }
39717
39718     }
39719
39720     PointLight.prototype.isPointLight = true;
39721
39722     class DirectionalLightShadow extends LightShadow {
39723
39724         constructor() {
39725
39726                 super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
39727
39728         }
39729
39730     }
39731
39732     DirectionalLightShadow.prototype.isDirectionalLightShadow = true;
39733
39734     class DirectionalLight extends Light {
39735
39736         constructor( color, intensity ) {
39737
39738                 super( color, intensity );
39739
39740                 this.type = 'DirectionalLight';
39741
39742                 this.position.copy( Object3D.DefaultUp );
39743                 this.updateMatrix();
39744
39745                 this.target = new Object3D();
39746
39747                 this.shadow = new DirectionalLightShadow();
39748
39749         }
39750
39751         dispose() {
39752
39753                 this.shadow.dispose();
39754
39755         }
39756
39757         copy( source ) {
39758
39759                 super.copy( source );
39760
39761                 this.target = source.target.clone();
39762                 this.shadow = source.shadow.clone();
39763
39764                 return this;
39765
39766         }
39767
39768     }
39769
39770     DirectionalLight.prototype.isDirectionalLight = true;
39771
39772     class AmbientLight extends Light {
39773
39774         constructor( color, intensity ) {
39775
39776                 super( color, intensity );
39777
39778                 this.type = 'AmbientLight';
39779
39780         }
39781
39782     }
39783
39784     AmbientLight.prototype.isAmbientLight = true;
39785
39786     class RectAreaLight extends Light {
39787
39788         constructor( color, intensity, width = 10, height = 10 ) {
39789
39790                 super( color, intensity );
39791
39792                 this.type = 'RectAreaLight';
39793
39794                 this.width = width;
39795                 this.height = height;
39796
39797         }
39798
39799         get power() {
39800
39801                 // compute the light's luminous power (in lumens) from its intensity (in nits)
39802                 return this.intensity * this.width * this.height * Math.PI;
39803
39804         }
39805
39806         set power( power ) {
39807
39808                 // set the light's intensity (in nits) from the desired luminous power (in lumens)
39809                 this.intensity = power / ( this.width * this.height * Math.PI );
39810
39811         }
39812
39813         copy( source ) {
39814
39815                 super.copy( source );
39816
39817                 this.width = source.width;
39818                 this.height = source.height;
39819
39820                 return this;
39821
39822         }
39823
39824         toJSON( meta ) {
39825
39826                 const data = super.toJSON( meta );
39827
39828                 data.object.width = this.width;
39829                 data.object.height = this.height;
39830
39831                 return data;
39832
39833         }
39834
39835     }
39836
39837     RectAreaLight.prototype.isRectAreaLight = true;
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                 this.coefficients = [];
39854
39855                 for ( let i = 0; i < 9; i ++ ) {
39856
39857                         this.coefficients.push( new Vector3() );
39858
39859                 }
39860
39861         }
39862
39863         set( coefficients ) {
39864
39865                 for ( let i = 0; i < 9; i ++ ) {
39866
39867                         this.coefficients[ i ].copy( coefficients[ i ] );
39868
39869                 }
39870
39871                 return this;
39872
39873         }
39874
39875         zero() {
39876
39877                 for ( let i = 0; i < 9; i ++ ) {
39878
39879                         this.coefficients[ i ].set( 0, 0, 0 );
39880
39881                 }
39882
39883                 return this;
39884
39885         }
39886
39887         // get the radiance in the direction of the normal
39888         // target is a Vector3
39889         getAt( normal, target ) {
39890
39891                 // normal is assumed to be unit length
39892
39893                 const x = normal.x, y = normal.y, z = normal.z;
39894
39895                 const coeff = this.coefficients;
39896
39897                 // band 0
39898                 target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
39899
39900                 // band 1
39901                 target.addScaledVector( coeff[ 1 ], 0.488603 * y );
39902                 target.addScaledVector( coeff[ 2 ], 0.488603 * z );
39903                 target.addScaledVector( coeff[ 3 ], 0.488603 * x );
39904
39905                 // band 2
39906                 target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
39907                 target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
39908                 target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
39909                 target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
39910                 target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
39911
39912                 return target;
39913
39914         }
39915
39916         // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
39917         // target is a Vector3
39918         // https://graphics.stanford.edu/papers/envmap/envmap.pdf
39919         getIrradianceAt( normal, target ) {
39920
39921                 // normal is assumed to be unit length
39922
39923                 const x = normal.x, y = normal.y, z = normal.z;
39924
39925                 const coeff = this.coefficients;
39926
39927                 // band 0
39928                 target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // Ï€ * 0.282095
39929
39930                 // band 1
39931                 target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * Ï€ / 3 ) * 0.488603
39932                 target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
39933                 target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
39934
39935                 // band 2
39936                 target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( Ï€ / 4 ) * 1.092548
39937                 target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
39938                 target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( Ï€ / 4 ) * 0.315392 * 3
39939                 target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
39940                 target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( Ï€ / 4 ) * 0.546274
39941
39942                 return target;
39943
39944         }
39945
39946         add( sh ) {
39947
39948                 for ( let i = 0; i < 9; i ++ ) {
39949
39950                         this.coefficients[ i ].add( sh.coefficients[ i ] );
39951
39952                 }
39953
39954                 return this;
39955
39956         }
39957
39958         addScaledSH( sh, s ) {
39959
39960                 for ( let i = 0; i < 9; i ++ ) {
39961
39962                         this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
39963
39964                 }
39965
39966                 return this;
39967
39968         }
39969
39970         scale( s ) {
39971
39972                 for ( let i = 0; i < 9; i ++ ) {
39973
39974                         this.coefficients[ i ].multiplyScalar( s );
39975
39976                 }
39977
39978                 return this;
39979
39980         }
39981
39982         lerp( sh, alpha ) {
39983
39984                 for ( let i = 0; i < 9; i ++ ) {
39985
39986                         this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
39987
39988                 }
39989
39990                 return this;
39991
39992         }
39993
39994         equals( sh ) {
39995
39996                 for ( let i = 0; i < 9; i ++ ) {
39997
39998                         if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
39999
40000                                 return false;
40001
40002                         }
40003
40004                 }
40005
40006                 return true;
40007
40008         }
40009
40010         copy( sh ) {
40011
40012                 return this.set( sh.coefficients );
40013
40014         }
40015
40016         clone() {
40017
40018                 return new this.constructor().copy( this );
40019
40020         }
40021
40022         fromArray( array, offset = 0 ) {
40023
40024                 const coefficients = this.coefficients;
40025
40026                 for ( let i = 0; i < 9; i ++ ) {
40027
40028                         coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
40029
40030                 }
40031
40032                 return this;
40033
40034         }
40035
40036         toArray( array = [], offset = 0 ) {
40037
40038                 const coefficients = this.coefficients;
40039
40040                 for ( let i = 0; i < 9; i ++ ) {
40041
40042                         coefficients[ i ].toArray( array, offset + ( i * 3 ) );
40043
40044                 }
40045
40046                 return array;
40047
40048         }
40049
40050         // evaluate the basis functions
40051         // shBasis is an Array[ 9 ]
40052         static getBasisAt( normal, shBasis ) {
40053
40054                 // normal is assumed to be unit length
40055
40056                 const x = normal.x, y = normal.y, z = normal.z;
40057
40058                 // band 0
40059                 shBasis[ 0 ] = 0.282095;
40060
40061                 // band 1
40062                 shBasis[ 1 ] = 0.488603 * y;
40063                 shBasis[ 2 ] = 0.488603 * z;
40064                 shBasis[ 3 ] = 0.488603 * x;
40065
40066                 // band 2
40067                 shBasis[ 4 ] = 1.092548 * x * y;
40068                 shBasis[ 5 ] = 1.092548 * y * z;
40069                 shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
40070                 shBasis[ 7 ] = 1.092548 * x * z;
40071                 shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
40072
40073         }
40074
40075     }
40076
40077     SphericalHarmonics3.prototype.isSphericalHarmonics3 = true;
40078
40079     class LightProbe extends Light {
40080
40081         constructor( sh = new SphericalHarmonics3(), intensity = 1 ) {
40082
40083                 super( undefined, intensity );
40084
40085                 this.sh = sh;
40086
40087         }
40088
40089         copy( source ) {
40090
40091                 super.copy( source );
40092
40093                 this.sh.copy( source.sh );
40094
40095                 return this;
40096
40097         }
40098
40099         fromJSON( json ) {
40100
40101                 this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
40102                 this.sh.fromArray( json.sh );
40103
40104                 return this;
40105
40106         }
40107
40108         toJSON( meta ) {
40109
40110                 const data = super.toJSON( meta );
40111
40112                 data.object.sh = this.sh.toArray();
40113
40114                 return data;
40115
40116         }
40117
40118     }
40119
40120     LightProbe.prototype.isLightProbe = true;
40121
40122     class LoaderUtils {
40123
40124         static decodeText( array ) {
40125
40126                 if ( typeof TextDecoder !== 'undefined' ) {
40127
40128                         return new TextDecoder().decode( array );
40129
40130                 }
40131
40132                 // Avoid the String.fromCharCode.apply(null, array) shortcut, which
40133                 // throws a "maximum call stack size exceeded" error for large arrays.
40134
40135                 let s = '';
40136
40137                 for ( let i = 0, il = array.length; i < il; i ++ ) {
40138
40139                         // Implicitly assumes little-endian.
40140                         s += String.fromCharCode( array[ i ] );
40141
40142                 }
40143
40144                 try {
40145
40146                         // merges multi-byte utf-8 characters.
40147
40148                         return decodeURIComponent( escape( s ) );
40149
40150                 } catch ( e ) { // see #16358
40151
40152                         return s;
40153
40154                 }
40155
40156         }
40157
40158         static extractUrlBase( url ) {
40159
40160                 const index = url.lastIndexOf( '/' );
40161
40162                 if ( index === - 1 ) return './';
40163
40164                 return url.substr( 0, index + 1 );
40165
40166         }
40167
40168         static resolveURL( url, path ) {
40169
40170                 // Invalid URL
40171                 if ( typeof url !== 'string' || url === '' ) return '';
40172
40173                 // Host Relative URL
40174                 if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) {
40175
40176                         path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' );
40177
40178                 }
40179
40180                 // Absolute URL http://,https://,//
40181                 if ( /^(https?:)?\/\//i.test( url ) ) return url;
40182
40183                 // Data URI
40184                 if ( /^data:.*,.*$/i.test( url ) ) return url;
40185
40186                 // Blob URL
40187                 if ( /^blob:.*$/i.test( url ) ) return url;
40188
40189                 // Relative URL
40190                 return path + url;
40191
40192         }
40193
40194     }
40195
40196     class InstancedBufferGeometry extends BufferGeometry {
40197
40198         constructor() {
40199
40200                 super();
40201
40202                 this.type = 'InstancedBufferGeometry';
40203                 this.instanceCount = Infinity;
40204
40205         }
40206
40207         copy( source ) {
40208
40209                 super.copy( source );
40210
40211                 this.instanceCount = source.instanceCount;
40212
40213                 return this;
40214
40215         }
40216
40217         clone() {
40218
40219                 return new this.constructor().copy( this );
40220
40221         }
40222
40223         toJSON() {
40224
40225                 const data = super.toJSON( this );
40226
40227                 data.instanceCount = this.instanceCount;
40228
40229                 data.isInstancedBufferGeometry = true;
40230
40231                 return data;
40232
40233         }
40234
40235     }
40236
40237     InstancedBufferGeometry.prototype.isInstancedBufferGeometry = true;
40238
40239     class ImageBitmapLoader extends Loader {
40240
40241         constructor( manager ) {
40242
40243                 super( manager );
40244
40245                 if ( typeof createImageBitmap === 'undefined' ) {
40246
40247                         console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
40248
40249                 }
40250
40251                 if ( typeof fetch === 'undefined' ) {
40252
40253                         console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
40254
40255                 }
40256
40257                 this.options = { premultiplyAlpha: 'none' };
40258
40259         }
40260
40261         setOptions( options ) {
40262
40263                 this.options = options;
40264
40265                 return this;
40266
40267         }
40268
40269         load( url, onLoad, onProgress, onError ) {
40270
40271                 if ( url === undefined ) url = '';
40272
40273                 if ( this.path !== undefined ) url = this.path + url;
40274
40275                 url = this.manager.resolveURL( url );
40276
40277                 const scope = this;
40278
40279                 const cached = Cache.get( url );
40280
40281                 if ( cached !== undefined ) {
40282
40283                         scope.manager.itemStart( url );
40284
40285                         setTimeout( function () {
40286
40287                                 if ( onLoad ) onLoad( cached );
40288
40289                                 scope.manager.itemEnd( url );
40290
40291                         }, 0 );
40292
40293                         return cached;
40294
40295                 }
40296
40297                 const fetchOptions = {};
40298                 fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
40299                 fetchOptions.headers = this.requestHeader;
40300
40301                 fetch( url, fetchOptions ).then( function ( res ) {
40302
40303                         return res.blob();
40304
40305                 } ).then( function ( blob ) {
40306
40307                         return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) );
40308
40309                 } ).then( function ( imageBitmap ) {
40310
40311                         Cache.add( url, imageBitmap );
40312
40313                         if ( onLoad ) onLoad( imageBitmap );
40314
40315                         scope.manager.itemEnd( url );
40316
40317                 } ).catch( function ( e ) {
40318
40319                         if ( onError ) onError( e );
40320
40321                         scope.manager.itemError( url );
40322                         scope.manager.itemEnd( url );
40323
40324                 } );
40325
40326                 scope.manager.itemStart( url );
40327
40328         }
40329
40330     }
40331
40332     ImageBitmapLoader.prototype.isImageBitmapLoader = true;
40333
40334     let _context;
40335
40336     const AudioContext = {
40337
40338         getContext: function () {
40339
40340                 if ( _context === undefined ) {
40341
40342                         _context = new ( window.AudioContext || window.webkitAudioContext )();
40343
40344                 }
40345
40346                 return _context;
40347
40348         },
40349
40350         setContext: function ( value ) {
40351
40352                 _context = value;
40353
40354         }
40355
40356     };
40357
40358     class AudioLoader extends Loader {
40359
40360         constructor( manager ) {
40361
40362                 super( manager );
40363
40364         }
40365
40366         load( url, onLoad, onProgress, onError ) {
40367
40368                 const scope = this;
40369
40370                 const loader = new FileLoader( this.manager );
40371                 loader.setResponseType( 'arraybuffer' );
40372                 loader.setPath( this.path );
40373                 loader.setRequestHeader( this.requestHeader );
40374                 loader.setWithCredentials( this.withCredentials );
40375                 loader.load( url, function ( buffer ) {
40376
40377                         try {
40378
40379                                 // Create a copy of the buffer. The `decodeAudioData` method
40380                                 // detaches the buffer when complete, preventing reuse.
40381                                 const bufferCopy = buffer.slice( 0 );
40382
40383                                 const context = AudioContext.getContext();
40384                                 context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
40385
40386                                         onLoad( audioBuffer );
40387
40388                                 } );
40389
40390                         } catch ( e ) {
40391
40392                                 if ( onError ) {
40393
40394                                         onError( e );
40395
40396                                 } else {
40397
40398                                         console.error( e );
40399
40400                                 }
40401
40402                                 scope.manager.itemError( url );
40403
40404                         }
40405
40406                 }, onProgress, onError );
40407
40408         }
40409
40410     }
40411
40412     class HemisphereLightProbe extends LightProbe {
40413
40414         constructor( skyColor, groundColor, intensity = 1 ) {
40415
40416                 super( undefined, intensity );
40417
40418                 const color1 = new Color().set( skyColor );
40419                 const color2 = new Color().set( groundColor );
40420
40421                 const sky = new Vector3( color1.r, color1.g, color1.b );
40422                 const ground = new Vector3( color2.r, color2.g, color2.b );
40423
40424                 // without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
40425                 const c0 = Math.sqrt( Math.PI );
40426                 const c1 = c0 * Math.sqrt( 0.75 );
40427
40428                 this.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
40429                 this.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
40430
40431         }
40432
40433     }
40434
40435     HemisphereLightProbe.prototype.isHemisphereLightProbe = true;
40436
40437     class AmbientLightProbe extends LightProbe {
40438
40439         constructor( color, intensity = 1 ) {
40440
40441                 super( undefined, intensity );
40442
40443                 const color1 = new Color().set( color );
40444
40445                 // without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
40446                 this.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );
40447
40448         }
40449
40450     }
40451
40452     AmbientLightProbe.prototype.isAmbientLightProbe = true;
40453
40454     class Clock {
40455
40456         constructor( autoStart = true ) {
40457
40458                 this.autoStart = autoStart;
40459
40460                 this.startTime = 0;
40461                 this.oldTime = 0;
40462                 this.elapsedTime = 0;
40463
40464                 this.running = false;
40465
40466         }
40467
40468         start() {
40469
40470                 this.startTime = now();
40471
40472                 this.oldTime = this.startTime;
40473                 this.elapsedTime = 0;
40474                 this.running = true;
40475
40476         }
40477
40478         stop() {
40479
40480                 this.getElapsedTime();
40481                 this.running = false;
40482                 this.autoStart = false;
40483
40484         }
40485
40486         getElapsedTime() {
40487
40488                 this.getDelta();
40489                 return this.elapsedTime;
40490
40491         }
40492
40493         getDelta() {
40494
40495                 let diff = 0;
40496
40497                 if ( this.autoStart && ! this.running ) {
40498
40499                         this.start();
40500                         return 0;
40501
40502                 }
40503
40504                 if ( this.running ) {
40505
40506                         const newTime = now();
40507
40508                         diff = ( newTime - this.oldTime ) / 1000;
40509                         this.oldTime = newTime;
40510
40511                         this.elapsedTime += diff;
40512
40513                 }
40514
40515                 return diff;
40516
40517         }
40518
40519     }
40520
40521     function now() {
40522
40523         return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
40524
40525     }
40526
40527     class Audio extends Object3D {
40528
40529         constructor( listener ) {
40530
40531                 super();
40532
40533                 this.type = 'Audio';
40534
40535                 this.listener = listener;
40536                 this.context = listener.context;
40537
40538                 this.gain = this.context.createGain();
40539                 this.gain.connect( listener.getInput() );
40540
40541                 this.autoplay = false;
40542
40543                 this.buffer = null;
40544                 this.detune = 0;
40545                 this.loop = false;
40546                 this.loopStart = 0;
40547                 this.loopEnd = 0;
40548                 this.offset = 0;
40549                 this.duration = undefined;
40550                 this.playbackRate = 1;
40551                 this.isPlaying = false;
40552                 this.hasPlaybackControl = true;
40553                 this.source = null;
40554                 this.sourceType = 'empty';
40555
40556                 this._startedAt = 0;
40557                 this._progress = 0;
40558                 this._connected = false;
40559
40560                 this.filters = [];
40561
40562         }
40563
40564         getOutput() {
40565
40566                 return this.gain;
40567
40568         }
40569
40570         setNodeSource( audioNode ) {
40571
40572                 this.hasPlaybackControl = false;
40573                 this.sourceType = 'audioNode';
40574                 this.source = audioNode;
40575                 this.connect();
40576
40577                 return this;
40578
40579         }
40580
40581         setMediaElementSource( mediaElement ) {
40582
40583                 this.hasPlaybackControl = false;
40584                 this.sourceType = 'mediaNode';
40585                 this.source = this.context.createMediaElementSource( mediaElement );
40586                 this.connect();
40587
40588                 return this;
40589
40590         }
40591
40592         setMediaStreamSource( mediaStream ) {
40593
40594                 this.hasPlaybackControl = false;
40595                 this.sourceType = 'mediaStreamNode';
40596                 this.source = this.context.createMediaStreamSource( mediaStream );
40597                 this.connect();
40598
40599                 return this;
40600
40601         }
40602
40603         setBuffer( audioBuffer ) {
40604
40605                 this.buffer = audioBuffer;
40606                 this.sourceType = 'buffer';
40607
40608                 if ( this.autoplay ) this.play();
40609
40610                 return this;
40611
40612         }
40613
40614         play( delay = 0 ) {
40615
40616                 if ( this.isPlaying === true ) {
40617
40618                         console.warn( 'THREE.Audio: Audio is already playing.' );
40619                         return;
40620
40621                 }
40622
40623                 if ( this.hasPlaybackControl === false ) {
40624
40625                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40626                         return;
40627
40628                 }
40629
40630                 this._startedAt = this.context.currentTime + delay;
40631
40632                 const source = this.context.createBufferSource();
40633                 source.buffer = this.buffer;
40634                 source.loop = this.loop;
40635                 source.loopStart = this.loopStart;
40636                 source.loopEnd = this.loopEnd;
40637                 source.onended = this.onEnded.bind( this );
40638                 source.start( this._startedAt, this._progress + this.offset, this.duration );
40639
40640                 this.isPlaying = true;
40641
40642                 this.source = source;
40643
40644                 this.setDetune( this.detune );
40645                 this.setPlaybackRate( this.playbackRate );
40646
40647                 return this.connect();
40648
40649         }
40650
40651         pause() {
40652
40653                 if ( this.hasPlaybackControl === false ) {
40654
40655                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40656                         return;
40657
40658                 }
40659
40660                 if ( this.isPlaying === true ) {
40661
40662                         // update current progress
40663
40664                         this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
40665
40666                         if ( this.loop === true ) {
40667
40668                                 // ensure _progress does not exceed duration with looped audios
40669
40670                                 this._progress = this._progress % ( this.duration || this.buffer.duration );
40671
40672                         }
40673
40674                         this.source.stop();
40675                         this.source.onended = null;
40676
40677                         this.isPlaying = false;
40678
40679                 }
40680
40681                 return this;
40682
40683         }
40684
40685         stop() {
40686
40687                 if ( this.hasPlaybackControl === false ) {
40688
40689                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40690                         return;
40691
40692                 }
40693
40694                 this._progress = 0;
40695
40696                 this.source.stop();
40697                 this.source.onended = null;
40698                 this.isPlaying = false;
40699
40700                 return this;
40701
40702         }
40703
40704         connect() {
40705
40706                 if ( this.filters.length > 0 ) {
40707
40708                         this.source.connect( this.filters[ 0 ] );
40709
40710                         for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
40711
40712                                 this.filters[ i - 1 ].connect( this.filters[ i ] );
40713
40714                         }
40715
40716                         this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
40717
40718                 } else {
40719
40720                         this.source.connect( this.getOutput() );
40721
40722                 }
40723
40724                 this._connected = true;
40725
40726                 return this;
40727
40728         }
40729
40730         disconnect() {
40731
40732                 if ( this.filters.length > 0 ) {
40733
40734                         this.source.disconnect( this.filters[ 0 ] );
40735
40736                         for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
40737
40738                                 this.filters[ i - 1 ].disconnect( this.filters[ i ] );
40739
40740                         }
40741
40742                         this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
40743
40744                 } else {
40745
40746                         this.source.disconnect( this.getOutput() );
40747
40748                 }
40749
40750                 this._connected = false;
40751
40752                 return this;
40753
40754         }
40755
40756         getFilters() {
40757
40758                 return this.filters;
40759
40760         }
40761
40762         setFilters( value ) {
40763
40764                 if ( ! value ) value = [];
40765
40766                 if ( this._connected === true ) {
40767
40768                         this.disconnect();
40769                         this.filters = value.slice();
40770                         this.connect();
40771
40772                 } else {
40773
40774                         this.filters = value.slice();
40775
40776                 }
40777
40778                 return this;
40779
40780         }
40781
40782         setDetune( value ) {
40783
40784                 this.detune = value;
40785
40786                 if ( this.source.detune === undefined ) return; // only set detune when available
40787
40788                 if ( this.isPlaying === true ) {
40789
40790                         this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
40791
40792                 }
40793
40794                 return this;
40795
40796         }
40797
40798         getDetune() {
40799
40800                 return this.detune;
40801
40802         }
40803
40804         getFilter() {
40805
40806                 return this.getFilters()[ 0 ];
40807
40808         }
40809
40810         setFilter( filter ) {
40811
40812                 return this.setFilters( filter ? [ filter ] : [] );
40813
40814         }
40815
40816         setPlaybackRate( value ) {
40817
40818                 if ( this.hasPlaybackControl === false ) {
40819
40820                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40821                         return;
40822
40823                 }
40824
40825                 this.playbackRate = value;
40826
40827                 if ( this.isPlaying === true ) {
40828
40829                         this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
40830
40831                 }
40832
40833                 return this;
40834
40835         }
40836
40837         getPlaybackRate() {
40838
40839                 return this.playbackRate;
40840
40841         }
40842
40843         onEnded() {
40844
40845                 this.isPlaying = false;
40846
40847         }
40848
40849         getLoop() {
40850
40851                 if ( this.hasPlaybackControl === false ) {
40852
40853                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40854                         return false;
40855
40856                 }
40857
40858                 return this.loop;
40859
40860         }
40861
40862         setLoop( value ) {
40863
40864                 if ( this.hasPlaybackControl === false ) {
40865
40866                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40867                         return;
40868
40869                 }
40870
40871                 this.loop = value;
40872
40873                 if ( this.isPlaying === true ) {
40874
40875                         this.source.loop = this.loop;
40876
40877                 }
40878
40879                 return this;
40880
40881         }
40882
40883         setLoopStart( value ) {
40884
40885                 this.loopStart = value;
40886
40887                 return this;
40888
40889         }
40890
40891         setLoopEnd( value ) {
40892
40893                 this.loopEnd = value;
40894
40895                 return this;
40896
40897         }
40898
40899         getVolume() {
40900
40901                 return this.gain.gain.value;
40902
40903         }
40904
40905         setVolume( value ) {
40906
40907                 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
40908
40909                 return this;
40910
40911         }
40912
40913     }
40914
40915     class PropertyMixer {
40916
40917         constructor( binding, typeName, valueSize ) {
40918
40919                 this.binding = binding;
40920                 this.valueSize = valueSize;
40921
40922                 let mixFunction,
40923                         mixFunctionAdditive,
40924                         setIdentity;
40925
40926                 // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
40927                 //
40928                 // interpolators can use .buffer as their .result
40929                 // the data then goes to 'incoming'
40930                 //
40931                 // 'accu0' and 'accu1' are used frame-interleaved for
40932                 // the cumulative result and are compared to detect
40933                 // changes
40934                 //
40935                 // 'orig' stores the original state of the property
40936                 //
40937                 // 'add' is used for additive cumulative results
40938                 //
40939                 // 'work' is optional and is only present for quaternion types. It is used
40940                 // to store intermediate quaternion multiplication results
40941
40942                 switch ( typeName ) {
40943
40944                         case 'quaternion':
40945                                 mixFunction = this._slerp;
40946                                 mixFunctionAdditive = this._slerpAdditive;
40947                                 setIdentity = this._setAdditiveIdentityQuaternion;
40948
40949                                 this.buffer = new Float64Array( valueSize * 6 );
40950                                 this._workIndex = 5;
40951                                 break;
40952
40953                         case 'string':
40954                         case 'bool':
40955                                 mixFunction = this._select;
40956
40957                                 // Use the regular mix function and for additive on these types,
40958                                 // additive is not relevant for non-numeric types
40959                                 mixFunctionAdditive = this._select;
40960
40961                                 setIdentity = this._setAdditiveIdentityOther;
40962
40963                                 this.buffer = new Array( valueSize * 5 );
40964                                 break;
40965
40966                         default:
40967                                 mixFunction = this._lerp;
40968                                 mixFunctionAdditive = this._lerpAdditive;
40969                                 setIdentity = this._setAdditiveIdentityNumeric;
40970
40971                                 this.buffer = new Float64Array( valueSize * 5 );
40972
40973                 }
40974
40975                 this._mixBufferRegion = mixFunction;
40976                 this._mixBufferRegionAdditive = mixFunctionAdditive;
40977                 this._setIdentity = setIdentity;
40978                 this._origIndex = 3;
40979                 this._addIndex = 4;
40980
40981                 this.cumulativeWeight = 0;
40982                 this.cumulativeWeightAdditive = 0;
40983
40984                 this.useCount = 0;
40985                 this.referenceCount = 0;
40986
40987         }
40988
40989         // accumulate data in the 'incoming' region into 'accu<i>'
40990         accumulate( accuIndex, weight ) {
40991
40992                 // note: happily accumulating nothing when weight = 0, the caller knows
40993                 // the weight and shouldn't have made the call in the first place
40994
40995                 const buffer = this.buffer,
40996                         stride = this.valueSize,
40997                         offset = accuIndex * stride + stride;
40998
40999                 let currentWeight = this.cumulativeWeight;
41000
41001                 if ( currentWeight === 0 ) {
41002
41003                         // accuN := incoming * weight
41004
41005                         for ( let i = 0; i !== stride; ++ i ) {
41006
41007                                 buffer[ offset + i ] = buffer[ i ];
41008
41009                         }
41010
41011                         currentWeight = weight;
41012
41013                 } else {
41014
41015                         // accuN := accuN + incoming * weight
41016
41017                         currentWeight += weight;
41018                         const mix = weight / currentWeight;
41019                         this._mixBufferRegion( buffer, offset, 0, mix, stride );
41020
41021                 }
41022
41023                 this.cumulativeWeight = currentWeight;
41024
41025         }
41026
41027         // accumulate data in the 'incoming' region into 'add'
41028         accumulateAdditive( weight ) {
41029
41030                 const buffer = this.buffer,
41031                         stride = this.valueSize,
41032                         offset = stride * this._addIndex;
41033
41034                 if ( this.cumulativeWeightAdditive === 0 ) {
41035
41036                         // add = identity
41037
41038                         this._setIdentity();
41039
41040                 }
41041
41042                 // add := add + incoming * weight
41043
41044                 this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
41045                 this.cumulativeWeightAdditive += weight;
41046
41047         }
41048
41049         // apply the state of 'accu<i>' to the binding when accus differ
41050         apply( accuIndex ) {
41051
41052                 const stride = this.valueSize,
41053                         buffer = this.buffer,
41054                         offset = accuIndex * stride + stride,
41055
41056                         weight = this.cumulativeWeight,
41057                         weightAdditive = this.cumulativeWeightAdditive,
41058
41059                         binding = this.binding;
41060
41061                 this.cumulativeWeight = 0;
41062                 this.cumulativeWeightAdditive = 0;
41063
41064                 if ( weight < 1 ) {
41065
41066                         // accuN := accuN + original * ( 1 - cumulativeWeight )
41067
41068                         const originalValueOffset = stride * this._origIndex;
41069
41070                         this._mixBufferRegion(
41071                                 buffer, offset, originalValueOffset, 1 - weight, stride );
41072
41073                 }
41074
41075                 if ( weightAdditive > 0 ) {
41076
41077                         // accuN := accuN + additive accuN
41078
41079                         this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
41080
41081                 }
41082
41083                 for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
41084
41085                         if ( buffer[ i ] !== buffer[ i + stride ] ) {
41086
41087                                 // value has changed -> update scene graph
41088
41089                                 binding.setValue( buffer, offset );
41090                                 break;
41091
41092                         }
41093
41094                 }
41095
41096         }
41097
41098         // remember the state of the bound property and copy it to both accus
41099         saveOriginalState() {
41100
41101                 const binding = this.binding;
41102
41103                 const buffer = this.buffer,
41104                         stride = this.valueSize,
41105
41106                         originalValueOffset = stride * this._origIndex;
41107
41108                 binding.getValue( buffer, originalValueOffset );
41109
41110                 // accu[0..1] := orig -- initially detect changes against the original
41111                 for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
41112
41113                         buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
41114
41115                 }
41116
41117                 // Add to identity for additive
41118                 this._setIdentity();
41119
41120                 this.cumulativeWeight = 0;
41121                 this.cumulativeWeightAdditive = 0;
41122
41123         }
41124
41125         // apply the state previously taken via 'saveOriginalState' to the binding
41126         restoreOriginalState() {
41127
41128                 const originalValueOffset = this.valueSize * 3;
41129                 this.binding.setValue( this.buffer, originalValueOffset );
41130
41131         }
41132
41133         _setAdditiveIdentityNumeric() {
41134
41135                 const startIndex = this._addIndex * this.valueSize;
41136                 const endIndex = startIndex + this.valueSize;
41137
41138                 for ( let i = startIndex; i < endIndex; i ++ ) {
41139
41140                         this.buffer[ i ] = 0;
41141
41142                 }
41143
41144         }
41145
41146         _setAdditiveIdentityQuaternion() {
41147
41148                 this._setAdditiveIdentityNumeric();
41149                 this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
41150
41151         }
41152
41153         _setAdditiveIdentityOther() {
41154
41155                 const startIndex = this._origIndex * this.valueSize;
41156                 const targetIndex = this._addIndex * this.valueSize;
41157
41158                 for ( let i = 0; i < this.valueSize; i ++ ) {
41159
41160                         this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
41161
41162                 }
41163
41164         }
41165
41166
41167         // mix functions
41168
41169         _select( buffer, dstOffset, srcOffset, t, stride ) {
41170
41171                 if ( t >= 0.5 ) {
41172
41173                         for ( let i = 0; i !== stride; ++ i ) {
41174
41175                                 buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
41176
41177                         }
41178
41179                 }
41180
41181         }
41182
41183         _slerp( buffer, dstOffset, srcOffset, t ) {
41184
41185                 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
41186
41187         }
41188
41189         _slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
41190
41191                 const workOffset = this._workIndex * stride;
41192
41193                 // Store result in intermediate buffer offset
41194                 Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
41195
41196                 // Slerp to the intermediate result
41197                 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
41198
41199         }
41200
41201         _lerp( buffer, dstOffset, srcOffset, t, stride ) {
41202
41203                 const s = 1 - t;
41204
41205                 for ( let i = 0; i !== stride; ++ i ) {
41206
41207                         const j = dstOffset + i;
41208
41209                         buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
41210
41211                 }
41212
41213         }
41214
41215         _lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
41216
41217                 for ( let i = 0; i !== stride; ++ i ) {
41218
41219                         const j = dstOffset + i;
41220
41221                         buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
41222
41223                 }
41224
41225         }
41226
41227     }
41228
41229     // Characters [].:/ are reserved for track binding syntax.
41230     const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
41231     const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
41232
41233     // Attempts to allow node names from any language. ES5's `\w` regexp matches
41234     // only latin characters, and the unicode \p{L} is not yet supported. So
41235     // instead, we exclude reserved characters and match everything else.
41236     const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
41237     const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
41238
41239     // Parent directories, delimited by '/' or ':'. Currently unused, but must
41240     // be matched to parse the rest of the track name.
41241     const _directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
41242
41243     // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
41244     const _nodeRe = /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
41245
41246     // Object on target node, and accessor. May not contain reserved
41247     // characters. Accessor may contain any character except closing bracket.
41248     const _objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
41249
41250     // Property and accessor. May not contain reserved characters. Accessor may
41251     // contain any non-bracket characters.
41252     const _propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
41253
41254     const _trackRe = new RegExp( ''
41255         + '^'
41256         + _directoryRe
41257         + _nodeRe
41258         + _objectRe
41259         + _propertyRe
41260         + '$'
41261     );
41262
41263     const _supportedObjectNames = [ 'material', 'materials', 'bones' ];
41264
41265     class Composite {
41266
41267         constructor( targetGroup, path, optionalParsedPath ) {
41268
41269                 const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
41270
41271                 this._targetGroup = targetGroup;
41272                 this._bindings = targetGroup.subscribe_( path, parsedPath );
41273
41274         }
41275
41276         getValue( array, offset ) {
41277
41278                 this.bind(); // bind all binding
41279
41280                 const firstValidIndex = this._targetGroup.nCachedObjects_,
41281                         binding = this._bindings[ firstValidIndex ];
41282
41283                 // and only call .getValue on the first
41284                 if ( binding !== undefined ) binding.getValue( array, offset );
41285
41286         }
41287
41288         setValue( array, offset ) {
41289
41290                 const bindings = this._bindings;
41291
41292                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
41293
41294                         bindings[ i ].setValue( array, offset );
41295
41296                 }
41297
41298         }
41299
41300         bind() {
41301
41302                 const bindings = this._bindings;
41303
41304                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
41305
41306                         bindings[ i ].bind();
41307
41308                 }
41309
41310         }
41311
41312         unbind() {
41313
41314                 const bindings = this._bindings;
41315
41316                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
41317
41318                         bindings[ i ].unbind();
41319
41320                 }
41321
41322         }
41323
41324     }
41325
41326     // Note: This class uses a State pattern on a per-method basis:
41327     // 'bind' sets 'this.getValue' / 'setValue' and shadows the
41328     // prototype version of these methods with one that represents
41329     // the bound state. When the property is not found, the methods
41330     // become no-ops.
41331     class PropertyBinding {
41332
41333         constructor( rootNode, path, parsedPath ) {
41334
41335                 this.path = path;
41336                 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
41337
41338                 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
41339
41340                 this.rootNode = rootNode;
41341
41342                 // initial state of these methods that calls 'bind'
41343                 this.getValue = this._getValue_unbound;
41344                 this.setValue = this._setValue_unbound;
41345
41346         }
41347
41348
41349         static create( root, path, parsedPath ) {
41350
41351                 if ( ! ( root && root.isAnimationObjectGroup ) ) {
41352
41353                         return new PropertyBinding( root, path, parsedPath );
41354
41355                 } else {
41356
41357                         return new PropertyBinding.Composite( root, path, parsedPath );
41358
41359                 }
41360
41361         }
41362
41363         /**
41364          * Replaces spaces with underscores and removes unsupported characters from
41365          * node names, to ensure compatibility with parseTrackName().
41366          *
41367          * @param {string} name Node name to be sanitized.
41368          * @return {string}
41369          */
41370         static sanitizeNodeName( name ) {
41371
41372                 return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
41373
41374         }
41375
41376         static parseTrackName( trackName ) {
41377
41378                 const matches = _trackRe.exec( trackName );
41379
41380                 if ( ! matches ) {
41381
41382                         throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
41383
41384                 }
41385
41386                 const results = {
41387                         // directoryName: matches[ 1 ], // (tschw) currently unused
41388                         nodeName: matches[ 2 ],
41389                         objectName: matches[ 3 ],
41390                         objectIndex: matches[ 4 ],
41391                         propertyName: matches[ 5 ], // required
41392                         propertyIndex: matches[ 6 ]
41393                 };
41394
41395                 const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
41396
41397                 if ( lastDot !== undefined && lastDot !== - 1 ) {
41398
41399                         const objectName = results.nodeName.substring( lastDot + 1 );
41400
41401                         // Object names must be checked against an allowlist. Otherwise, there
41402                         // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
41403                         // 'bar' could be the objectName, or part of a nodeName (which can
41404                         // include '.' characters).
41405                         if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
41406
41407                                 results.nodeName = results.nodeName.substring( 0, lastDot );
41408                                 results.objectName = objectName;
41409
41410                         }
41411
41412                 }
41413
41414                 if ( results.propertyName === null || results.propertyName.length === 0 ) {
41415
41416                         throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
41417
41418                 }
41419
41420                 return results;
41421
41422         }
41423
41424         static findNode( root, nodeName ) {
41425
41426                 if ( ! nodeName || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
41427
41428                         return root;
41429
41430                 }
41431
41432                 // search into skeleton bones.
41433                 if ( root.skeleton ) {
41434
41435                         const bone = root.skeleton.getBoneByName( nodeName );
41436
41437                         if ( bone !== undefined ) {
41438
41439                                 return bone;
41440
41441                         }
41442
41443                 }
41444
41445                 // search into node subtree.
41446                 if ( root.children ) {
41447
41448                         const searchNodeSubtree = function ( children ) {
41449
41450                                 for ( let i = 0; i < children.length; i ++ ) {
41451
41452                                         const childNode = children[ i ];
41453
41454                                         if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
41455
41456                                                 return childNode;
41457
41458                                         }
41459
41460                                         const result = searchNodeSubtree( childNode.children );
41461
41462                                         if ( result ) return result;
41463
41464                                 }
41465
41466                                 return null;
41467
41468                         };
41469
41470                         const subTreeNode = searchNodeSubtree( root.children );
41471
41472                         if ( subTreeNode ) {
41473
41474                                 return subTreeNode;
41475
41476                         }
41477
41478                 }
41479
41480                 return null;
41481
41482         }
41483
41484         // these are used to "bind" a nonexistent property
41485         _getValue_unavailable() {}
41486         _setValue_unavailable() {}
41487
41488         // Getters
41489
41490         _getValue_direct( buffer, offset ) {
41491
41492                 buffer[ offset ] = this.targetObject[ this.propertyName ];
41493
41494         }
41495
41496         _getValue_array( buffer, offset ) {
41497
41498                 const source = this.resolvedProperty;
41499
41500                 for ( let i = 0, n = source.length; i !== n; ++ i ) {
41501
41502                         buffer[ offset ++ ] = source[ i ];
41503
41504                 }
41505
41506         }
41507
41508         _getValue_arrayElement( buffer, offset ) {
41509
41510                 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
41511
41512         }
41513
41514         _getValue_toArray( buffer, offset ) {
41515
41516                 this.resolvedProperty.toArray( buffer, offset );
41517
41518         }
41519
41520         // Direct
41521
41522         _setValue_direct( buffer, offset ) {
41523
41524                 this.targetObject[ this.propertyName ] = buffer[ offset ];
41525
41526         }
41527
41528         _setValue_direct_setNeedsUpdate( buffer, offset ) {
41529
41530                 this.targetObject[ this.propertyName ] = buffer[ offset ];
41531                 this.targetObject.needsUpdate = true;
41532
41533         }
41534
41535         _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
41536
41537                 this.targetObject[ this.propertyName ] = buffer[ offset ];
41538                 this.targetObject.matrixWorldNeedsUpdate = true;
41539
41540         }
41541
41542         // EntireArray
41543
41544         _setValue_array( buffer, offset ) {
41545
41546                 const dest = this.resolvedProperty;
41547
41548                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
41549
41550                         dest[ i ] = buffer[ offset ++ ];
41551
41552                 }
41553
41554         }
41555
41556         _setValue_array_setNeedsUpdate( buffer, offset ) {
41557
41558                 const dest = this.resolvedProperty;
41559
41560                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
41561
41562                         dest[ i ] = buffer[ offset ++ ];
41563
41564                 }
41565
41566                 this.targetObject.needsUpdate = true;
41567
41568         }
41569
41570         _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
41571
41572                 const dest = this.resolvedProperty;
41573
41574                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
41575
41576                         dest[ i ] = buffer[ offset ++ ];
41577
41578                 }
41579
41580                 this.targetObject.matrixWorldNeedsUpdate = true;
41581
41582         }
41583
41584         // ArrayElement
41585
41586         _setValue_arrayElement( buffer, offset ) {
41587
41588                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
41589
41590         }
41591
41592         _setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
41593
41594                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
41595                 this.targetObject.needsUpdate = true;
41596
41597         }
41598
41599         _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
41600
41601                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
41602                 this.targetObject.matrixWorldNeedsUpdate = true;
41603
41604         }
41605
41606         // HasToFromArray
41607
41608         _setValue_fromArray( buffer, offset ) {
41609
41610                 this.resolvedProperty.fromArray( buffer, offset );
41611
41612         }
41613
41614         _setValue_fromArray_setNeedsUpdate( buffer, offset ) {
41615
41616                 this.resolvedProperty.fromArray( buffer, offset );
41617                 this.targetObject.needsUpdate = true;
41618
41619         }
41620
41621         _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
41622
41623                 this.resolvedProperty.fromArray( buffer, offset );
41624                 this.targetObject.matrixWorldNeedsUpdate = true;
41625
41626         }
41627
41628         _getValue_unbound( targetArray, offset ) {
41629
41630                 this.bind();
41631                 this.getValue( targetArray, offset );
41632
41633         }
41634
41635         _setValue_unbound( sourceArray, offset ) {
41636
41637                 this.bind();
41638                 this.setValue( sourceArray, offset );
41639
41640         }
41641
41642         // create getter / setter pair for a property in the scene graph
41643         bind() {
41644
41645                 let targetObject = this.node;
41646                 const parsedPath = this.parsedPath;
41647
41648                 const objectName = parsedPath.objectName;
41649                 const propertyName = parsedPath.propertyName;
41650                 let propertyIndex = parsedPath.propertyIndex;
41651
41652                 if ( ! targetObject ) {
41653
41654                         targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
41655
41656                         this.node = targetObject;
41657
41658                 }
41659
41660                 // set fail state so we can just 'return' on error
41661                 this.getValue = this._getValue_unavailable;
41662                 this.setValue = this._setValue_unavailable;
41663
41664                 // ensure there is a value node
41665                 if ( ! targetObject ) {
41666
41667                         console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
41668                         return;
41669
41670                 }
41671
41672                 if ( objectName ) {
41673
41674                         let objectIndex = parsedPath.objectIndex;
41675
41676                         // special cases were we need to reach deeper into the hierarchy to get the face materials....
41677                         switch ( objectName ) {
41678
41679                                 case 'materials':
41680
41681                                         if ( ! targetObject.material ) {
41682
41683                                                 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
41684                                                 return;
41685
41686                                         }
41687
41688                                         if ( ! targetObject.material.materials ) {
41689
41690                                                 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
41691                                                 return;
41692
41693                                         }
41694
41695                                         targetObject = targetObject.material.materials;
41696
41697                                         break;
41698
41699                                 case 'bones':
41700
41701                                         if ( ! targetObject.skeleton ) {
41702
41703                                                 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
41704                                                 return;
41705
41706                                         }
41707
41708                                         // potential future optimization: skip this if propertyIndex is already an integer
41709                                         // and convert the integer string to a true integer.
41710
41711                                         targetObject = targetObject.skeleton.bones;
41712
41713                                         // support resolving morphTarget names into indices.
41714                                         for ( let i = 0; i < targetObject.length; i ++ ) {
41715
41716                                                 if ( targetObject[ i ].name === objectIndex ) {
41717
41718                                                         objectIndex = i;
41719                                                         break;
41720
41721                                                 }
41722
41723                                         }
41724
41725                                         break;
41726
41727                                 default:
41728
41729                                         if ( targetObject[ objectName ] === undefined ) {
41730
41731                                                 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
41732                                                 return;
41733
41734                                         }
41735
41736                                         targetObject = targetObject[ objectName ];
41737
41738                         }
41739
41740
41741                         if ( objectIndex !== undefined ) {
41742
41743                                 if ( targetObject[ objectIndex ] === undefined ) {
41744
41745                                         console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
41746                                         return;
41747
41748                                 }
41749
41750                                 targetObject = targetObject[ objectIndex ];
41751
41752                         }
41753
41754                 }
41755
41756                 // resolve property
41757                 const nodeProperty = targetObject[ propertyName ];
41758
41759                 if ( nodeProperty === undefined ) {
41760
41761                         const nodeName = parsedPath.nodeName;
41762
41763                         console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
41764                                 '.' + propertyName + ' but it wasn\'t found.', targetObject );
41765                         return;
41766
41767                 }
41768
41769                 // determine versioning scheme
41770                 let versioning = this.Versioning.None;
41771
41772                 this.targetObject = targetObject;
41773
41774                 if ( targetObject.needsUpdate !== undefined ) { // material
41775
41776                         versioning = this.Versioning.NeedsUpdate;
41777
41778                 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
41779
41780                         versioning = this.Versioning.MatrixWorldNeedsUpdate;
41781
41782                 }
41783
41784                 // determine how the property gets bound
41785                 let bindingType = this.BindingType.Direct;
41786
41787                 if ( propertyIndex !== undefined ) {
41788
41789                         // access a sub element of the property array (only primitives are supported right now)
41790
41791                         if ( propertyName === 'morphTargetInfluences' ) {
41792
41793                                 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
41794
41795                                 // support resolving morphTarget names into indices.
41796                                 if ( ! targetObject.geometry ) {
41797
41798                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
41799                                         return;
41800
41801                                 }
41802
41803                                 if ( targetObject.geometry.isBufferGeometry ) {
41804
41805                                         if ( ! targetObject.geometry.morphAttributes ) {
41806
41807                                                 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
41808                                                 return;
41809
41810                                         }
41811
41812                                         if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
41813
41814                                                 propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
41815
41816                                         }
41817
41818
41819                                 } else {
41820
41821                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences on THREE.Geometry. Use THREE.BufferGeometry instead.', this );
41822                                         return;
41823
41824                                 }
41825
41826                         }
41827
41828                         bindingType = this.BindingType.ArrayElement;
41829
41830                         this.resolvedProperty = nodeProperty;
41831                         this.propertyIndex = propertyIndex;
41832
41833                 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
41834
41835                         // must use copy for Object3D.Euler/Quaternion
41836
41837                         bindingType = this.BindingType.HasFromToArray;
41838
41839                         this.resolvedProperty = nodeProperty;
41840
41841                 } else if ( Array.isArray( nodeProperty ) ) {
41842
41843                         bindingType = this.BindingType.EntireArray;
41844
41845                         this.resolvedProperty = nodeProperty;
41846
41847                 } else {
41848
41849                         this.propertyName = propertyName;
41850
41851                 }
41852
41853                 // select getter / setter
41854                 this.getValue = this.GetterByBindingType[ bindingType ];
41855                 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
41856
41857         }
41858
41859         unbind() {
41860
41861                 this.node = null;
41862
41863                 // back to the prototype version of getValue / setValue
41864                 // note: avoiding to mutate the shape of 'this' via 'delete'
41865                 this.getValue = this._getValue_unbound;
41866                 this.setValue = this._setValue_unbound;
41867
41868         }
41869
41870     }
41871
41872     PropertyBinding.Composite = Composite;
41873
41874     PropertyBinding.prototype.BindingType = {
41875         Direct: 0,
41876         EntireArray: 1,
41877         ArrayElement: 2,
41878         HasFromToArray: 3
41879     };
41880
41881     PropertyBinding.prototype.Versioning = {
41882         None: 0,
41883         NeedsUpdate: 1,
41884         MatrixWorldNeedsUpdate: 2
41885     };
41886
41887     PropertyBinding.prototype.GetterByBindingType = [
41888
41889         PropertyBinding.prototype._getValue_direct,
41890         PropertyBinding.prototype._getValue_array,
41891         PropertyBinding.prototype._getValue_arrayElement,
41892         PropertyBinding.prototype._getValue_toArray,
41893
41894     ];
41895
41896     PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
41897
41898         [
41899                 // Direct
41900                 PropertyBinding.prototype._setValue_direct,
41901                 PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
41902                 PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate,
41903
41904         ], [
41905
41906                 // EntireArray
41907
41908                 PropertyBinding.prototype._setValue_array,
41909                 PropertyBinding.prototype._setValue_array_setNeedsUpdate,
41910                 PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate,
41911
41912         ], [
41913
41914                 // ArrayElement
41915                 PropertyBinding.prototype._setValue_arrayElement,
41916                 PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
41917                 PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate,
41918
41919         ], [
41920
41921                 // HasToFromArray
41922                 PropertyBinding.prototype._setValue_fromArray,
41923                 PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
41924                 PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate,
41925
41926         ]
41927
41928     ];
41929
41930     class AnimationAction {
41931
41932         constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
41933
41934                 this._mixer = mixer;
41935                 this._clip = clip;
41936                 this._localRoot = localRoot;
41937                 this.blendMode = blendMode;
41938
41939                 const tracks = clip.tracks,
41940                         nTracks = tracks.length,
41941                         interpolants = new Array( nTracks );
41942
41943                 const interpolantSettings = {
41944                         endingStart: ZeroCurvatureEnding,
41945                         endingEnd: ZeroCurvatureEnding
41946                 };
41947
41948                 for ( let i = 0; i !== nTracks; ++ i ) {
41949
41950                         const interpolant = tracks[ i ].createInterpolant( null );
41951                         interpolants[ i ] = interpolant;
41952                         interpolant.settings = interpolantSettings;
41953
41954                 }
41955
41956                 this._interpolantSettings = interpolantSettings;
41957
41958                 this._interpolants = interpolants; // bound by the mixer
41959
41960                 // inside: PropertyMixer (managed by the mixer)
41961                 this._propertyBindings = new Array( nTracks );
41962
41963                 this._cacheIndex = null; // for the memory manager
41964                 this._byClipCacheIndex = null; // for the memory manager
41965
41966                 this._timeScaleInterpolant = null;
41967                 this._weightInterpolant = null;
41968
41969                 this.loop = LoopRepeat;
41970                 this._loopCount = - 1;
41971
41972                 // global mixer time when the action is to be started
41973                 // it's set back to 'null' upon start of the action
41974                 this._startTime = null;
41975
41976                 // scaled local time of the action
41977                 // gets clamped or wrapped to 0..clip.duration according to loop
41978                 this.time = 0;
41979
41980                 this.timeScale = 1;
41981                 this._effectiveTimeScale = 1;
41982
41983                 this.weight = 1;
41984                 this._effectiveWeight = 1;
41985
41986                 this.repetitions = Infinity; // no. of repetitions when looping
41987
41988                 this.paused = false; // true -> zero effective time scale
41989                 this.enabled = true; // false -> zero effective weight
41990
41991                 this.clampWhenFinished = false;// keep feeding the last frame?
41992
41993                 this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
41994                 this.zeroSlopeAtEnd = true;// clips for start, loop and end
41995
41996         }
41997
41998         // State & Scheduling
41999
42000         play() {
42001
42002                 this._mixer._activateAction( this );
42003
42004                 return this;
42005
42006         }
42007
42008         stop() {
42009
42010                 this._mixer._deactivateAction( this );
42011
42012                 return this.reset();
42013
42014         }
42015
42016         reset() {
42017
42018                 this.paused = false;
42019                 this.enabled = true;
42020
42021                 this.time = 0; // restart clip
42022                 this._loopCount = - 1;// forget previous loops
42023                 this._startTime = null;// forget scheduling
42024
42025                 return this.stopFading().stopWarping();
42026
42027         }
42028
42029         isRunning() {
42030
42031                 return this.enabled && ! this.paused && this.timeScale !== 0 &&
42032                         this._startTime === null && this._mixer._isActiveAction( this );
42033
42034         }
42035
42036         // return true when play has been called
42037         isScheduled() {
42038
42039                 return this._mixer._isActiveAction( this );
42040
42041         }
42042
42043         startAt( time ) {
42044
42045                 this._startTime = time;
42046
42047                 return this;
42048
42049         }
42050
42051         setLoop( mode, repetitions ) {
42052
42053                 this.loop = mode;
42054                 this.repetitions = repetitions;
42055
42056                 return this;
42057
42058         }
42059
42060         // Weight
42061
42062         // set the weight stopping any scheduled fading
42063         // although .enabled = false yields an effective weight of zero, this
42064         // method does *not* change .enabled, because it would be confusing
42065         setEffectiveWeight( weight ) {
42066
42067                 this.weight = weight;
42068
42069                 // note: same logic as when updated at runtime
42070                 this._effectiveWeight = this.enabled ? weight : 0;
42071
42072                 return this.stopFading();
42073
42074         }
42075
42076         // return the weight considering fading and .enabled
42077         getEffectiveWeight() {
42078
42079                 return this._effectiveWeight;
42080
42081         }
42082
42083         fadeIn( duration ) {
42084
42085                 return this._scheduleFading( duration, 0, 1 );
42086
42087         }
42088
42089         fadeOut( duration ) {
42090
42091                 return this._scheduleFading( duration, 1, 0 );
42092
42093         }
42094
42095         crossFadeFrom( fadeOutAction, duration, warp ) {
42096
42097                 fadeOutAction.fadeOut( duration );
42098                 this.fadeIn( duration );
42099
42100                 if ( warp ) {
42101
42102                         const fadeInDuration = this._clip.duration,
42103                                 fadeOutDuration = fadeOutAction._clip.duration,
42104
42105                                 startEndRatio = fadeOutDuration / fadeInDuration,
42106                                 endStartRatio = fadeInDuration / fadeOutDuration;
42107
42108                         fadeOutAction.warp( 1.0, startEndRatio, duration );
42109                         this.warp( endStartRatio, 1.0, duration );
42110
42111                 }
42112
42113                 return this;
42114
42115         }
42116
42117         crossFadeTo( fadeInAction, duration, warp ) {
42118
42119                 return fadeInAction.crossFadeFrom( this, duration, warp );
42120
42121         }
42122
42123         stopFading() {
42124
42125                 const weightInterpolant = this._weightInterpolant;
42126
42127                 if ( weightInterpolant !== null ) {
42128
42129                         this._weightInterpolant = null;
42130                         this._mixer._takeBackControlInterpolant( weightInterpolant );
42131
42132                 }
42133
42134                 return this;
42135
42136         }
42137
42138         // Time Scale Control
42139
42140         // set the time scale stopping any scheduled warping
42141         // although .paused = true yields an effective time scale of zero, this
42142         // method does *not* change .paused, because it would be confusing
42143         setEffectiveTimeScale( timeScale ) {
42144
42145                 this.timeScale = timeScale;
42146                 this._effectiveTimeScale = this.paused ? 0 : timeScale;
42147
42148                 return this.stopWarping();
42149
42150         }
42151
42152         // return the time scale considering warping and .paused
42153         getEffectiveTimeScale() {
42154
42155                 return this._effectiveTimeScale;
42156
42157         }
42158
42159         setDuration( duration ) {
42160
42161                 this.timeScale = this._clip.duration / duration;
42162
42163                 return this.stopWarping();
42164
42165         }
42166
42167         syncWith( action ) {
42168
42169                 this.time = action.time;
42170                 this.timeScale = action.timeScale;
42171
42172                 return this.stopWarping();
42173
42174         }
42175
42176         halt( duration ) {
42177
42178                 return this.warp( this._effectiveTimeScale, 0, duration );
42179
42180         }
42181
42182         warp( startTimeScale, endTimeScale, duration ) {
42183
42184                 const mixer = this._mixer,
42185                         now = mixer.time,
42186                         timeScale = this.timeScale;
42187
42188                 let interpolant = this._timeScaleInterpolant;
42189
42190                 if ( interpolant === null ) {
42191
42192                         interpolant = mixer._lendControlInterpolant();
42193                         this._timeScaleInterpolant = interpolant;
42194
42195                 }
42196
42197                 const times = interpolant.parameterPositions,
42198                         values = interpolant.sampleValues;
42199
42200                 times[ 0 ] = now;
42201                 times[ 1 ] = now + duration;
42202
42203                 values[ 0 ] = startTimeScale / timeScale;
42204                 values[ 1 ] = endTimeScale / timeScale;
42205
42206                 return this;
42207
42208         }
42209
42210         stopWarping() {
42211
42212                 const timeScaleInterpolant = this._timeScaleInterpolant;
42213
42214                 if ( timeScaleInterpolant !== null ) {
42215
42216                         this._timeScaleInterpolant = null;
42217                         this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
42218
42219                 }
42220
42221                 return this;
42222
42223         }
42224
42225         // Object Accessors
42226
42227         getMixer() {
42228
42229                 return this._mixer;
42230
42231         }
42232
42233         getClip() {
42234
42235                 return this._clip;
42236
42237         }
42238
42239         getRoot() {
42240
42241                 return this._localRoot || this._mixer._root;
42242
42243         }
42244
42245         // Interna
42246
42247         _update( time, deltaTime, timeDirection, accuIndex ) {
42248
42249                 // called by the mixer
42250
42251                 if ( ! this.enabled ) {
42252
42253                         // call ._updateWeight() to update ._effectiveWeight
42254
42255                         this._updateWeight( time );
42256                         return;
42257
42258                 }
42259
42260                 const startTime = this._startTime;
42261
42262                 if ( startTime !== null ) {
42263
42264                         // check for scheduled start of action
42265
42266                         const timeRunning = ( time - startTime ) * timeDirection;
42267                         if ( timeRunning < 0 || timeDirection === 0 ) {
42268
42269                                 return; // yet to come / don't decide when delta = 0
42270
42271                         }
42272
42273                         // start
42274
42275                         this._startTime = null; // unschedule
42276                         deltaTime = timeDirection * timeRunning;
42277
42278                 }
42279
42280                 // apply time scale and advance time
42281
42282                 deltaTime *= this._updateTimeScale( time );
42283                 const clipTime = this._updateTime( deltaTime );
42284
42285                 // note: _updateTime may disable the action resulting in
42286                 // an effective weight of 0
42287
42288                 const weight = this._updateWeight( time );
42289
42290                 if ( weight > 0 ) {
42291
42292                         const interpolants = this._interpolants;
42293                         const propertyMixers = this._propertyBindings;
42294
42295                         switch ( this.blendMode ) {
42296
42297                                 case AdditiveAnimationBlendMode:
42298
42299                                         for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
42300
42301                                                 interpolants[ j ].evaluate( clipTime );
42302                                                 propertyMixers[ j ].accumulateAdditive( weight );
42303
42304                                         }
42305
42306                                         break;
42307
42308                                 case NormalAnimationBlendMode:
42309                                 default:
42310
42311                                         for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
42312
42313                                                 interpolants[ j ].evaluate( clipTime );
42314                                                 propertyMixers[ j ].accumulate( accuIndex, weight );
42315
42316                                         }
42317
42318                         }
42319
42320                 }
42321
42322         }
42323
42324         _updateWeight( time ) {
42325
42326                 let weight = 0;
42327
42328                 if ( this.enabled ) {
42329
42330                         weight = this.weight;
42331                         const interpolant = this._weightInterpolant;
42332
42333                         if ( interpolant !== null ) {
42334
42335                                 const interpolantValue = interpolant.evaluate( time )[ 0 ];
42336
42337                                 weight *= interpolantValue;
42338
42339                                 if ( time > interpolant.parameterPositions[ 1 ] ) {
42340
42341                                         this.stopFading();
42342
42343                                         if ( interpolantValue === 0 ) {
42344
42345                                                 // faded out, disable
42346                                                 this.enabled = false;
42347
42348                                         }
42349
42350                                 }
42351
42352                         }
42353
42354                 }
42355
42356                 this._effectiveWeight = weight;
42357                 return weight;
42358
42359         }
42360
42361         _updateTimeScale( time ) {
42362
42363                 let timeScale = 0;
42364
42365                 if ( ! this.paused ) {
42366
42367                         timeScale = this.timeScale;
42368
42369                         const interpolant = this._timeScaleInterpolant;
42370
42371                         if ( interpolant !== null ) {
42372
42373                                 const interpolantValue = interpolant.evaluate( time )[ 0 ];
42374
42375                                 timeScale *= interpolantValue;
42376
42377                                 if ( time > interpolant.parameterPositions[ 1 ] ) {
42378
42379                                         this.stopWarping();
42380
42381                                         if ( timeScale === 0 ) {
42382
42383                                                 // motion has halted, pause
42384                                                 this.paused = true;
42385
42386                                         } else {
42387
42388                                                 // warp done - apply final time scale
42389                                                 this.timeScale = timeScale;
42390
42391                                         }
42392
42393                                 }
42394
42395                         }
42396
42397                 }
42398
42399                 this._effectiveTimeScale = timeScale;
42400                 return timeScale;
42401
42402         }
42403
42404         _updateTime( deltaTime ) {
42405
42406                 const duration = this._clip.duration;
42407                 const loop = this.loop;
42408
42409                 let time = this.time + deltaTime;
42410                 let loopCount = this._loopCount;
42411
42412                 const pingPong = ( loop === LoopPingPong );
42413
42414                 if ( deltaTime === 0 ) {
42415
42416                         if ( loopCount === - 1 ) return time;
42417
42418                         return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
42419
42420                 }
42421
42422                 if ( loop === LoopOnce ) {
42423
42424                         if ( loopCount === - 1 ) {
42425
42426                                 // just started
42427
42428                                 this._loopCount = 0;
42429                                 this._setEndings( true, true, false );
42430
42431                         }
42432
42433                         handle_stop: {
42434
42435                                 if ( time >= duration ) {
42436
42437                                         time = duration;
42438
42439                                 } else if ( time < 0 ) {
42440
42441                                         time = 0;
42442
42443                                 } else {
42444
42445                                         this.time = time;
42446
42447                                         break handle_stop;
42448
42449                                 }
42450
42451                                 if ( this.clampWhenFinished ) this.paused = true;
42452                                 else this.enabled = false;
42453
42454                                 this.time = time;
42455
42456                                 this._mixer.dispatchEvent( {
42457                                         type: 'finished', action: this,
42458                                         direction: deltaTime < 0 ? - 1 : 1
42459                                 } );
42460
42461                         }
42462
42463                 } else { // repetitive Repeat or PingPong
42464
42465                         if ( loopCount === - 1 ) {
42466
42467                                 // just started
42468
42469                                 if ( deltaTime >= 0 ) {
42470
42471                                         loopCount = 0;
42472
42473                                         this._setEndings( true, this.repetitions === 0, pingPong );
42474
42475                                 } else {
42476
42477                                         // when looping in reverse direction, the initial
42478                                         // transition through zero counts as a repetition,
42479                                         // so leave loopCount at -1
42480
42481                                         this._setEndings( this.repetitions === 0, true, pingPong );
42482
42483                                 }
42484
42485                         }
42486
42487                         if ( time >= duration || time < 0 ) {
42488
42489                                 // wrap around
42490
42491                                 const loopDelta = Math.floor( time / duration ); // signed
42492                                 time -= duration * loopDelta;
42493
42494                                 loopCount += Math.abs( loopDelta );
42495
42496                                 const pending = this.repetitions - loopCount;
42497
42498                                 if ( pending <= 0 ) {
42499
42500                                         // have to stop (switch state, clamp time, fire event)
42501
42502                                         if ( this.clampWhenFinished ) this.paused = true;
42503                                         else this.enabled = false;
42504
42505                                         time = deltaTime > 0 ? duration : 0;
42506
42507                                         this.time = time;
42508
42509                                         this._mixer.dispatchEvent( {
42510                                                 type: 'finished', action: this,
42511                                                 direction: deltaTime > 0 ? 1 : - 1
42512                                         } );
42513
42514                                 } else {
42515
42516                                         // keep running
42517
42518                                         if ( pending === 1 ) {
42519
42520                                                 // entering the last round
42521
42522                                                 const atStart = deltaTime < 0;
42523                                                 this._setEndings( atStart, ! atStart, pingPong );
42524
42525                                         } else {
42526
42527                                                 this._setEndings( false, false, pingPong );
42528
42529                                         }
42530
42531                                         this._loopCount = loopCount;
42532
42533                                         this.time = time;
42534
42535                                         this._mixer.dispatchEvent( {
42536                                                 type: 'loop', action: this, loopDelta: loopDelta
42537                                         } );
42538
42539                                 }
42540
42541                         } else {
42542
42543                                 this.time = time;
42544
42545                         }
42546
42547                         if ( pingPong && ( loopCount & 1 ) === 1 ) {
42548
42549                                 // invert time for the "pong round"
42550
42551                                 return duration - time;
42552
42553                         }
42554
42555                 }
42556
42557                 return time;
42558
42559         }
42560
42561         _setEndings( atStart, atEnd, pingPong ) {
42562
42563                 const settings = this._interpolantSettings;
42564
42565                 if ( pingPong ) {
42566
42567                         settings.endingStart = ZeroSlopeEnding;
42568                         settings.endingEnd = ZeroSlopeEnding;
42569
42570                 } else {
42571
42572                         // assuming for LoopOnce atStart == atEnd == true
42573
42574                         if ( atStart ) {
42575
42576                                 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
42577
42578                         } else {
42579
42580                                 settings.endingStart = WrapAroundEnding;
42581
42582                         }
42583
42584                         if ( atEnd ) {
42585
42586                                 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
42587
42588                         } else {
42589
42590                                 settings.endingEnd       = WrapAroundEnding;
42591
42592                         }
42593
42594                 }
42595
42596         }
42597
42598         _scheduleFading( duration, weightNow, weightThen ) {
42599
42600                 const mixer = this._mixer, now = mixer.time;
42601                 let interpolant = this._weightInterpolant;
42602
42603                 if ( interpolant === null ) {
42604
42605                         interpolant = mixer._lendControlInterpolant();
42606                         this._weightInterpolant = interpolant;
42607
42608                 }
42609
42610                 const times = interpolant.parameterPositions,
42611                         values = interpolant.sampleValues;
42612
42613                 times[ 0 ] = now;
42614                 values[ 0 ] = weightNow;
42615                 times[ 1 ] = now + duration;
42616                 values[ 1 ] = weightThen;
42617
42618                 return this;
42619
42620         }
42621
42622     }
42623
42624     class AnimationMixer extends EventDispatcher {
42625
42626         constructor( root ) {
42627
42628                 super();
42629
42630                 this._root = root;
42631                 this._initMemoryManager();
42632                 this._accuIndex = 0;
42633                 this.time = 0;
42634                 this.timeScale = 1.0;
42635
42636         }
42637
42638         _bindAction( action, prototypeAction ) {
42639
42640                 const root = action._localRoot || this._root,
42641                         tracks = action._clip.tracks,
42642                         nTracks = tracks.length,
42643                         bindings = action._propertyBindings,
42644                         interpolants = action._interpolants,
42645                         rootUuid = root.uuid,
42646                         bindingsByRoot = this._bindingsByRootAndName;
42647
42648                 let bindingsByName = bindingsByRoot[ rootUuid ];
42649
42650                 if ( bindingsByName === undefined ) {
42651
42652                         bindingsByName = {};
42653                         bindingsByRoot[ rootUuid ] = bindingsByName;
42654
42655                 }
42656
42657                 for ( let i = 0; i !== nTracks; ++ i ) {
42658
42659                         const track = tracks[ i ],
42660                                 trackName = track.name;
42661
42662                         let binding = bindingsByName[ trackName ];
42663
42664                         if ( binding !== undefined ) {
42665
42666                                 bindings[ i ] = binding;
42667
42668                         } else {
42669
42670                                 binding = bindings[ i ];
42671
42672                                 if ( binding !== undefined ) {
42673
42674                                         // existing binding, make sure the cache knows
42675
42676                                         if ( binding._cacheIndex === null ) {
42677
42678                                                 ++ binding.referenceCount;
42679                                                 this._addInactiveBinding( binding, rootUuid, trackName );
42680
42681                                         }
42682
42683                                         continue;
42684
42685                                 }
42686
42687                                 const path = prototypeAction && prototypeAction.
42688                                         _propertyBindings[ i ].binding.parsedPath;
42689
42690                                 binding = new PropertyMixer(
42691                                         PropertyBinding.create( root, trackName, path ),
42692                                         track.ValueTypeName, track.getValueSize() );
42693
42694                                 ++ binding.referenceCount;
42695                                 this._addInactiveBinding( binding, rootUuid, trackName );
42696
42697                                 bindings[ i ] = binding;
42698
42699                         }
42700
42701                         interpolants[ i ].resultBuffer = binding.buffer;
42702
42703                 }
42704
42705         }
42706
42707         _activateAction( action ) {
42708
42709                 if ( ! this._isActiveAction( action ) ) {
42710
42711                         if ( action._cacheIndex === null ) {
42712
42713                                 // this action has been forgotten by the cache, but the user
42714                                 // appears to be still using it -> rebind
42715
42716                                 const rootUuid = ( action._localRoot || this._root ).uuid,
42717                                         clipUuid = action._clip.uuid,
42718                                         actionsForClip = this._actionsByClip[ clipUuid ];
42719
42720                                 this._bindAction( action,
42721                                         actionsForClip && actionsForClip.knownActions[ 0 ] );
42722
42723                                 this._addInactiveAction( action, clipUuid, rootUuid );
42724
42725                         }
42726
42727                         const bindings = action._propertyBindings;
42728
42729                         // increment reference counts / sort out state
42730                         for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
42731
42732                                 const binding = bindings[ i ];
42733
42734                                 if ( binding.useCount ++ === 0 ) {
42735
42736                                         this._lendBinding( binding );
42737                                         binding.saveOriginalState();
42738
42739                                 }
42740
42741                         }
42742
42743                         this._lendAction( action );
42744
42745                 }
42746
42747         }
42748
42749         _deactivateAction( action ) {
42750
42751                 if ( this._isActiveAction( action ) ) {
42752
42753                         const bindings = action._propertyBindings;
42754
42755                         // decrement reference counts / sort out state
42756                         for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
42757
42758                                 const binding = bindings[ i ];
42759
42760                                 if ( -- binding.useCount === 0 ) {
42761
42762                                         binding.restoreOriginalState();
42763                                         this._takeBackBinding( binding );
42764
42765                                 }
42766
42767                         }
42768
42769                         this._takeBackAction( action );
42770
42771                 }
42772
42773         }
42774
42775         // Memory manager
42776
42777         _initMemoryManager() {
42778
42779                 this._actions = []; // 'nActiveActions' followed by inactive ones
42780                 this._nActiveActions = 0;
42781
42782                 this._actionsByClip = {};
42783                 // inside:
42784                 // {
42785                 //      knownActions: Array< AnimationAction > - used as prototypes
42786                 //      actionByRoot: AnimationAction - lookup
42787                 // }
42788
42789
42790                 this._bindings = []; // 'nActiveBindings' followed by inactive ones
42791                 this._nActiveBindings = 0;
42792
42793                 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
42794
42795
42796                 this._controlInterpolants = []; // same game as above
42797                 this._nActiveControlInterpolants = 0;
42798
42799                 const scope = this;
42800
42801                 this.stats = {
42802
42803                         actions: {
42804                                 get total() {
42805
42806                                         return scope._actions.length;
42807
42808                                 },
42809                                 get inUse() {
42810
42811                                         return scope._nActiveActions;
42812
42813                                 }
42814                         },
42815                         bindings: {
42816                                 get total() {
42817
42818                                         return scope._bindings.length;
42819
42820                                 },
42821                                 get inUse() {
42822
42823                                         return scope._nActiveBindings;
42824
42825                                 }
42826                         },
42827                         controlInterpolants: {
42828                                 get total() {
42829
42830                                         return scope._controlInterpolants.length;
42831
42832                                 },
42833                                 get inUse() {
42834
42835                                         return scope._nActiveControlInterpolants;
42836
42837                                 }
42838                         }
42839
42840                 };
42841
42842         }
42843
42844         // Memory management for AnimationAction objects
42845
42846         _isActiveAction( action ) {
42847
42848                 const index = action._cacheIndex;
42849                 return index !== null && index < this._nActiveActions;
42850
42851         }
42852
42853         _addInactiveAction( action, clipUuid, rootUuid ) {
42854
42855                 const actions = this._actions,
42856                         actionsByClip = this._actionsByClip;
42857
42858                 let actionsForClip = actionsByClip[ clipUuid ];
42859
42860                 if ( actionsForClip === undefined ) {
42861
42862                         actionsForClip = {
42863
42864                                 knownActions: [ action ],
42865                                 actionByRoot: {}
42866
42867                         };
42868
42869                         action._byClipCacheIndex = 0;
42870
42871                         actionsByClip[ clipUuid ] = actionsForClip;
42872
42873                 } else {
42874
42875                         const knownActions = actionsForClip.knownActions;
42876
42877                         action._byClipCacheIndex = knownActions.length;
42878                         knownActions.push( action );
42879
42880                 }
42881
42882                 action._cacheIndex = actions.length;
42883                 actions.push( action );
42884
42885                 actionsForClip.actionByRoot[ rootUuid ] = action;
42886
42887         }
42888
42889         _removeInactiveAction( action ) {
42890
42891                 const actions = this._actions,
42892                         lastInactiveAction = actions[ actions.length - 1 ],
42893                         cacheIndex = action._cacheIndex;
42894
42895                 lastInactiveAction._cacheIndex = cacheIndex;
42896                 actions[ cacheIndex ] = lastInactiveAction;
42897                 actions.pop();
42898
42899                 action._cacheIndex = null;
42900
42901
42902                 const clipUuid = action._clip.uuid,
42903                         actionsByClip = this._actionsByClip,
42904                         actionsForClip = actionsByClip[ clipUuid ],
42905                         knownActionsForClip = actionsForClip.knownActions,
42906
42907                         lastKnownAction =
42908                                 knownActionsForClip[ knownActionsForClip.length - 1 ],
42909
42910                         byClipCacheIndex = action._byClipCacheIndex;
42911
42912                 lastKnownAction._byClipCacheIndex = byClipCacheIndex;
42913                 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
42914                 knownActionsForClip.pop();
42915
42916                 action._byClipCacheIndex = null;
42917
42918
42919                 const actionByRoot = actionsForClip.actionByRoot,
42920                         rootUuid = ( action._localRoot || this._root ).uuid;
42921
42922                 delete actionByRoot[ rootUuid ];
42923
42924                 if ( knownActionsForClip.length === 0 ) {
42925
42926                         delete actionsByClip[ clipUuid ];
42927
42928                 }
42929
42930                 this._removeInactiveBindingsForAction( action );
42931
42932         }
42933
42934         _removeInactiveBindingsForAction( action ) {
42935
42936                 const bindings = action._propertyBindings;
42937
42938                 for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
42939
42940                         const binding = bindings[ i ];
42941
42942                         if ( -- binding.referenceCount === 0 ) {
42943
42944                                 this._removeInactiveBinding( binding );
42945
42946                         }
42947
42948                 }
42949
42950         }
42951
42952         _lendAction( action ) {
42953
42954                 // [ active actions |  inactive actions  ]
42955                 // [  active actions >| inactive actions ]
42956                 //                 s        a
42957                 //                  <-swap->
42958                 //                 a        s
42959
42960                 const actions = this._actions,
42961                         prevIndex = action._cacheIndex,
42962
42963                         lastActiveIndex = this._nActiveActions ++,
42964
42965                         firstInactiveAction = actions[ lastActiveIndex ];
42966
42967                 action._cacheIndex = lastActiveIndex;
42968                 actions[ lastActiveIndex ] = action;
42969
42970                 firstInactiveAction._cacheIndex = prevIndex;
42971                 actions[ prevIndex ] = firstInactiveAction;
42972
42973         }
42974
42975         _takeBackAction( action ) {
42976
42977                 // [  active actions  | inactive actions ]
42978                 // [ active actions |< inactive actions  ]
42979                 //        a        s
42980                 //         <-swap->
42981                 //        s        a
42982
42983                 const actions = this._actions,
42984                         prevIndex = action._cacheIndex,
42985
42986                         firstInactiveIndex = -- this._nActiveActions,
42987
42988                         lastActiveAction = actions[ firstInactiveIndex ];
42989
42990                 action._cacheIndex = firstInactiveIndex;
42991                 actions[ firstInactiveIndex ] = action;
42992
42993                 lastActiveAction._cacheIndex = prevIndex;
42994                 actions[ prevIndex ] = lastActiveAction;
42995
42996         }
42997
42998         // Memory management for PropertyMixer objects
42999
43000         _addInactiveBinding( binding, rootUuid, trackName ) {
43001
43002                 const bindingsByRoot = this._bindingsByRootAndName,
43003                         bindings = this._bindings;
43004
43005                 let bindingByName = bindingsByRoot[ rootUuid ];
43006
43007                 if ( bindingByName === undefined ) {
43008
43009                         bindingByName = {};
43010                         bindingsByRoot[ rootUuid ] = bindingByName;
43011
43012                 }
43013
43014                 bindingByName[ trackName ] = binding;
43015
43016                 binding._cacheIndex = bindings.length;
43017                 bindings.push( binding );
43018
43019         }
43020
43021         _removeInactiveBinding( binding ) {
43022
43023                 const bindings = this._bindings,
43024                         propBinding = binding.binding,
43025                         rootUuid = propBinding.rootNode.uuid,
43026                         trackName = propBinding.path,
43027                         bindingsByRoot = this._bindingsByRootAndName,
43028                         bindingByName = bindingsByRoot[ rootUuid ],
43029
43030                         lastInactiveBinding = bindings[ bindings.length - 1 ],
43031                         cacheIndex = binding._cacheIndex;
43032
43033                 lastInactiveBinding._cacheIndex = cacheIndex;
43034                 bindings[ cacheIndex ] = lastInactiveBinding;
43035                 bindings.pop();
43036
43037                 delete bindingByName[ trackName ];
43038
43039                 if ( Object.keys( bindingByName ).length === 0 ) {
43040
43041                         delete bindingsByRoot[ rootUuid ];
43042
43043                 }
43044
43045         }
43046
43047         _lendBinding( binding ) {
43048
43049                 const bindings = this._bindings,
43050                         prevIndex = binding._cacheIndex,
43051
43052                         lastActiveIndex = this._nActiveBindings ++,
43053
43054                         firstInactiveBinding = bindings[ lastActiveIndex ];
43055
43056                 binding._cacheIndex = lastActiveIndex;
43057                 bindings[ lastActiveIndex ] = binding;
43058
43059                 firstInactiveBinding._cacheIndex = prevIndex;
43060                 bindings[ prevIndex ] = firstInactiveBinding;
43061
43062         }
43063
43064         _takeBackBinding( binding ) {
43065
43066                 const bindings = this._bindings,
43067                         prevIndex = binding._cacheIndex,
43068
43069                         firstInactiveIndex = -- this._nActiveBindings,
43070
43071                         lastActiveBinding = bindings[ firstInactiveIndex ];
43072
43073                 binding._cacheIndex = firstInactiveIndex;
43074                 bindings[ firstInactiveIndex ] = binding;
43075
43076                 lastActiveBinding._cacheIndex = prevIndex;
43077                 bindings[ prevIndex ] = lastActiveBinding;
43078
43079         }
43080
43081
43082         // Memory management of Interpolants for weight and time scale
43083
43084         _lendControlInterpolant() {
43085
43086                 const interpolants = this._controlInterpolants,
43087                         lastActiveIndex = this._nActiveControlInterpolants ++;
43088
43089                 let interpolant = interpolants[ lastActiveIndex ];
43090
43091                 if ( interpolant === undefined ) {
43092
43093                         interpolant = new LinearInterpolant(
43094                                 new Float32Array( 2 ), new Float32Array( 2 ),
43095                                 1, this._controlInterpolantsResultBuffer );
43096
43097                         interpolant.__cacheIndex = lastActiveIndex;
43098                         interpolants[ lastActiveIndex ] = interpolant;
43099
43100                 }
43101
43102                 return interpolant;
43103
43104         }
43105
43106         _takeBackControlInterpolant( interpolant ) {
43107
43108                 const interpolants = this._controlInterpolants,
43109                         prevIndex = interpolant.__cacheIndex,
43110
43111                         firstInactiveIndex = -- this._nActiveControlInterpolants,
43112
43113                         lastActiveInterpolant = interpolants[ firstInactiveIndex ];
43114
43115                 interpolant.__cacheIndex = firstInactiveIndex;
43116                 interpolants[ firstInactiveIndex ] = interpolant;
43117
43118                 lastActiveInterpolant.__cacheIndex = prevIndex;
43119                 interpolants[ prevIndex ] = lastActiveInterpolant;
43120
43121         }
43122
43123         // return an action for a clip optionally using a custom root target
43124         // object (this method allocates a lot of dynamic memory in case a
43125         // previously unknown clip/root combination is specified)
43126         clipAction( clip, optionalRoot, blendMode ) {
43127
43128                 const root = optionalRoot || this._root,
43129                         rootUuid = root.uuid;
43130
43131                 let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
43132
43133                 const clipUuid = clipObject !== null ? clipObject.uuid : clip;
43134
43135                 const actionsForClip = this._actionsByClip[ clipUuid ];
43136                 let prototypeAction = null;
43137
43138                 if ( blendMode === undefined ) {
43139
43140                         if ( clipObject !== null ) {
43141
43142                                 blendMode = clipObject.blendMode;
43143
43144                         } else {
43145
43146                                 blendMode = NormalAnimationBlendMode;
43147
43148                         }
43149
43150                 }
43151
43152                 if ( actionsForClip !== undefined ) {
43153
43154                         const existingAction = actionsForClip.actionByRoot[ rootUuid ];
43155
43156                         if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
43157
43158                                 return existingAction;
43159
43160                         }
43161
43162                         // we know the clip, so we don't have to parse all
43163                         // the bindings again but can just copy
43164                         prototypeAction = actionsForClip.knownActions[ 0 ];
43165
43166                         // also, take the clip from the prototype action
43167                         if ( clipObject === null )
43168                                 clipObject = prototypeAction._clip;
43169
43170                 }
43171
43172                 // clip must be known when specified via string
43173                 if ( clipObject === null ) return null;
43174
43175                 // allocate all resources required to run it
43176                 const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
43177
43178                 this._bindAction( newAction, prototypeAction );
43179
43180                 // and make the action known to the memory manager
43181                 this._addInactiveAction( newAction, clipUuid, rootUuid );
43182
43183                 return newAction;
43184
43185         }
43186
43187         // get an existing action
43188         existingAction( clip, optionalRoot ) {
43189
43190                 const root = optionalRoot || this._root,
43191                         rootUuid = root.uuid,
43192
43193                         clipObject = typeof clip === 'string' ?
43194                                 AnimationClip.findByName( root, clip ) : clip,
43195
43196                         clipUuid = clipObject ? clipObject.uuid : clip,
43197
43198                         actionsForClip = this._actionsByClip[ clipUuid ];
43199
43200                 if ( actionsForClip !== undefined ) {
43201
43202                         return actionsForClip.actionByRoot[ rootUuid ] || null;
43203
43204                 }
43205
43206                 return null;
43207
43208         }
43209
43210         // deactivates all previously scheduled actions
43211         stopAllAction() {
43212
43213                 const actions = this._actions,
43214                         nActions = this._nActiveActions;
43215
43216                 for ( let i = nActions - 1; i >= 0; -- i ) {
43217
43218                         actions[ i ].stop();
43219
43220                 }
43221
43222                 return this;
43223
43224         }
43225
43226         // advance the time and update apply the animation
43227         update( deltaTime ) {
43228
43229                 deltaTime *= this.timeScale;
43230
43231                 const actions = this._actions,
43232                         nActions = this._nActiveActions,
43233
43234                         time = this.time += deltaTime,
43235                         timeDirection = Math.sign( deltaTime ),
43236
43237                         accuIndex = this._accuIndex ^= 1;
43238
43239                 // run active actions
43240
43241                 for ( let i = 0; i !== nActions; ++ i ) {
43242
43243                         const action = actions[ i ];
43244
43245                         action._update( time, deltaTime, timeDirection, accuIndex );
43246
43247                 }
43248
43249                 // update scene graph
43250
43251                 const bindings = this._bindings,
43252                         nBindings = this._nActiveBindings;
43253
43254                 for ( let i = 0; i !== nBindings; ++ i ) {
43255
43256                         bindings[ i ].apply( accuIndex );
43257
43258                 }
43259
43260                 return this;
43261
43262         }
43263
43264         // Allows you to seek to a specific time in an animation.
43265         setTime( timeInSeconds ) {
43266
43267                 this.time = 0; // Zero out time attribute for AnimationMixer object;
43268                 for ( let i = 0; i < this._actions.length; i ++ ) {
43269
43270                         this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
43271
43272                 }
43273
43274                 return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
43275
43276         }
43277
43278         // return this mixer's root target object
43279         getRoot() {
43280
43281                 return this._root;
43282
43283         }
43284
43285         // free all resources specific to a particular clip
43286         uncacheClip( clip ) {
43287
43288                 const actions = this._actions,
43289                         clipUuid = clip.uuid,
43290                         actionsByClip = this._actionsByClip,
43291                         actionsForClip = actionsByClip[ clipUuid ];
43292
43293                 if ( actionsForClip !== undefined ) {
43294
43295                         // note: just calling _removeInactiveAction would mess up the
43296                         // iteration state and also require updating the state we can
43297                         // just throw away
43298
43299                         const actionsToRemove = actionsForClip.knownActions;
43300
43301                         for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
43302
43303                                 const action = actionsToRemove[ i ];
43304
43305                                 this._deactivateAction( action );
43306
43307                                 const cacheIndex = action._cacheIndex,
43308                                         lastInactiveAction = actions[ actions.length - 1 ];
43309
43310                                 action._cacheIndex = null;
43311                                 action._byClipCacheIndex = null;
43312
43313                                 lastInactiveAction._cacheIndex = cacheIndex;
43314                                 actions[ cacheIndex ] = lastInactiveAction;
43315                                 actions.pop();
43316
43317                                 this._removeInactiveBindingsForAction( action );
43318
43319                         }
43320
43321                         delete actionsByClip[ clipUuid ];
43322
43323                 }
43324
43325         }
43326
43327         // free all resources specific to a particular root target object
43328         uncacheRoot( root ) {
43329
43330                 const rootUuid = root.uuid,
43331                         actionsByClip = this._actionsByClip;
43332
43333                 for ( const clipUuid in actionsByClip ) {
43334
43335                         const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
43336                                 action = actionByRoot[ rootUuid ];
43337
43338                         if ( action !== undefined ) {
43339
43340                                 this._deactivateAction( action );
43341                                 this._removeInactiveAction( action );
43342
43343                         }
43344
43345                 }
43346
43347                 const bindingsByRoot = this._bindingsByRootAndName,
43348                         bindingByName = bindingsByRoot[ rootUuid ];
43349
43350                 if ( bindingByName !== undefined ) {
43351
43352                         for ( const trackName in bindingByName ) {
43353
43354                                 const binding = bindingByName[ trackName ];
43355                                 binding.restoreOriginalState();
43356                                 this._removeInactiveBinding( binding );
43357
43358                         }
43359
43360                 }
43361
43362         }
43363
43364         // remove a targeted clip from the cache
43365         uncacheAction( clip, optionalRoot ) {
43366
43367                 const action = this.existingAction( clip, optionalRoot );
43368
43369                 if ( action !== null ) {
43370
43371                         this._deactivateAction( action );
43372                         this._removeInactiveAction( action );
43373
43374                 }
43375
43376         }
43377
43378     }
43379
43380     AnimationMixer.prototype._controlInterpolantsResultBuffer = new Float32Array( 1 );
43381
43382     class InstancedInterleavedBuffer extends InterleavedBuffer {
43383
43384         constructor( array, stride, meshPerAttribute = 1 ) {
43385
43386                 super( array, stride );
43387
43388                 this.meshPerAttribute = meshPerAttribute;
43389
43390         }
43391
43392         copy( source ) {
43393
43394                 super.copy( source );
43395
43396                 this.meshPerAttribute = source.meshPerAttribute;
43397
43398                 return this;
43399
43400         }
43401
43402         clone( data ) {
43403
43404                 const ib = super.clone( data );
43405
43406                 ib.meshPerAttribute = this.meshPerAttribute;
43407
43408                 return ib;
43409
43410         }
43411
43412         toJSON( data ) {
43413
43414                 const json = super.toJSON( data );
43415
43416                 json.isInstancedInterleavedBuffer = true;
43417                 json.meshPerAttribute = this.meshPerAttribute;
43418
43419                 return json;
43420
43421         }
43422
43423     }
43424
43425     InstancedInterleavedBuffer.prototype.isInstancedInterleavedBuffer = true;
43426
43427     class Raycaster {
43428
43429         constructor( origin, direction, near = 0, far = Infinity ) {
43430
43431                 this.ray = new Ray( origin, direction );
43432                 // direction is assumed to be normalized (for accurate distance calculations)
43433
43434                 this.near = near;
43435                 this.far = far;
43436                 this.camera = null;
43437                 this.layers = new Layers();
43438
43439                 this.params = {
43440                         Mesh: {},
43441                         Line: { threshold: 1 },
43442                         LOD: {},
43443                         Points: { threshold: 1 },
43444                         Sprite: {}
43445                 };
43446
43447         }
43448
43449         set( origin, direction ) {
43450
43451                 // direction is assumed to be normalized (for accurate distance calculations)
43452
43453                 this.ray.set( origin, direction );
43454
43455         }
43456
43457         setFromCamera( coords, camera ) {
43458
43459                 if ( camera && camera.isPerspectiveCamera ) {
43460
43461                         this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
43462                         this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
43463                         this.camera = camera;
43464
43465                 } else if ( camera && camera.isOrthographicCamera ) {
43466
43467                         this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
43468                         this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
43469                         this.camera = camera;
43470
43471                 } else {
43472
43473                         console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type );
43474
43475                 }
43476
43477         }
43478
43479         intersectObject( object, recursive = true, intersects = [] ) {
43480
43481                 intersectObject( object, this, intersects, recursive );
43482
43483                 intersects.sort( ascSort );
43484
43485                 return intersects;
43486
43487         }
43488
43489         intersectObjects( objects, recursive = true, intersects = [] ) {
43490
43491                 for ( let i = 0, l = objects.length; i < l; i ++ ) {
43492
43493                         intersectObject( objects[ i ], this, intersects, recursive );
43494
43495                 }
43496
43497                 intersects.sort( ascSort );
43498
43499                 return intersects;
43500
43501         }
43502
43503     }
43504
43505     function ascSort( a, b ) {
43506
43507         return a.distance - b.distance;
43508
43509     }
43510
43511     function intersectObject( object, raycaster, intersects, recursive ) {
43512
43513         if ( object.layers.test( raycaster.layers ) ) {
43514
43515                 object.raycast( raycaster, intersects );
43516
43517         }
43518
43519         if ( recursive === true ) {
43520
43521                 const children = object.children;
43522
43523                 for ( let i = 0, l = children.length; i < l; i ++ ) {
43524
43525                         intersectObject( children[ i ], raycaster, intersects, true );
43526
43527                 }
43528
43529         }
43530
43531     }
43532
43533     const _vector$2 = /*@__PURE__*/ new Vector3();
43534     const _boneMatrix = /*@__PURE__*/ new Matrix4();
43535     const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
43536
43537
43538     class SkeletonHelper extends LineSegments {
43539
43540         constructor( object ) {
43541
43542                 const bones = getBoneList( object );
43543
43544                 const geometry = new BufferGeometry();
43545
43546                 const vertices = [];
43547                 const colors = [];
43548
43549                 const color1 = new Color( 0, 0, 1 );
43550                 const color2 = new Color( 0, 1, 0 );
43551
43552                 for ( let i = 0; i < bones.length; i ++ ) {
43553
43554                         const bone = bones[ i ];
43555
43556                         if ( bone.parent && bone.parent.isBone ) {
43557
43558                                 vertices.push( 0, 0, 0 );
43559                                 vertices.push( 0, 0, 0 );
43560                                 colors.push( color1.r, color1.g, color1.b );
43561                                 colors.push( color2.r, color2.g, color2.b );
43562
43563                         }
43564
43565                 }
43566
43567                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
43568                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
43569
43570                 const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
43571
43572                 super( geometry, material );
43573
43574                 this.type = 'SkeletonHelper';
43575                 this.isSkeletonHelper = true;
43576
43577                 this.root = object;
43578                 this.bones = bones;
43579
43580                 this.matrix = object.matrixWorld;
43581                 this.matrixAutoUpdate = false;
43582
43583         }
43584
43585         updateMatrixWorld( force ) {
43586
43587                 const bones = this.bones;
43588
43589                 const geometry = this.geometry;
43590                 const position = geometry.getAttribute( 'position' );
43591
43592                 _matrixWorldInv.copy( this.root.matrixWorld ).invert();
43593
43594                 for ( let i = 0, j = 0; i < bones.length; i ++ ) {
43595
43596                         const bone = bones[ i ];
43597
43598                         if ( bone.parent && bone.parent.isBone ) {
43599
43600                                 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
43601                                 _vector$2.setFromMatrixPosition( _boneMatrix );
43602                                 position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z );
43603
43604                                 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
43605                                 _vector$2.setFromMatrixPosition( _boneMatrix );
43606                                 position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z );
43607
43608                                 j += 2;
43609
43610                         }
43611
43612                 }
43613
43614                 geometry.getAttribute( 'position' ).needsUpdate = true;
43615
43616                 super.updateMatrixWorld( force );
43617
43618         }
43619
43620     }
43621
43622
43623     function getBoneList( object ) {
43624
43625         const boneList = [];
43626
43627         if ( object && object.isBone ) {
43628
43629                 boneList.push( object );
43630
43631         }
43632
43633         for ( let i = 0; i < object.children.length; i ++ ) {
43634
43635                 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
43636
43637         }
43638
43639         return boneList;
43640
43641     }
43642
43643     class GridHelper extends LineSegments {
43644
43645         constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
43646
43647                 color1 = new Color( color1 );
43648                 color2 = new Color( color2 );
43649
43650                 const center = divisions / 2;
43651                 const step = size / divisions;
43652                 const halfSize = size / 2;
43653
43654                 const vertices = [], colors = [];
43655
43656                 for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
43657
43658                         vertices.push( - halfSize, 0, k, halfSize, 0, k );
43659                         vertices.push( k, 0, - halfSize, k, 0, halfSize );
43660
43661                         const color = i === center ? color1 : color2;
43662
43663                         color.toArray( colors, j ); j += 3;
43664                         color.toArray( colors, j ); j += 3;
43665                         color.toArray( colors, j ); j += 3;
43666                         color.toArray( colors, j ); j += 3;
43667
43668                 }
43669
43670                 const geometry = new BufferGeometry();
43671                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
43672                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
43673
43674                 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
43675
43676                 super( geometry, material );
43677
43678                 this.type = 'GridHelper';
43679
43680         }
43681
43682     }
43683
43684     const _floatView = new Float32Array( 1 );
43685     new Int32Array( _floatView.buffer );
43686
43687     //
43688
43689     Curve.create = function ( construct, getPoint ) {
43690
43691         console.log( 'THREE.Curve.create() has been deprecated' );
43692
43693         construct.prototype = Object.create( Curve.prototype );
43694         construct.prototype.constructor = construct;
43695         construct.prototype.getPoint = getPoint;
43696
43697         return construct;
43698
43699     };
43700
43701     //
43702
43703     Path.prototype.fromPoints = function ( points ) {
43704
43705         console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
43706         return this.setFromPoints( points );
43707
43708     };
43709
43710     GridHelper.prototype.setColors = function () {
43711
43712         console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
43713
43714     };
43715
43716     SkeletonHelper.prototype.update = function () {
43717
43718         console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
43719
43720     };
43721
43722     //
43723
43724     Loader.prototype.extractUrlBase = function ( url ) {
43725
43726         console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
43727         return LoaderUtils.extractUrlBase( url );
43728
43729     };
43730
43731     Loader.Handlers = {
43732
43733         add: function ( /* regex, loader */ ) {
43734
43735                 console.error( 'THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.' );
43736
43737         },
43738
43739         get: function ( /* file */ ) {
43740
43741                 console.error( 'THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.' );
43742
43743         }
43744
43745     };
43746
43747     //
43748
43749     Box3.prototype.center = function ( optionalTarget ) {
43750
43751         console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
43752         return this.getCenter( optionalTarget );
43753
43754     };
43755
43756     Box3.prototype.empty = function () {
43757
43758         console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
43759         return this.isEmpty();
43760
43761     };
43762
43763     Box3.prototype.isIntersectionBox = function ( box ) {
43764
43765         console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
43766         return this.intersectsBox( box );
43767
43768     };
43769
43770     Box3.prototype.isIntersectionSphere = function ( sphere ) {
43771
43772         console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
43773         return this.intersectsSphere( sphere );
43774
43775     };
43776
43777     Box3.prototype.size = function ( optionalTarget ) {
43778
43779         console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
43780         return this.getSize( optionalTarget );
43781
43782     };
43783
43784     //
43785
43786     Sphere.prototype.empty = function () {
43787
43788         console.warn( 'THREE.Sphere: .empty() has been renamed to .isEmpty().' );
43789         return this.isEmpty();
43790
43791     };
43792
43793     //
43794
43795     Frustum.prototype.setFromMatrix = function ( m ) {
43796
43797         console.warn( 'THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix().' );
43798         return this.setFromProjectionMatrix( m );
43799
43800     };
43801
43802     //
43803
43804     Matrix3.prototype.flattenToArrayOffset = function ( array, offset ) {
43805
43806         console.warn( 'THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
43807         return this.toArray( array, offset );
43808
43809     };
43810
43811     Matrix3.prototype.multiplyVector3 = function ( vector ) {
43812
43813         console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
43814         return vector.applyMatrix3( this );
43815
43816     };
43817
43818     Matrix3.prototype.multiplyVector3Array = function ( /* a */ ) {
43819
43820         console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
43821
43822     };
43823
43824     Matrix3.prototype.applyToBufferAttribute = function ( attribute ) {
43825
43826         console.warn( 'THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead.' );
43827         return attribute.applyMatrix3( this );
43828
43829     };
43830
43831     Matrix3.prototype.applyToVector3Array = function ( /* array, offset, length */ ) {
43832
43833         console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
43834
43835     };
43836
43837     Matrix3.prototype.getInverse = function ( matrix ) {
43838
43839         console.warn( 'THREE.Matrix3: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
43840         return this.copy( matrix ).invert();
43841
43842     };
43843
43844     //
43845
43846     Matrix4.prototype.extractPosition = function ( m ) {
43847
43848         console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
43849         return this.copyPosition( m );
43850
43851     };
43852
43853     Matrix4.prototype.flattenToArrayOffset = function ( array, offset ) {
43854
43855         console.warn( 'THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
43856         return this.toArray( array, offset );
43857
43858     };
43859
43860     Matrix4.prototype.getPosition = function () {
43861
43862         console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
43863         return new Vector3().setFromMatrixColumn( this, 3 );
43864
43865     };
43866
43867     Matrix4.prototype.setRotationFromQuaternion = function ( q ) {
43868
43869         console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
43870         return this.makeRotationFromQuaternion( q );
43871
43872     };
43873
43874     Matrix4.prototype.multiplyToArray = function () {
43875
43876         console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
43877
43878     };
43879
43880     Matrix4.prototype.multiplyVector3 = function ( vector ) {
43881
43882         console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
43883         return vector.applyMatrix4( this );
43884
43885     };
43886
43887     Matrix4.prototype.multiplyVector4 = function ( vector ) {
43888
43889         console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
43890         return vector.applyMatrix4( this );
43891
43892     };
43893
43894     Matrix4.prototype.multiplyVector3Array = function ( /* a */ ) {
43895
43896         console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
43897
43898     };
43899
43900     Matrix4.prototype.rotateAxis = function ( v ) {
43901
43902         console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
43903         v.transformDirection( this );
43904
43905     };
43906
43907     Matrix4.prototype.crossVector = function ( vector ) {
43908
43909         console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
43910         return vector.applyMatrix4( this );
43911
43912     };
43913
43914     Matrix4.prototype.translate = function () {
43915
43916         console.error( 'THREE.Matrix4: .translate() has been removed.' );
43917
43918     };
43919
43920     Matrix4.prototype.rotateX = function () {
43921
43922         console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
43923
43924     };
43925
43926     Matrix4.prototype.rotateY = function () {
43927
43928         console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
43929
43930     };
43931
43932     Matrix4.prototype.rotateZ = function () {
43933
43934         console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
43935
43936     };
43937
43938     Matrix4.prototype.rotateByAxis = function () {
43939
43940         console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
43941
43942     };
43943
43944     Matrix4.prototype.applyToBufferAttribute = function ( attribute ) {
43945
43946         console.warn( 'THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead.' );
43947         return attribute.applyMatrix4( this );
43948
43949     };
43950
43951     Matrix4.prototype.applyToVector3Array = function ( /* array, offset, length */ ) {
43952
43953         console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
43954
43955     };
43956
43957     Matrix4.prototype.makeFrustum = function ( left, right, bottom, top, near, far ) {
43958
43959         console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
43960         return this.makePerspective( left, right, top, bottom, near, far );
43961
43962     };
43963
43964     Matrix4.prototype.getInverse = function ( matrix ) {
43965
43966         console.warn( 'THREE.Matrix4: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
43967         return this.copy( matrix ).invert();
43968
43969     };
43970
43971     //
43972
43973     Plane.prototype.isIntersectionLine = function ( line ) {
43974
43975         console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
43976         return this.intersectsLine( line );
43977
43978     };
43979
43980     //
43981
43982     Quaternion.prototype.multiplyVector3 = function ( vector ) {
43983
43984         console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
43985         return vector.applyQuaternion( this );
43986
43987     };
43988
43989     Quaternion.prototype.inverse = function ( ) {
43990
43991         console.warn( 'THREE.Quaternion: .inverse() has been renamed to invert().' );
43992         return this.invert();
43993
43994     };
43995
43996     //
43997
43998     Ray.prototype.isIntersectionBox = function ( box ) {
43999
44000         console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
44001         return this.intersectsBox( box );
44002
44003     };
44004
44005     Ray.prototype.isIntersectionPlane = function ( plane ) {
44006
44007         console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
44008         return this.intersectsPlane( plane );
44009
44010     };
44011
44012     Ray.prototype.isIntersectionSphere = function ( sphere ) {
44013
44014         console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
44015         return this.intersectsSphere( sphere );
44016
44017     };
44018
44019     //
44020
44021     Triangle.prototype.area = function () {
44022
44023         console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
44024         return this.getArea();
44025
44026     };
44027
44028     Triangle.prototype.barycoordFromPoint = function ( point, target ) {
44029
44030         console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
44031         return this.getBarycoord( point, target );
44032
44033     };
44034
44035     Triangle.prototype.midpoint = function ( target ) {
44036
44037         console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
44038         return this.getMidpoint( target );
44039
44040     };
44041
44042     Triangle.prototypenormal = function ( target ) {
44043
44044         console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
44045         return this.getNormal( target );
44046
44047     };
44048
44049     Triangle.prototype.plane = function ( target ) {
44050
44051         console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
44052         return this.getPlane( target );
44053
44054     };
44055
44056     Triangle.barycoordFromPoint = function ( point, a, b, c, target ) {
44057
44058         console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
44059         return Triangle.getBarycoord( point, a, b, c, target );
44060
44061     };
44062
44063     Triangle.normal = function ( a, b, c, target ) {
44064
44065         console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
44066         return Triangle.getNormal( a, b, c, target );
44067
44068     };
44069
44070     //
44071
44072     Shape.prototype.extractAllPoints = function ( divisions ) {
44073
44074         console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
44075         return this.extractPoints( divisions );
44076
44077     };
44078
44079     Shape.prototype.extrude = function ( options ) {
44080
44081         console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
44082         return new ExtrudeGeometry( this, options );
44083
44084     };
44085
44086     Shape.prototype.makeGeometry = function ( options ) {
44087
44088         console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
44089         return new ShapeGeometry( this, options );
44090
44091     };
44092
44093     //
44094
44095     Vector2.prototype.fromAttribute = function ( attribute, index, offset ) {
44096
44097         console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
44098         return this.fromBufferAttribute( attribute, index, offset );
44099
44100     };
44101
44102     Vector2.prototype.distanceToManhattan = function ( v ) {
44103
44104         console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
44105         return this.manhattanDistanceTo( v );
44106
44107     };
44108
44109     Vector2.prototype.lengthManhattan = function () {
44110
44111         console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
44112         return this.manhattanLength();
44113
44114     };
44115
44116     //
44117
44118     Vector3.prototype.setEulerFromRotationMatrix = function () {
44119
44120         console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
44121
44122     };
44123
44124     Vector3.prototype.setEulerFromQuaternion = function () {
44125
44126         console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
44127
44128     };
44129
44130     Vector3.prototype.getPositionFromMatrix = function ( m ) {
44131
44132         console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
44133         return this.setFromMatrixPosition( m );
44134
44135     };
44136
44137     Vector3.prototype.getScaleFromMatrix = function ( m ) {
44138
44139         console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
44140         return this.setFromMatrixScale( m );
44141
44142     };
44143
44144     Vector3.prototype.getColumnFromMatrix = function ( index, matrix ) {
44145
44146         console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
44147         return this.setFromMatrixColumn( matrix, index );
44148
44149     };
44150
44151     Vector3.prototype.applyProjection = function ( m ) {
44152
44153         console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
44154         return this.applyMatrix4( m );
44155
44156     };
44157
44158     Vector3.prototype.fromAttribute = function ( attribute, index, offset ) {
44159
44160         console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
44161         return this.fromBufferAttribute( attribute, index, offset );
44162
44163     };
44164
44165     Vector3.prototype.distanceToManhattan = function ( v ) {
44166
44167         console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
44168         return this.manhattanDistanceTo( v );
44169
44170     };
44171
44172     Vector3.prototype.lengthManhattan = function () {
44173
44174         console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
44175         return this.manhattanLength();
44176
44177     };
44178
44179     //
44180
44181     Vector4.prototype.fromAttribute = function ( attribute, index, offset ) {
44182
44183         console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
44184         return this.fromBufferAttribute( attribute, index, offset );
44185
44186     };
44187
44188     Vector4.prototype.lengthManhattan = function () {
44189
44190         console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
44191         return this.manhattanLength();
44192
44193     };
44194
44195     //
44196
44197     Object3D.prototype.getChildByName = function ( name ) {
44198
44199         console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
44200         return this.getObjectByName( name );
44201
44202     };
44203
44204     Object3D.prototype.renderDepth = function () {
44205
44206         console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
44207
44208     };
44209
44210     Object3D.prototype.translate = function ( distance, axis ) {
44211
44212         console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
44213         return this.translateOnAxis( axis, distance );
44214
44215     };
44216
44217     Object3D.prototype.getWorldRotation = function () {
44218
44219         console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
44220
44221     };
44222
44223     Object3D.prototype.applyMatrix = function ( matrix ) {
44224
44225         console.warn( 'THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4().' );
44226         return this.applyMatrix4( matrix );
44227
44228     };
44229
44230     Object.defineProperties( Object3D.prototype, {
44231
44232         eulerOrder: {
44233                 get: function () {
44234
44235                         console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
44236                         return this.rotation.order;
44237
44238                 },
44239                 set: function ( value ) {
44240
44241                         console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
44242                         this.rotation.order = value;
44243
44244                 }
44245         },
44246         useQuaternion: {
44247                 get: function () {
44248
44249                         console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
44250
44251                 },
44252                 set: function () {
44253
44254                         console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
44255
44256                 }
44257         }
44258
44259     } );
44260
44261     Mesh.prototype.setDrawMode = function () {
44262
44263         console.error( 'THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
44264
44265     };
44266
44267     Object.defineProperties( Mesh.prototype, {
44268
44269         drawMode: {
44270                 get: function () {
44271
44272                         console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.' );
44273                         return TrianglesDrawMode;
44274
44275                 },
44276                 set: function () {
44277
44278                         console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
44279
44280                 }
44281         }
44282
44283     } );
44284
44285     SkinnedMesh.prototype.initBones = function () {
44286
44287         console.error( 'THREE.SkinnedMesh: initBones() has been removed.' );
44288
44289     };
44290
44291     //
44292
44293     PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
44294
44295         console.warn( 'THREE.PerspectiveCamera.setLens is deprecated. ' +
44296                         'Use .setFocalLength and .filmGauge for a photographic setup.' );
44297
44298         if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
44299         this.setFocalLength( focalLength );
44300
44301     };
44302
44303     //
44304
44305     Object.defineProperties( Light.prototype, {
44306         onlyShadow: {
44307                 set: function () {
44308
44309                         console.warn( 'THREE.Light: .onlyShadow has been removed.' );
44310
44311                 }
44312         },
44313         shadowCameraFov: {
44314                 set: function ( value ) {
44315
44316                         console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
44317                         this.shadow.camera.fov = value;
44318
44319                 }
44320         },
44321         shadowCameraLeft: {
44322                 set: function ( value ) {
44323
44324                         console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
44325                         this.shadow.camera.left = value;
44326
44327                 }
44328         },
44329         shadowCameraRight: {
44330                 set: function ( value ) {
44331
44332                         console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
44333                         this.shadow.camera.right = value;
44334
44335                 }
44336         },
44337         shadowCameraTop: {
44338                 set: function ( value ) {
44339
44340                         console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
44341                         this.shadow.camera.top = value;
44342
44343                 }
44344         },
44345         shadowCameraBottom: {
44346                 set: function ( value ) {
44347
44348                         console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
44349                         this.shadow.camera.bottom = value;
44350
44351                 }
44352         },
44353         shadowCameraNear: {
44354                 set: function ( value ) {
44355
44356                         console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
44357                         this.shadow.camera.near = value;
44358
44359                 }
44360         },
44361         shadowCameraFar: {
44362                 set: function ( value ) {
44363
44364                         console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
44365                         this.shadow.camera.far = value;
44366
44367                 }
44368         },
44369         shadowCameraVisible: {
44370                 set: function () {
44371
44372                         console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
44373
44374                 }
44375         },
44376         shadowBias: {
44377                 set: function ( value ) {
44378
44379                         console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
44380                         this.shadow.bias = value;
44381
44382                 }
44383         },
44384         shadowDarkness: {
44385                 set: function () {
44386
44387                         console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
44388
44389                 }
44390         },
44391         shadowMapWidth: {
44392                 set: function ( value ) {
44393
44394                         console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
44395                         this.shadow.mapSize.width = value;
44396
44397                 }
44398         },
44399         shadowMapHeight: {
44400                 set: function ( value ) {
44401
44402                         console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
44403                         this.shadow.mapSize.height = value;
44404
44405                 }
44406         }
44407     } );
44408
44409     //
44410
44411     Object.defineProperties( BufferAttribute.prototype, {
44412
44413         length: {
44414                 get: function () {
44415
44416                         console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
44417                         return this.array.length;
44418
44419                 }
44420         },
44421         dynamic: {
44422                 get: function () {
44423
44424                         console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
44425                         return this.usage === DynamicDrawUsage;
44426
44427                 },
44428                 set: function ( /* value */ ) {
44429
44430                         console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
44431                         this.setUsage( DynamicDrawUsage );
44432
44433                 }
44434         }
44435
44436     } );
44437
44438     BufferAttribute.prototype.setDynamic = function ( value ) {
44439
44440         console.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );
44441         this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
44442         return this;
44443
44444     };
44445
44446     BufferAttribute.prototype.copyIndicesArray = function ( /* indices */ ) {
44447
44448         console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
44449
44450     },
44451
44452     BufferAttribute.prototype.setArray = function ( /* array */ ) {
44453
44454         console.error( 'THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
44455
44456     };
44457
44458     //
44459
44460     BufferGeometry.prototype.addIndex = function ( index ) {
44461
44462         console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
44463         this.setIndex( index );
44464
44465     };
44466
44467     BufferGeometry.prototype.addAttribute = function ( name, attribute ) {
44468
44469         console.warn( 'THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().' );
44470
44471         if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
44472
44473                 console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
44474
44475                 return this.setAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
44476
44477         }
44478
44479         if ( name === 'index' ) {
44480
44481                 console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
44482                 this.setIndex( attribute );
44483
44484                 return this;
44485
44486         }
44487
44488         return this.setAttribute( name, attribute );
44489
44490     };
44491
44492     BufferGeometry.prototype.addDrawCall = function ( start, count, indexOffset ) {
44493
44494         if ( indexOffset !== undefined ) {
44495
44496                 console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
44497
44498         }
44499
44500         console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
44501         this.addGroup( start, count );
44502
44503     };
44504
44505     BufferGeometry.prototype.clearDrawCalls = function () {
44506
44507         console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
44508         this.clearGroups();
44509
44510     };
44511
44512     BufferGeometry.prototype.computeOffsets = function () {
44513
44514         console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
44515
44516     };
44517
44518     BufferGeometry.prototype.removeAttribute = function ( name ) {
44519
44520         console.warn( 'THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().' );
44521
44522         return this.deleteAttribute( name );
44523
44524     };
44525
44526     BufferGeometry.prototype.applyMatrix = function ( matrix ) {
44527
44528         console.warn( 'THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4().' );
44529         return this.applyMatrix4( matrix );
44530
44531     };
44532
44533     Object.defineProperties( BufferGeometry.prototype, {
44534
44535         drawcalls: {
44536                 get: function () {
44537
44538                         console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
44539                         return this.groups;
44540
44541                 }
44542         },
44543         offsets: {
44544                 get: function () {
44545
44546                         console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
44547                         return this.groups;
44548
44549                 }
44550         }
44551
44552     } );
44553
44554     InterleavedBuffer.prototype.setDynamic = function ( value ) {
44555
44556         console.warn( 'THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.' );
44557         this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
44558         return this;
44559
44560     };
44561
44562     InterleavedBuffer.prototype.setArray = function ( /* array */ ) {
44563
44564         console.error( 'THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
44565
44566     };
44567
44568     //
44569
44570     ExtrudeGeometry.prototype.getArrays = function () {
44571
44572         console.error( 'THREE.ExtrudeGeometry: .getArrays() has been removed.' );
44573
44574     };
44575
44576     ExtrudeGeometry.prototype.addShapeList = function () {
44577
44578         console.error( 'THREE.ExtrudeGeometry: .addShapeList() has been removed.' );
44579
44580     };
44581
44582     ExtrudeGeometry.prototype.addShape = function () {
44583
44584         console.error( 'THREE.ExtrudeGeometry: .addShape() has been removed.' );
44585
44586     };
44587
44588     //
44589
44590     Scene.prototype.dispose = function () {
44591
44592         console.error( 'THREE.Scene: .dispose() has been removed.' );
44593
44594     };
44595
44596     //
44597
44598     Object.defineProperties( Material.prototype, {
44599
44600         wrapAround: {
44601                 get: function () {
44602
44603                         console.warn( 'THREE.Material: .wrapAround has been removed.' );
44604
44605                 },
44606                 set: function () {
44607
44608                         console.warn( 'THREE.Material: .wrapAround has been removed.' );
44609
44610                 }
44611         },
44612
44613         overdraw: {
44614                 get: function () {
44615
44616                         console.warn( 'THREE.Material: .overdraw has been removed.' );
44617
44618                 },
44619                 set: function () {
44620
44621                         console.warn( 'THREE.Material: .overdraw has been removed.' );
44622
44623                 }
44624         },
44625
44626         wrapRGB: {
44627                 get: function () {
44628
44629                         console.warn( 'THREE.Material: .wrapRGB has been removed.' );
44630                         return new Color();
44631
44632                 }
44633         },
44634
44635         shading: {
44636                 get: function () {
44637
44638                         console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
44639
44640                 },
44641                 set: function ( value ) {
44642
44643                         console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
44644                         this.flatShading = ( value === FlatShading );
44645
44646                 }
44647         },
44648
44649         stencilMask: {
44650                 get: function () {
44651
44652                         console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
44653                         return this.stencilFuncMask;
44654
44655                 },
44656                 set: function ( value ) {
44657
44658                         console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
44659                         this.stencilFuncMask = value;
44660
44661                 }
44662         },
44663
44664         vertexTangents: {
44665                 get: function () {
44666
44667                         console.warn( 'THREE.' + this.type + ': .vertexTangents has been removed.' );
44668
44669                 },
44670                 set: function () {
44671
44672                         console.warn( 'THREE.' + this.type + ': .vertexTangents has been removed.' );
44673
44674                 }
44675         },
44676
44677     } );
44678
44679     Object.defineProperties( ShaderMaterial.prototype, {
44680
44681         derivatives: {
44682                 get: function () {
44683
44684                         console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
44685                         return this.extensions.derivatives;
44686
44687                 },
44688                 set: function ( value ) {
44689
44690                         console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
44691                         this.extensions.derivatives = value;
44692
44693                 }
44694         }
44695
44696     } );
44697
44698     //
44699
44700     WebGLRenderer.prototype.clearTarget = function ( renderTarget, color, depth, stencil ) {
44701
44702         console.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );
44703         this.setRenderTarget( renderTarget );
44704         this.clear( color, depth, stencil );
44705
44706     };
44707
44708     WebGLRenderer.prototype.animate = function ( callback ) {
44709
44710         console.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );
44711         this.setAnimationLoop( callback );
44712
44713     };
44714
44715     WebGLRenderer.prototype.getCurrentRenderTarget = function () {
44716
44717         console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
44718         return this.getRenderTarget();
44719
44720     };
44721
44722     WebGLRenderer.prototype.getMaxAnisotropy = function () {
44723
44724         console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
44725         return this.capabilities.getMaxAnisotropy();
44726
44727     };
44728
44729     WebGLRenderer.prototype.getPrecision = function () {
44730
44731         console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
44732         return this.capabilities.precision;
44733
44734     };
44735
44736     WebGLRenderer.prototype.resetGLState = function () {
44737
44738         console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
44739         return this.state.reset();
44740
44741     };
44742
44743     WebGLRenderer.prototype.supportsFloatTextures = function () {
44744
44745         console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
44746         return this.extensions.get( 'OES_texture_float' );
44747
44748     };
44749
44750     WebGLRenderer.prototype.supportsHalfFloatTextures = function () {
44751
44752         console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
44753         return this.extensions.get( 'OES_texture_half_float' );
44754
44755     };
44756
44757     WebGLRenderer.prototype.supportsStandardDerivatives = function () {
44758
44759         console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
44760         return this.extensions.get( 'OES_standard_derivatives' );
44761
44762     };
44763
44764     WebGLRenderer.prototype.supportsCompressedTextureS3TC = function () {
44765
44766         console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
44767         return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
44768
44769     };
44770
44771     WebGLRenderer.prototype.supportsCompressedTexturePVRTC = function () {
44772
44773         console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
44774         return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
44775
44776     };
44777
44778     WebGLRenderer.prototype.supportsBlendMinMax = function () {
44779
44780         console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
44781         return this.extensions.get( 'EXT_blend_minmax' );
44782
44783     };
44784
44785     WebGLRenderer.prototype.supportsVertexTextures = function () {
44786
44787         console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
44788         return this.capabilities.vertexTextures;
44789
44790     };
44791
44792     WebGLRenderer.prototype.supportsInstancedArrays = function () {
44793
44794         console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
44795         return this.extensions.get( 'ANGLE_instanced_arrays' );
44796
44797     };
44798
44799     WebGLRenderer.prototype.enableScissorTest = function ( boolean ) {
44800
44801         console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
44802         this.setScissorTest( boolean );
44803
44804     };
44805
44806     WebGLRenderer.prototype.initMaterial = function () {
44807
44808         console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
44809
44810     };
44811
44812     WebGLRenderer.prototype.addPrePlugin = function () {
44813
44814         console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
44815
44816     };
44817
44818     WebGLRenderer.prototype.addPostPlugin = function () {
44819
44820         console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
44821
44822     };
44823
44824     WebGLRenderer.prototype.updateShadowMap = function () {
44825
44826         console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
44827
44828     };
44829
44830     WebGLRenderer.prototype.setFaceCulling = function () {
44831
44832         console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
44833
44834     };
44835
44836     WebGLRenderer.prototype.allocTextureUnit = function () {
44837
44838         console.warn( 'THREE.WebGLRenderer: .allocTextureUnit() has been removed.' );
44839
44840     };
44841
44842     WebGLRenderer.prototype.setTexture = function () {
44843
44844         console.warn( 'THREE.WebGLRenderer: .setTexture() has been removed.' );
44845
44846     };
44847
44848     WebGLRenderer.prototype.setTexture2D = function () {
44849
44850         console.warn( 'THREE.WebGLRenderer: .setTexture2D() has been removed.' );
44851
44852     };
44853
44854     WebGLRenderer.prototype.setTextureCube = function () {
44855
44856         console.warn( 'THREE.WebGLRenderer: .setTextureCube() has been removed.' );
44857
44858     };
44859
44860     WebGLRenderer.prototype.getActiveMipMapLevel = function () {
44861
44862         console.warn( 'THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().' );
44863         return this.getActiveMipmapLevel();
44864
44865     };
44866
44867     Object.defineProperties( WebGLRenderer.prototype, {
44868
44869         shadowMapEnabled: {
44870                 get: function () {
44871
44872                         return this.shadowMap.enabled;
44873
44874                 },
44875                 set: function ( value ) {
44876
44877                         console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
44878                         this.shadowMap.enabled = value;
44879
44880                 }
44881         },
44882         shadowMapType: {
44883                 get: function () {
44884
44885                         return this.shadowMap.type;
44886
44887                 },
44888                 set: function ( value ) {
44889
44890                         console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
44891                         this.shadowMap.type = value;
44892
44893                 }
44894         },
44895         shadowMapCullFace: {
44896                 get: function () {
44897
44898                         console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
44899                         return undefined;
44900
44901                 },
44902                 set: function ( /* value */ ) {
44903
44904                         console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
44905
44906                 }
44907         },
44908         context: {
44909                 get: function () {
44910
44911                         console.warn( 'THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.' );
44912                         return this.getContext();
44913
44914                 }
44915         },
44916         vr: {
44917                 get: function () {
44918
44919                         console.warn( 'THREE.WebGLRenderer: .vr has been renamed to .xr' );
44920                         return this.xr;
44921
44922                 }
44923         },
44924         gammaInput: {
44925                 get: function () {
44926
44927                         console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
44928                         return false;
44929
44930                 },
44931                 set: function () {
44932
44933                         console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
44934
44935                 }
44936         },
44937         gammaOutput: {
44938                 get: function () {
44939
44940                         console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
44941                         return false;
44942
44943                 },
44944                 set: function ( value ) {
44945
44946                         console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
44947                         this.outputEncoding = ( value === true ) ? sRGBEncoding : LinearEncoding;
44948
44949                 }
44950         },
44951         toneMappingWhitePoint: {
44952                 get: function () {
44953
44954                         console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
44955                         return 1.0;
44956
44957                 },
44958                 set: function () {
44959
44960                         console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
44961
44962                 }
44963         },
44964
44965     } );
44966
44967     Object.defineProperties( WebGLShadowMap.prototype, {
44968
44969         cullFace: {
44970                 get: function () {
44971
44972                         console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
44973                         return undefined;
44974
44975                 },
44976                 set: function ( /* cullFace */ ) {
44977
44978                         console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
44979
44980                 }
44981         },
44982         renderReverseSided: {
44983                 get: function () {
44984
44985                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
44986                         return undefined;
44987
44988                 },
44989                 set: function () {
44990
44991                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
44992
44993                 }
44994         },
44995         renderSingleSided: {
44996                 get: function () {
44997
44998                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
44999                         return undefined;
45000
45001                 },
45002                 set: function () {
45003
45004                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
45005
45006                 }
45007         }
45008
45009     } );
45010
45011     //
45012
45013     Object.defineProperties( WebGLRenderTarget.prototype, {
45014
45015         wrapS: {
45016                 get: function () {
45017
45018                         console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
45019                         return this.texture.wrapS;
45020
45021                 },
45022                 set: function ( value ) {
45023
45024                         console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
45025                         this.texture.wrapS = value;
45026
45027                 }
45028         },
45029         wrapT: {
45030                 get: function () {
45031
45032                         console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
45033                         return this.texture.wrapT;
45034
45035                 },
45036                 set: function ( value ) {
45037
45038                         console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
45039                         this.texture.wrapT = value;
45040
45041                 }
45042         },
45043         magFilter: {
45044                 get: function () {
45045
45046                         console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
45047                         return this.texture.magFilter;
45048
45049                 },
45050                 set: function ( value ) {
45051
45052                         console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
45053                         this.texture.magFilter = value;
45054
45055                 }
45056         },
45057         minFilter: {
45058                 get: function () {
45059
45060                         console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
45061                         return this.texture.minFilter;
45062
45063                 },
45064                 set: function ( value ) {
45065
45066                         console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
45067                         this.texture.minFilter = value;
45068
45069                 }
45070         },
45071         anisotropy: {
45072                 get: function () {
45073
45074                         console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
45075                         return this.texture.anisotropy;
45076
45077                 },
45078                 set: function ( value ) {
45079
45080                         console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
45081                         this.texture.anisotropy = value;
45082
45083                 }
45084         },
45085         offset: {
45086                 get: function () {
45087
45088                         console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
45089                         return this.texture.offset;
45090
45091                 },
45092                 set: function ( value ) {
45093
45094                         console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
45095                         this.texture.offset = value;
45096
45097                 }
45098         },
45099         repeat: {
45100                 get: function () {
45101
45102                         console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
45103                         return this.texture.repeat;
45104
45105                 },
45106                 set: function ( value ) {
45107
45108                         console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
45109                         this.texture.repeat = value;
45110
45111                 }
45112         },
45113         format: {
45114                 get: function () {
45115
45116                         console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
45117                         return this.texture.format;
45118
45119                 },
45120                 set: function ( value ) {
45121
45122                         console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
45123                         this.texture.format = value;
45124
45125                 }
45126         },
45127         type: {
45128                 get: function () {
45129
45130                         console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
45131                         return this.texture.type;
45132
45133                 },
45134                 set: function ( value ) {
45135
45136                         console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
45137                         this.texture.type = value;
45138
45139                 }
45140         },
45141         generateMipmaps: {
45142                 get: function () {
45143
45144                         console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
45145                         return this.texture.generateMipmaps;
45146
45147                 },
45148                 set: function ( value ) {
45149
45150                         console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
45151                         this.texture.generateMipmaps = value;
45152
45153                 }
45154         }
45155
45156     } );
45157
45158     //
45159
45160     Audio.prototype.load = function ( file ) {
45161
45162         console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
45163         const scope = this;
45164         const audioLoader = new AudioLoader();
45165         audioLoader.load( file, function ( buffer ) {
45166
45167                 scope.setBuffer( buffer );
45168
45169         } );
45170         return this;
45171
45172     };
45173
45174     //
45175
45176     CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
45177
45178         console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
45179         return this.update( renderer, scene );
45180
45181     };
45182
45183     CubeCamera.prototype.clear = function ( renderer, color, depth, stencil ) {
45184
45185         console.warn( 'THREE.CubeCamera: .clear() is now .renderTarget.clear().' );
45186         return this.renderTarget.clear( renderer, color, depth, stencil );
45187
45188     };
45189
45190     ImageUtils.crossOrigin = undefined;
45191
45192     ImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {
45193
45194         console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
45195
45196         const loader = new TextureLoader();
45197         loader.setCrossOrigin( this.crossOrigin );
45198
45199         const texture = loader.load( url, onLoad, undefined, onError );
45200
45201         if ( mapping ) texture.mapping = mapping;
45202
45203         return texture;
45204
45205     };
45206
45207     ImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {
45208
45209         console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
45210
45211         const loader = new CubeTextureLoader();
45212         loader.setCrossOrigin( this.crossOrigin );
45213
45214         const texture = loader.load( urls, onLoad, undefined, onError );
45215
45216         if ( mapping ) texture.mapping = mapping;
45217
45218         return texture;
45219
45220     };
45221
45222     ImageUtils.loadCompressedTexture = function () {
45223
45224         console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
45225
45226     };
45227
45228     ImageUtils.loadCompressedTextureCube = function () {
45229
45230         console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
45231
45232     };
45233
45234     if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
45235
45236         /* eslint-disable no-undef */
45237         __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
45238                 revision: REVISION,
45239         } } ) );
45240         /* eslint-enable no-undef */
45241
45242     }
45243
45244     if ( typeof window !== 'undefined' ) {
45245
45246         if ( window.__THREE__ ) {
45247
45248                 console.warn( 'WARNING: Multiple instances of Three.js being imported.' );
45249
45250         } else {
45251
45252                 window.__THREE__ = REVISION;
45253
45254         }
45255
45256     }
45257
45258     const DEG2RAD = Math.PI / 180;
45259     const RAD2DEG = 180 / Math.PI;
45260     const WGS84A = 6378137.0;
45261     const WGS84B = 6356752.31424518;
45262     /**
45263      * Convert coordinates from geodetic (WGS84) reference to local topocentric
45264      * (ENU) reference.
45265      *
45266      * @param {number} lng Longitude in degrees.
45267      * @param {number} lat Latitude in degrees.
45268      * @param {number} alt Altitude in meters.
45269      * @param {number} refLng Reference longitude in degrees.
45270      * @param {number} refLat Reference latitude in degrees.
45271      * @param {number} refAlt Reference altitude in meters.
45272      * @returns {Array<number>} The x, y, z local topocentric ENU coordinates.
45273      */
45274     function geodeticToEnu(lng, lat, alt, refLng, refLat, refAlt) {
45275         const ecef = geodeticToEcef(lng, lat, alt);
45276         return ecefToEnu(ecef[0], ecef[1], ecef[2], refLng, refLat, refAlt);
45277     }
45278     /**
45279      * Convert coordinates from local topocentric (ENU) reference to
45280      * geodetic (WGS84) reference.
45281      *
45282      * @param {number} x Topocentric ENU coordinate in East direction.
45283      * @param {number} y Topocentric ENU coordinate in North direction.
45284      * @param {number} z Topocentric ENU coordinate in Up direction.
45285      * @param {number} refLng Reference longitude in degrees.
45286      * @param {number} refLat Reference latitude in degrees.
45287      * @param {number} refAlt Reference altitude in meters.
45288      * @returns {Array<number>} The longitude, latitude in degrees
45289      * and altitude in meters.
45290      */
45291     function enuToGeodetic(x, y, z, refLng, refLat, refAlt) {
45292         const ecef = enuToEcef(x, y, z, refLng, refLat, refAlt);
45293         return ecefToGeodetic(ecef[0], ecef[1], ecef[2]);
45294     }
45295     /**
45296      * Convert coordinates from Earth-Centered, Earth-Fixed (ECEF) reference
45297      * to local topocentric (ENU) reference.
45298      *
45299      * @param {number} X ECEF X-value.
45300      * @param {number} Y ECEF Y-value.
45301      * @param {number} Z ECEF Z-value.
45302      * @param {number} refLng Reference longitude in degrees.
45303      * @param {number} refLat Reference latitude in degrees.
45304      * @param {number} refAlt Reference altitude in meters.
45305      * @returns {Array<number>} The x, y, z topocentric ENU coordinates in East, North
45306      * and Up directions respectively.
45307      */
45308     function ecefToEnu(X, Y, Z, refLng, refLat, refAlt) {
45309         const refEcef = geodeticToEcef(refLng, refLat, refAlt);
45310         const V = [
45311             X - refEcef[0],
45312             Y - refEcef[1],
45313             Z - refEcef[2],
45314         ];
45315         refLng = refLng * DEG2RAD;
45316         refLat = refLat * DEG2RAD;
45317         const cosLng = Math.cos(refLng);
45318         const sinLng = Math.sin(refLng);
45319         const cosLat = Math.cos(refLat);
45320         const sinLat = Math.sin(refLat);
45321         const x = -sinLng * V[0] + cosLng * V[1];
45322         const y = -sinLat * cosLng * V[0] - sinLat * sinLng * V[1] + cosLat * V[2];
45323         const z = cosLat * cosLng * V[0] + cosLat * sinLng * V[1] + sinLat * V[2];
45324         return [x, y, z];
45325     }
45326     /**
45327      * Convert coordinates from local topocentric (ENU) reference
45328      * to Earth-Centered, Earth-Fixed (ECEF) reference.
45329      *
45330      * @param {number} x Topocentric ENU coordinate in East direction.
45331      * @param {number} y Topocentric ENU coordinate in North direction.
45332      * @param {number} z Topocentric ENU coordinate in Up direction.
45333      * @param {number} refLng Reference longitude in degrees.
45334      * @param {number} refLat Reference latitude in degrees.
45335      * @param {number} refAlt Reference altitude in meters.
45336      * @returns {Array<number>} The X, Y, Z ECEF coordinates.
45337      */
45338     function enuToEcef(x, y, z, refLng, refLat, refAlt) {
45339         const refEcef = geodeticToEcef(refLng, refLat, refAlt);
45340         refLng = refLng * DEG2RAD;
45341         refLat = refLat * DEG2RAD;
45342         const cosLng = Math.cos(refLng);
45343         const sinLng = Math.sin(refLng);
45344         const cosLat = Math.cos(refLat);
45345         const sinLat = Math.sin(refLat);
45346         const X = -sinLng * x
45347             - sinLat * cosLng * y
45348             + cosLat * cosLng * z
45349             + refEcef[0];
45350         const Y = cosLng * x
45351             - sinLat * sinLng * y
45352             + cosLat * sinLng * z
45353             + refEcef[1];
45354         const Z = cosLat * y +
45355             sinLat * z +
45356             refEcef[2];
45357         return [X, Y, Z];
45358     }
45359     /**
45360      * Convert coordinates from geodetic reference (WGS84) to Earth-Centered,
45361      * Earth-Fixed (ECEF) reference.
45362      *
45363      * @param {number} lng Longitude in degrees.
45364      * @param {number} lat Latitude in degrees.
45365      * @param {number} alt Altitude in meters.
45366      * @returns {Array<number>} The X, Y, Z ECEF coordinates.
45367      */
45368     function geodeticToEcef(lng, lat, alt) {
45369         const a = WGS84A;
45370         const b = WGS84B;
45371         lng = lng * DEG2RAD;
45372         lat = lat * DEG2RAD;
45373         const cosLng = Math.cos(lng);
45374         const sinLng = Math.sin(lng);
45375         const cosLat = Math.cos(lat);
45376         const sinLat = Math.sin(lat);
45377         const a2 = a * a;
45378         const b2 = b * b;
45379         const L = 1.0 / Math.sqrt(a2 * cosLat * cosLat + b2 * sinLat * sinLat);
45380         const nhcl = (a2 * L + alt) * cosLat;
45381         const X = nhcl * cosLng;
45382         const Y = nhcl * sinLng;
45383         const Z = (b2 * L + alt) * sinLat;
45384         return [X, Y, Z];
45385     }
45386     /**
45387      * Convert coordinates from Earth-Centered, Earth-Fixed (ECEF) reference
45388      * to geodetic reference (WGS84).
45389      *
45390      * @param {number} X ECEF X-value.
45391      * @param {number} Y ECEF Y-value.
45392      * @param {number} Z ECEF Z-value.
45393      * @returns {Array<number>} The longitude, latitude in degrees
45394      * and altitude in meters.
45395      */
45396     function ecefToGeodetic(X, Y, Z) {
45397         const a = WGS84A;
45398         const b = WGS84B;
45399         const a2 = a * a;
45400         const b2 = b * b;
45401         const a2mb2 = a2 - b2;
45402         const ea = Math.sqrt(a2mb2 / a2);
45403         const eb = Math.sqrt(a2mb2 / b2);
45404         const p = Math.sqrt(X * X + Y * Y);
45405         const theta = Math.atan2(Z * a, p * b);
45406         const sinTheta = Math.sin(theta);
45407         const cosTheta = Math.cos(theta);
45408         const lng = Math.atan2(Y, X);
45409         const lat = Math.atan2(Z + eb * eb * b * sinTheta * sinTheta * sinTheta, p - ea * ea * a * cosTheta * cosTheta * cosTheta);
45410         const sinLat = Math.sin(lat);
45411         const cosLat = Math.cos(lat);
45412         const N = a / Math.sqrt(1 - ea * ea * sinLat * sinLat);
45413         const alt = p / cosLat - N;
45414         return [
45415             lng * RAD2DEG,
45416             lat * RAD2DEG,
45417             alt
45418         ];
45419     }
45420
45421     /**
45422      * @class GraphCalculator
45423      *
45424      * @classdesc Represents a calculator for graph entities.
45425      */
45426     class GraphCalculator {
45427         /**
45428          * Get the bounding box corners for a circle with radius of a threshold
45429          * with center in a geodetic position.
45430          *
45431          * @param {LngLat} lngLat - Longitude, latitude to encode.
45432          * @param {number} threshold - Threshold distance from the position in meters.
45433          *
45434          * @returns {Array<LngLat>} The south west and north east corners of the
45435          * bounding box.
45436          */
45437         boundingBoxCorners(lngLat, threshold) {
45438             const sw = enuToGeodetic(-threshold, -threshold, 0, lngLat.lng, lngLat.lat, 0);
45439             const ne = enuToGeodetic(threshold, threshold, 0, lngLat.lng, lngLat.lat, 0);
45440             return [
45441                 { lat: sw[1], lng: sw[0] },
45442                 { lat: ne[1], lng: ne[0] },
45443             ];
45444         }
45445         /**
45446          * Convert a compass angle to an angle axis rotation vector.
45447          *
45448          * @param {number} compassAngle - The compass angle in degrees.
45449          * @param {number} orientation - The orientation of the original image.
45450          *
45451          * @returns {Array<number>} Angle axis rotation vector.
45452          */
45453         rotationFromCompass(compassAngle, orientation) {
45454             let x = 0;
45455             let y = 0;
45456             let z = 0;
45457             switch (orientation) {
45458                 case 1:
45459                     x = Math.PI / 2;
45460                     break;
45461                 case 3:
45462                     x = -Math.PI / 2;
45463                     z = Math.PI;
45464                     break;
45465                 case 6:
45466                     y = -Math.PI / 2;
45467                     z = -Math.PI / 2;
45468                     break;
45469                 case 8:
45470                     y = Math.PI / 2;
45471                     z = Math.PI / 2;
45472                     break;
45473             }
45474             const rz = new Matrix4()
45475                 .makeRotationZ(z);
45476             const euler = new Euler(x, y, compassAngle * Math.PI / 180, "XYZ");
45477             const re = new Matrix4()
45478                 .makeRotationFromEuler(euler);
45479             const rotation = new Vector4()
45480                 .setAxisAngleFromRotationMatrix(re.multiply(rz));
45481             return rotation
45482                 .multiplyScalar(rotation.w)
45483                 .toArray()
45484                 .slice(0, 3);
45485         }
45486     }
45487
45488     /**
45489      * @class Image
45490      *
45491      * @classdesc Represents a image in the navigation graph.
45492      *
45493      * Explanation of position and bearing properties:
45494      *
45495      * When images are uploaded they will have GPS information in the EXIF, this is what
45496      * is called `originalLngLat` {@link Image.originalLngLat}.
45497      *
45498      * When Structure from Motions has been run for a image a `computedLngLat` that
45499      * differs from the `originalLngLat` will be created. It is different because
45500      * GPS positions are not very exact and SfM aligns the camera positions according
45501      * to the 3D reconstruction {@link Image.computedLngLat}.
45502      *
45503      * At last there exist a `lngLat` property which evaluates to
45504      * the `computedLngLat` from SfM if it exists but falls back
45505      * to the `originalLngLat` from the EXIF GPS otherwise {@link Image.lngLat}.
45506      *
45507      * Everything that is done in in the Viewer is based on the SfM positions,
45508      * i.e. `computedLngLat`. That is why the smooth transitions go in the right
45509      * direction (nd not in strange directions because of bad GPS).
45510      *
45511      * E.g. when placing a marker in the Viewer it is relative to the SfM
45512      * position i.e. the `computedLngLat`.
45513      *
45514      * The same concept as above also applies to the compass angle (or bearing) properties
45515      * `originalCa`, `computedCa` and `ca`.
45516      */
45517     class Image$1 {
45518         /**
45519          * Create a new image instance.
45520          *
45521          * @description Images are always created internally by the library.
45522          * Images can not be added to the library through any API method.
45523          *
45524          * @param {CoreImageEnt} core- Raw core image data.
45525          * @ignore
45526          */
45527         constructor(core) {
45528             if (!core) {
45529                 throw new Error(`Incorrect core image data ${core}`);
45530             }
45531             this._cache = null;
45532             this._core = core;
45533             this._spatial = null;
45534         }
45535         /**
45536          * Get assets cached.
45537          *
45538          * @description The assets that need to be cached for this property
45539          * to report true are the following: fill properties, image and mesh.
45540          * The library ensures that the current image will always have the
45541          * assets cached.
45542          *
45543          * @returns {boolean} Value indicating whether all assets have been
45544          * cached.
45545          *
45546          * @ignore
45547          */
45548         get assetsCached() {
45549             return this._core != null &&
45550                 this._spatial != null &&
45551                 this._cache != null &&
45552                 this._cache.image != null &&
45553                 this._cache.mesh != null;
45554         }
45555         /**
45556          * Get cameraParameters.
45557          *
45558          * @description Will be undefined if SfM has
45559          * not been run.
45560          *
45561          * Camera type dependent parameters.
45562          *
45563          * For perspective and fisheye camera types,
45564          * the camera parameters array should be
45565          * constructed according to
45566          *
45567          * `[focal, k1, k2]`
45568          *
45569          * where focal is the camera focal length,
45570          * and k1, k2 are radial distortion parameters.
45571          *
45572          * For spherical camera type the camera
45573          * parameters are unset or emtpy array.
45574          *
45575          * @returns {Array<number>} The parameters
45576          * related to the camera type.
45577          */
45578         get cameraParameters() {
45579             return this._spatial.camera_parameters;
45580         }
45581         /**
45582          * Get cameraType.
45583          *
45584          * @description Will be undefined if SfM has not been run.
45585          *
45586          * @returns {string} The camera type that captured the image.
45587          */
45588         get cameraType() {
45589             return this._spatial.camera_type;
45590         }
45591         /**
45592          * Get capturedAt.
45593          *
45594          * @description Timestamp of the image capture date
45595          * and time represented as a Unix epoch timestamp in milliseconds.
45596          *
45597          * @returns {number} Timestamp when the image was captured.
45598          */
45599         get capturedAt() {
45600             return this._spatial.captured_at;
45601         }
45602         /**
45603          * Get clusterId.
45604          *
45605          * @returns {string} Globally unique id of the SfM cluster to which
45606          * the image belongs.
45607          */
45608         get clusterId() {
45609             return !!this._spatial.cluster ?
45610                 this._spatial.cluster.id :
45611                 null;
45612         }
45613         /**
45614          * Get clusterUrl.
45615          *
45616          * @returns {string} Url to the cluster reconstruction file.
45617          *
45618          * @ignore
45619          */
45620         get clusterUrl() {
45621             return !!this._spatial.cluster ?
45622                 this._spatial.cluster.url :
45623                 null;
45624         }
45625         /**
45626          * Get compassAngle.
45627          *
45628          * @description If the SfM computed compass angle exists it will
45629          * be returned, otherwise the original EXIF compass angle.
45630          *
45631          * @returns {number} Compass angle, measured in degrees
45632          * clockwise with respect to north.
45633          */
45634         get compassAngle() {
45635             return this._spatial.computed_compass_angle != null ?
45636                 this._spatial.computed_compass_angle :
45637                 this._spatial.compass_angle;
45638         }
45639         /**
45640          * Get complete.
45641          *
45642          * @description The library ensures that the current image will
45643          * always be full.
45644          *
45645          * @returns {boolean} Value indicating whether the image has all
45646          * properties filled.
45647          *
45648          * @ignore
45649          */
45650         get complete() {
45651             return this._spatial != null;
45652         }
45653         /**
45654          * Get computedAltitude.
45655          *
45656          * @description If SfM has not been run the computed altitude is
45657          * set to a default value of two meters.
45658          *
45659          * @returns {number} Altitude, in meters.
45660          */
45661         get computedAltitude() {
45662             return this._spatial.computed_altitude;
45663         }
45664         /**
45665          * Get computedCompassAngle.
45666          *
45667          * @description Will not be set if SfM has not been run.
45668          *
45669          * @returns {number} SfM computed compass angle, measured
45670          * in degrees clockwise with respect to north.
45671          */
45672         get computedCompassAngle() {
45673             return this._spatial.computed_compass_angle;
45674         }
45675         /**
45676          * Get computedLngLat.
45677          *
45678          * @description Will not be set if SfM has not been run.
45679          *
45680          * @returns {LngLat} SfM computed longitude, latitude in WGS84 datum,
45681          * measured in degrees.
45682          */
45683         get computedLngLat() {
45684             return this._core.computed_geometry;
45685         }
45686         /**
45687          * Get creatorId.
45688          *
45689          * @description Note that the creator ID will not be set when using
45690          * the Mapillary API.
45691          *
45692          * @returns {string} Globally unique id of the user who uploaded
45693          * the image.
45694          */
45695         get creatorId() {
45696             return this._spatial.creator.id;
45697         }
45698         /**
45699          * Get creatorUsername.
45700          *
45701          * @description Note that the creator username will not be set when
45702          * using the Mapillary API.
45703          *
45704          * @returns {string} Username of the creator who uploaded
45705          * the image.
45706          */
45707         get creatorUsername() {
45708             return this._spatial.creator.username;
45709         }
45710         /**
45711          * Get exifOrientation.
45712          *
45713          * @returns {number} EXIF orientation of original image.
45714          */
45715         get exifOrientation() {
45716             return this._spatial.exif_orientation;
45717         }
45718         /**
45719          * Get height.
45720          *
45721          * @returns {number} Height of original image, not adjusted
45722          * for orientation.
45723          */
45724         get height() {
45725             return this._spatial.height;
45726         }
45727         /**
45728          * Get image.
45729          *
45730          * @description The image will always be set on the current image.
45731          *
45732          * @returns {HTMLImageElement} Cached image element of the image.
45733          */
45734         get image() {
45735             return this._cache.image;
45736         }
45737         /**
45738          * Get image$.
45739          *
45740          * @returns {Observable<HTMLImageElement>} Observable emitting
45741          * the cached image when it is updated.
45742          *
45743          * @ignore
45744          */
45745         get image$() {
45746             return this._cache.image$;
45747         }
45748         /**
45749          * Get id.
45750          *
45751          * @returns {string} Globally unique id of the image.
45752          */
45753         get id() {
45754             return this._core.id;
45755         }
45756         /**
45757          * Get lngLat.
45758          *
45759          * @description If the SfM computed longitude, latitude exist
45760          * it will be returned, otherwise the original EXIF latitude
45761          * longitude.
45762          *
45763          * @returns {LngLat} Longitude, latitude in WGS84 datum,
45764          * measured in degrees.
45765          */
45766         get lngLat() {
45767             return this._core.computed_geometry != null ?
45768                 this._core.computed_geometry :
45769                 this._core.geometry;
45770         }
45771         /**
45772          * Get merged.
45773          *
45774          * @returns {boolean} Value indicating whether SfM has been
45775          * run on the image and the image has been merged into a
45776          * connected component.
45777          */
45778         get merged() {
45779             return this._spatial != null &&
45780                 this._spatial.merge_id != null;
45781         }
45782         /**
45783          * Get mergeId.
45784          *
45785          * @description Will not be set if SfM has not yet been run on
45786          * image.
45787          *
45788          * @returns {stirng} Id of connected component to which image
45789          * belongs after the aligning merge.
45790          */
45791         get mergeId() {
45792             return this._spatial.merge_id;
45793         }
45794         /**
45795          * Get mesh.
45796          *
45797          * @description The mesh will always be set on the current image.
45798          *
45799          * @returns {MeshContract} SfM triangulated mesh of reconstructed
45800          * atomic 3D points.
45801          */
45802         get mesh() {
45803             return this._cache.mesh;
45804         }
45805         /**
45806          * Get originalAltitude.
45807          *
45808          * @returns {number} EXIF altitude, in meters, if available.
45809          */
45810         get originalAltitude() {
45811             return this._spatial.altitude;
45812         }
45813         /**
45814          * Get originalCompassAngle.
45815          *
45816          * @returns {number} Original EXIF compass angle, measured in
45817          * degrees.
45818          */
45819         get originalCompassAngle() {
45820             return this._spatial.compass_angle;
45821         }
45822         /**
45823          * Get originalLngLat.
45824          *
45825          * @returns {LngLat} Original EXIF longitude, latitude in
45826          * WGS84 datum, measured in degrees.
45827          */
45828         get originalLngLat() {
45829             return this._core.geometry;
45830         }
45831         /**
45832          * Get ownerId.
45833          *
45834          * @returns {string} Globally unique id of the owner to which
45835          * the image belongs. If the image does not belong to an
45836          * owner the owner id will be undefined.
45837          */
45838         get ownerId() {
45839             return !!this._spatial.owner ?
45840                 this._spatial.owner.id :
45841                 null;
45842         }
45843         /**
45844          * Get private.
45845          *
45846          * @returns {boolean} Value specifying if image is accessible to
45847          * organization members only or to everyone.
45848          */
45849         get private() {
45850             return this._spatial.private;
45851         }
45852         /**
45853          * Get qualityScore.
45854          *
45855          * @returns {number} A number between zero and one
45856          * determining the quality of the image. Blurriness
45857          * (motion blur / out-of-focus), occlusion (camera
45858          * mount, ego vehicle, water-drops), windshield
45859          * reflections, bad illumination (exposure, glare),
45860          * and bad weather condition (fog, rain, snow)
45861          * affect the quality score.
45862          *
45863          * @description Value should be on the interval [0, 1].
45864          */
45865         get qualityScore() {
45866             return this._spatial.quality_score;
45867         }
45868         /**
45869          * Get rotation.
45870          *
45871          * @description Will not be set if SfM has not been run.
45872          *
45873          * @returns {Array<number>} Rotation vector in angle axis representation.
45874          */
45875         get rotation() {
45876             return this._spatial.computed_rotation;
45877         }
45878         /**
45879          * Get scale.
45880          *
45881          * @description Will not be set if SfM has not been run.
45882          *
45883          * @returns {number} Scale of reconstruction the image
45884          * belongs to.
45885          */
45886         get scale() {
45887             return this._spatial.atomic_scale;
45888         }
45889         /**
45890          * Get sequenceId.
45891          *
45892          * @returns {string} Globally unique id of the sequence
45893          * to which the image belongs.
45894          */
45895         get sequenceId() {
45896             return !!this._core.sequence ?
45897                 this._core.sequence.id :
45898                 null;
45899         }
45900         /**
45901          * Get sequenceEdges.
45902          *
45903          * @returns {NavigationEdgeStatus} Value describing the status of the
45904          * sequence edges.
45905          *
45906          * @ignore
45907          */
45908         get sequenceEdges() {
45909             return this._cache.sequenceEdges;
45910         }
45911         /**
45912          * Get sequenceEdges$.
45913          *
45914          * @description Internal observable, should not be used as an API.
45915          *
45916          * @returns {Observable<NavigationEdgeStatus>} Observable emitting
45917          * values describing the status of the sequence edges.
45918          *
45919          * @ignore
45920          */
45921         get sequenceEdges$() {
45922             return this._cache.sequenceEdges$;
45923         }
45924         /**
45925          * Get spatialEdges.
45926          *
45927          * @returns {NavigationEdgeStatus} Value describing the status of the
45928          * spatial edges.
45929          *
45930          * @ignore
45931          */
45932         get spatialEdges() {
45933             return this._cache.spatialEdges;
45934         }
45935         /**
45936          * Get spatialEdges$.
45937          *
45938          * @description Internal observable, should not be used as an API.
45939          *
45940          * @returns {Observable<NavigationEdgeStatus>} Observable emitting
45941          * values describing the status of the spatial edges.
45942          *
45943          * @ignore
45944          */
45945         get spatialEdges$() {
45946             return this._cache.spatialEdges$;
45947         }
45948         /**
45949          * Get width.
45950          *
45951          * @returns {number} Width of original image, not
45952          * adjusted for orientation.
45953          */
45954         get width() {
45955             return this._spatial.width;
45956         }
45957         /**
45958          * Cache the image and mesh assets.
45959          *
45960          * @description The assets are always cached internally by the
45961          * library prior to setting a image as the current image.
45962          *
45963          * @returns {Observable<Image>} Observable emitting this image whenever the
45964          * load status has changed and when the mesh or image has been fully loaded.
45965          *
45966          * @ignore
45967          */
45968         cacheAssets$() {
45969             return this._cache
45970                 .cacheAssets$(this._spatial, this.merged)
45971                 .pipe(map(() => { return this; }));
45972         }
45973         /**
45974          * Cache the image asset.
45975          *
45976          * @description Use for caching a differently sized image than
45977          * the one currently held by the image.
45978          *
45979          * @returns {Observable<Image>} Observable emitting this image whenever the
45980          * load status has changed and when the mesh or image has been fully loaded.
45981          *
45982          * @ignore
45983          */
45984         cacheImage$() {
45985             return this._cache
45986                 .cacheImage$(this._spatial)
45987                 .pipe(map(() => { return this; }));
45988         }
45989         /**
45990          * Cache the sequence edges.
45991          *
45992          * @description The sequence edges are cached asynchronously
45993          * internally by the library.
45994          *
45995          * @param {Array<NavigationEdge>} edges - Sequence edges to cache.
45996          * @ignore
45997          */
45998         cacheSequenceEdges(edges) {
45999             this._cache.cacheSequenceEdges(edges);
46000         }
46001         /**
46002          * Cache the spatial edges.
46003          *
46004          * @description The spatial edges are cached asynchronously
46005          * internally by the library.
46006          *
46007          * @param {Array<NavigationEdge>} edges - Spatial edges to cache.
46008          * @ignore
46009          */
46010         cacheSpatialEdges(edges) {
46011             this._cache.cacheSpatialEdges(edges);
46012         }
46013         /**
46014          * Dispose the image.
46015          *
46016          * @description Disposes all cached assets.
46017          * @ignore
46018          */
46019         dispose() {
46020             if (this._cache != null) {
46021                 this._cache.dispose();
46022                 this._cache = null;
46023             }
46024             this._core = null;
46025             this._spatial = null;
46026         }
46027         /**
46028          * Initialize the image cache.
46029          *
46030          * @description The image cache is initialized internally by
46031          * the library.
46032          *
46033          * @param {ImageCache} cache - The image cache to set as cache.
46034          * @ignore
46035          */
46036         initializeCache(cache) {
46037             if (this._cache != null) {
46038                 throw new Error(`Image cache already initialized (${this.id}).`);
46039             }
46040             this._cache = cache;
46041         }
46042         /**
46043          * Complete an image with spatial properties.
46044          *
46045          * @description The image is completed internally by
46046          * the library.
46047          *
46048          * @param {SpatialImageEnt} fill - The spatial image struct.
46049          * @ignore
46050          */
46051         makeComplete(fill) {
46052             if (fill == null) {
46053                 throw new Error("Fill can not be null.");
46054             }
46055             this._spatial = fill;
46056         }
46057         /**
46058          * Reset the sequence edges.
46059          *
46060          * @ignore
46061          */
46062         resetSequenceEdges() {
46063             this._cache.resetSequenceEdges();
46064         }
46065         /**
46066          * Reset the spatial edges.
46067          *
46068          * @ignore
46069          */
46070         resetSpatialEdges() {
46071             this._cache.resetSpatialEdges();
46072         }
46073         /**
46074          * Clears the image and mesh assets, aborts
46075          * any outstanding requests and resets edges.
46076          *
46077          * @ignore
46078          */
46079         uncache() {
46080             if (this._cache == null) {
46081                 return;
46082             }
46083             this._cache.dispose();
46084             this._cache = null;
46085         }
46086     }
46087
46088     /**
46089      * @class ImageCache
46090      *
46091      * @classdesc Represents the cached properties of a image.
46092      */
46093     class ImageCache {
46094         /**
46095          * Create a new image cache instance.
46096          */
46097         constructor(provider) {
46098             this._disposed = false;
46099             this._provider = provider;
46100             this._image = null;
46101             this._mesh = null;
46102             this._sequenceEdges = { cached: false, edges: [] };
46103             this._spatialEdges = { cached: false, edges: [] };
46104             this._imageChanged$ = new Subject();
46105             this._image$ = this._imageChanged$.pipe(startWith(null), publishReplay(1), refCount());
46106             this._iamgeSubscription = this._image$.subscribe();
46107             this._sequenceEdgesChanged$ = new Subject();
46108             this._sequenceEdges$ = this._sequenceEdgesChanged$.pipe(startWith(this._sequenceEdges), publishReplay(1), refCount());
46109             this._sequenceEdgesSubscription = this._sequenceEdges$.subscribe(() => { });
46110             this._spatialEdgesChanged$ = new Subject();
46111             this._spatialEdges$ = this._spatialEdgesChanged$.pipe(startWith(this._spatialEdges), publishReplay(1), refCount());
46112             this._spatialEdgesSubscription = this._spatialEdges$.subscribe(() => { });
46113             this._cachingAssets$ = null;
46114         }
46115         /**
46116          * Get image.
46117          *
46118          * @description Will not be set when assets have not been cached
46119          * or when the object has been disposed.
46120          *
46121          * @returns {HTMLImageElement} Cached image element of the image.
46122          */
46123         get image() {
46124             return this._image;
46125         }
46126         /**
46127          * Get image$.
46128          *
46129          * @returns {Observable<HTMLImageElement>} Observable emitting
46130          * the cached image when it is updated.
46131          */
46132         get image$() {
46133             return this._image$;
46134         }
46135         /**
46136          * Get mesh.
46137          *
46138          * @description Will not be set when assets have not been cached
46139          * or when the object has been disposed.
46140          *
46141          * @returns {MeshContract} SfM triangulated mesh of reconstructed
46142          * atomic 3D points.
46143          */
46144         get mesh() {
46145             return this._mesh;
46146         }
46147         /**
46148          * Get sequenceEdges.
46149          *
46150          * @returns {NavigationEdgeStatus} Value describing the status of the
46151          * sequence edges.
46152          */
46153         get sequenceEdges() {
46154             return this._sequenceEdges;
46155         }
46156         /**
46157          * Get sequenceEdges$.
46158          *
46159          * @returns {Observable<NavigationEdgeStatus>} Observable emitting
46160          * values describing the status of the sequence edges.
46161          */
46162         get sequenceEdges$() {
46163             return this._sequenceEdges$;
46164         }
46165         /**
46166          * Get spatialEdges.
46167          *
46168          * @returns {NavigationEdgeStatus} Value describing the status of the
46169          * spatial edges.
46170          */
46171         get spatialEdges() {
46172             return this._spatialEdges;
46173         }
46174         /**
46175          * Get spatialEdges$.
46176          *
46177          * @returns {Observable<NavigationEdgeStatus>} Observable emitting
46178          * values describing the status of the spatial edges.
46179          */
46180         get spatialEdges$() {
46181             return this._spatialEdges$;
46182         }
46183         /**
46184          * Cache the image and mesh assets.
46185          *
46186          * @param {SpatialImageEnt} spatial - Spatial props of the image to cache.
46187          * @param {boolean} spherical - Value indicating whether image is a spherical.
46188          * @param {boolean} merged - Value indicating whether image is merged.
46189          * @returns {Observable<ImageCache>} Observable emitting this image
46190          * cache whenever the load status has changed and when the mesh or image
46191          * has been fully loaded.
46192          */
46193         cacheAssets$(spatial, merged) {
46194             if (this._cachingAssets$ != null) {
46195                 return this._cachingAssets$;
46196             }
46197             this._cachingAssets$ = combineLatest(this._cacheImage$(spatial), this._cacheMesh$(spatial, merged)).pipe(map(([image, mesh]) => {
46198                 this._image = image;
46199                 this._mesh = mesh;
46200                 return this;
46201             }), finalize(() => {
46202                 this._cachingAssets$ = null;
46203             }), publishReplay(1), refCount());
46204             this._cachingAssets$.pipe(first((imageCache) => {
46205                 return !!imageCache._image;
46206             }))
46207                 .subscribe(() => {
46208                 this._imageChanged$.next(this._image);
46209             }, () => { });
46210             return this._cachingAssets$;
46211         }
46212         /**
46213          * Cache an image with a higher resolution than the current one.
46214          *
46215          * @param {SpatialImageEnt} spatial - Spatial props.
46216          * @returns {Observable<ImageCache>} Observable emitting a single item,
46217          * the image cache, when the image has been cached. If supplied image
46218          * size is not larger than the current image size the image cache is
46219          * returned immediately.
46220          */
46221         cacheImage$(spatial) {
46222             if (this._image != null) {
46223                 return of(this);
46224             }
46225             const cacheImage$ = this._cacheImage$(spatial)
46226                 .pipe(first((image) => {
46227                 return !!image;
46228             }), tap((image) => {
46229                 this._disposeImage();
46230                 this._image = image;
46231             }), map(() => {
46232                 return this;
46233             }), publishReplay(1), refCount());
46234             cacheImage$
46235                 .subscribe(() => {
46236                 this._imageChanged$.next(this._image);
46237             }, () => { });
46238             return cacheImage$;
46239         }
46240         /**
46241          * Cache the sequence edges.
46242          *
46243          * @param {Array<NavigationEdge>} edges - Sequence edges to cache.
46244          */
46245         cacheSequenceEdges(edges) {
46246             this._sequenceEdges = { cached: true, edges: edges };
46247             this._sequenceEdgesChanged$.next(this._sequenceEdges);
46248         }
46249         /**
46250          * Cache the spatial edges.
46251          *
46252          * @param {Array<NavigationEdge>} edges - Spatial edges to cache.
46253          */
46254         cacheSpatialEdges(edges) {
46255             this._spatialEdges = { cached: true, edges: edges };
46256             this._spatialEdgesChanged$.next(this._spatialEdges);
46257         }
46258         /**
46259          * Dispose the image cache.
46260          *
46261          * @description Disposes all cached assets and unsubscribes to
46262          * all streams.
46263          */
46264         dispose() {
46265             this._iamgeSubscription.unsubscribe();
46266             this._sequenceEdgesSubscription.unsubscribe();
46267             this._spatialEdgesSubscription.unsubscribe();
46268             this._disposeImage();
46269             this._mesh = null;
46270             this._sequenceEdges = { cached: false, edges: [] };
46271             this._spatialEdges = { cached: false, edges: [] };
46272             this._imageChanged$.next(null);
46273             this._sequenceEdgesChanged$.next(this._sequenceEdges);
46274             this._spatialEdgesChanged$.next(this._spatialEdges);
46275             this._disposed = true;
46276             if (this._imageAborter != null) {
46277                 this._imageAborter();
46278                 this._imageAborter = null;
46279             }
46280             if (this._meshAborter != null) {
46281                 this._meshAborter();
46282                 this._meshAborter = null;
46283             }
46284         }
46285         /**
46286          * Reset the sequence edges.
46287          */
46288         resetSequenceEdges() {
46289             this._sequenceEdges = { cached: false, edges: [] };
46290             this._sequenceEdgesChanged$.next(this._sequenceEdges);
46291         }
46292         /**
46293          * Reset the spatial edges.
46294          */
46295         resetSpatialEdges() {
46296             this._spatialEdges = { cached: false, edges: [] };
46297             this._spatialEdgesChanged$.next(this._spatialEdges);
46298         }
46299         /**
46300          * Cache the image.
46301          *
46302          * @param {SpatialImageEnt} spatial - Spatial image.
46303          * @param {boolean} spherical - Value indicating whether image is a spherical.
46304          * @returns {Observable<ILoadStatusObject<HTMLImageElement>>} Observable
46305          * emitting a load status object every time the load status changes
46306          * and completes when the image is fully loaded.
46307          */
46308         _cacheImage$(spatial) {
46309             return Observable.create((subscriber) => {
46310                 const abort = new Promise((_, reject) => {
46311                     this._imageAborter = reject;
46312                 });
46313                 const url = spatial.thumb.url;
46314                 if (!url) {
46315                     const thumbId = spatial.thumb.id;
46316                     const message = `Incorrect thumb URL for ${spatial.id} ` +
46317                         `(${thumbId}, ${url})`;
46318                     subscriber.error(new Error(message));
46319                     return;
46320                 }
46321                 this._provider.getImageBuffer(url, abort)
46322                     .then((buffer) => {
46323                     this._imageAborter = null;
46324                     const image = new Image();
46325                     image.crossOrigin = "Anonymous";
46326                     image.onload = () => {
46327                         if (this._disposed) {
46328                             window.URL.revokeObjectURL(image.src);
46329                             const message = `Image load was aborted (${url})`;
46330                             subscriber.error(new Error(message));
46331                             return;
46332                         }
46333                         subscriber.next(image);
46334                         subscriber.complete();
46335                     };
46336                     image.onerror = () => {
46337                         this._imageAborter = null;
46338                         subscriber.error(new Error(`Failed to load image (${url})`));
46339                     };
46340                     const blob = new Blob([buffer]);
46341                     image.src = window.URL.createObjectURL(blob);
46342                 }, (error) => {
46343                     this._imageAborter = null;
46344                     subscriber.error(error);
46345                 });
46346             });
46347         }
46348         /**
46349          * Cache the mesh.
46350          *
46351          * @param {SpatialImageEnt} spatial - Spatial props.
46352          * @param {boolean} merged - Value indicating whether image is merged.
46353          * @returns {Observable<ILoadStatusObject<MeshContract>>} Observable emitting
46354          * a load status object every time the load status changes and completes
46355          * when the mesh is fully loaded.
46356          */
46357         _cacheMesh$(spatial, merged) {
46358             return Observable.create((subscriber) => {
46359                 if (!merged) {
46360                     subscriber.next(this._createEmptyMesh());
46361                     subscriber.complete();
46362                     return;
46363                 }
46364                 const url = spatial.mesh.url;
46365                 if (!url) {
46366                     const meshId = spatial.mesh.id;
46367                     const message = `Incorrect mesh URL for ${spatial.id} ` +
46368                         `(${meshId}, ${url})`;
46369                     console.warn(message);
46370                     subscriber.next(this._createEmptyMesh());
46371                     subscriber.complete();
46372                     return;
46373                 }
46374                 const abort = new Promise((_, reject) => {
46375                     this._meshAborter = reject;
46376                 });
46377                 this._provider.getMesh(url, abort)
46378                     .then((mesh) => {
46379                     this._meshAborter = null;
46380                     if (this._disposed) {
46381                         return;
46382                     }
46383                     subscriber.next(mesh);
46384                     subscriber.complete();
46385                 }, (error) => {
46386                     this._meshAborter = null;
46387                     console.error(error);
46388                     subscriber.next(this._createEmptyMesh());
46389                     subscriber.complete();
46390                 });
46391             });
46392         }
46393         /**
46394          * Create a load status object with an empty mesh.
46395          *
46396          * @returns {ILoadStatusObject<MeshContract>} Load status object
46397          * with empty mesh.
46398          */
46399         _createEmptyMesh() {
46400             return { faces: [], vertices: [] };
46401         }
46402         _disposeImage() {
46403             if (this._image != null) {
46404                 window.URL.revokeObjectURL(this._image.src);
46405             }
46406             this._image = null;
46407         }
46408     }
46409
46410     /**
46411      * @class Sequence
46412      *
46413      * @classdesc Represents a sequence of ordered images.
46414      */
46415     class Sequence {
46416         /**
46417          * Create a new sequene instance.
46418          *
46419          * @param {SequenceEnt} sequence - Raw sequence data.
46420          */
46421         constructor(sequence) {
46422             this._id = sequence.id;
46423             this._imageIds = sequence.image_ids;
46424         }
46425         /**
46426          * Get id.
46427          *
46428          * @returns {string} Unique sequence id.
46429          */
46430         get id() {
46431             return this._id;
46432         }
46433         /**
46434          * Get ids.
46435          *
46436          * @returns {Array<string>} Array of ordered image ids in the sequence.
46437          */
46438         get imageIds() {
46439             return this._imageIds;
46440         }
46441         /**
46442          * Dispose the sequence.
46443          *
46444          * @description Disposes all cached assets.
46445          */
46446         dispose() {
46447             this._id = null;
46448             this._imageIds = null;
46449         }
46450         /**
46451          * Find the next image id in the sequence with respect to
46452          * the provided image id.
46453          *
46454          * @param {string} id - Reference image id.
46455          * @returns {string} Next id in sequence if it exists, null otherwise.
46456          */
46457         findNext(id) {
46458             let i = this._imageIds.indexOf(id);
46459             if ((i + 1) >= this._imageIds.length || i === -1) {
46460                 return null;
46461             }
46462             else {
46463                 return this._imageIds[i + 1];
46464             }
46465         }
46466         /**
46467          * Find the previous image id in the sequence with respect to
46468          * the provided image id.
46469          *
46470          * @param {string} id - Reference image id.
46471          * @returns {string} Previous id in sequence if it exists, null otherwise.
46472          */
46473         findPrev(id) {
46474             let i = this._imageIds.indexOf(id);
46475             if (i === 0 || i === -1) {
46476                 return null;
46477             }
46478             else {
46479                 return this._imageIds[i - 1];
46480             }
46481         }
46482     }
46483
46484     class EdgeCalculatorCoefficients {
46485         constructor() {
46486             this.sphericalPreferredDistance = 2;
46487             this.sphericalMotion = 2;
46488             this.sphericalSequencePenalty = 1;
46489             this.sphericalMergeCCPenalty = 4;
46490             this.stepPreferredDistance = 4;
46491             this.stepMotion = 3;
46492             this.stepRotation = 4;
46493             this.stepSequencePenalty = 2;
46494             this.stepMergeCCPenalty = 6;
46495             this.similarDistance = 2;
46496             this.similarRotation = 3;
46497             this.turnDistance = 4;
46498             this.turnMotion = 2;
46499             this.turnSequencePenalty = 1;
46500             this.turnMergeCCPenalty = 4;
46501         }
46502     }
46503
46504     /**
46505      * Enumeration for edge directions
46506      * @enum {number}
46507      * @readonly
46508      * @description Directions for edges in image graph describing
46509      * sequence, spatial and image type relations between nodes.
46510      */
46511     exports.NavigationDirection = void 0;
46512     (function (NavigationDirection) {
46513         /**
46514          * Next image in the sequence.
46515          */
46516         NavigationDirection[NavigationDirection["Next"] = 0] = "Next";
46517         /**
46518          * Previous image in the sequence.
46519          */
46520         NavigationDirection[NavigationDirection["Prev"] = 1] = "Prev";
46521         /**
46522          * Step to the left keeping viewing direction.
46523          */
46524         NavigationDirection[NavigationDirection["StepLeft"] = 2] = "StepLeft";
46525         /**
46526          * Step to the right keeping viewing direction.
46527          */
46528         NavigationDirection[NavigationDirection["StepRight"] = 3] = "StepRight";
46529         /**
46530          * Step forward keeping viewing direction.
46531          */
46532         NavigationDirection[NavigationDirection["StepForward"] = 4] = "StepForward";
46533         /**
46534          * Step backward keeping viewing direction.
46535          */
46536         NavigationDirection[NavigationDirection["StepBackward"] = 5] = "StepBackward";
46537         /**
46538          * Turn 90 degrees counter clockwise.
46539          */
46540         NavigationDirection[NavigationDirection["TurnLeft"] = 6] = "TurnLeft";
46541         /**
46542          * Turn 90 degrees clockwise.
46543          */
46544         NavigationDirection[NavigationDirection["TurnRight"] = 7] = "TurnRight";
46545         /**
46546          * Turn 180 degrees.
46547          */
46548         NavigationDirection[NavigationDirection["TurnU"] = 8] = "TurnU";
46549         /**
46550          * Spherical in general direction.
46551          */
46552         NavigationDirection[NavigationDirection["Spherical"] = 9] = "Spherical";
46553         /**
46554          * Looking in roughly the same direction at rougly the same position.
46555          */
46556         NavigationDirection[NavigationDirection["Similar"] = 10] = "Similar";
46557     })(exports.NavigationDirection || (exports.NavigationDirection = {}));
46558
46559     class EdgeCalculatorDirections {
46560         constructor() {
46561             this.steps = {};
46562             this.turns = {};
46563             this.spherical = {};
46564             this.steps[exports.NavigationDirection.StepForward] = {
46565                 direction: exports.NavigationDirection.StepForward,
46566                 motionChange: 0,
46567                 useFallback: true,
46568             };
46569             this.steps[exports.NavigationDirection.StepBackward] = {
46570                 direction: exports.NavigationDirection.StepBackward,
46571                 motionChange: Math.PI,
46572                 useFallback: true,
46573             };
46574             this.steps[exports.NavigationDirection.StepLeft] = {
46575                 direction: exports.NavigationDirection.StepLeft,
46576                 motionChange: Math.PI / 2,
46577                 useFallback: false,
46578             };
46579             this.steps[exports.NavigationDirection.StepRight] = {
46580                 direction: exports.NavigationDirection.StepRight,
46581                 motionChange: -Math.PI / 2,
46582                 useFallback: false,
46583             };
46584             this.turns[exports.NavigationDirection.TurnLeft] = {
46585                 direction: exports.NavigationDirection.TurnLeft,
46586                 directionChange: Math.PI / 2,
46587                 motionChange: Math.PI / 4,
46588             };
46589             this.turns[exports.NavigationDirection.TurnRight] = {
46590                 direction: exports.NavigationDirection.TurnRight,
46591                 directionChange: -Math.PI / 2,
46592                 motionChange: -Math.PI / 4,
46593             };
46594             this.turns[exports.NavigationDirection.TurnU] = {
46595                 direction: exports.NavigationDirection.TurnU,
46596                 directionChange: Math.PI,
46597                 motionChange: null,
46598             };
46599             this.spherical[exports.NavigationDirection.StepForward] = {
46600                 direction: exports.NavigationDirection.StepForward,
46601                 directionChange: 0,
46602                 next: exports.NavigationDirection.StepLeft,
46603                 prev: exports.NavigationDirection.StepRight,
46604             };
46605             this.spherical[exports.NavigationDirection.StepBackward] = {
46606                 direction: exports.NavigationDirection.StepBackward,
46607                 directionChange: Math.PI,
46608                 next: exports.NavigationDirection.StepRight,
46609                 prev: exports.NavigationDirection.StepLeft,
46610             };
46611             this.spherical[exports.NavigationDirection.StepLeft] = {
46612                 direction: exports.NavigationDirection.StepLeft,
46613                 directionChange: Math.PI / 2,
46614                 next: exports.NavigationDirection.StepBackward,
46615                 prev: exports.NavigationDirection.StepForward,
46616             };
46617             this.spherical[exports.NavigationDirection.StepRight] = {
46618                 direction: exports.NavigationDirection.StepRight,
46619                 directionChange: -Math.PI / 2,
46620                 next: exports.NavigationDirection.StepForward,
46621                 prev: exports.NavigationDirection.StepBackward,
46622             };
46623         }
46624     }
46625
46626     class EdgeCalculatorSettings {
46627         constructor() {
46628             this.sphericalMinDistance = 0.1;
46629             this.sphericalMaxDistance = 20;
46630             this.sphericalPreferredDistance = 5;
46631             this.sphericalMaxItems = 4;
46632             this.sphericalMaxStepTurnChange = Math.PI / 8;
46633             this.rotationMaxDistance = this.turnMaxRigDistance;
46634             this.rotationMaxDirectionChange = Math.PI / 6;
46635             this.rotationMaxVerticalDirectionChange = Math.PI / 8;
46636             this.similarMaxDirectionChange = Math.PI / 8;
46637             this.similarMaxDistance = 12;
46638             this.similarMinTimeDifference = 12 * 3600 * 1000;
46639             this.stepMaxDistance = 20;
46640             this.stepMaxDirectionChange = Math.PI / 6;
46641             this.stepMaxDrift = Math.PI / 6;
46642             this.stepPreferredDistance = 4;
46643             this.turnMaxDistance = 15;
46644             this.turnMaxDirectionChange = 2 * Math.PI / 9;
46645             this.turnMaxRigDistance = 0.65;
46646             this.turnMinRigDirectionChange = Math.PI / 6;
46647         }
46648         get maxDistance() {
46649             return Math.max(this.sphericalMaxDistance, this.similarMaxDistance, this.stepMaxDistance, this.turnMaxDistance);
46650         }
46651     }
46652
46653     /**
46654      * @class MapillaryError
46655      *
46656      * @classdesc Generic Mapillary error.
46657      */
46658     class MapillaryError extends Error {
46659         constructor(message) {
46660             super(message);
46661             Object.setPrototypeOf(this, MapillaryError.prototype);
46662             this.name = "MapillaryError";
46663         }
46664     }
46665
46666     class ArgumentMapillaryError extends MapillaryError {
46667         constructor(message) {
46668             super(message != null ? message : "The argument is not valid.");
46669             Object.setPrototypeOf(this, ArgumentMapillaryError.prototype);
46670             this.name = "ArgumentMapillaryError";
46671         }
46672     }
46673
46674     /**
46675      * @class Spatial
46676      *
46677      * @classdesc Provides methods for scalar, vector and matrix calculations.
46678      */
46679     class Spatial {
46680         constructor() {
46681             this._epsilon = 1e-9;
46682         }
46683         /**
46684          * Converts azimuthal phi rotation (counter-clockwise with origin on X-axis) to
46685          * bearing (clockwise with origin at north or Y-axis).
46686          *
46687          * @param {number} phi - Azimuthal phi angle in radians.
46688          * @returns {number} Bearing in radians.
46689          */
46690         azimuthalToBearing(phi) {
46691             return -phi + Math.PI / 2;
46692         }
46693         /**
46694          * Converts degrees to radians.
46695          *
46696          * @param {number} deg - Degrees.
46697          * @returns {number} Radians.
46698          */
46699         degToRad(deg) {
46700             return Math.PI * deg / 180;
46701         }
46702         /**
46703          * Converts radians to degrees.
46704          *
46705          * @param {number} rad - Radians.
46706          * @returns {number} Degrees.
46707          */
46708         radToDeg(rad) {
46709             return 180 * rad / Math.PI;
46710         }
46711         /**
46712          * Creates a rotation matrix from an angle-axis vector.
46713          *
46714          * @param {Array<number>} angleAxis - Angle-axis representation of a rotation.
46715          * @returns {THREE.Matrix4} Rotation matrix.
46716          */
46717         rotationMatrix(angleAxis) {
46718             let axis = new Vector3(angleAxis[0], angleAxis[1], angleAxis[2]);
46719             let angle = axis.length();
46720             if (angle > 0) {
46721                 axis.normalize();
46722             }
46723             return new Matrix4().makeRotationAxis(axis, angle);
46724         }
46725         /**
46726          * Rotates a vector according to a angle-axis rotation vector.
46727          *
46728          * @param {Array<number>} vector - Vector to rotate.
46729          * @param {Array<number>} angleAxis - Angle-axis representation of a rotation.
46730          * @returns {THREE.Vector3} Rotated vector.
46731          */
46732         rotate(vector, angleAxis) {
46733             let v = new Vector3(vector[0], vector[1], vector[2]);
46734             let rotationMatrix = this.rotationMatrix(angleAxis);
46735             v.applyMatrix4(rotationMatrix);
46736             return v;
46737         }
46738         /**
46739          * Calculates the optical center from a rotation vector
46740          * on the angle-axis representation and a translation vector
46741          * according to C = -R^T t.
46742          *
46743          * @param {Array<number>} rotation - Angle-axis representation of a rotation.
46744          * @param {Array<number>} translation - Translation vector.
46745          * @returns {THREE.Vector3} Optical center.
46746          */
46747         opticalCenter(rotation, translation) {
46748             let angleAxis = [-rotation[0], -rotation[1], -rotation[2]];
46749             let vector = [-translation[0], -translation[1], -translation[2]];
46750             return this.rotate(vector, angleAxis);
46751         }
46752         /**
46753          * Calculates the viewing direction from a rotation vector
46754          * on the angle-axis representation.
46755          *
46756          * @param {number[]} rotation - Angle-axis representation of a rotation.
46757          * @returns {THREE.Vector3} Viewing direction.
46758          */
46759         viewingDirection(rotation) {
46760             let angleAxis = [-rotation[0], -rotation[1], -rotation[2]];
46761             return this.rotate([0, 0, 1], angleAxis);
46762         }
46763         /**
46764          * Wrap a number on the interval [min, max].
46765          *
46766          * @param {number} value - Value to wrap.
46767          * @param {number} min - Lower endpoint of interval.
46768          * @param {number} max - Upper endpoint of interval.
46769          * @returns {number} The wrapped number.
46770          */
46771         wrap(value, min, max) {
46772             if (max < min) {
46773                 throw new Error("Invalid arguments: max must be larger than min.");
46774             }
46775             let interval = (max - min);
46776             while (value > max || value < min) {
46777                 if (value > max) {
46778                     value = value - interval;
46779                 }
46780                 else if (value < min) {
46781                     value = value + interval;
46782                 }
46783             }
46784             return value;
46785         }
46786         /**
46787          * Wrap an angle on the interval [-Pi, Pi].
46788          *
46789          * @param {number} angle - Value to wrap.
46790          * @returns {number} Wrapped angle.
46791          */
46792         wrapAngle(angle) {
46793             return this.wrap(angle, -Math.PI, Math.PI);
46794         }
46795         /**
46796          * Limit the value to the interval [min, max] by changing the value to
46797          * the nearest available one when it is outside the interval.
46798          *
46799          * @param {number} value - Value to clamp.
46800          * @param {number} min - Minimum of the interval.
46801          * @param {number} max - Maximum of the interval.
46802          * @returns {number} Clamped value.
46803          */
46804         clamp(value, min, max) {
46805             if (value < min) {
46806                 return min;
46807             }
46808             if (value > max) {
46809                 return max;
46810             }
46811             return value;
46812         }
46813         /**
46814          * Calculates the counter-clockwise angle from the first
46815          * vector (x1, y1)^T to the second (x2, y2)^T.
46816          *
46817          * @param {number} x1 - X coordinate of first vector.
46818          * @param {number} y1 - Y coordinate of first vector.
46819          * @param {number} x2 - X coordinate of second vector.
46820          * @param {number} y2 - Y coordinate of second vector.
46821          * @returns {number} Counter clockwise angle between the vectors.
46822          */
46823         angleBetweenVector2(x1, y1, x2, y2) {
46824             let angle = Math.atan2(y2, x2) - Math.atan2(y1, x1);
46825             return this.wrapAngle(angle);
46826         }
46827         /**
46828          * Calculates the minimum (absolute) angle change for rotation
46829          * from one angle to another on the [-Pi, Pi] interval.
46830          *
46831          * @param {number} angle1 - Start angle.
46832          * @param {number} angle2 - Destination angle.
46833          * @returns {number} Absolute angle change between angles.
46834          */
46835         angleDifference(angle1, angle2) {
46836             let angle = angle2 - angle1;
46837             return this.wrapAngle(angle);
46838         }
46839         /**
46840          * Calculates the relative rotation angle between two
46841          * angle-axis vectors.
46842          *
46843          * @param {number} rotation1 - First angle-axis vector.
46844          * @param {number} rotation2 - Second angle-axis vector.
46845          * @returns {number} Relative rotation angle.
46846          */
46847         relativeRotationAngle(rotation1, rotation2) {
46848             let R1T = this.rotationMatrix([-rotation1[0], -rotation1[1], -rotation1[2]]);
46849             let R2 = this.rotationMatrix(rotation2);
46850             let R = R1T.multiply(R2);
46851             let elements = R.elements;
46852             // from Tr(R) = 1 + 2 * cos(theta)
46853             let tr = elements[0] + elements[5] + elements[10];
46854             let theta = Math.acos(Math.max(Math.min((tr - 1) / 2, 1), -1));
46855             return theta;
46856         }
46857         /**
46858          * Calculates the angle from a vector to a plane.
46859          *
46860          * @param {Array<number>} vector - The vector.
46861          * @param {Array<number>} planeNormal - Normal of the plane.
46862          * @returns {number} Angle from between plane and vector.
46863          */
46864         angleToPlane(vector, planeNormal) {
46865             let v = new Vector3().fromArray(vector);
46866             let norm = v.length();
46867             if (norm < this._epsilon) {
46868                 return 0;
46869             }
46870             let projection = v.dot(new Vector3().fromArray(planeNormal));
46871             return Math.asin(projection / norm);
46872         }
46873         azimuthal(direction, up) {
46874             const directionVector = new Vector3().fromArray(direction);
46875             const upVector = new Vector3().fromArray(up);
46876             const upProjection = directionVector.clone().dot(upVector);
46877             const planeProjection = directionVector.clone().sub(upVector.clone().multiplyScalar(upProjection));
46878             return Math.atan2(planeProjection.y, planeProjection.x);
46879         }
46880         /**
46881          * Calculates the distance between two coordinates
46882          * (longitude, latitude pairs) in meters according to
46883          * the haversine formula.
46884          *
46885          * @param {number} lat1 - Latitude of the first coordinate in degrees.
46886          * @param {number} lng1 - Longitude of the first coordinate in degrees.
46887          * @param {number} lat2 - Latitude of the second coordinate in degrees.
46888          * @param {number} lng2 - Longitude of the second coordinate in degrees.
46889          * @returns {number} Distance between lat lon positions in meters.
46890          */
46891         distanceFromLngLat(lng1, lat1, lng2, lat2) {
46892             let r = 6371000;
46893             let dLat = this.degToRad(lat2 - lat1);
46894             let dLng = this.degToRad(lng2 - lng1);
46895             let hav = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
46896                 Math.cos(this.degToRad(lat1)) * Math.cos(this.degToRad(lat2)) *
46897                     Math.sin(dLng / 2) * Math.sin(dLng / 2);
46898             let d = 2 * r * Math.atan2(Math.sqrt(hav), Math.sqrt(1 - hav));
46899             return d;
46900         }
46901     }
46902
46903     const spatial = new Spatial();
46904     function isSpherical(cameraType) {
46905         return cameraType === "spherical";
46906     }
46907     function isFisheye(cameraType) {
46908         return cameraType === "fisheye";
46909     }
46910     function computeTranslation(position, rotation, reference) {
46911         const C = geodeticToEnu(position.lng, position.lat, position.alt, reference.lng, reference.lat, reference.alt);
46912         const RC = spatial.rotate(C, rotation);
46913         const translation = [-RC.x, -RC.y, -RC.z];
46914         return translation;
46915     }
46916     function computeProjectedPoints(transform, basicVertices, basicDirections, pointsPerLine, viewportCoords) {
46917         const basicPoints = [];
46918         for (let side = 0; side < basicVertices.length; ++side) {
46919             const v = basicVertices[side];
46920             const d = basicDirections[side];
46921             for (let i = 0; i <= pointsPerLine; ++i) {
46922                 basicPoints.push([v[0] + d[0] * i / pointsPerLine,
46923                     v[1] + d[1] * i / pointsPerLine]);
46924             }
46925         }
46926         const camera = new Camera$1();
46927         camera.up.copy(transform.upVector());
46928         camera.position.copy(new Vector3().fromArray(transform.unprojectSfM([0, 0], 0)));
46929         camera.lookAt(new Vector3().fromArray(transform.unprojectSfM([0, 0], 10)));
46930         camera.updateMatrix();
46931         camera.updateMatrixWorld(true);
46932         const projectedPoints = basicPoints
46933             .map((basicPoint) => {
46934             const worldPoint = transform.unprojectBasic(basicPoint, 10000);
46935             const cameraPoint = viewportCoords.worldToCamera(worldPoint, camera);
46936             return [
46937                 Math.abs(cameraPoint[0] / cameraPoint[2]),
46938                 Math.abs(cameraPoint[1] / cameraPoint[2]),
46939             ];
46940         });
46941         return projectedPoints;
46942     }
46943
46944     /**
46945      * @class EdgeCalculator
46946      *
46947      * @classdesc Represents a class for calculating node edges.
46948      */
46949     class EdgeCalculator {
46950         /**
46951          * Create a new edge calculator instance.
46952          *
46953          * @param {EdgeCalculatorSettings} settings - Settings struct.
46954          * @param {EdgeCalculatorDirections} directions - Directions struct.
46955          * @param {EdgeCalculatorCoefficients} coefficients - Coefficients struct.
46956          */
46957         constructor(settings, directions, coefficients) {
46958             this._spatial = new Spatial();
46959             this._settings = settings != null ? settings : new EdgeCalculatorSettings();
46960             this._directions = directions != null ? directions : new EdgeCalculatorDirections();
46961             this._coefficients = coefficients != null ? coefficients : new EdgeCalculatorCoefficients();
46962         }
46963         /**
46964          * Returns the potential edges to destination nodes for a set
46965          * of nodes with respect to a source node.
46966          *
46967          * @param {Image} node - Source node.
46968          * @param {Array<Image>} nodes - Potential destination nodes.
46969          * @param {Array<string>} fallbackIds - Ids for destination nodes
46970          * that should be returned even if they do not meet the
46971          * criteria for a potential edge.
46972          * @throws {ArgumentMapillaryError} If node is not full.
46973          */
46974         getPotentialEdges(node, potentialImages, fallbackIds) {
46975             if (!node.complete) {
46976                 throw new ArgumentMapillaryError("Image has to be full.");
46977             }
46978             if (!node.merged) {
46979                 return [];
46980             }
46981             let currentDirection = this._spatial.viewingDirection(node.rotation);
46982             let currentVerticalDirection = this._spatial.angleToPlane(currentDirection.toArray(), [0, 0, 1]);
46983             let potentialEdges = [];
46984             for (let potential of potentialImages) {
46985                 if (!potential.merged ||
46986                     potential.id === node.id) {
46987                     continue;
46988                 }
46989                 let enu = geodeticToEnu(potential.lngLat.lng, potential.lngLat.lat, potential.computedAltitude, node.lngLat.lng, node.lngLat.lat, node.computedAltitude);
46990                 let motion = new Vector3(enu[0], enu[1], enu[2]);
46991                 let distance = motion.length();
46992                 if (distance > this._settings.maxDistance &&
46993                     fallbackIds.indexOf(potential.id) < 0) {
46994                     continue;
46995                 }
46996                 let motionChange = this._spatial.angleBetweenVector2(currentDirection.x, currentDirection.y, motion.x, motion.y);
46997                 let verticalMotion = this._spatial.angleToPlane(motion.toArray(), [0, 0, 1]);
46998                 let direction = this._spatial.viewingDirection(potential.rotation);
46999                 let directionChange = this._spatial.angleBetweenVector2(currentDirection.x, currentDirection.y, direction.x, direction.y);
47000                 let verticalDirection = this._spatial.angleToPlane(direction.toArray(), [0, 0, 1]);
47001                 let verticalDirectionChange = verticalDirection - currentVerticalDirection;
47002                 let rotation = this._spatial.relativeRotationAngle(node.rotation, potential.rotation);
47003                 let worldMotionAzimuth = this._spatial.angleBetweenVector2(1, 0, motion.x, motion.y);
47004                 let sameSequence = potential.sequenceId != null &&
47005                     node.sequenceId != null &&
47006                     potential.sequenceId === node.sequenceId;
47007                 let sameMergeCC = potential.mergeId === node.mergeId;
47008                 let sameUser = potential.creatorId === node.creatorId;
47009                 let potentialEdge = {
47010                     capturedAt: potential.capturedAt,
47011                     directionChange: directionChange,
47012                     distance: distance,
47013                     spherical: isSpherical(potential.cameraType),
47014                     id: potential.id,
47015                     motionChange: motionChange,
47016                     rotation: rotation,
47017                     sameMergeCC: sameMergeCC,
47018                     sameSequence: sameSequence,
47019                     sameUser: sameUser,
47020                     sequenceId: potential.sequenceId,
47021                     verticalDirectionChange: verticalDirectionChange,
47022                     verticalMotion: verticalMotion,
47023                     worldMotionAzimuth: worldMotionAzimuth,
47024                 };
47025                 potentialEdges.push(potentialEdge);
47026             }
47027             return potentialEdges;
47028         }
47029         /**
47030          * Computes the sequence edges for a node.
47031          *
47032          * @param {Image} node - Source node.
47033          * @throws {ArgumentMapillaryError} If node is not full.
47034          */
47035         computeSequenceEdges(node, sequence) {
47036             if (!node.complete) {
47037                 throw new ArgumentMapillaryError("Image has to be full.");
47038             }
47039             if (node.sequenceId !== sequence.id) {
47040                 throw new ArgumentMapillaryError("Image and sequence does not correspond.");
47041             }
47042             let edges = [];
47043             let nextId = sequence.findNext(node.id);
47044             if (nextId != null) {
47045                 edges.push({
47046                     data: {
47047                         direction: exports.NavigationDirection.Next,
47048                         worldMotionAzimuth: Number.NaN,
47049                     },
47050                     source: node.id,
47051                     target: nextId,
47052                 });
47053             }
47054             let prevId = sequence.findPrev(node.id);
47055             if (prevId != null) {
47056                 edges.push({
47057                     data: {
47058                         direction: exports.NavigationDirection.Prev,
47059                         worldMotionAzimuth: Number.NaN,
47060                     },
47061                     source: node.id,
47062                     target: prevId,
47063                 });
47064             }
47065             return edges;
47066         }
47067         /**
47068          * Computes the similar edges for a node.
47069          *
47070          * @description Similar edges for perspective images
47071          * look roughly in the same direction and are positioned closed to the node.
47072          * Similar edges for spherical only target other spherical.
47073          *
47074          * @param {Image} node - Source node.
47075          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
47076          * @throws {ArgumentMapillaryError} If node is not full.
47077          */
47078         computeSimilarEdges(node, potentialEdges) {
47079             if (!node.complete) {
47080                 throw new ArgumentMapillaryError("Image has to be full.");
47081             }
47082             let nodeSpherical = isSpherical(node.cameraType);
47083             let sequenceGroups = {};
47084             for (let potentialEdge of potentialEdges) {
47085                 if (potentialEdge.sequenceId == null) {
47086                     continue;
47087                 }
47088                 if (potentialEdge.sameSequence) {
47089                     continue;
47090                 }
47091                 if (nodeSpherical) {
47092                     if (!potentialEdge.spherical) {
47093                         continue;
47094                     }
47095                 }
47096                 else {
47097                     if (!potentialEdge.spherical &&
47098                         Math.abs(potentialEdge.directionChange) > this._settings.similarMaxDirectionChange) {
47099                         continue;
47100                     }
47101                 }
47102                 if (potentialEdge.distance > this._settings.similarMaxDistance) {
47103                     continue;
47104                 }
47105                 if (potentialEdge.sameUser &&
47106                     Math.abs(potentialEdge.capturedAt - node.capturedAt) <
47107                         this._settings.similarMinTimeDifference) {
47108                     continue;
47109                 }
47110                 if (sequenceGroups[potentialEdge.sequenceId] == null) {
47111                     sequenceGroups[potentialEdge.sequenceId] = [];
47112                 }
47113                 sequenceGroups[potentialEdge.sequenceId].push(potentialEdge);
47114             }
47115             let similarEdges = [];
47116             let calculateScore = isSpherical(node.cameraType) ?
47117                 (potentialEdge) => {
47118                     return potentialEdge.distance;
47119                 } :
47120                 (potentialEdge) => {
47121                     return this._coefficients.similarDistance * potentialEdge.distance +
47122                         this._coefficients.similarRotation * potentialEdge.rotation;
47123                 };
47124             for (let sequenceId in sequenceGroups) {
47125                 if (!sequenceGroups.hasOwnProperty(sequenceId)) {
47126                     continue;
47127                 }
47128                 let lowestScore = Number.MAX_VALUE;
47129                 let similarEdge = null;
47130                 for (let potentialEdge of sequenceGroups[sequenceId]) {
47131                     let score = calculateScore(potentialEdge);
47132                     if (score < lowestScore) {
47133                         lowestScore = score;
47134                         similarEdge = potentialEdge;
47135                     }
47136                 }
47137                 if (similarEdge == null) {
47138                     continue;
47139                 }
47140                 similarEdges.push(similarEdge);
47141             }
47142             return similarEdges
47143                 .map((potentialEdge) => {
47144                 return {
47145                     data: {
47146                         direction: exports.NavigationDirection.Similar,
47147                         worldMotionAzimuth: potentialEdge.worldMotionAzimuth,
47148                     },
47149                     source: node.id,
47150                     target: potentialEdge.id,
47151                 };
47152             });
47153         }
47154         /**
47155          * Computes the step edges for a perspective node.
47156          *
47157          * @description Step edge targets can only be other perspective nodes.
47158          * Returns an empty array for spherical.
47159          *
47160          * @param {Image} node - Source node.
47161          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
47162          * @param {string} prevId - Id of previous node in sequence.
47163          * @param {string} nextId - Id of next node in sequence.
47164          * @throws {ArgumentMapillaryError} If node is not full.
47165          */
47166         computeStepEdges(node, potentialEdges, prevId, nextId) {
47167             if (!node.complete) {
47168                 throw new ArgumentMapillaryError("Image has to be full.");
47169             }
47170             let edges = [];
47171             if (isSpherical(node.cameraType)) {
47172                 return edges;
47173             }
47174             for (let k in this._directions.steps) {
47175                 if (!this._directions.steps.hasOwnProperty(k)) {
47176                     continue;
47177                 }
47178                 let step = this._directions.steps[k];
47179                 let lowestScore = Number.MAX_VALUE;
47180                 let edge = null;
47181                 let fallback = null;
47182                 for (let potential of potentialEdges) {
47183                     if (potential.spherical) {
47184                         continue;
47185                     }
47186                     if (Math.abs(potential.directionChange) > this._settings.stepMaxDirectionChange) {
47187                         continue;
47188                     }
47189                     let motionDifference = this._spatial.angleDifference(step.motionChange, potential.motionChange);
47190                     let directionMotionDifference = this._spatial.angleDifference(potential.directionChange, motionDifference);
47191                     let drift = Math.max(Math.abs(motionDifference), Math.abs(directionMotionDifference));
47192                     if (Math.abs(drift) > this._settings.stepMaxDrift) {
47193                         continue;
47194                     }
47195                     let potentialId = potential.id;
47196                     if (step.useFallback && (potentialId === prevId || potentialId === nextId)) {
47197                         fallback = potential;
47198                     }
47199                     if (potential.distance > this._settings.stepMaxDistance) {
47200                         continue;
47201                     }
47202                     motionDifference = Math.sqrt(motionDifference * motionDifference +
47203                         potential.verticalMotion * potential.verticalMotion);
47204                     let score = this._coefficients.stepPreferredDistance *
47205                         Math.abs(potential.distance - this._settings.stepPreferredDistance) /
47206                         this._settings.stepMaxDistance +
47207                         this._coefficients.stepMotion * motionDifference / this._settings.stepMaxDrift +
47208                         this._coefficients.stepRotation * potential.rotation / this._settings.stepMaxDirectionChange +
47209                         this._coefficients.stepSequencePenalty * (potential.sameSequence ? 0 : 1) +
47210                         this._coefficients.stepMergeCCPenalty * (potential.sameMergeCC ? 0 : 1);
47211                     if (score < lowestScore) {
47212                         lowestScore = score;
47213                         edge = potential;
47214                     }
47215                 }
47216                 edge = edge == null ? fallback : edge;
47217                 if (edge != null) {
47218                     edges.push({
47219                         data: {
47220                             direction: step.direction,
47221                             worldMotionAzimuth: edge.worldMotionAzimuth,
47222                         },
47223                         source: node.id,
47224                         target: edge.id,
47225                     });
47226                 }
47227             }
47228             return edges;
47229         }
47230         /**
47231          * Computes the turn edges for a perspective node.
47232          *
47233          * @description Turn edge targets can only be other perspective images.
47234          * Returns an empty array for spherical.
47235          *
47236          * @param {Image} node - Source node.
47237          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
47238          * @throws {ArgumentMapillaryError} If node is not full.
47239          */
47240         computeTurnEdges(node, potentialEdges) {
47241             if (!node.complete) {
47242                 throw new ArgumentMapillaryError("Image has to be full.");
47243             }
47244             let edges = [];
47245             if (isSpherical(node.cameraType)) {
47246                 return edges;
47247             }
47248             for (let k in this._directions.turns) {
47249                 if (!this._directions.turns.hasOwnProperty(k)) {
47250                     continue;
47251                 }
47252                 let turn = this._directions.turns[k];
47253                 let lowestScore = Number.MAX_VALUE;
47254                 let edge = null;
47255                 for (let potential of potentialEdges) {
47256                     if (potential.spherical) {
47257                         continue;
47258                     }
47259                     if (potential.distance > this._settings.turnMaxDistance) {
47260                         continue;
47261                     }
47262                     let rig = turn.direction !== exports.NavigationDirection.TurnU &&
47263                         potential.distance < this._settings.turnMaxRigDistance &&
47264                         Math.abs(potential.directionChange) > this._settings.turnMinRigDirectionChange;
47265                     let directionDifference = this._spatial.angleDifference(turn.directionChange, potential.directionChange);
47266                     let score;
47267                     if (rig &&
47268                         potential.directionChange * turn.directionChange > 0 &&
47269                         Math.abs(potential.directionChange) < Math.abs(turn.directionChange)) {
47270                         score = -Math.PI / 2 + Math.abs(potential.directionChange);
47271                     }
47272                     else {
47273                         if (Math.abs(directionDifference) > this._settings.turnMaxDirectionChange) {
47274                             continue;
47275                         }
47276                         let motionDifference = turn.motionChange ?
47277                             this._spatial.angleDifference(turn.motionChange, potential.motionChange) : 0;
47278                         motionDifference = Math.sqrt(motionDifference * motionDifference +
47279                             potential.verticalMotion * potential.verticalMotion);
47280                         score =
47281                             this._coefficients.turnDistance * potential.distance /
47282                                 this._settings.turnMaxDistance +
47283                                 this._coefficients.turnMotion * motionDifference / Math.PI +
47284                                 this._coefficients.turnSequencePenalty * (potential.sameSequence ? 0 : 1) +
47285                                 this._coefficients.turnMergeCCPenalty * (potential.sameMergeCC ? 0 : 1);
47286                     }
47287                     if (score < lowestScore) {
47288                         lowestScore = score;
47289                         edge = potential;
47290                     }
47291                 }
47292                 if (edge != null) {
47293                     edges.push({
47294                         data: {
47295                             direction: turn.direction,
47296                             worldMotionAzimuth: edge.worldMotionAzimuth,
47297                         },
47298                         source: node.id,
47299                         target: edge.id,
47300                     });
47301                 }
47302             }
47303             return edges;
47304         }
47305         /**
47306          * Computes the spherical edges for a perspective node.
47307          *
47308          * @description Perspective to spherical edge targets can only be
47309          * spherical nodes. Returns an empty array for spherical.
47310          *
47311          * @param {Image} node - Source node.
47312          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
47313          * @throws {ArgumentMapillaryError} If node is not full.
47314          */
47315         computePerspectiveToSphericalEdges(node, potentialEdges) {
47316             if (!node.complete) {
47317                 throw new ArgumentMapillaryError("Image has to be full.");
47318             }
47319             if (isSpherical(node.cameraType)) {
47320                 return [];
47321             }
47322             let lowestScore = Number.MAX_VALUE;
47323             let edge = null;
47324             for (let potential of potentialEdges) {
47325                 if (!potential.spherical) {
47326                     continue;
47327                 }
47328                 let score = this._coefficients.sphericalPreferredDistance *
47329                     Math.abs(potential.distance - this._settings.sphericalPreferredDistance) /
47330                     this._settings.sphericalMaxDistance +
47331                     this._coefficients.sphericalMotion * Math.abs(potential.motionChange) / Math.PI +
47332                     this._coefficients.sphericalMergeCCPenalty * (potential.sameMergeCC ? 0 : 1);
47333                 if (score < lowestScore) {
47334                     lowestScore = score;
47335                     edge = potential;
47336                 }
47337             }
47338             if (edge == null) {
47339                 return [];
47340             }
47341             return [
47342                 {
47343                     data: {
47344                         direction: exports.NavigationDirection.Spherical,
47345                         worldMotionAzimuth: edge.worldMotionAzimuth,
47346                     },
47347                     source: node.id,
47348                     target: edge.id,
47349                 },
47350             ];
47351         }
47352         /**
47353          * Computes the spherical and step edges for a spherical node.
47354          *
47355          * @description Spherical to spherical edge targets can only be
47356          * spherical nodes. spherical to step edge targets can only be perspective
47357          * nodes.
47358          *
47359          * @param {Image} node - Source node.
47360          * @param {Array<PotentialEdge>} potentialEdges - Potential edges.
47361          * @throws {ArgumentMapillaryError} If node is not full.
47362          */
47363         computeSphericalEdges(node, potentialEdges) {
47364             if (!node.complete) {
47365                 throw new ArgumentMapillaryError("Image has to be full.");
47366             }
47367             if (!isSpherical(node.cameraType)) {
47368                 return [];
47369             }
47370             let sphericalEdges = [];
47371             let potentialSpherical = [];
47372             let potentialSteps = [];
47373             for (let potential of potentialEdges) {
47374                 if (potential.distance > this._settings.sphericalMaxDistance) {
47375                     continue;
47376                 }
47377                 if (potential.spherical) {
47378                     if (potential.distance < this._settings.sphericalMinDistance) {
47379                         continue;
47380                     }
47381                     potentialSpherical.push(potential);
47382                 }
47383                 else {
47384                     for (let k in this._directions.spherical) {
47385                         if (!this._directions.spherical.hasOwnProperty(k)) {
47386                             continue;
47387                         }
47388                         let spherical = this._directions.spherical[k];
47389                         let turn = this._spatial.angleDifference(potential.directionChange, potential.motionChange);
47390                         let turnChange = this._spatial.angleDifference(spherical.directionChange, turn);
47391                         if (Math.abs(turnChange) > this._settings.sphericalMaxStepTurnChange) {
47392                             continue;
47393                         }
47394                         potentialSteps.push([spherical.direction, potential]);
47395                         // break if step direction found
47396                         break;
47397                     }
47398                 }
47399             }
47400             let maxRotationDifference = Math.PI / this._settings.sphericalMaxItems;
47401             let occupiedAngles = [];
47402             let stepAngles = [];
47403             for (let index = 0; index < this._settings.sphericalMaxItems; index++) {
47404                 let rotation = index / this._settings.sphericalMaxItems * 2 * Math.PI;
47405                 let lowestScore = Number.MAX_VALUE;
47406                 let edge = null;
47407                 for (let potential of potentialSpherical) {
47408                     let motionDifference = this._spatial.angleDifference(rotation, potential.motionChange);
47409                     if (Math.abs(motionDifference) > maxRotationDifference) {
47410                         continue;
47411                     }
47412                     let occupiedDifference = Number.MAX_VALUE;
47413                     for (let occupiedAngle of occupiedAngles) {
47414                         let difference = Math.abs(this._spatial.angleDifference(occupiedAngle, potential.motionChange));
47415                         if (difference < occupiedDifference) {
47416                             occupiedDifference = difference;
47417                         }
47418                     }
47419                     if (occupiedDifference <= maxRotationDifference) {
47420                         continue;
47421                     }
47422                     let score = this._coefficients.sphericalPreferredDistance *
47423                         Math.abs(potential.distance - this._settings.sphericalPreferredDistance) /
47424                         this._settings.sphericalMaxDistance +
47425                         this._coefficients.sphericalMotion * Math.abs(motionDifference) / maxRotationDifference +
47426                         this._coefficients.sphericalSequencePenalty * (potential.sameSequence ? 0 : 1) +
47427                         this._coefficients.sphericalMergeCCPenalty * (potential.sameMergeCC ? 0 : 1);
47428                     if (score < lowestScore) {
47429                         lowestScore = score;
47430                         edge = potential;
47431                     }
47432                 }
47433                 if (edge != null) {
47434                     occupiedAngles.push(edge.motionChange);
47435                     sphericalEdges.push({
47436                         data: {
47437                             direction: exports.NavigationDirection.Spherical,
47438                             worldMotionAzimuth: edge.worldMotionAzimuth,
47439                         },
47440                         source: node.id,
47441                         target: edge.id,
47442                     });
47443                 }
47444                 else {
47445                     stepAngles.push(rotation);
47446                 }
47447             }
47448             let occupiedStepAngles = {};
47449             occupiedStepAngles[exports.NavigationDirection.Spherical] = occupiedAngles;
47450             occupiedStepAngles[exports.NavigationDirection.StepForward] = [];
47451             occupiedStepAngles[exports.NavigationDirection.StepLeft] = [];
47452             occupiedStepAngles[exports.NavigationDirection.StepBackward] = [];
47453             occupiedStepAngles[exports.NavigationDirection.StepRight] = [];
47454             for (let stepAngle of stepAngles) {
47455                 let occupations = [];
47456                 for (let k in this._directions.spherical) {
47457                     if (!this._directions.spherical.hasOwnProperty(k)) {
47458                         continue;
47459                     }
47460                     let spherical = this._directions.spherical[k];
47461                     let allOccupiedAngles = occupiedStepAngles[exports.NavigationDirection.Spherical]
47462                         .concat(occupiedStepAngles[spherical.direction])
47463                         .concat(occupiedStepAngles[spherical.prev])
47464                         .concat(occupiedStepAngles[spherical.next]);
47465                     let lowestScore = Number.MAX_VALUE;
47466                     let edge = null;
47467                     for (let potential of potentialSteps) {
47468                         if (potential[0] !== spherical.direction) {
47469                             continue;
47470                         }
47471                         let motionChange = this._spatial.angleDifference(stepAngle, potential[1].motionChange);
47472                         if (Math.abs(motionChange) > maxRotationDifference) {
47473                             continue;
47474                         }
47475                         let minOccupiedDifference = Number.MAX_VALUE;
47476                         for (let occupiedAngle of allOccupiedAngles) {
47477                             let occupiedDifference = Math.abs(this._spatial.angleDifference(occupiedAngle, potential[1].motionChange));
47478                             if (occupiedDifference < minOccupiedDifference) {
47479                                 minOccupiedDifference = occupiedDifference;
47480                             }
47481                         }
47482                         if (minOccupiedDifference <= maxRotationDifference) {
47483                             continue;
47484                         }
47485                         let score = this._coefficients.sphericalPreferredDistance *
47486                             Math.abs(potential[1].distance - this._settings.sphericalPreferredDistance) /
47487                             this._settings.sphericalMaxDistance +
47488                             this._coefficients.sphericalMotion * Math.abs(motionChange) / maxRotationDifference +
47489                             this._coefficients.sphericalMergeCCPenalty * (potential[1].sameMergeCC ? 0 : 1);
47490                         if (score < lowestScore) {
47491                             lowestScore = score;
47492                             edge = potential;
47493                         }
47494                     }
47495                     if (edge != null) {
47496                         occupations.push(edge);
47497                         sphericalEdges.push({
47498                             data: {
47499                                 direction: edge[0],
47500                                 worldMotionAzimuth: edge[1].worldMotionAzimuth,
47501                             },
47502                             source: node.id,
47503                             target: edge[1].id,
47504                         });
47505                     }
47506                 }
47507                 for (let occupation of occupations) {
47508                     occupiedStepAngles[occupation[0]].push(occupation[1].motionChange);
47509                 }
47510             }
47511             return sphericalEdges;
47512         }
47513     }
47514
47515     class GraphMapillaryError extends MapillaryError {
47516         constructor(message) {
47517             super(message);
47518             Object.setPrototypeOf(this, GraphMapillaryError.prototype);
47519             this.name = "GraphMapillaryError";
47520         }
47521     }
47522
47523     /**
47524      * @class Graph
47525      *
47526      * @classdesc Represents a graph of nodes with edges.
47527      */
47528     class Graph {
47529         /**
47530          * Create a new graph instance.
47531          *
47532          * @param {APIWrapper} [api] - API instance for retrieving data.
47533          * @param {rbush.RBush<NodeIndexItem>} [nodeIndex] - Node index for fast spatial retreival.
47534          * @param {GraphCalculator} [graphCalculator] - Instance for graph calculations.
47535          * @param {EdgeCalculator} [edgeCalculator] - Instance for edge calculations.
47536          * @param {FilterCreator} [filterCreator] - Instance for  filter creation.
47537          * @param {GraphConfiguration} [configuration] - Configuration struct.
47538          */
47539         constructor(api, nodeIndex, graphCalculator, edgeCalculator, filterCreator, configuration) {
47540             this._api = api;
47541             this._cachedNodes = {};
47542             this._cachedNodeTiles = {};
47543             this._cachedSequenceNodes = {};
47544             this._cachedSpatialEdges = {};
47545             this._cachedTiles = {};
47546             this._cachingFill$ = {};
47547             this._cachingFull$ = {};
47548             this._cachingSequenceNodes$ = {};
47549             this._cachingSequences$ = {};
47550             this._cachingSpatialArea$ = {};
47551             this._cachingTiles$ = {};
47552             this._changed$ = new Subject();
47553             this._filterCreator = filterCreator !== null && filterCreator !== void 0 ? filterCreator : new FilterCreator();
47554             this._filter = this._filterCreator.createFilter(undefined);
47555             this._filterSubject$ = new Subject();
47556             this._filter$ =
47557                 concat(of(this._filter), this._filterSubject$).pipe(publishReplay(1), refCount());
47558             this._filterSubscription = this._filter$.subscribe(() => { });
47559             this._defaultAlt = 2;
47560             this._edgeCalculator = edgeCalculator !== null && edgeCalculator !== void 0 ? edgeCalculator : new EdgeCalculator();
47561             this._graphCalculator = graphCalculator !== null && graphCalculator !== void 0 ? graphCalculator : new GraphCalculator();
47562             this._configuration = configuration !== null && configuration !== void 0 ? configuration : {
47563                 maxSequences: 50,
47564                 maxUnusedImages: 100,
47565                 maxUnusedPreStoredImages: 30,
47566                 maxUnusedTiles: 20,
47567             };
47568             this._nodes = {};
47569             this._nodeIndex = nodeIndex !== null && nodeIndex !== void 0 ? nodeIndex : new Graph._spatialIndex(16);
47570             this._nodeIndexTiles = {};
47571             this._nodeToTile = {};
47572             this._preStored = {};
47573             this._requiredNodeTiles = {};
47574             this._requiredSpatialArea = {};
47575             this._sequences = {};
47576             this._tileThreshold = 20;
47577         }
47578         static register(spatialIndex) {
47579             Graph._spatialIndex = spatialIndex;
47580         }
47581         /**
47582          * Get api.
47583          *
47584          * @returns {APIWrapper} The API instance used by
47585          * the graph.
47586          */
47587         get api() {
47588             return this._api;
47589         }
47590         /**
47591          * Get changed$.
47592          *
47593          * @returns {Observable<Graph>} Observable emitting
47594          * the graph every time it has changed.
47595          */
47596         get changed$() {
47597             return this._changed$;
47598         }
47599         /**
47600          * Get filter$.
47601          *
47602          * @returns {Observable<FilterFunction>} Observable emitting
47603          * the filter every time it has changed.
47604          */
47605         get filter$() {
47606             return this._filter$;
47607         }
47608         /**
47609          * Caches the full node data for all images within a bounding
47610          * box.
47611          *
47612          * @description The node assets are not cached.
47613          *
47614          * @param {LngLat} sw - South west corner of bounding box.
47615          * @param {LngLat} ne - North east corner of bounding box.
47616          * @returns {Observable<Array<Image>>} Observable emitting
47617          * the full nodes in the bounding box.
47618          */
47619         cacheBoundingBox$(sw, ne) {
47620             const cacheTiles$ = this._api.data.geometry.bboxToCellIds(sw, ne)
47621                 .filter((h) => {
47622                 return !(h in this._cachedTiles);
47623             })
47624                 .map((h) => {
47625                 return h in this._cachingTiles$ ?
47626                     this._cachingTiles$[h] :
47627                     this._cacheTile$(h);
47628             });
47629             if (cacheTiles$.length === 0) {
47630                 cacheTiles$.push(of(this));
47631             }
47632             return from(cacheTiles$).pipe(mergeAll(), last(), mergeMap(() => {
47633                 const nodes = this._nodeIndex
47634                     .search({
47635                     maxX: ne.lng,
47636                     maxY: ne.lat,
47637                     minX: sw.lng,
47638                     minY: sw.lat,
47639                 })
47640                     .map((item) => {
47641                     return item.node;
47642                 });
47643                 const fullNodes = [];
47644                 const coreNodes = [];
47645                 for (const node of nodes) {
47646                     if (node.complete) {
47647                         fullNodes.push(node);
47648                     }
47649                     else {
47650                         coreNodes.push(node.id);
47651                     }
47652                 }
47653                 const coreNodeBatches = [];
47654                 const batchSize = 200;
47655                 while (coreNodes.length > 0) {
47656                     coreNodeBatches.push(coreNodes.splice(0, batchSize));
47657                 }
47658                 const fullNodes$ = of(fullNodes);
47659                 const fillNodes$ = coreNodeBatches
47660                     .map((batch) => {
47661                     return this._api
47662                         .getSpatialImages$(batch)
47663                         .pipe(map((items) => {
47664                         const result = [];
47665                         for (const item of items) {
47666                             const exists = this
47667                                 .hasNode(item.node_id);
47668                             if (!exists) {
47669                                 continue;
47670                             }
47671                             const node = this
47672                                 .getNode(item.node_id);
47673                             if (!node.complete) {
47674                                 this._makeFull(node, item.node);
47675                             }
47676                             result.push(node);
47677                         }
47678                         return result;
47679                     }));
47680                 });
47681                 return merge(fullNodes$, from(fillNodes$).pipe(mergeAll()));
47682             }), reduce((acc, value) => {
47683                 return acc.concat(value);
47684             }));
47685         }
47686         /**
47687          * Caches the full node data for all images of a cell.
47688          *
47689          * @description The node assets are not cached.
47690          *
47691          * @param {string} cellId - Cell id.
47692          * @returns {Observable<Array<Image>>} Observable
47693          * emitting the full nodes of the cell.
47694          */
47695         cacheCell$(cellId) {
47696             const cacheCell$ = cellId in this._cachedTiles ?
47697                 of(this) :
47698                 cellId in this._cachingTiles$ ?
47699                     this._cachingTiles$[cellId] :
47700                     this._cacheTile$(cellId);
47701             return cacheCell$.pipe(mergeMap(() => {
47702                 const cachedCell = this._cachedTiles[cellId];
47703                 cachedCell.accessed = new Date().getTime();
47704                 const cellNodes = cachedCell.nodes;
47705                 const fullNodes = [];
47706                 const coreNodes = [];
47707                 for (const node of cellNodes) {
47708                     if (node.complete) {
47709                         fullNodes.push(node);
47710                     }
47711                     else {
47712                         coreNodes.push(node.id);
47713                     }
47714                 }
47715                 const coreNodeBatches = [];
47716                 const batchSize = 200;
47717                 while (coreNodes.length > 0) {
47718                     coreNodeBatches.push(coreNodes.splice(0, batchSize));
47719                 }
47720                 const fullNodes$ = of(fullNodes);
47721                 const fillNodes$ = coreNodeBatches
47722                     .map((batch) => {
47723                     return this._api.getSpatialImages$(batch).pipe(map((items) => {
47724                         const filled = [];
47725                         for (const item of items) {
47726                             if (!item.node) {
47727                                 console.warn(`Image is empty (${item.node})`);
47728                                 continue;
47729                             }
47730                             const id = item.node_id;
47731                             if (!this.hasNode(id)) {
47732                                 continue;
47733                             }
47734                             const node = this.getNode(id);
47735                             if (!node.complete) {
47736                                 this._makeFull(node, item.node);
47737                             }
47738                             filled.push(node);
47739                         }
47740                         return filled;
47741                     }));
47742                 });
47743                 return merge(fullNodes$, from(fillNodes$).pipe(mergeAll()));
47744             }), reduce((acc, value) => {
47745                 return acc.concat(value);
47746             }));
47747         }
47748         /**
47749          * Retrieve and cache node fill properties.
47750          *
47751          * @param {string} key - Key of node to fill.
47752          * @returns {Observable<Graph>} Observable emitting the graph
47753          * when the node has been updated.
47754          * @throws {GraphMapillaryError} When the operation is not valid on the
47755          * current graph.
47756          */
47757         cacheFill$(key) {
47758             if (key in this._cachingFull$) {
47759                 throw new GraphMapillaryError(`Cannot fill node while caching full (${key}).`);
47760             }
47761             if (!this.hasNode(key)) {
47762                 throw new GraphMapillaryError(`Cannot fill node that does not exist in graph (${key}).`);
47763             }
47764             if (key in this._cachingFill$) {
47765                 return this._cachingFill$[key];
47766             }
47767             const node = this.getNode(key);
47768             if (node.complete) {
47769                 throw new GraphMapillaryError(`Cannot fill node that is already full (${key}).`);
47770             }
47771             this._cachingFill$[key] = this._api.getSpatialImages$([key]).pipe(tap((items) => {
47772                 for (const item of items) {
47773                     if (!item.node) {
47774                         console.warn(`Image is empty ${item.node_id}`);
47775                     }
47776                     if (!node.complete) {
47777                         this._makeFull(node, item.node);
47778                     }
47779                     delete this._cachingFill$[item.node_id];
47780                 }
47781             }), map(() => { return this; }), finalize(() => {
47782                 if (key in this._cachingFill$) {
47783                     delete this._cachingFill$[key];
47784                 }
47785                 this._changed$.next(this);
47786             }), publish(), refCount());
47787             return this._cachingFill$[key];
47788         }
47789         /**
47790          * Retrieve and cache full node properties.
47791          *
47792          * @param {string} key - Key of node to fill.
47793          * @returns {Observable<Graph>} Observable emitting the graph
47794          * when the node has been updated.
47795          * @throws {GraphMapillaryError} When the operation is not valid on the
47796          * current graph.
47797          */
47798         cacheFull$(key) {
47799             if (key in this._cachingFull$) {
47800                 return this._cachingFull$[key];
47801             }
47802             if (this.hasNode(key)) {
47803                 throw new GraphMapillaryError(`Cannot cache full node that already exist in graph (${key}).`);
47804             }
47805             this._cachingFull$[key] = this._api.getImages$([key]).pipe(tap((items) => {
47806                 for (const item of items) {
47807                     if (!item.node) {
47808                         throw new GraphMapillaryError(`Image does not exist (${key}, ${item.node}).`);
47809                     }
47810                     const id = item.node_id;
47811                     if (this.hasNode(id)) {
47812                         const node = this.getNode(key);
47813                         if (!node.complete) {
47814                             this._makeFull(node, item.node);
47815                         }
47816                     }
47817                     else {
47818                         if (item.node.sequence.id == null) {
47819                             throw new GraphMapillaryError(`Image has no sequence key (${key}).`);
47820                         }
47821                         const node = new Image$1(item.node);
47822                         this._makeFull(node, item.node);
47823                         const cellId = this._api.data.geometry
47824                             .lngLatToCellId(node.originalLngLat);
47825                         this._preStore(cellId, node);
47826                         this._setNode(node);
47827                         delete this._cachingFull$[id];
47828                     }
47829                 }
47830             }), map(() => this), finalize(() => {
47831                 if (key in this._cachingFull$) {
47832                     delete this._cachingFull$[key];
47833                 }
47834                 this._changed$.next(this);
47835             }), publish(), refCount());
47836             return this._cachingFull$[key];
47837         }
47838         /**
47839          * Retrieve and cache a node sequence.
47840          *
47841          * @param {string} key - Key of node for which to retrieve sequence.
47842          * @returns {Observable<Graph>} Observable emitting the graph
47843          * when the sequence has been retrieved.
47844          * @throws {GraphMapillaryError} When the operation is not valid on the
47845          * current graph.
47846          */
47847         cacheNodeSequence$(key) {
47848             if (!this.hasNode(key)) {
47849                 throw new GraphMapillaryError(`Cannot cache sequence edges of node that does not exist in graph (${key}).`);
47850             }
47851             let node = this.getNode(key);
47852             if (node.sequenceId in this._sequences) {
47853                 throw new GraphMapillaryError(`Sequence already cached (${key}), (${node.sequenceId}).`);
47854             }
47855             return this._cacheSequence$(node.sequenceId);
47856         }
47857         /**
47858          * Retrieve and cache a sequence.
47859          *
47860          * @param {string} sequenceKey - Key of sequence to cache.
47861          * @returns {Observable<Graph>} Observable emitting the graph
47862          * when the sequence has been retrieved.
47863          * @throws {GraphMapillaryError} When the operation is not valid on the
47864          * current graph.
47865          */
47866         cacheSequence$(sequenceKey) {
47867             if (sequenceKey in this._sequences) {
47868                 throw new GraphMapillaryError(`Sequence already cached (${sequenceKey})`);
47869             }
47870             return this._cacheSequence$(sequenceKey);
47871         }
47872         /**
47873          * Cache sequence edges for a node.
47874          *
47875          * @param {string} key - Key of node.
47876          * @throws {GraphMapillaryError} When the operation is not valid on the
47877          * current graph.
47878          */
47879         cacheSequenceEdges(key) {
47880             let node = this.getNode(key);
47881             if (!(node.sequenceId in this._sequences)) {
47882                 throw new GraphMapillaryError(`Sequence is not cached (${key}), (${node.sequenceId})`);
47883             }
47884             let sequence = this._sequences[node.sequenceId].sequence;
47885             let edges = this._edgeCalculator.computeSequenceEdges(node, sequence);
47886             node.cacheSequenceEdges(edges);
47887         }
47888         /**
47889          * Retrieve and cache full nodes for all keys in a sequence.
47890          *
47891          * @param {string} sequenceKey - Key of sequence.
47892          * @param {string} referenceNodeKey - Key of node to use as reference
47893          * for optimized caching.
47894          * @returns {Observable<Graph>} Observable emitting the graph
47895          * when the nodes of the sequence has been cached.
47896          */
47897         cacheSequenceNodes$(sequenceKey, referenceNodeKey) {
47898             if (!this.hasSequence(sequenceKey)) {
47899                 throw new GraphMapillaryError(`Cannot cache sequence nodes of sequence that does not exist in graph (${sequenceKey}).`);
47900             }
47901             if (this.hasSequenceNodes(sequenceKey)) {
47902                 throw new GraphMapillaryError(`Sequence nodes already cached (${sequenceKey}).`);
47903             }
47904             const sequence = this.getSequence(sequenceKey);
47905             if (sequence.id in this._cachingSequenceNodes$) {
47906                 return this._cachingSequenceNodes$[sequence.id];
47907             }
47908             const batches = [];
47909             const keys = sequence.imageIds.slice();
47910             const referenceBatchSize = 50;
47911             if (!!referenceNodeKey && keys.length > referenceBatchSize) {
47912                 const referenceIndex = keys.indexOf(referenceNodeKey);
47913                 const startIndex = Math.max(0, Math.min(referenceIndex - referenceBatchSize / 2, keys.length - referenceBatchSize));
47914                 batches.push(keys.splice(startIndex, referenceBatchSize));
47915             }
47916             const batchSize = 200;
47917             while (keys.length > 0) {
47918                 batches.push(keys.splice(0, batchSize));
47919             }
47920             let batchesToCache = batches.length;
47921             const sequenceNodes$ = from(batches).pipe(mergeMap((batch) => {
47922                 return this._api.getImages$(batch).pipe(tap((items) => {
47923                     for (const item of items) {
47924                         if (!item.node) {
47925                             console.warn(`Image empty (${item.node_id})`);
47926                             continue;
47927                         }
47928                         const id = item.node_id;
47929                         if (this.hasNode(id)) {
47930                             const node = this.getNode(id);
47931                             if (!node.complete) {
47932                                 this._makeFull(node, item.node);
47933                             }
47934                         }
47935                         else {
47936                             if (item.node.sequence.id == null) {
47937                                 console.warn(`Sequence missing, discarding node (${item.node_id})`);
47938                             }
47939                             const node = new Image$1(item.node);
47940                             this._makeFull(node, item.node);
47941                             const cellId = this._api.data.geometry
47942                                 .lngLatToCellId(node.originalLngLat);
47943                             this._preStore(cellId, node);
47944                             this._setNode(node);
47945                         }
47946                     }
47947                     batchesToCache--;
47948                 }), map(() => this));
47949             }, 6), last(), finalize(() => {
47950                 delete this._cachingSequenceNodes$[sequence.id];
47951                 if (batchesToCache === 0) {
47952                     this._cachedSequenceNodes[sequence.id] = true;
47953                 }
47954             }), publish(), refCount());
47955             this._cachingSequenceNodes$[sequence.id] = sequenceNodes$;
47956             return sequenceNodes$;
47957         }
47958         /**
47959          * Retrieve and cache full nodes for a node spatial area.
47960          *
47961          * @param {string} key - Key of node for which to retrieve sequence.
47962          * @returns {Observable<Graph>} Observable emitting the graph
47963          * when the nodes in the spatial area has been made full.
47964          * @throws {GraphMapillaryError} When the operation is not valid on the
47965          * current graph.
47966          */
47967         cacheSpatialArea$(key) {
47968             if (!this.hasNode(key)) {
47969                 throw new GraphMapillaryError(`Cannot cache spatial area of node that does not exist in graph (${key}).`);
47970             }
47971             if (key in this._cachedSpatialEdges) {
47972                 throw new GraphMapillaryError(`Image already spatially cached (${key}).`);
47973             }
47974             if (!(key in this._requiredSpatialArea)) {
47975                 throw new GraphMapillaryError(`Spatial area not determined (${key}).`);
47976             }
47977             let spatialArea = this._requiredSpatialArea[key];
47978             if (Object.keys(spatialArea.cacheNodes).length === 0) {
47979                 throw new GraphMapillaryError(`Spatial nodes already cached (${key}).`);
47980             }
47981             if (key in this._cachingSpatialArea$) {
47982                 return this._cachingSpatialArea$[key];
47983             }
47984             let batches = [];
47985             while (spatialArea.cacheKeys.length > 0) {
47986                 batches.push(spatialArea.cacheKeys.splice(0, 200));
47987             }
47988             let batchesToCache = batches.length;
47989             let spatialNodes$ = [];
47990             for (let batch of batches) {
47991                 let spatialNodeBatch$ = this._api.getSpatialImages$(batch).pipe(tap((items) => {
47992                     for (const item of items) {
47993                         if (!item.node) {
47994                             console.warn(`Image is empty (${item.node_id})`);
47995                             continue;
47996                         }
47997                         const id = item.node_id;
47998                         const spatialNode = spatialArea.cacheNodes[id];
47999                         if (spatialNode.complete) {
48000                             delete spatialArea.cacheNodes[id];
48001                             continue;
48002                         }
48003                         this._makeFull(spatialNode, item.node);
48004                         delete spatialArea.cacheNodes[id];
48005                     }
48006                     if (--batchesToCache === 0) {
48007                         delete this._cachingSpatialArea$[key];
48008                     }
48009                 }), map(() => { return this; }), catchError((error) => {
48010                     for (let batchKey of batch) {
48011                         if (batchKey in spatialArea.all) {
48012                             delete spatialArea.all[batchKey];
48013                         }
48014                         if (batchKey in spatialArea.cacheNodes) {
48015                             delete spatialArea.cacheNodes[batchKey];
48016                         }
48017                     }
48018                     if (--batchesToCache === 0) {
48019                         delete this._cachingSpatialArea$[key];
48020                     }
48021                     throw error;
48022                 }), finalize(() => {
48023                     if (Object.keys(spatialArea.cacheNodes).length === 0) {
48024                         this._changed$.next(this);
48025                     }
48026                 }), publish(), refCount());
48027                 spatialNodes$.push(spatialNodeBatch$);
48028             }
48029             this._cachingSpatialArea$[key] = spatialNodes$;
48030             return spatialNodes$;
48031         }
48032         /**
48033          * Cache spatial edges for a node.
48034          *
48035          * @param {string} key - Key of node.
48036          * @throws {GraphMapillaryError} When the operation is not valid on the
48037          * current graph.
48038          */
48039         cacheSpatialEdges(key) {
48040             if (key in this._cachedSpatialEdges) {
48041                 throw new GraphMapillaryError(`Spatial edges already cached (${key}).`);
48042             }
48043             let node = this.getNode(key);
48044             let sequence = this._sequences[node.sequenceId].sequence;
48045             let fallbackKeys = [];
48046             let prevKey = sequence.findPrev(node.id);
48047             if (prevKey != null) {
48048                 fallbackKeys.push(prevKey);
48049             }
48050             let nextKey = sequence.findNext(node.id);
48051             if (nextKey != null) {
48052                 fallbackKeys.push(nextKey);
48053             }
48054             let allSpatialNodes = this._requiredSpatialArea[key].all;
48055             let potentialNodes = [];
48056             let filter = this._filter;
48057             for (let spatialNodeKey in allSpatialNodes) {
48058                 if (!allSpatialNodes.hasOwnProperty(spatialNodeKey)) {
48059                     continue;
48060                 }
48061                 let spatialNode = allSpatialNodes[spatialNodeKey];
48062                 if (filter(spatialNode)) {
48063                     potentialNodes.push(spatialNode);
48064                 }
48065             }
48066             let potentialEdges = this._edgeCalculator.getPotentialEdges(node, potentialNodes, fallbackKeys);
48067             let edges = this._edgeCalculator.computeStepEdges(node, potentialEdges, prevKey, nextKey);
48068             edges = edges.concat(this._edgeCalculator.computeTurnEdges(node, potentialEdges));
48069             edges = edges.concat(this._edgeCalculator.computeSphericalEdges(node, potentialEdges));
48070             edges = edges.concat(this._edgeCalculator.computePerspectiveToSphericalEdges(node, potentialEdges));
48071             edges = edges.concat(this._edgeCalculator.computeSimilarEdges(node, potentialEdges));
48072             node.cacheSpatialEdges(edges);
48073             this._cachedSpatialEdges[key] = node;
48074             delete this._requiredSpatialArea[key];
48075             delete this._cachedNodeTiles[key];
48076         }
48077         /**
48078          * Retrieve and cache tiles for a node.
48079          *
48080          * @param {string} key - Key of node for which to retrieve tiles.
48081          * @returns {Array<Observable<Graph>>} Array of observables emitting
48082          * the graph for each tile required for the node has been cached.
48083          * @throws {GraphMapillaryError} When the operation is not valid on the
48084          * current graph.
48085          */
48086         cacheTiles$(key) {
48087             if (key in this._cachedNodeTiles) {
48088                 throw new GraphMapillaryError(`Tiles already cached (${key}).`);
48089             }
48090             if (key in this._cachedSpatialEdges) {
48091                 throw new GraphMapillaryError(`Spatial edges already cached so tiles considered cached (${key}).`);
48092             }
48093             if (!(key in this._requiredNodeTiles)) {
48094                 throw new GraphMapillaryError(`Tiles have not been determined (${key}).`);
48095             }
48096             let nodeTiles = this._requiredNodeTiles[key];
48097             if (nodeTiles.cache.length === 0 &&
48098                 nodeTiles.caching.length === 0) {
48099                 throw new GraphMapillaryError(`Tiles already cached (${key}).`);
48100             }
48101             if (!this.hasNode(key)) {
48102                 throw new GraphMapillaryError(`Cannot cache tiles of node that does not exist in graph (${key}).`);
48103             }
48104             let hs = nodeTiles.cache.slice();
48105             nodeTiles.caching = this._requiredNodeTiles[key].caching.concat(hs);
48106             nodeTiles.cache = [];
48107             let cacheTiles$ = [];
48108             for (let h of nodeTiles.caching) {
48109                 const cacheTile$ = h in this._cachingTiles$ ?
48110                     this._cachingTiles$[h] :
48111                     this._cacheTile$(h);
48112                 cacheTiles$.push(cacheTile$.pipe(tap((graph) => {
48113                     let index = nodeTiles.caching.indexOf(h);
48114                     if (index > -1) {
48115                         nodeTiles.caching.splice(index, 1);
48116                     }
48117                     if (nodeTiles.caching.length === 0 &&
48118                         nodeTiles.cache.length === 0) {
48119                         delete this._requiredNodeTiles[key];
48120                         this._cachedNodeTiles[key] = true;
48121                     }
48122                 }), catchError((error) => {
48123                     let index = nodeTiles.caching.indexOf(h);
48124                     if (index > -1) {
48125                         nodeTiles.caching.splice(index, 1);
48126                     }
48127                     if (nodeTiles.caching.length === 0 &&
48128                         nodeTiles.cache.length === 0) {
48129                         delete this._requiredNodeTiles[key];
48130                         this._cachedNodeTiles[key] = true;
48131                     }
48132                     throw error;
48133                 }), finalize(() => {
48134                     this._changed$.next(this);
48135                 }), publish(), refCount()));
48136             }
48137             return cacheTiles$;
48138         }
48139         /**
48140          * Initialize the cache for a node.
48141          *
48142          * @param {string} key - Key of node.
48143          * @throws {GraphMapillaryError} When the operation is not valid on the
48144          * current graph.
48145          */
48146         initializeCache(key) {
48147             if (key in this._cachedNodes) {
48148                 throw new GraphMapillaryError(`Image already in cache (${key}).`);
48149             }
48150             const node = this.getNode(key);
48151             const provider = this._api.data;
48152             node.initializeCache(new ImageCache(provider));
48153             const accessed = new Date().getTime();
48154             this._cachedNodes[key] = { accessed: accessed, node: node };
48155             this._updateCachedTileAccess(key, accessed);
48156         }
48157         /**
48158          * Get a value indicating if the graph is fill caching a node.
48159          *
48160          * @param {string} key - Key of node.
48161          * @returns {boolean} Value indicating if the node is being fill cached.
48162          */
48163         isCachingFill(key) {
48164             return key in this._cachingFill$;
48165         }
48166         /**
48167          * Get a value indicating if the graph is fully caching a node.
48168          *
48169          * @param {string} key - Key of node.
48170          * @returns {boolean} Value indicating if the node is being fully cached.
48171          */
48172         isCachingFull(key) {
48173             return key in this._cachingFull$;
48174         }
48175         /**
48176          * Get a value indicating if the graph is caching a sequence of a node.
48177          *
48178          * @param {string} key - Key of node.
48179          * @returns {boolean} Value indicating if the sequence of a node is
48180          * being cached.
48181          */
48182         isCachingNodeSequence(key) {
48183             let node = this.getNode(key);
48184             return node.sequenceId in this._cachingSequences$;
48185         }
48186         /**
48187          * Get a value indicating if the graph is caching a sequence.
48188          *
48189          * @param {string} sequenceKey - Key of sequence.
48190          * @returns {boolean} Value indicating if the sequence is
48191          * being cached.
48192          */
48193         isCachingSequence(sequenceKey) {
48194             return sequenceKey in this._cachingSequences$;
48195         }
48196         /**
48197          * Get a value indicating if the graph is caching sequence nodes.
48198          *
48199          * @param {string} sequenceKey - Key of sequence.
48200          * @returns {boolean} Value indicating if the sequence nodes are
48201          * being cached.
48202          */
48203         isCachingSequenceNodes(sequenceKey) {
48204             return sequenceKey in this._cachingSequenceNodes$;
48205         }
48206         /**
48207          * Get a value indicating if the graph is caching the tiles
48208          * required for calculating spatial edges of a node.
48209          *
48210          * @param {string} key - Key of node.
48211          * @returns {boolean} Value indicating if the tiles of
48212          * a node are being cached.
48213          */
48214         isCachingTiles(key) {
48215             return key in this._requiredNodeTiles &&
48216                 this._requiredNodeTiles[key].cache.length === 0 &&
48217                 this._requiredNodeTiles[key].caching.length > 0;
48218         }
48219         /**
48220          * Get a value indicating if the cache has been initialized
48221          * for a node.
48222          *
48223          * @param {string} key - Key of node.
48224          * @returns {boolean} Value indicating if the cache has been
48225          * initialized for a node.
48226          */
48227         hasInitializedCache(key) {
48228             return key in this._cachedNodes;
48229         }
48230         /**
48231          * Get a value indicating if a node exist in the graph.
48232          *
48233          * @param {string} key - Key of node.
48234          * @returns {boolean} Value indicating if a node exist in the graph.
48235          */
48236         hasNode(key) {
48237             let accessed = new Date().getTime();
48238             this._updateCachedNodeAccess(key, accessed);
48239             this._updateCachedTileAccess(key, accessed);
48240             return key in this._nodes;
48241         }
48242         /**
48243          * Get a value indicating if a node sequence exist in the graph.
48244          *
48245          * @param {string} key - Key of node.
48246          * @returns {boolean} Value indicating if a node sequence exist
48247          * in the graph.
48248          */
48249         hasNodeSequence(key) {
48250             let node = this.getNode(key);
48251             let sequenceKey = node.sequenceId;
48252             let hasNodeSequence = sequenceKey in this._sequences;
48253             if (hasNodeSequence) {
48254                 this._sequences[sequenceKey].accessed = new Date().getTime();
48255             }
48256             return hasNodeSequence;
48257         }
48258         /**
48259          * Get a value indicating if a sequence exist in the graph.
48260          *
48261          * @param {string} sequenceKey - Key of sequence.
48262          * @returns {boolean} Value indicating if a sequence exist
48263          * in the graph.
48264          */
48265         hasSequence(sequenceKey) {
48266             let hasSequence = sequenceKey in this._sequences;
48267             if (hasSequence) {
48268                 this._sequences[sequenceKey].accessed = new Date().getTime();
48269             }
48270             return hasSequence;
48271         }
48272         /**
48273          * Get a value indicating if sequence nodes has been cached in the graph.
48274          *
48275          * @param {string} sequenceKey - Key of sequence.
48276          * @returns {boolean} Value indicating if a sequence nodes has been
48277          * cached in the graph.
48278          */
48279         hasSequenceNodes(sequenceKey) {
48280             return sequenceKey in this._cachedSequenceNodes;
48281         }
48282         /**
48283          * Get a value indicating if the graph has fully cached
48284          * all nodes in the spatial area of a node.
48285          *
48286          * @param {string} key - Key of node.
48287          * @returns {boolean} Value indicating if the spatial area
48288          * of a node has been cached.
48289          */
48290         hasSpatialArea(key) {
48291             if (!this.hasNode(key)) {
48292                 throw new GraphMapillaryError(`Spatial area nodes cannot be determined if node not in graph (${key}).`);
48293             }
48294             if (key in this._cachedSpatialEdges) {
48295                 return true;
48296             }
48297             if (key in this._requiredSpatialArea) {
48298                 return Object
48299                     .keys(this._requiredSpatialArea[key].cacheNodes)
48300                     .length === 0;
48301             }
48302             let node = this.getNode(key);
48303             let bbox = this._graphCalculator
48304                 .boundingBoxCorners(node.lngLat, this._tileThreshold);
48305             let spatialItems = this._nodeIndex
48306                 .search({
48307                 maxX: bbox[1].lng,
48308                 maxY: bbox[1].lat,
48309                 minX: bbox[0].lng,
48310                 minY: bbox[0].lat,
48311             });
48312             let spatialNodes = {
48313                 all: {},
48314                 cacheKeys: [],
48315                 cacheNodes: {},
48316             };
48317             for (let spatialItem of spatialItems) {
48318                 spatialNodes.all[spatialItem.node.id] = spatialItem.node;
48319                 if (!spatialItem.node.complete) {
48320                     spatialNodes.cacheKeys.push(spatialItem.node.id);
48321                     spatialNodes.cacheNodes[spatialItem.node.id] = spatialItem.node;
48322                 }
48323             }
48324             this._requiredSpatialArea[key] = spatialNodes;
48325             return spatialNodes.cacheKeys.length === 0;
48326         }
48327         /**
48328          * Get a value indicating if the graph has a tiles required
48329          * for a node.
48330          *
48331          * @param {string} key - Key of node.
48332          * @returns {boolean} Value indicating if the the tiles required
48333          * by a node has been cached.
48334          */
48335         hasTiles(key) {
48336             if (key in this._cachedNodeTiles) {
48337                 return true;
48338             }
48339             if (key in this._cachedSpatialEdges) {
48340                 return true;
48341             }
48342             if (!this.hasNode(key)) {
48343                 throw new GraphMapillaryError(`Image does not exist in graph (${key}).`);
48344             }
48345             let nodeTiles = { cache: [], caching: [] };
48346             if (!(key in this._requiredNodeTiles)) {
48347                 const node = this.getNode(key);
48348                 const [sw, ne] = this._graphCalculator
48349                     .boundingBoxCorners(node.lngLat, this._tileThreshold);
48350                 nodeTiles.cache = this._api.data.geometry
48351                     .bboxToCellIds(sw, ne)
48352                     .filter((h) => {
48353                     return !(h in this._cachedTiles);
48354                 });
48355                 if (nodeTiles.cache.length > 0) {
48356                     this._requiredNodeTiles[key] = nodeTiles;
48357                 }
48358             }
48359             else {
48360                 nodeTiles = this._requiredNodeTiles[key];
48361             }
48362             return nodeTiles.cache.length === 0 && nodeTiles.caching.length === 0;
48363         }
48364         /**
48365          * Get a node.
48366          *
48367          * @param {string} key - Key of node.
48368          * @returns {Image} Retrieved node.
48369          */
48370         getNode(key) {
48371             let accessed = new Date().getTime();
48372             this._updateCachedNodeAccess(key, accessed);
48373             this._updateCachedTileAccess(key, accessed);
48374             return this._nodes[key];
48375         }
48376         /**
48377          * Get a sequence.
48378          *
48379          * @param {string} sequenceKey - Key of sequence.
48380          * @returns {Image} Retrieved sequence.
48381          */
48382         getSequence(sequenceKey) {
48383             let sequenceAccess = this._sequences[sequenceKey];
48384             sequenceAccess.accessed = new Date().getTime();
48385             return sequenceAccess.sequence;
48386         }
48387         /**
48388          * Reset all spatial edges of the graph nodes.
48389          */
48390         resetSpatialEdges() {
48391             let cachedKeys = Object.keys(this._cachedSpatialEdges);
48392             for (let cachedKey of cachedKeys) {
48393                 let node = this._cachedSpatialEdges[cachedKey];
48394                 node.resetSpatialEdges();
48395                 delete this._cachedSpatialEdges[cachedKey];
48396             }
48397         }
48398         /**
48399          * Reset the complete graph but keep the nodes corresponding
48400          * to the supplied keys. All other nodes will be disposed.
48401          *
48402          * @param {Array<string>} keepKeys - Keys for nodes to keep
48403          * in graph after reset.
48404          */
48405         reset(keepKeys) {
48406             const nodes = [];
48407             for (const key of keepKeys) {
48408                 if (!this.hasNode(key)) {
48409                     throw new Error(`Image does not exist ${key}`);
48410                 }
48411                 const node = this.getNode(key);
48412                 node.resetSequenceEdges();
48413                 node.resetSpatialEdges();
48414                 nodes.push(node);
48415             }
48416             for (let cachedKey of Object.keys(this._cachedNodes)) {
48417                 if (keepKeys.indexOf(cachedKey) !== -1) {
48418                     continue;
48419                 }
48420                 this._cachedNodes[cachedKey].node.dispose();
48421                 delete this._cachedNodes[cachedKey];
48422             }
48423             this._cachedNodeTiles = {};
48424             this._cachedSpatialEdges = {};
48425             this._cachedTiles = {};
48426             this._cachingFill$ = {};
48427             this._cachingFull$ = {};
48428             this._cachingSequences$ = {};
48429             this._cachingSpatialArea$ = {};
48430             this._cachingTiles$ = {};
48431             this._nodes = {};
48432             this._nodeToTile = {};
48433             this._preStored = {};
48434             for (const node of nodes) {
48435                 this._nodes[node.id] = node;
48436                 const h = this._api.data.geometry.lngLatToCellId(node.originalLngLat);
48437                 this._preStore(h, node);
48438             }
48439             this._requiredNodeTiles = {};
48440             this._requiredSpatialArea = {};
48441             this._sequences = {};
48442             this._nodeIndexTiles = {};
48443             this._nodeIndex.clear();
48444         }
48445         /**
48446          * Set the spatial node filter.
48447          *
48448          * @emits FilterFunction The filter function to the {@link Graph.filter$}
48449          * observable.
48450          *
48451          * @param {FilterExpression} filter - Filter expression to be applied
48452          * when calculating spatial edges.
48453          */
48454         setFilter(filter) {
48455             this._filter = this._filterCreator.createFilter(filter);
48456             this._filterSubject$.next(this._filter);
48457         }
48458         /**
48459          * Uncache the graph according to the graph configuration.
48460          *
48461          * @description Uncaches unused tiles, unused nodes and
48462          * sequences according to the numbers specified in the
48463          * graph configuration. Sequences does not have a direct
48464          * reference to either tiles or nodes and may be uncached
48465          * even if they are related to the nodes that should be kept.
48466          *
48467          * @param {Array<string>} keepIds - Ids of nodes to keep in
48468          * graph unrelated to last access. Tiles related to those keys
48469          * will also be kept in graph.
48470          * @param {Array<string>} keepCellIds - Ids of cells to keep in
48471          * graph unrelated to last access. The nodes of the cells may
48472          * still be uncached if not specified in the keep ids param
48473          * but are guaranteed to not be disposed.
48474          * @param {string} keepSequenceId - Optional id of sequence
48475          * for which the belonging nodes should not be disposed or
48476          * removed from the graph. These nodes may still be uncached if
48477          * not specified in keep ids param but are guaranteed to not
48478          * be disposed.
48479          */
48480         uncache(keepIds, keepCellIds, keepSequenceId) {
48481             const idsInUse = {};
48482             this._addNewKeys(idsInUse, this._cachingFull$);
48483             this._addNewKeys(idsInUse, this._cachingFill$);
48484             this._addNewKeys(idsInUse, this._cachingSpatialArea$);
48485             this._addNewKeys(idsInUse, this._requiredNodeTiles);
48486             this._addNewKeys(idsInUse, this._requiredSpatialArea);
48487             for (const key of keepIds) {
48488                 if (key in idsInUse) {
48489                     continue;
48490                 }
48491                 idsInUse[key] = true;
48492             }
48493             const tileThreshold = this._tileThreshold;
48494             const calculator = this._graphCalculator;
48495             const geometry = this._api.data.geometry;
48496             const keepCells = new Set(keepCellIds);
48497             for (let id in idsInUse) {
48498                 if (!idsInUse.hasOwnProperty(id)) {
48499                     continue;
48500                 }
48501                 const node = this._nodes[id];
48502                 const [sw, ne] = calculator
48503                     .boundingBoxCorners(node.lngLat, tileThreshold);
48504                 const nodeCellIds = geometry.bboxToCellIds(sw, ne);
48505                 for (const nodeCellId of nodeCellIds) {
48506                     if (!keepCells.has(nodeCellId)) {
48507                         keepCells.add(nodeCellId);
48508                     }
48509                 }
48510             }
48511             const potentialCells = [];
48512             for (let cellId in this._cachedTiles) {
48513                 if (!this._cachedTiles.hasOwnProperty(cellId) ||
48514                     keepCells.has(cellId)) {
48515                     continue;
48516                 }
48517                 potentialCells.push([cellId, this._cachedTiles[cellId]]);
48518             }
48519             const uncacheCells = potentialCells
48520                 .sort((h1, h2) => {
48521                 return h2[1].accessed - h1[1].accessed;
48522             })
48523                 .slice(this._configuration.maxUnusedTiles)
48524                 .map((h) => {
48525                 return h[0];
48526             });
48527             for (let uncacheCell of uncacheCells) {
48528                 this._uncacheTile(uncacheCell, keepSequenceId);
48529             }
48530             const potentialPreStored = [];
48531             const nonCachedPreStored = [];
48532             for (let cellId in this._preStored) {
48533                 if (!this._preStored.hasOwnProperty(cellId) ||
48534                     cellId in this._cachingTiles$) {
48535                     continue;
48536                 }
48537                 const prestoredNodes = this._preStored[cellId];
48538                 for (let id in prestoredNodes) {
48539                     if (!prestoredNodes.hasOwnProperty(id) || id in idsInUse) {
48540                         continue;
48541                     }
48542                     if (prestoredNodes[id].sequenceId === keepSequenceId) {
48543                         continue;
48544                     }
48545                     if (id in this._cachedNodes) {
48546                         potentialPreStored.push([this._cachedNodes[id], cellId]);
48547                     }
48548                     else {
48549                         nonCachedPreStored.push([id, cellId]);
48550                     }
48551                 }
48552             }
48553             const uncachePreStored = potentialPreStored
48554                 .sort(([na1], [na2]) => {
48555                 return na2.accessed - na1.accessed;
48556             })
48557                 .slice(this._configuration.maxUnusedPreStoredImages)
48558                 .map(([na, h]) => {
48559                 return [na.node.id, h];
48560             });
48561             this._uncachePreStored(nonCachedPreStored);
48562             this._uncachePreStored(uncachePreStored);
48563             const potentialNodes = [];
48564             for (let id in this._cachedNodes) {
48565                 if (!this._cachedNodes.hasOwnProperty(id) || id in idsInUse) {
48566                     continue;
48567                 }
48568                 potentialNodes.push(this._cachedNodes[id]);
48569             }
48570             const uncacheNodes = potentialNodes
48571                 .sort((n1, n2) => {
48572                 return n2.accessed - n1.accessed;
48573             })
48574                 .slice(this._configuration.maxUnusedImages);
48575             for (const nodeAccess of uncacheNodes) {
48576                 nodeAccess.node.uncache();
48577                 const id = nodeAccess.node.id;
48578                 delete this._cachedNodes[id];
48579                 if (id in this._cachedNodeTiles) {
48580                     delete this._cachedNodeTiles[id];
48581                 }
48582                 if (id in this._cachedSpatialEdges) {
48583                     delete this._cachedSpatialEdges[id];
48584                 }
48585             }
48586             const potentialSequences = [];
48587             for (let sequenceId in this._sequences) {
48588                 if (!this._sequences.hasOwnProperty(sequenceId) ||
48589                     sequenceId in this._cachingSequences$ ||
48590                     sequenceId === keepSequenceId) {
48591                     continue;
48592                 }
48593                 potentialSequences.push(this._sequences[sequenceId]);
48594             }
48595             const uncacheSequences = potentialSequences
48596                 .sort((s1, s2) => {
48597                 return s2.accessed - s1.accessed;
48598             })
48599                 .slice(this._configuration.maxSequences);
48600             for (const sequenceAccess of uncacheSequences) {
48601                 const sequenceId = sequenceAccess.sequence.id;
48602                 delete this._sequences[sequenceId];
48603                 if (sequenceId in this._cachedSequenceNodes) {
48604                     delete this._cachedSequenceNodes[sequenceId];
48605                 }
48606                 sequenceAccess.sequence.dispose();
48607             }
48608         }
48609         /**
48610          * Updates existing cells with new core nodes.
48611          *
48612          * @description Non-existing cells are discarded
48613          * and not requested at all.
48614          *
48615          * Existing nodes are not changed.
48616          *
48617          * New nodes are not made full or getting assets
48618          * cached.
48619          *
48620          * @param {Array<string>} cellIds - Cell ids.
48621          * @returns {Observable<Array<Image>>} Observable
48622          * emitting the updated cells.
48623          */
48624         updateCells$(cellIds) {
48625             const cachedCells = this._cachedTiles;
48626             const cachingCells = this._cachingTiles$;
48627             return from(cellIds)
48628                 .pipe(mergeMap((cellId) => {
48629                 if (cellId in cachedCells) {
48630                     return this._updateCell$(cellId);
48631                 }
48632                 if (cellId in cachingCells) {
48633                     return cachingCells[cellId]
48634                         .pipe(catchError(() => {
48635                         return of(this);
48636                     }), mergeMap(() => this._updateCell$(cellId)));
48637                 }
48638                 return empty();
48639             }));
48640         }
48641         /**
48642          * Unsubscribes all subscriptions.
48643          *
48644          * @description Afterwards, you must not call any other methods
48645          * on the graph instance.
48646          */
48647         unsubscribe() {
48648             this._filterSubscription.unsubscribe();
48649         }
48650         _addNewKeys(keys, dict) {
48651             for (let key in dict) {
48652                 if (!dict.hasOwnProperty(key) || !this.hasNode(key)) {
48653                     continue;
48654                 }
48655                 if (!(key in keys)) {
48656                     keys[key] = true;
48657                 }
48658             }
48659         }
48660         _cacheSequence$(sequenceId) {
48661             if (sequenceId in this._cachingSequences$) {
48662                 return this._cachingSequences$[sequenceId];
48663             }
48664             this._cachingSequences$[sequenceId] = this._api
48665                 .getSequence$(sequenceId)
48666                 .pipe(tap((sequence) => {
48667                 if (!sequence) {
48668                     console.warn(`Sequence does not exist ` +
48669                         `(${sequenceId})`);
48670                 }
48671                 else {
48672                     if (!(sequence.id in this._sequences)) {
48673                         this._sequences[sequence.id] = {
48674                             accessed: new Date().getTime(),
48675                             sequence: new Sequence(sequence),
48676                         };
48677                     }
48678                     delete this._cachingSequences$[sequenceId];
48679                 }
48680             }), map(() => { return this; }), finalize(() => {
48681                 if (sequenceId in this._cachingSequences$) {
48682                     delete this._cachingSequences$[sequenceId];
48683                 }
48684                 this._changed$.next(this);
48685             }), publish(), refCount());
48686             return this._cachingSequences$[sequenceId];
48687         }
48688         _cacheTile$(cellId) {
48689             this._cachingTiles$[cellId] = this._api
48690                 .getCoreImages$(cellId)
48691                 .pipe(tap((contract) => {
48692                 if (cellId in this._cachedTiles) {
48693                     return;
48694                 }
48695                 const cores = contract.images;
48696                 this._nodeIndexTiles[cellId] = [];
48697                 this._cachedTiles[cellId] = {
48698                     accessed: new Date().getTime(),
48699                     nodes: [],
48700                 };
48701                 const hCache = this._cachedTiles[cellId].nodes;
48702                 const preStored = this._removeFromPreStore(cellId);
48703                 for (const core of cores) {
48704                     if (!core) {
48705                         break;
48706                     }
48707                     if (core.sequence.id == null) {
48708                         console.warn(`Sequence missing, discarding ` +
48709                             `node (${core.id})`);
48710                         continue;
48711                     }
48712                     if (preStored != null && core.id in preStored) {
48713                         const preStoredNode = preStored[core.id];
48714                         delete preStored[core.id];
48715                         hCache.push(preStoredNode);
48716                         const preStoredNodeIndexItem = {
48717                             lat: preStoredNode.lngLat.lat,
48718                             lng: preStoredNode.lngLat.lng,
48719                             node: preStoredNode,
48720                         };
48721                         this._nodeIndex.insert(preStoredNodeIndexItem);
48722                         this._nodeIndexTiles[cellId]
48723                             .push(preStoredNodeIndexItem);
48724                         this._nodeToTile[preStoredNode.id] = cellId;
48725                         continue;
48726                     }
48727                     const node = new Image$1(core);
48728                     hCache.push(node);
48729                     const nodeIndexItem = {
48730                         lat: node.lngLat.lat,
48731                         lng: node.lngLat.lng,
48732                         node: node,
48733                     };
48734                     this._nodeIndex.insert(nodeIndexItem);
48735                     this._nodeIndexTiles[cellId].push(nodeIndexItem);
48736                     this._nodeToTile[node.id] = cellId;
48737                     this._setNode(node);
48738                 }
48739                 delete this._cachingTiles$[cellId];
48740             }), map(() => this), catchError((error) => {
48741                 delete this._cachingTiles$[cellId];
48742                 throw error;
48743             }), publish(), refCount());
48744             return this._cachingTiles$[cellId];
48745         }
48746         _makeFull(node, fillNode) {
48747             if (fillNode.computed_altitude == null) {
48748                 fillNode.computed_altitude = this._defaultAlt;
48749             }
48750             if (fillNode.computed_rotation == null) {
48751                 fillNode.computed_rotation = this._graphCalculator.rotationFromCompass(fillNode.compass_angle, fillNode.exif_orientation);
48752             }
48753             node.makeComplete(fillNode);
48754         }
48755         _preStore(h, node) {
48756             if (!(h in this._preStored)) {
48757                 this._preStored[h] = {};
48758             }
48759             this._preStored[h][node.id] = node;
48760         }
48761         _removeFromPreStore(h) {
48762             let preStored = null;
48763             if (h in this._preStored) {
48764                 preStored = this._preStored[h];
48765                 delete this._preStored[h];
48766             }
48767             return preStored;
48768         }
48769         _setNode(node) {
48770             let key = node.id;
48771             if (this.hasNode(key)) {
48772                 throw new GraphMapillaryError(`Image already exist (${key}).`);
48773             }
48774             this._nodes[key] = node;
48775         }
48776         _uncacheTile(h, keepSequenceKey) {
48777             for (let node of this._cachedTiles[h].nodes) {
48778                 let key = node.id;
48779                 delete this._nodeToTile[key];
48780                 if (key in this._cachedNodes) {
48781                     delete this._cachedNodes[key];
48782                 }
48783                 if (key in this._cachedNodeTiles) {
48784                     delete this._cachedNodeTiles[key];
48785                 }
48786                 if (key in this._cachedSpatialEdges) {
48787                     delete this._cachedSpatialEdges[key];
48788                 }
48789                 if (node.sequenceId === keepSequenceKey) {
48790                     this._preStore(h, node);
48791                     node.uncache();
48792                 }
48793                 else {
48794                     delete this._nodes[key];
48795                     if (node.sequenceId in this._cachedSequenceNodes) {
48796                         delete this._cachedSequenceNodes[node.sequenceId];
48797                     }
48798                     node.dispose();
48799                 }
48800             }
48801             for (let nodeIndexItem of this._nodeIndexTiles[h]) {
48802                 this._nodeIndex.remove(nodeIndexItem);
48803             }
48804             delete this._nodeIndexTiles[h];
48805             delete this._cachedTiles[h];
48806         }
48807         _uncachePreStored(preStored) {
48808             let hs = {};
48809             for (let [key, h] of preStored) {
48810                 if (key in this._nodes) {
48811                     delete this._nodes[key];
48812                 }
48813                 if (key in this._cachedNodes) {
48814                     delete this._cachedNodes[key];
48815                 }
48816                 let node = this._preStored[h][key];
48817                 if (node.sequenceId in this._cachedSequenceNodes) {
48818                     delete this._cachedSequenceNodes[node.sequenceId];
48819                 }
48820                 delete this._preStored[h][key];
48821                 node.dispose();
48822                 hs[h] = true;
48823             }
48824             for (let h in hs) {
48825                 if (!hs.hasOwnProperty(h)) {
48826                     continue;
48827                 }
48828                 if (Object.keys(this._preStored[h]).length === 0) {
48829                     delete this._preStored[h];
48830                 }
48831             }
48832         }
48833         _updateCachedTileAccess(key, accessed) {
48834             if (key in this._nodeToTile) {
48835                 this._cachedTiles[this._nodeToTile[key]].accessed = accessed;
48836             }
48837         }
48838         _updateCachedNodeAccess(key, accessed) {
48839             if (key in this._cachedNodes) {
48840                 this._cachedNodes[key].accessed = accessed;
48841             }
48842         }
48843         _updateCell$(cellId) {
48844             return this._api.getCoreImages$(cellId).pipe(mergeMap((contract) => {
48845                 if (!(cellId in this._cachedTiles)) {
48846                     return empty();
48847                 }
48848                 const nodeIndex = this._nodeIndex;
48849                 const nodeIndexCell = this._nodeIndexTiles[cellId];
48850                 const nodeToCell = this._nodeToTile;
48851                 const cell = this._cachedTiles[cellId];
48852                 cell.accessed = new Date().getTime();
48853                 const cellNodes = cell.nodes;
48854                 const cores = contract.images;
48855                 for (const core of cores) {
48856                     if (core == null) {
48857                         break;
48858                     }
48859                     if (this.hasNode(core.id)) {
48860                         continue;
48861                     }
48862                     if (core.sequence.id == null) {
48863                         console.warn(`Sequence missing, discarding ` +
48864                             `node (${core.id})`);
48865                         continue;
48866                     }
48867                     const node = new Image$1(core);
48868                     cellNodes.push(node);
48869                     const nodeIndexItem = {
48870                         lat: node.lngLat.lat,
48871                         lng: node.lngLat.lng,
48872                         node: node,
48873                     };
48874                     nodeIndex.insert(nodeIndexItem);
48875                     nodeIndexCell.push(nodeIndexItem);
48876                     nodeToCell[node.id] = cellId;
48877                     this._setNode(node);
48878                 }
48879                 return of(cellId);
48880             }), catchError((error) => {
48881                 console.error(error);
48882                 return empty();
48883             }));
48884         }
48885     }
48886
48887     class MarkerSet {
48888         constructor() {
48889             this._hash = {};
48890             this._index = new MarkerSet._spatialIndex(16);
48891             this._indexChanged$ = new Subject();
48892             this._updated$ = new Subject();
48893         }
48894         static register(spatialIndex) {
48895             MarkerSet._spatialIndex = spatialIndex;
48896         }
48897         get changed$() {
48898             return this._indexChanged$;
48899         }
48900         get updated$() {
48901             return this._updated$;
48902         }
48903         add(markers) {
48904             const updated = [];
48905             const hash = this._hash;
48906             const index = this._index;
48907             for (const marker of markers) {
48908                 const id = marker.id;
48909                 if (id in hash) {
48910                     index.remove(hash[id]);
48911                     updated.push(marker);
48912                 }
48913                 const item = {
48914                     lat: marker.lngLat.lat,
48915                     lng: marker.lngLat.lng,
48916                     marker: marker,
48917                 };
48918                 hash[id] = item;
48919                 index.insert(item);
48920             }
48921             if (updated.length > 0) {
48922                 this._updated$.next(updated);
48923             }
48924             if (markers.length > updated.length) {
48925                 this._indexChanged$.next(this);
48926             }
48927         }
48928         has(id) {
48929             return id in this._hash;
48930         }
48931         get(id) {
48932             return this.has(id) ? this._hash[id].marker : undefined;
48933         }
48934         getAll() {
48935             return this._index
48936                 .all()
48937                 .map((indexItem) => {
48938                 return indexItem.marker;
48939             });
48940         }
48941         remove(ids) {
48942             const hash = this._hash;
48943             const index = this._index;
48944             let changed = false;
48945             for (const id of ids) {
48946                 if (!(id in hash)) {
48947                     continue;
48948                 }
48949                 const item = hash[id];
48950                 index.remove(item);
48951                 delete hash[id];
48952                 changed = true;
48953             }
48954             if (changed) {
48955                 this._indexChanged$.next(this);
48956             }
48957         }
48958         removeAll() {
48959             this._hash = {};
48960             this._index.clear();
48961             this._indexChanged$.next(this);
48962         }
48963         search([sw, ne]) {
48964             return this._index
48965                 .search({
48966                 maxX: ne.lng,
48967                 maxY: ne.lat,
48968                 minX: sw.lng,
48969                 minY: sw.lat,
48970             })
48971                 .map((indexItem) => {
48972                 return indexItem.marker;
48973             });
48974         }
48975         update(marker) {
48976             const hash = this._hash;
48977             const index = this._index;
48978             const id = marker.id;
48979             if (!(id in hash)) {
48980                 return;
48981             }
48982             index.remove(hash[id]);
48983             const item = {
48984                 lat: marker.lngLat.lat,
48985                 lng: marker.lngLat.lng,
48986                 marker: marker,
48987             };
48988             hash[id] = item;
48989             index.insert(item);
48990         }
48991     }
48992
48993     function quickselect(arr, k, left, right, compare) {
48994         quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare$2);
48995     }
48996
48997     function quickselectStep(arr, k, left, right, compare) {
48998
48999         while (right > left) {
49000             if (right - left > 600) {
49001                 var n = right - left + 1;
49002                 var m = k - left + 1;
49003                 var z = Math.log(n);
49004                 var s = 0.5 * Math.exp(2 * z / 3);
49005                 var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
49006                 var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
49007                 var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
49008                 quickselectStep(arr, k, newLeft, newRight, compare);
49009             }
49010
49011             var t = arr[k];
49012             var i = left;
49013             var j = right;
49014
49015             swap(arr, left, k);
49016             if (compare(arr[right], t) > 0) swap(arr, left, right);
49017
49018             while (i < j) {
49019                 swap(arr, i, j);
49020                 i++;
49021                 j--;
49022                 while (compare(arr[i], t) < 0) i++;
49023                 while (compare(arr[j], t) > 0) j--;
49024             }
49025
49026             if (compare(arr[left], t) === 0) swap(arr, left, j);
49027             else {
49028                 j++;
49029                 swap(arr, j, right);
49030             }
49031
49032             if (j <= k) left = j + 1;
49033             if (k <= j) right = j - 1;
49034         }
49035     }
49036
49037     function swap(arr, i, j) {
49038         var tmp = arr[i];
49039         arr[i] = arr[j];
49040         arr[j] = tmp;
49041     }
49042
49043     function defaultCompare$2(a, b) {
49044         return a < b ? -1 : a > b ? 1 : 0;
49045     }
49046
49047     class RBush {
49048         constructor(maxEntries = 9) {
49049             // max entries in a node is 9 by default; min node fill is 40% for best performance
49050             this._maxEntries = Math.max(4, maxEntries);
49051             this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
49052             this.clear();
49053         }
49054
49055         all() {
49056             return this._all(this.data, []);
49057         }
49058
49059         search(bbox) {
49060             let node = this.data;
49061             const result = [];
49062
49063             if (!intersects$1(bbox, node)) return result;
49064
49065             const toBBox = this.toBBox;
49066             const nodesToSearch = [];
49067
49068             while (node) {
49069                 for (let i = 0; i < node.children.length; i++) {
49070                     const child = node.children[i];
49071                     const childBBox = node.leaf ? toBBox(child) : child;
49072
49073                     if (intersects$1(bbox, childBBox)) {
49074                         if (node.leaf) result.push(child);
49075                         else if (contains(bbox, childBBox)) this._all(child, result);
49076                         else nodesToSearch.push(child);
49077                     }
49078                 }
49079                 node = nodesToSearch.pop();
49080             }
49081
49082             return result;
49083         }
49084
49085         collides(bbox) {
49086             let node = this.data;
49087
49088             if (!intersects$1(bbox, node)) return false;
49089
49090             const nodesToSearch = [];
49091             while (node) {
49092                 for (let i = 0; i < node.children.length; i++) {
49093                     const child = node.children[i];
49094                     const childBBox = node.leaf ? this.toBBox(child) : child;
49095
49096                     if (intersects$1(bbox, childBBox)) {
49097                         if (node.leaf || contains(bbox, childBBox)) return true;
49098                         nodesToSearch.push(child);
49099                     }
49100                 }
49101                 node = nodesToSearch.pop();
49102             }
49103
49104             return false;
49105         }
49106
49107         load(data) {
49108             if (!(data && data.length)) return this;
49109
49110             if (data.length < this._minEntries) {
49111                 for (let i = 0; i < data.length; i++) {
49112                     this.insert(data[i]);
49113                 }
49114                 return this;
49115             }
49116
49117             // recursively build the tree with the given data from scratch using OMT algorithm
49118             let node = this._build(data.slice(), 0, data.length - 1, 0);
49119
49120             if (!this.data.children.length) {
49121                 // save as is if tree is empty
49122                 this.data = node;
49123
49124             } else if (this.data.height === node.height) {
49125                 // split root if trees have the same height
49126                 this._splitRoot(this.data, node);
49127
49128             } else {
49129                 if (this.data.height < node.height) {
49130                     // swap trees if inserted one is bigger
49131                     const tmpNode = this.data;
49132                     this.data = node;
49133                     node = tmpNode;
49134                 }
49135
49136                 // insert the small tree into the large tree at appropriate level
49137                 this._insert(node, this.data.height - node.height - 1, true);
49138             }
49139
49140             return this;
49141         }
49142
49143         insert(item) {
49144             if (item) this._insert(item, this.data.height - 1);
49145             return this;
49146         }
49147
49148         clear() {
49149             this.data = createNode([]);
49150             return this;
49151         }
49152
49153         remove(item, equalsFn) {
49154             if (!item) return this;
49155
49156             let node = this.data;
49157             const bbox = this.toBBox(item);
49158             const path = [];
49159             const indexes = [];
49160             let i, parent, goingUp;
49161
49162             // depth-first iterative tree traversal
49163             while (node || path.length) {
49164
49165                 if (!node) { // go up
49166                     node = path.pop();
49167                     parent = path[path.length - 1];
49168                     i = indexes.pop();
49169                     goingUp = true;
49170                 }
49171
49172                 if (node.leaf) { // check current node
49173                     const index = findItem(item, node.children, equalsFn);
49174
49175                     if (index !== -1) {
49176                         // item found, remove the item and condense tree upwards
49177                         node.children.splice(index, 1);
49178                         path.push(node);
49179                         this._condense(path);
49180                         return this;
49181                     }
49182                 }
49183
49184                 if (!goingUp && !node.leaf && contains(node, bbox)) { // go down
49185                     path.push(node);
49186                     indexes.push(i);
49187                     i = 0;
49188                     parent = node;
49189                     node = node.children[0];
49190
49191                 } else if (parent) { // go right
49192                     i++;
49193                     node = parent.children[i];
49194                     goingUp = false;
49195
49196                 } else node = null; // nothing found
49197             }
49198
49199             return this;
49200         }
49201
49202         toBBox(item) { return item; }
49203
49204         compareMinX(a, b) { return a.minX - b.minX; }
49205         compareMinY(a, b) { return a.minY - b.minY; }
49206
49207         toJSON() { return this.data; }
49208
49209         fromJSON(data) {
49210             this.data = data;
49211             return this;
49212         }
49213
49214         _all(node, result) {
49215             const nodesToSearch = [];
49216             while (node) {
49217                 if (node.leaf) result.push(...node.children);
49218                 else nodesToSearch.push(...node.children);
49219
49220                 node = nodesToSearch.pop();
49221             }
49222             return result;
49223         }
49224
49225         _build(items, left, right, height) {
49226
49227             const N = right - left + 1;
49228             let M = this._maxEntries;
49229             let node;
49230
49231             if (N <= M) {
49232                 // reached leaf level; return leaf
49233                 node = createNode(items.slice(left, right + 1));
49234                 calcBBox(node, this.toBBox);
49235                 return node;
49236             }
49237
49238             if (!height) {
49239                 // target height of the bulk-loaded tree
49240                 height = Math.ceil(Math.log(N) / Math.log(M));
49241
49242                 // target number of root entries to maximize storage utilization
49243                 M = Math.ceil(N / Math.pow(M, height - 1));
49244             }
49245
49246             node = createNode([]);
49247             node.leaf = false;
49248             node.height = height;
49249
49250             // split the items into M mostly square tiles
49251
49252             const N2 = Math.ceil(N / M);
49253             const N1 = N2 * Math.ceil(Math.sqrt(M));
49254
49255             multiSelect(items, left, right, N1, this.compareMinX);
49256
49257             for (let i = left; i <= right; i += N1) {
49258
49259                 const right2 = Math.min(i + N1 - 1, right);
49260
49261                 multiSelect(items, i, right2, N2, this.compareMinY);
49262
49263                 for (let j = i; j <= right2; j += N2) {
49264
49265                     const right3 = Math.min(j + N2 - 1, right2);
49266
49267                     // pack each entry recursively
49268                     node.children.push(this._build(items, j, right3, height - 1));
49269                 }
49270             }
49271
49272             calcBBox(node, this.toBBox);
49273
49274             return node;
49275         }
49276
49277         _chooseSubtree(bbox, node, level, path) {
49278             while (true) {
49279                 path.push(node);
49280
49281                 if (node.leaf || path.length - 1 === level) break;
49282
49283                 let minArea = Infinity;
49284                 let minEnlargement = Infinity;
49285                 let targetNode;
49286
49287                 for (let i = 0; i < node.children.length; i++) {
49288                     const child = node.children[i];
49289                     const area = bboxArea(child);
49290                     const enlargement = enlargedArea(bbox, child) - area;
49291
49292                     // choose entry with the least area enlargement
49293                     if (enlargement < minEnlargement) {
49294                         minEnlargement = enlargement;
49295                         minArea = area < minArea ? area : minArea;
49296                         targetNode = child;
49297
49298                     } else if (enlargement === minEnlargement) {
49299                         // otherwise choose one with the smallest area
49300                         if (area < minArea) {
49301                             minArea = area;
49302                             targetNode = child;
49303                         }
49304                     }
49305                 }
49306
49307                 node = targetNode || node.children[0];
49308             }
49309
49310             return node;
49311         }
49312
49313         _insert(item, level, isNode) {
49314             const bbox = isNode ? item : this.toBBox(item);
49315             const insertPath = [];
49316
49317             // find the best node for accommodating the item, saving all nodes along the path too
49318             const node = this._chooseSubtree(bbox, this.data, level, insertPath);
49319
49320             // put the item into the node
49321             node.children.push(item);
49322             extend(node, bbox);
49323
49324             // split on node overflow; propagate upwards if necessary
49325             while (level >= 0) {
49326                 if (insertPath[level].children.length > this._maxEntries) {
49327                     this._split(insertPath, level);
49328                     level--;
49329                 } else break;
49330             }
49331
49332             // adjust bboxes along the insertion path
49333             this._adjustParentBBoxes(bbox, insertPath, level);
49334         }
49335
49336         // split overflowed node into two
49337         _split(insertPath, level) {
49338             const node = insertPath[level];
49339             const M = node.children.length;
49340             const m = this._minEntries;
49341
49342             this._chooseSplitAxis(node, m, M);
49343
49344             const splitIndex = this._chooseSplitIndex(node, m, M);
49345
49346             const newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
49347             newNode.height = node.height;
49348             newNode.leaf = node.leaf;
49349
49350             calcBBox(node, this.toBBox);
49351             calcBBox(newNode, this.toBBox);
49352
49353             if (level) insertPath[level - 1].children.push(newNode);
49354             else this._splitRoot(node, newNode);
49355         }
49356
49357         _splitRoot(node, newNode) {
49358             // split root node
49359             this.data = createNode([node, newNode]);
49360             this.data.height = node.height + 1;
49361             this.data.leaf = false;
49362             calcBBox(this.data, this.toBBox);
49363         }
49364
49365         _chooseSplitIndex(node, m, M) {
49366             let index;
49367             let minOverlap = Infinity;
49368             let minArea = Infinity;
49369
49370             for (let i = m; i <= M - m; i++) {
49371                 const bbox1 = distBBox(node, 0, i, this.toBBox);
49372                 const bbox2 = distBBox(node, i, M, this.toBBox);
49373
49374                 const overlap = intersectionArea(bbox1, bbox2);
49375                 const area = bboxArea(bbox1) + bboxArea(bbox2);
49376
49377                 // choose distribution with minimum overlap
49378                 if (overlap < minOverlap) {
49379                     minOverlap = overlap;
49380                     index = i;
49381
49382                     minArea = area < minArea ? area : minArea;
49383
49384                 } else if (overlap === minOverlap) {
49385                     // otherwise choose distribution with minimum area
49386                     if (area < minArea) {
49387                         minArea = area;
49388                         index = i;
49389                     }
49390                 }
49391             }
49392
49393             return index || M - m;
49394         }
49395
49396         // sorts node children by the best axis for split
49397         _chooseSplitAxis(node, m, M) {
49398             const compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
49399             const compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
49400             const xMargin = this._allDistMargin(node, m, M, compareMinX);
49401             const yMargin = this._allDistMargin(node, m, M, compareMinY);
49402
49403             // if total distributions margin value is minimal for x, sort by minX,
49404             // otherwise it's already sorted by minY
49405             if (xMargin < yMargin) node.children.sort(compareMinX);
49406         }
49407
49408         // total margin of all possible split distributions where each node is at least m full
49409         _allDistMargin(node, m, M, compare) {
49410             node.children.sort(compare);
49411
49412             const toBBox = this.toBBox;
49413             const leftBBox = distBBox(node, 0, m, toBBox);
49414             const rightBBox = distBBox(node, M - m, M, toBBox);
49415             let margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
49416
49417             for (let i = m; i < M - m; i++) {
49418                 const child = node.children[i];
49419                 extend(leftBBox, node.leaf ? toBBox(child) : child);
49420                 margin += bboxMargin(leftBBox);
49421             }
49422
49423             for (let i = M - m - 1; i >= m; i--) {
49424                 const child = node.children[i];
49425                 extend(rightBBox, node.leaf ? toBBox(child) : child);
49426                 margin += bboxMargin(rightBBox);
49427             }
49428
49429             return margin;
49430         }
49431
49432         _adjustParentBBoxes(bbox, path, level) {
49433             // adjust bboxes along the given tree path
49434             for (let i = level; i >= 0; i--) {
49435                 extend(path[i], bbox);
49436             }
49437         }
49438
49439         _condense(path) {
49440             // go through the path, removing empty nodes and updating bboxes
49441             for (let i = path.length - 1, siblings; i >= 0; i--) {
49442                 if (path[i].children.length === 0) {
49443                     if (i > 0) {
49444                         siblings = path[i - 1].children;
49445                         siblings.splice(siblings.indexOf(path[i]), 1);
49446
49447                     } else this.clear();
49448
49449                 } else calcBBox(path[i], this.toBBox);
49450             }
49451         }
49452     }
49453
49454     function findItem(item, items, equalsFn) {
49455         if (!equalsFn) return items.indexOf(item);
49456
49457         for (let i = 0; i < items.length; i++) {
49458             if (equalsFn(item, items[i])) return i;
49459         }
49460         return -1;
49461     }
49462
49463     // calculate node's bbox from bboxes of its children
49464     function calcBBox(node, toBBox) {
49465         distBBox(node, 0, node.children.length, toBBox, node);
49466     }
49467
49468     // min bounding rectangle of node children from k to p-1
49469     function distBBox(node, k, p, toBBox, destNode) {
49470         if (!destNode) destNode = createNode(null);
49471         destNode.minX = Infinity;
49472         destNode.minY = Infinity;
49473         destNode.maxX = -Infinity;
49474         destNode.maxY = -Infinity;
49475
49476         for (let i = k; i < p; i++) {
49477             const child = node.children[i];
49478             extend(destNode, node.leaf ? toBBox(child) : child);
49479         }
49480
49481         return destNode;
49482     }
49483
49484     function extend(a, b) {
49485         a.minX = Math.min(a.minX, b.minX);
49486         a.minY = Math.min(a.minY, b.minY);
49487         a.maxX = Math.max(a.maxX, b.maxX);
49488         a.maxY = Math.max(a.maxY, b.maxY);
49489         return a;
49490     }
49491
49492     function compareNodeMinX(a, b) { return a.minX - b.minX; }
49493     function compareNodeMinY(a, b) { return a.minY - b.minY; }
49494
49495     function bboxArea(a)   { return (a.maxX - a.minX) * (a.maxY - a.minY); }
49496     function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
49497
49498     function enlargedArea(a, b) {
49499         return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
49500                (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
49501     }
49502
49503     function intersectionArea(a, b) {
49504         const minX = Math.max(a.minX, b.minX);
49505         const minY = Math.max(a.minY, b.minY);
49506         const maxX = Math.min(a.maxX, b.maxX);
49507         const maxY = Math.min(a.maxY, b.maxY);
49508
49509         return Math.max(0, maxX - minX) *
49510                Math.max(0, maxY - minY);
49511     }
49512
49513     function contains(a, b) {
49514         return a.minX <= b.minX &&
49515                a.minY <= b.minY &&
49516                b.maxX <= a.maxX &&
49517                b.maxY <= a.maxY;
49518     }
49519
49520     function intersects$1(a, b) {
49521         return b.minX <= a.maxX &&
49522                b.minY <= a.maxY &&
49523                b.maxX >= a.minX &&
49524                b.maxY >= a.minY;
49525     }
49526
49527     function createNode(children) {
49528         return {
49529             children,
49530             height: 1,
49531             leaf: true,
49532             minX: Infinity,
49533             minY: Infinity,
49534             maxX: -Infinity,
49535             maxY: -Infinity
49536         };
49537     }
49538
49539     // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
49540     // combines selection algorithm with binary divide & conquer approach
49541
49542     function multiSelect(arr, left, right, n, compare) {
49543         const stack = [left, right];
49544
49545         while (stack.length) {
49546             right = stack.pop();
49547             left = stack.pop();
49548
49549             if (right - left <= n) continue;
49550
49551             const mid = left + Math.ceil((right - left) / n / 2) * n;
49552             quickselect(arr, mid, left, right, compare);
49553
49554             stack.push(left, mid, mid, right);
49555         }
49556     }
49557
49558     class GeoRBush extends RBush {
49559         compareMinX(a, b) {
49560             return a.lng - b.lng;
49561         }
49562         compareMinY(a, b) {
49563             return a.lat - b.lat;
49564         }
49565         toBBox(item) {
49566             return {
49567                 minX: item.lng,
49568                 minY: item.lat,
49569                 maxX: item.lng,
49570                 maxY: item.lat,
49571             };
49572         }
49573     }
49574
49575     class ComponentService {
49576         constructor(container, navigator) {
49577             this._components = {};
49578             for (const componentName in ComponentService.registeredComponents) {
49579                 if (!ComponentService.registeredComponents.hasOwnProperty(componentName)) {
49580                     continue;
49581                 }
49582                 const component = ComponentService.registeredComponents[componentName];
49583                 this._components[componentName] = {
49584                     active: false,
49585                     component: new component(componentName, container, navigator),
49586                 };
49587             }
49588             this._coverComponent = new ComponentService.registeredCoverComponent("cover", container, navigator);
49589             this._coverComponent.activate();
49590             this._coverActivated = true;
49591         }
49592         static register(component) {
49593             if (ComponentService.registeredComponents[component.componentName] === undefined) {
49594                 ComponentService.registeredComponents[component.componentName] = component;
49595             }
49596         }
49597         static registerCover(coverComponent) {
49598             ComponentService.registeredCoverComponent = coverComponent;
49599         }
49600         get coverActivated() {
49601             return this._coverActivated;
49602         }
49603         activateCover() {
49604             if (this._coverActivated) {
49605                 return;
49606             }
49607             this._coverActivated = true;
49608             for (const componentName in this._components) {
49609                 if (!this._components.hasOwnProperty(componentName)) {
49610                     continue;
49611                 }
49612                 const component = this._components[componentName];
49613                 if (component.active) {
49614                     component.component.deactivate();
49615                 }
49616             }
49617         }
49618         deactivateCover() {
49619             if (!this._coverActivated) {
49620                 return;
49621             }
49622             this._coverActivated = false;
49623             for (const componentName in this._components) {
49624                 if (!this._components.hasOwnProperty(componentName)) {
49625                     continue;
49626                 }
49627                 const component = this._components[componentName];
49628                 if (component.active) {
49629                     component.component.activate();
49630                 }
49631             }
49632         }
49633         activate(name) {
49634             this._checkName(name);
49635             this._components[name].active = true;
49636             if (!this._coverActivated) {
49637                 this.get(name).activate();
49638             }
49639         }
49640         configure(name, conf) {
49641             this._checkName(name);
49642             this.get(name).configure(conf);
49643         }
49644         deactivate(name) {
49645             this._checkName(name);
49646             this._components[name].active = false;
49647             if (!this._coverActivated) {
49648                 this.get(name).deactivate();
49649             }
49650         }
49651         get(name) {
49652             return this._components[name].component;
49653         }
49654         getCover() {
49655             return this._coverComponent;
49656         }
49657         remove() {
49658             this._coverComponent.deactivate();
49659             for (const componentName in this._components) {
49660                 if (!this._components.hasOwnProperty(componentName)) {
49661                     continue;
49662                 }
49663                 this._components[componentName].component.deactivate();
49664             }
49665         }
49666         _checkName(name) {
49667             if (!(name in this._components)) {
49668                 throw new ArgumentMapillaryError(`Component does not exist: ${name}`);
49669             }
49670         }
49671     }
49672     ComponentService.registeredComponents = {};
49673
49674     var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
49675
49676     function getAugmentedNamespace(n) {
49677         if (n.__esModule) return n;
49678         var a = Object.defineProperty({}, '__esModule', {value: true});
49679         Object.keys(n).forEach(function (k) {
49680                 var d = Object.getOwnPropertyDescriptor(n, k);
49681                 Object.defineProperty(a, k, d.get ? d : {
49682                         enumerable: true,
49683                         get: function () {
49684                                 return n[k];
49685                         }
49686                 });
49687         });
49688         return a;
49689     }
49690
49691     function commonjsRequire (path) {
49692         throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
49693     }
49694
49695     var nativeIsArray = Array.isArray;
49696     var toString$2 = Object.prototype.toString;
49697
49698     var xIsArray = nativeIsArray || isArray$3;
49699
49700     function isArray$3(obj) {
49701         return toString$2.call(obj) === "[object Array]"
49702     }
49703
49704     var version$5 = "2";
49705
49706     var version$4 = version$5;
49707
49708     VirtualPatch.NONE = 0;
49709     VirtualPatch.VTEXT = 1;
49710     VirtualPatch.VNODE = 2;
49711     VirtualPatch.WIDGET = 3;
49712     VirtualPatch.PROPS = 4;
49713     VirtualPatch.ORDER = 5;
49714     VirtualPatch.INSERT = 6;
49715     VirtualPatch.REMOVE = 7;
49716     VirtualPatch.THUNK = 8;
49717
49718     var vpatch = VirtualPatch;
49719
49720     function VirtualPatch(type, vNode, patch) {
49721         this.type = Number(type);
49722         this.vNode = vNode;
49723         this.patch = patch;
49724     }
49725
49726     VirtualPatch.prototype.version = version$4;
49727     VirtualPatch.prototype.type = "VirtualPatch";
49728
49729     var version$3 = version$5;
49730
49731     var isVnode = isVirtualNode;
49732
49733     function isVirtualNode(x) {
49734         return x && x.type === "VirtualNode" && x.version === version$3
49735     }
49736
49737     var version$2 = version$5;
49738
49739     var isVtext = isVirtualText;
49740
49741     function isVirtualText(x) {
49742         return x && x.type === "VirtualText" && x.version === version$2
49743     }
49744
49745     var isWidget_1 = isWidget$7;
49746
49747     function isWidget$7(w) {
49748         return w && w.type === "Widget"
49749     }
49750
49751     var isThunk_1 = isThunk$3;
49752
49753     function isThunk$3(t) {
49754         return t && t.type === "Thunk"
49755     }
49756
49757     var isVNode$4 = isVnode;
49758     var isVText$3 = isVtext;
49759     var isWidget$6 = isWidget_1;
49760     var isThunk$2 = isThunk_1;
49761
49762     var handleThunk_1 = handleThunk$2;
49763
49764     function handleThunk$2(a, b) {
49765         var renderedA = a;
49766         var renderedB = b;
49767
49768         if (isThunk$2(b)) {
49769             renderedB = renderThunk(b, a);
49770         }
49771
49772         if (isThunk$2(a)) {
49773             renderedA = renderThunk(a, null);
49774         }
49775
49776         return {
49777             a: renderedA,
49778             b: renderedB
49779         }
49780     }
49781
49782     function renderThunk(thunk, previous) {
49783         var renderedThunk = thunk.vnode;
49784
49785         if (!renderedThunk) {
49786             renderedThunk = thunk.vnode = thunk.render(previous);
49787         }
49788
49789         if (!(isVNode$4(renderedThunk) ||
49790                 isVText$3(renderedThunk) ||
49791                 isWidget$6(renderedThunk))) {
49792             throw new Error("thunk did not return a valid node");
49793         }
49794
49795         return renderedThunk
49796     }
49797
49798     var isObject$2 = function isObject(x) {
49799         return typeof x === 'object' && x !== null;
49800     };
49801
49802     var isVhook = isHook$3;
49803
49804     function isHook$3(hook) {
49805         return hook &&
49806           (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") ||
49807            typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook"))
49808     }
49809
49810     var isObject$1 = isObject$2;
49811     var isHook$2 = isVhook;
49812
49813     var diffProps_1 = diffProps$1;
49814
49815     function diffProps$1(a, b) {
49816         var diff;
49817
49818         for (var aKey in a) {
49819             if (!(aKey in b)) {
49820                 diff = diff || {};
49821                 diff[aKey] = undefined;
49822             }
49823
49824             var aValue = a[aKey];
49825             var bValue = b[aKey];
49826
49827             if (aValue === bValue) {
49828                 continue
49829             } else if (isObject$1(aValue) && isObject$1(bValue)) {
49830                 if (getPrototype$1(bValue) !== getPrototype$1(aValue)) {
49831                     diff = diff || {};
49832                     diff[aKey] = bValue;
49833                 } else if (isHook$2(bValue)) {
49834                      diff = diff || {};
49835                      diff[aKey] = bValue;
49836                 } else {
49837                     var objectDiff = diffProps$1(aValue, bValue);
49838                     if (objectDiff) {
49839                         diff = diff || {};
49840                         diff[aKey] = objectDiff;
49841                     }
49842                 }
49843             } else {
49844                 diff = diff || {};
49845                 diff[aKey] = bValue;
49846             }
49847         }
49848
49849         for (var bKey in b) {
49850             if (!(bKey in a)) {
49851                 diff = diff || {};
49852                 diff[bKey] = b[bKey];
49853             }
49854         }
49855
49856         return diff
49857     }
49858
49859     function getPrototype$1(value) {
49860       if (Object.getPrototypeOf) {
49861         return Object.getPrototypeOf(value)
49862       } else if (value.__proto__) {
49863         return value.__proto__
49864       } else if (value.constructor) {
49865         return value.constructor.prototype
49866       }
49867     }
49868
49869     var isArray$2 = xIsArray;
49870
49871     var VPatch$1 = vpatch;
49872     var isVNode$3 = isVnode;
49873     var isVText$2 = isVtext;
49874     var isWidget$5 = isWidget_1;
49875     var isThunk$1 = isThunk_1;
49876     var handleThunk$1 = handleThunk_1;
49877
49878     var diffProps = diffProps_1;
49879
49880     var diff_1$1 = diff$2;
49881
49882     function diff$2(a, b) {
49883         var patch = { a: a };
49884         walk(a, b, patch, 0);
49885         return patch
49886     }
49887
49888     function walk(a, b, patch, index) {
49889         if (a === b) {
49890             return
49891         }
49892
49893         var apply = patch[index];
49894         var applyClear = false;
49895
49896         if (isThunk$1(a) || isThunk$1(b)) {
49897             thunks(a, b, patch, index);
49898         } else if (b == null) {
49899
49900             // If a is a widget we will add a remove patch for it
49901             // Otherwise any child widgets/hooks must be destroyed.
49902             // This prevents adding two remove patches for a widget.
49903             if (!isWidget$5(a)) {
49904                 clearState(a, patch, index);
49905                 apply = patch[index];
49906             }
49907
49908             apply = appendPatch(apply, new VPatch$1(VPatch$1.REMOVE, a, b));
49909         } else if (isVNode$3(b)) {
49910             if (isVNode$3(a)) {
49911                 if (a.tagName === b.tagName &&
49912                     a.namespace === b.namespace &&
49913                     a.key === b.key) {
49914                     var propsPatch = diffProps(a.properties, b.properties);
49915                     if (propsPatch) {
49916                         apply = appendPatch(apply,
49917                             new VPatch$1(VPatch$1.PROPS, a, propsPatch));
49918                     }
49919                     apply = diffChildren(a, b, patch, apply, index);
49920                 } else {
49921                     apply = appendPatch(apply, new VPatch$1(VPatch$1.VNODE, a, b));
49922                     applyClear = true;
49923                 }
49924             } else {
49925                 apply = appendPatch(apply, new VPatch$1(VPatch$1.VNODE, a, b));
49926                 applyClear = true;
49927             }
49928         } else if (isVText$2(b)) {
49929             if (!isVText$2(a)) {
49930                 apply = appendPatch(apply, new VPatch$1(VPatch$1.VTEXT, a, b));
49931                 applyClear = true;
49932             } else if (a.text !== b.text) {
49933                 apply = appendPatch(apply, new VPatch$1(VPatch$1.VTEXT, a, b));
49934             }
49935         } else if (isWidget$5(b)) {
49936             if (!isWidget$5(a)) {
49937                 applyClear = true;
49938             }
49939
49940             apply = appendPatch(apply, new VPatch$1(VPatch$1.WIDGET, a, b));
49941         }
49942
49943         if (apply) {
49944             patch[index] = apply;
49945         }
49946
49947         if (applyClear) {
49948             clearState(a, patch, index);
49949         }
49950     }
49951
49952     function diffChildren(a, b, patch, apply, index) {
49953         var aChildren = a.children;
49954         var orderedSet = reorder(aChildren, b.children);
49955         var bChildren = orderedSet.children;
49956
49957         var aLen = aChildren.length;
49958         var bLen = bChildren.length;
49959         var len = aLen > bLen ? aLen : bLen;
49960
49961         for (var i = 0; i < len; i++) {
49962             var leftNode = aChildren[i];
49963             var rightNode = bChildren[i];
49964             index += 1;
49965
49966             if (!leftNode) {
49967                 if (rightNode) {
49968                     // Excess nodes in b need to be added
49969                     apply = appendPatch(apply,
49970                         new VPatch$1(VPatch$1.INSERT, null, rightNode));
49971                 }
49972             } else {
49973                 walk(leftNode, rightNode, patch, index);
49974             }
49975
49976             if (isVNode$3(leftNode) && leftNode.count) {
49977                 index += leftNode.count;
49978             }
49979         }
49980
49981         if (orderedSet.moves) {
49982             // Reorder nodes last
49983             apply = appendPatch(apply, new VPatch$1(
49984                 VPatch$1.ORDER,
49985                 a,
49986                 orderedSet.moves
49987             ));
49988         }
49989
49990         return apply
49991     }
49992
49993     function clearState(vNode, patch, index) {
49994         // TODO: Make this a single walk, not two
49995         unhook(vNode, patch, index);
49996         destroyWidgets(vNode, patch, index);
49997     }
49998
49999     // Patch records for all destroyed widgets must be added because we need
50000     // a DOM node reference for the destroy function
50001     function destroyWidgets(vNode, patch, index) {
50002         if (isWidget$5(vNode)) {
50003             if (typeof vNode.destroy === "function") {
50004                 patch[index] = appendPatch(
50005                     patch[index],
50006                     new VPatch$1(VPatch$1.REMOVE, vNode, null)
50007                 );
50008             }
50009         } else if (isVNode$3(vNode) && (vNode.hasWidgets || vNode.hasThunks)) {
50010             var children = vNode.children;
50011             var len = children.length;
50012             for (var i = 0; i < len; i++) {
50013                 var child = children[i];
50014                 index += 1;
50015
50016                 destroyWidgets(child, patch, index);
50017
50018                 if (isVNode$3(child) && child.count) {
50019                     index += child.count;
50020                 }
50021             }
50022         } else if (isThunk$1(vNode)) {
50023             thunks(vNode, null, patch, index);
50024         }
50025     }
50026
50027     // Create a sub-patch for thunks
50028     function thunks(a, b, patch, index) {
50029         var nodes = handleThunk$1(a, b);
50030         var thunkPatch = diff$2(nodes.a, nodes.b);
50031         if (hasPatches(thunkPatch)) {
50032             patch[index] = new VPatch$1(VPatch$1.THUNK, null, thunkPatch);
50033         }
50034     }
50035
50036     function hasPatches(patch) {
50037         for (var index in patch) {
50038             if (index !== "a") {
50039                 return true
50040             }
50041         }
50042
50043         return false
50044     }
50045
50046     // Execute hooks when two nodes are identical
50047     function unhook(vNode, patch, index) {
50048         if (isVNode$3(vNode)) {
50049             if (vNode.hooks) {
50050                 patch[index] = appendPatch(
50051                     patch[index],
50052                     new VPatch$1(
50053                         VPatch$1.PROPS,
50054                         vNode,
50055                         undefinedKeys(vNode.hooks)
50056                     )
50057                 );
50058             }
50059
50060             if (vNode.descendantHooks || vNode.hasThunks) {
50061                 var children = vNode.children;
50062                 var len = children.length;
50063                 for (var i = 0; i < len; i++) {
50064                     var child = children[i];
50065                     index += 1;
50066
50067                     unhook(child, patch, index);
50068
50069                     if (isVNode$3(child) && child.count) {
50070                         index += child.count;
50071                     }
50072                 }
50073             }
50074         } else if (isThunk$1(vNode)) {
50075             thunks(vNode, null, patch, index);
50076         }
50077     }
50078
50079     function undefinedKeys(obj) {
50080         var result = {};
50081
50082         for (var key in obj) {
50083             result[key] = undefined;
50084         }
50085
50086         return result
50087     }
50088
50089     // List diff, naive left to right reordering
50090     function reorder(aChildren, bChildren) {
50091         // O(M) time, O(M) memory
50092         var bChildIndex = keyIndex(bChildren);
50093         var bKeys = bChildIndex.keys;
50094         var bFree = bChildIndex.free;
50095
50096         if (bFree.length === bChildren.length) {
50097             return {
50098                 children: bChildren,
50099                 moves: null
50100             }
50101         }
50102
50103         // O(N) time, O(N) memory
50104         var aChildIndex = keyIndex(aChildren);
50105         var aKeys = aChildIndex.keys;
50106         var aFree = aChildIndex.free;
50107
50108         if (aFree.length === aChildren.length) {
50109             return {
50110                 children: bChildren,
50111                 moves: null
50112             }
50113         }
50114
50115         // O(MAX(N, M)) memory
50116         var newChildren = [];
50117
50118         var freeIndex = 0;
50119         var freeCount = bFree.length;
50120         var deletedItems = 0;
50121
50122         // Iterate through a and match a node in b
50123         // O(N) time,
50124         for (var i = 0 ; i < aChildren.length; i++) {
50125             var aItem = aChildren[i];
50126             var itemIndex;
50127
50128             if (aItem.key) {
50129                 if (bKeys.hasOwnProperty(aItem.key)) {
50130                     // Match up the old keys
50131                     itemIndex = bKeys[aItem.key];
50132                     newChildren.push(bChildren[itemIndex]);
50133
50134                 } else {
50135                     // Remove old keyed items
50136                     itemIndex = i - deletedItems++;
50137                     newChildren.push(null);
50138                 }
50139             } else {
50140                 // Match the item in a with the next free item in b
50141                 if (freeIndex < freeCount) {
50142                     itemIndex = bFree[freeIndex++];
50143                     newChildren.push(bChildren[itemIndex]);
50144                 } else {
50145                     // There are no free items in b to match with
50146                     // the free items in a, so the extra free nodes
50147                     // are deleted.
50148                     itemIndex = i - deletedItems++;
50149                     newChildren.push(null);
50150                 }
50151             }
50152         }
50153
50154         var lastFreeIndex = freeIndex >= bFree.length ?
50155             bChildren.length :
50156             bFree[freeIndex];
50157
50158         // Iterate through b and append any new keys
50159         // O(M) time
50160         for (var j = 0; j < bChildren.length; j++) {
50161             var newItem = bChildren[j];
50162
50163             if (newItem.key) {
50164                 if (!aKeys.hasOwnProperty(newItem.key)) {
50165                     // Add any new keyed items
50166                     // We are adding new items to the end and then sorting them
50167                     // in place. In future we should insert new items in place.
50168                     newChildren.push(newItem);
50169                 }
50170             } else if (j >= lastFreeIndex) {
50171                 // Add any leftover non-keyed items
50172                 newChildren.push(newItem);
50173             }
50174         }
50175
50176         var simulate = newChildren.slice();
50177         var simulateIndex = 0;
50178         var removes = [];
50179         var inserts = [];
50180         var simulateItem;
50181
50182         for (var k = 0; k < bChildren.length;) {
50183             var wantedItem = bChildren[k];
50184             simulateItem = simulate[simulateIndex];
50185
50186             // remove items
50187             while (simulateItem === null && simulate.length) {
50188                 removes.push(remove(simulate, simulateIndex, null));
50189                 simulateItem = simulate[simulateIndex];
50190             }
50191
50192             if (!simulateItem || simulateItem.key !== wantedItem.key) {
50193                 // if we need a key in this position...
50194                 if (wantedItem.key) {
50195                     if (simulateItem && simulateItem.key) {
50196                         // if an insert doesn't put this key in place, it needs to move
50197                         if (bKeys[simulateItem.key] !== k + 1) {
50198                             removes.push(remove(simulate, simulateIndex, simulateItem.key));
50199                             simulateItem = simulate[simulateIndex];
50200                             // if the remove didn't put the wanted item in place, we need to insert it
50201                             if (!simulateItem || simulateItem.key !== wantedItem.key) {
50202                                 inserts.push({key: wantedItem.key, to: k});
50203                             }
50204                             // items are matching, so skip ahead
50205                             else {
50206                                 simulateIndex++;
50207                             }
50208                         }
50209                         else {
50210                             inserts.push({key: wantedItem.key, to: k});
50211                         }
50212                     }
50213                     else {
50214                         inserts.push({key: wantedItem.key, to: k});
50215                     }
50216                     k++;
50217                 }
50218                 // a key in simulate has no matching wanted key, remove it
50219                 else if (simulateItem && simulateItem.key) {
50220                     removes.push(remove(simulate, simulateIndex, simulateItem.key));
50221                 }
50222             }
50223             else {
50224                 simulateIndex++;
50225                 k++;
50226             }
50227         }
50228
50229         // remove all the remaining nodes from simulate
50230         while(simulateIndex < simulate.length) {
50231             simulateItem = simulate[simulateIndex];
50232             removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key));
50233         }
50234
50235         // If the only moves we have are deletes then we can just
50236         // let the delete patch remove these items.
50237         if (removes.length === deletedItems && !inserts.length) {
50238             return {
50239                 children: newChildren,
50240                 moves: null
50241             }
50242         }
50243
50244         return {
50245             children: newChildren,
50246             moves: {
50247                 removes: removes,
50248                 inserts: inserts
50249             }
50250         }
50251     }
50252
50253     function remove(arr, index, key) {
50254         arr.splice(index, 1);
50255
50256         return {
50257             from: index,
50258             key: key
50259         }
50260     }
50261
50262     function keyIndex(children) {
50263         var keys = {};
50264         var free = [];
50265         var length = children.length;
50266
50267         for (var i = 0; i < length; i++) {
50268             var child = children[i];
50269
50270             if (child.key) {
50271                 keys[child.key] = i;
50272             } else {
50273                 free.push(i);
50274             }
50275         }
50276
50277         return {
50278             keys: keys,     // A hash of key name to index
50279             free: free      // An array of unkeyed item indices
50280         }
50281     }
50282
50283     function appendPatch(apply, patch) {
50284         if (apply) {
50285             if (isArray$2(apply)) {
50286                 apply.push(patch);
50287             } else {
50288                 apply = [apply, patch];
50289             }
50290
50291             return apply
50292         } else {
50293             return patch
50294         }
50295     }
50296
50297     var diff$1 = diff_1$1;
50298
50299     var diff_1 = diff$1;
50300
50301     var slice = Array.prototype.slice;
50302
50303     var domWalk$2 = iterativelyWalk;
50304
50305     function iterativelyWalk(nodes, cb) {
50306         if (!('length' in nodes)) {
50307             nodes = [nodes];
50308         }
50309         
50310         nodes = slice.call(nodes);
50311
50312         while(nodes.length) {
50313             var node = nodes.shift(),
50314                 ret = cb(node);
50315
50316             if (ret) {
50317                 return ret
50318             }
50319
50320             if (node.childNodes && node.childNodes.length) {
50321                 nodes = slice.call(node.childNodes).concat(nodes);
50322             }
50323         }
50324     }
50325
50326     var domComment = Comment$1;
50327
50328     function Comment$1(data, owner) {
50329         if (!(this instanceof Comment$1)) {
50330             return new Comment$1(data, owner)
50331         }
50332
50333         this.data = data;
50334         this.nodeValue = data;
50335         this.length = data.length;
50336         this.ownerDocument = owner || null;
50337     }
50338
50339     Comment$1.prototype.nodeType = 8;
50340     Comment$1.prototype.nodeName = "#comment";
50341
50342     Comment$1.prototype.toString = function _Comment_toString() {
50343         return "[object Comment]"
50344     };
50345
50346     var domText = DOMText$1;
50347
50348     function DOMText$1(value, owner) {
50349         if (!(this instanceof DOMText$1)) {
50350             return new DOMText$1(value)
50351         }
50352
50353         this.data = value || "";
50354         this.length = this.data.length;
50355         this.ownerDocument = owner || null;
50356     }
50357
50358     DOMText$1.prototype.type = "DOMTextNode";
50359     DOMText$1.prototype.nodeType = 3;
50360     DOMText$1.prototype.nodeName = "#text";
50361
50362     DOMText$1.prototype.toString = function _Text_toString() {
50363         return this.data
50364     };
50365
50366     DOMText$1.prototype.replaceData = function replaceData(index, length, value) {
50367         var current = this.data;
50368         var left = current.substring(0, index);
50369         var right = current.substring(index + length, current.length);
50370         this.data = left + value + right;
50371         this.length = this.data.length;
50372     };
50373
50374     var dispatchEvent_1 = dispatchEvent$2;
50375
50376     function dispatchEvent$2(ev) {
50377         var elem = this;
50378         var type = ev.type;
50379
50380         if (!ev.target) {
50381             ev.target = elem;
50382         }
50383
50384         if (!elem.listeners) {
50385             elem.listeners = {};
50386         }
50387
50388         var listeners = elem.listeners[type];
50389
50390         if (listeners) {
50391             return listeners.forEach(function (listener) {
50392                 ev.currentTarget = elem;
50393                 if (typeof listener === 'function') {
50394                     listener(ev);
50395                 } else {
50396                     listener.handleEvent(ev);
50397                 }
50398             })
50399         }
50400
50401         if (elem.parentNode) {
50402             elem.parentNode.dispatchEvent(ev);
50403         }
50404     }
50405
50406     var addEventListener_1 = addEventListener$2;
50407
50408     function addEventListener$2(type, listener) {
50409         var elem = this;
50410
50411         if (!elem.listeners) {
50412             elem.listeners = {};
50413         }
50414
50415         if (!elem.listeners[type]) {
50416             elem.listeners[type] = [];
50417         }
50418
50419         if (elem.listeners[type].indexOf(listener) === -1) {
50420             elem.listeners[type].push(listener);
50421         }
50422     }
50423
50424     var removeEventListener_1 = removeEventListener$2;
50425
50426     function removeEventListener$2(type, listener) {
50427         var elem = this;
50428
50429         if (!elem.listeners) {
50430             return
50431         }
50432
50433         if (!elem.listeners[type]) {
50434             return
50435         }
50436
50437         var list = elem.listeners[type];
50438         var index = list.indexOf(listener);
50439         if (index !== -1) {
50440             list.splice(index, 1);
50441         }
50442     }
50443
50444     var serialize = serializeNode$1;
50445
50446     var voidElements = ["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"];
50447
50448     function serializeNode$1(node) {
50449         switch (node.nodeType) {
50450             case 3:
50451                 return escapeText(node.data)
50452             case 8:
50453                 return "<!--" + node.data + "-->"
50454             default:
50455                 return serializeElement(node)
50456         }
50457     }
50458
50459     function serializeElement(elem) {
50460         var strings = [];
50461
50462         var tagname = elem.tagName;
50463
50464         if (elem.namespaceURI === "http://www.w3.org/1999/xhtml") {
50465             tagname = tagname.toLowerCase();
50466         }
50467
50468         strings.push("<" + tagname + properties(elem) + datasetify(elem));
50469
50470         if (voidElements.indexOf(tagname) > -1) {
50471             strings.push(" />");
50472         } else {
50473             strings.push(">");
50474
50475             if (elem.childNodes.length) {
50476                 strings.push.apply(strings, elem.childNodes.map(serializeNode$1));
50477             } else if (elem.textContent || elem.innerText) {
50478                 strings.push(escapeText(elem.textContent || elem.innerText));
50479             } else if (elem.innerHTML) {
50480                 strings.push(elem.innerHTML);
50481             }
50482
50483             strings.push("</" + tagname + ">");
50484         }
50485
50486         return strings.join("")
50487     }
50488
50489     function isProperty(elem, key) {
50490         var type = typeof elem[key];
50491
50492         if (key === "style" && Object.keys(elem.style).length > 0) {
50493           return true
50494         }
50495
50496         return elem.hasOwnProperty(key) &&
50497             (type === "string" || type === "boolean" || type === "number") &&
50498             key !== "nodeName" && key !== "className" && key !== "tagName" &&
50499             key !== "textContent" && key !== "innerText" && key !== "namespaceURI" &&  key !== "innerHTML"
50500     }
50501
50502     function stylify(styles) {
50503         if (typeof styles === 'string') return styles
50504         var attr = "";
50505         Object.keys(styles).forEach(function (key) {
50506             var value = styles[key];
50507             key = key.replace(/[A-Z]/g, function(c) {
50508                 return "-" + c.toLowerCase();
50509             });
50510             attr += key + ":" + value + ";";
50511         });
50512         return attr
50513     }
50514
50515     function datasetify(elem) {
50516         var ds = elem.dataset;
50517         var props = [];
50518
50519         for (var key in ds) {
50520             props.push({ name: "data-" + key, value: ds[key] });
50521         }
50522
50523         return props.length ? stringify(props) : ""
50524     }
50525
50526     function stringify(list) {
50527         var attributes = [];
50528         list.forEach(function (tuple) {
50529             var name = tuple.name;
50530             var value = tuple.value;
50531
50532             if (name === "style") {
50533                 value = stylify(value);
50534             }
50535
50536             attributes.push(name + "=" + "\"" + escapeAttributeValue(value) + "\"");
50537         });
50538
50539         return attributes.length ? " " + attributes.join(" ") : ""
50540     }
50541
50542     function properties(elem) {
50543         var props = [];
50544         for (var key in elem) {
50545             if (isProperty(elem, key)) {
50546                 props.push({ name: key, value: elem[key] });
50547             }
50548         }
50549
50550         for (var ns in elem._attributes) {
50551           for (var attribute in elem._attributes[ns]) {
50552             var prop = elem._attributes[ns][attribute];
50553             var name = (prop.prefix ? prop.prefix + ":" : "") + attribute;
50554             props.push({ name: name, value: prop.value });
50555           }
50556         }
50557
50558         if (elem.className) {
50559             props.push({ name: "class", value: elem.className });
50560         }
50561
50562         return props.length ? stringify(props) : ""
50563     }
50564
50565     function escapeText(s) {
50566         var str = '';
50567
50568         if (typeof(s) === 'string') { 
50569             str = s; 
50570         } else if (s) {
50571             str = s.toString();
50572         }
50573
50574         return str
50575             .replace(/&/g, "&amp;")
50576             .replace(/</g, "&lt;")
50577             .replace(/>/g, "&gt;")
50578     }
50579
50580     function escapeAttributeValue(str) {
50581         return escapeText(str).replace(/"/g, "&quot;")
50582     }
50583
50584     var domWalk$1 = domWalk$2;
50585     var dispatchEvent$1 = dispatchEvent_1;
50586     var addEventListener$1 = addEventListener_1;
50587     var removeEventListener$1 = removeEventListener_1;
50588     var serializeNode = serialize;
50589
50590     var htmlns = "http://www.w3.org/1999/xhtml";
50591
50592     var domElement = DOMElement$2;
50593
50594     function DOMElement$2(tagName, owner, namespace) {
50595         if (!(this instanceof DOMElement$2)) {
50596             return new DOMElement$2(tagName)
50597         }
50598
50599         var ns = namespace === undefined ? htmlns : (namespace || null);
50600
50601         this.tagName = ns === htmlns ? String(tagName).toUpperCase() : tagName;
50602         this.nodeName = this.tagName;
50603         this.className = "";
50604         this.dataset = {};
50605         this.childNodes = [];
50606         this.parentNode = null;
50607         this.style = {};
50608         this.ownerDocument = owner || null;
50609         this.namespaceURI = ns;
50610         this._attributes = {};
50611
50612         if (this.tagName === 'INPUT') {
50613           this.type = 'text';
50614         }
50615     }
50616
50617     DOMElement$2.prototype.type = "DOMElement";
50618     DOMElement$2.prototype.nodeType = 1;
50619
50620     DOMElement$2.prototype.appendChild = function _Element_appendChild(child) {
50621         if (child.parentNode) {
50622             child.parentNode.removeChild(child);
50623         }
50624
50625         this.childNodes.push(child);
50626         child.parentNode = this;
50627
50628         return child
50629     };
50630
50631     DOMElement$2.prototype.replaceChild =
50632         function _Element_replaceChild(elem, needle) {
50633             // TODO: Throw NotFoundError if needle.parentNode !== this
50634
50635             if (elem.parentNode) {
50636                 elem.parentNode.removeChild(elem);
50637             }
50638
50639             var index = this.childNodes.indexOf(needle);
50640
50641             needle.parentNode = null;
50642             this.childNodes[index] = elem;
50643             elem.parentNode = this;
50644
50645             return needle
50646         };
50647
50648     DOMElement$2.prototype.removeChild = function _Element_removeChild(elem) {
50649         // TODO: Throw NotFoundError if elem.parentNode !== this
50650
50651         var index = this.childNodes.indexOf(elem);
50652         this.childNodes.splice(index, 1);
50653
50654         elem.parentNode = null;
50655         return elem
50656     };
50657
50658     DOMElement$2.prototype.insertBefore =
50659         function _Element_insertBefore(elem, needle) {
50660             // TODO: Throw NotFoundError if referenceElement is a dom node
50661             // and parentNode !== this
50662
50663             if (elem.parentNode) {
50664                 elem.parentNode.removeChild(elem);
50665             }
50666
50667             var index = needle === null || needle === undefined ?
50668                 -1 :
50669                 this.childNodes.indexOf(needle);
50670
50671             if (index > -1) {
50672                 this.childNodes.splice(index, 0, elem);
50673             } else {
50674                 this.childNodes.push(elem);
50675             }
50676
50677             elem.parentNode = this;
50678             return elem
50679         };
50680
50681     DOMElement$2.prototype.setAttributeNS =
50682         function _Element_setAttributeNS(namespace, name, value) {
50683             var prefix = null;
50684             var localName = name;
50685             var colonPosition = name.indexOf(":");
50686             if (colonPosition > -1) {
50687                 prefix = name.substr(0, colonPosition);
50688                 localName = name.substr(colonPosition + 1);
50689             }
50690             if (this.tagName === 'INPUT' && name === 'type') {
50691               this.type = value;
50692             }
50693             else {
50694               var attributes = this._attributes[namespace] || (this._attributes[namespace] = {});
50695               attributes[localName] = {value: value, prefix: prefix};
50696             }
50697         };
50698
50699     DOMElement$2.prototype.getAttributeNS =
50700         function _Element_getAttributeNS(namespace, name) {
50701             var attributes = this._attributes[namespace];
50702             var value = attributes && attributes[name] && attributes[name].value;
50703             if (this.tagName === 'INPUT' && name === 'type') {
50704               return this.type;
50705             }
50706             if (typeof value !== "string") {
50707                 return null
50708             }
50709             return value
50710         };
50711
50712     DOMElement$2.prototype.removeAttributeNS =
50713         function _Element_removeAttributeNS(namespace, name) {
50714             var attributes = this._attributes[namespace];
50715             if (attributes) {
50716                 delete attributes[name];
50717             }
50718         };
50719
50720     DOMElement$2.prototype.hasAttributeNS =
50721         function _Element_hasAttributeNS(namespace, name) {
50722             var attributes = this._attributes[namespace];
50723             return !!attributes && name in attributes;
50724         };
50725
50726     DOMElement$2.prototype.setAttribute = function _Element_setAttribute(name, value) {
50727         return this.setAttributeNS(null, name, value)
50728     };
50729
50730     DOMElement$2.prototype.getAttribute = function _Element_getAttribute(name) {
50731         return this.getAttributeNS(null, name)
50732     };
50733
50734     DOMElement$2.prototype.removeAttribute = function _Element_removeAttribute(name) {
50735         return this.removeAttributeNS(null, name)
50736     };
50737
50738     DOMElement$2.prototype.hasAttribute = function _Element_hasAttribute(name) {
50739         return this.hasAttributeNS(null, name)
50740     };
50741
50742     DOMElement$2.prototype.removeEventListener = removeEventListener$1;
50743     DOMElement$2.prototype.addEventListener = addEventListener$1;
50744     DOMElement$2.prototype.dispatchEvent = dispatchEvent$1;
50745
50746     // Un-implemented
50747     DOMElement$2.prototype.focus = function _Element_focus() {
50748         return void 0
50749     };
50750
50751     DOMElement$2.prototype.toString = function _Element_toString() {
50752         return serializeNode(this)
50753     };
50754
50755     DOMElement$2.prototype.getElementsByClassName = function _Element_getElementsByClassName(classNames) {
50756         var classes = classNames.split(" ");
50757         var elems = [];
50758
50759         domWalk$1(this, function (node) {
50760             if (node.nodeType === 1) {
50761                 var nodeClassName = node.className || "";
50762                 var nodeClasses = nodeClassName.split(" ");
50763
50764                 if (classes.every(function (item) {
50765                     return nodeClasses.indexOf(item) !== -1
50766                 })) {
50767                     elems.push(node);
50768                 }
50769             }
50770         });
50771
50772         return elems
50773     };
50774
50775     DOMElement$2.prototype.getElementsByTagName = function _Element_getElementsByTagName(tagName) {
50776         tagName = tagName.toLowerCase();
50777         var elems = [];
50778
50779         domWalk$1(this.childNodes, function (node) {
50780             if (node.nodeType === 1 && (tagName === '*' || node.tagName.toLowerCase() === tagName)) {
50781                 elems.push(node);
50782             }
50783         });
50784
50785         return elems
50786     };
50787
50788     DOMElement$2.prototype.contains = function _Element_contains(element) {
50789         return domWalk$1(this, function (node) {
50790             return element === node
50791         }) || false
50792     };
50793
50794     var DOMElement$1 = domElement;
50795
50796     var domFragment = DocumentFragment$1;
50797
50798     function DocumentFragment$1(owner) {
50799         if (!(this instanceof DocumentFragment$1)) {
50800             return new DocumentFragment$1()
50801         }
50802
50803         this.childNodes = [];
50804         this.parentNode = null;
50805         this.ownerDocument = owner || null;
50806     }
50807
50808     DocumentFragment$1.prototype.type = "DocumentFragment";
50809     DocumentFragment$1.prototype.nodeType = 11;
50810     DocumentFragment$1.prototype.nodeName = "#document-fragment";
50811
50812     DocumentFragment$1.prototype.appendChild  = DOMElement$1.prototype.appendChild;
50813     DocumentFragment$1.prototype.replaceChild = DOMElement$1.prototype.replaceChild;
50814     DocumentFragment$1.prototype.removeChild  = DOMElement$1.prototype.removeChild;
50815
50816     DocumentFragment$1.prototype.toString =
50817         function _DocumentFragment_toString() {
50818             return this.childNodes.map(function (node) {
50819                 return String(node)
50820             }).join("")
50821         };
50822
50823     var event = Event$1;
50824
50825     function Event$1(family) {}
50826
50827     Event$1.prototype.initEvent = function _Event_initEvent(type, bubbles, cancelable) {
50828         this.type = type;
50829         this.bubbles = bubbles;
50830         this.cancelable = cancelable;
50831     };
50832
50833     Event$1.prototype.preventDefault = function _Event_preventDefault() {
50834         
50835     };
50836
50837     var domWalk = domWalk$2;
50838
50839     var Comment = domComment;
50840     var DOMText = domText;
50841     var DOMElement = domElement;
50842     var DocumentFragment = domFragment;
50843     var Event = event;
50844     var dispatchEvent = dispatchEvent_1;
50845     var addEventListener = addEventListener_1;
50846     var removeEventListener = removeEventListener_1;
50847
50848     var document$3 = Document$1;
50849
50850     function Document$1() {
50851         if (!(this instanceof Document$1)) {
50852             return new Document$1();
50853         }
50854
50855         this.head = this.createElement("head");
50856         this.body = this.createElement("body");
50857         this.documentElement = this.createElement("html");
50858         this.documentElement.appendChild(this.head);
50859         this.documentElement.appendChild(this.body);
50860         this.childNodes = [this.documentElement];
50861         this.nodeType = 9;
50862     }
50863
50864     var proto = Document$1.prototype;
50865     proto.createTextNode = function createTextNode(value) {
50866         return new DOMText(value, this)
50867     };
50868
50869     proto.createElementNS = function createElementNS(namespace, tagName) {
50870         var ns = namespace === null ? null : String(namespace);
50871         return new DOMElement(tagName, this, ns)
50872     };
50873
50874     proto.createElement = function createElement(tagName) {
50875         return new DOMElement(tagName, this)
50876     };
50877
50878     proto.createDocumentFragment = function createDocumentFragment() {
50879         return new DocumentFragment(this)
50880     };
50881
50882     proto.createEvent = function createEvent(family) {
50883         return new Event(family)
50884     };
50885
50886     proto.createComment = function createComment(data) {
50887         return new Comment(data, this)
50888     };
50889
50890     proto.getElementById = function getElementById(id) {
50891         id = String(id);
50892
50893         var result = domWalk(this.childNodes, function (node) {
50894             if (String(node.id) === id) {
50895                 return node
50896             }
50897         });
50898
50899         return result || null
50900     };
50901
50902     proto.getElementsByClassName = DOMElement.prototype.getElementsByClassName;
50903     proto.getElementsByTagName = DOMElement.prototype.getElementsByTagName;
50904     proto.contains = DOMElement.prototype.contains;
50905
50906     proto.removeEventListener = removeEventListener;
50907     proto.addEventListener = addEventListener;
50908     proto.dispatchEvent = dispatchEvent;
50909
50910     var Document = document$3;
50911
50912     var minDocument = new Document();
50913
50914     var topLevel = typeof commonjsGlobal !== 'undefined' ? commonjsGlobal :
50915         typeof window !== 'undefined' ? window : {};
50916     var minDoc = minDocument;
50917
50918     var doccy;
50919
50920     if (typeof document !== 'undefined') {
50921         doccy = document;
50922     } else {
50923         doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
50924
50925         if (!doccy) {
50926             doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
50927         }
50928     }
50929
50930     var document_1 = doccy;
50931
50932     var isObject = isObject$2;
50933     var isHook$1 = isVhook;
50934
50935     var applyProperties_1 = applyProperties$2;
50936
50937     function applyProperties$2(node, props, previous) {
50938         for (var propName in props) {
50939             var propValue = props[propName];
50940
50941             if (propValue === undefined) {
50942                 removeProperty(node, propName, propValue, previous);
50943             } else if (isHook$1(propValue)) {
50944                 removeProperty(node, propName, propValue, previous);
50945                 if (propValue.hook) {
50946                     propValue.hook(node,
50947                         propName,
50948                         previous ? previous[propName] : undefined);
50949                 }
50950             } else {
50951                 if (isObject(propValue)) {
50952                     patchObject(node, props, previous, propName, propValue);
50953                 } else {
50954                     node[propName] = propValue;
50955                 }
50956             }
50957         }
50958     }
50959
50960     function removeProperty(node, propName, propValue, previous) {
50961         if (previous) {
50962             var previousValue = previous[propName];
50963
50964             if (!isHook$1(previousValue)) {
50965                 if (propName === "attributes") {
50966                     for (var attrName in previousValue) {
50967                         node.removeAttribute(attrName);
50968                     }
50969                 } else if (propName === "style") {
50970                     for (var i in previousValue) {
50971                         node.style[i] = "";
50972                     }
50973                 } else if (typeof previousValue === "string") {
50974                     node[propName] = "";
50975                 } else {
50976                     node[propName] = null;
50977                 }
50978             } else if (previousValue.unhook) {
50979                 previousValue.unhook(node, propName, propValue);
50980             }
50981         }
50982     }
50983
50984     function patchObject(node, props, previous, propName, propValue) {
50985         var previousValue = previous ? previous[propName] : undefined;
50986
50987         // Set attributes
50988         if (propName === "attributes") {
50989             for (var attrName in propValue) {
50990                 var attrValue = propValue[attrName];
50991
50992                 if (attrValue === undefined) {
50993                     node.removeAttribute(attrName);
50994                 } else {
50995                     node.setAttribute(attrName, attrValue);
50996                 }
50997             }
50998
50999             return
51000         }
51001
51002         if(previousValue && isObject(previousValue) &&
51003             getPrototype(previousValue) !== getPrototype(propValue)) {
51004             node[propName] = propValue;
51005             return
51006         }
51007
51008         if (!isObject(node[propName])) {
51009             node[propName] = {};
51010         }
51011
51012         var replacer = propName === "style" ? "" : undefined;
51013
51014         for (var k in propValue) {
51015             var value = propValue[k];
51016             node[propName][k] = (value === undefined) ? replacer : value;
51017         }
51018     }
51019
51020     function getPrototype(value) {
51021         if (Object.getPrototypeOf) {
51022             return Object.getPrototypeOf(value)
51023         } else if (value.__proto__) {
51024             return value.__proto__
51025         } else if (value.constructor) {
51026             return value.constructor.prototype
51027         }
51028     }
51029
51030     var document$2 = document_1;
51031
51032     var applyProperties$1 = applyProperties_1;
51033
51034     var isVNode$2 = isVnode;
51035     var isVText$1 = isVtext;
51036     var isWidget$4 = isWidget_1;
51037     var handleThunk = handleThunk_1;
51038
51039     var createElement_1$1 = createElement$1;
51040
51041     function createElement$1(vnode, opts) {
51042         var doc = opts ? opts.document || document$2 : document$2;
51043         var warn = opts ? opts.warn : null;
51044
51045         vnode = handleThunk(vnode).a;
51046
51047         if (isWidget$4(vnode)) {
51048             return vnode.init()
51049         } else if (isVText$1(vnode)) {
51050             return doc.createTextNode(vnode.text)
51051         } else if (!isVNode$2(vnode)) {
51052             if (warn) {
51053                 warn("Item is not a valid virtual dom node", vnode);
51054             }
51055             return null
51056         }
51057
51058         var node = (vnode.namespace === null) ?
51059             doc.createElement(vnode.tagName) :
51060             doc.createElementNS(vnode.namespace, vnode.tagName);
51061
51062         var props = vnode.properties;
51063         applyProperties$1(node, props);
51064
51065         var children = vnode.children;
51066
51067         for (var i = 0; i < children.length; i++) {
51068             var childNode = createElement$1(children[i], opts);
51069             if (childNode) {
51070                 node.appendChild(childNode);
51071             }
51072         }
51073
51074         return node
51075     }
51076
51077     // Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
51078     // We don't want to read all of the DOM nodes in the tree so we use
51079     // the in-order tree indexing to eliminate recursion down certain branches.
51080     // We only recurse into a DOM node if we know that it contains a child of
51081     // interest.
51082
51083     var noChild = {};
51084
51085     var domIndex_1 = domIndex$1;
51086
51087     function domIndex$1(rootNode, tree, indices, nodes) {
51088         if (!indices || indices.length === 0) {
51089             return {}
51090         } else {
51091             indices.sort(ascending);
51092             return recurse(rootNode, tree, indices, nodes, 0)
51093         }
51094     }
51095
51096     function recurse(rootNode, tree, indices, nodes, rootIndex) {
51097         nodes = nodes || {};
51098
51099
51100         if (rootNode) {
51101             if (indexInRange(indices, rootIndex, rootIndex)) {
51102                 nodes[rootIndex] = rootNode;
51103             }
51104
51105             var vChildren = tree.children;
51106
51107             if (vChildren) {
51108
51109                 var childNodes = rootNode.childNodes;
51110
51111                 for (var i = 0; i < tree.children.length; i++) {
51112                     rootIndex += 1;
51113
51114                     var vChild = vChildren[i] || noChild;
51115                     var nextIndex = rootIndex + (vChild.count || 0);
51116
51117                     // skip recursion down the tree if there are no nodes down here
51118                     if (indexInRange(indices, rootIndex, nextIndex)) {
51119                         recurse(childNodes[i], vChild, indices, nodes, rootIndex);
51120                     }
51121
51122                     rootIndex = nextIndex;
51123                 }
51124             }
51125         }
51126
51127         return nodes
51128     }
51129
51130     // Binary search for an index in the interval [left, right]
51131     function indexInRange(indices, left, right) {
51132         if (indices.length === 0) {
51133             return false
51134         }
51135
51136         var minIndex = 0;
51137         var maxIndex = indices.length - 1;
51138         var currentIndex;
51139         var currentItem;
51140
51141         while (minIndex <= maxIndex) {
51142             currentIndex = ((maxIndex + minIndex) / 2) >> 0;
51143             currentItem = indices[currentIndex];
51144
51145             if (minIndex === maxIndex) {
51146                 return currentItem >= left && currentItem <= right
51147             } else if (currentItem < left) {
51148                 minIndex = currentIndex + 1;
51149             } else  if (currentItem > right) {
51150                 maxIndex = currentIndex - 1;
51151             } else {
51152                 return true
51153             }
51154         }
51155
51156         return false;
51157     }
51158
51159     function ascending(a, b) {
51160         return a > b ? 1 : -1
51161     }
51162
51163     var isWidget$3 = isWidget_1;
51164
51165     var updateWidget_1 = updateWidget$1;
51166
51167     function updateWidget$1(a, b) {
51168         if (isWidget$3(a) && isWidget$3(b)) {
51169             if ("name" in a && "name" in b) {
51170                 return a.id === b.id
51171             } else {
51172                 return a.init === b.init
51173             }
51174         }
51175
51176         return false
51177     }
51178
51179     var applyProperties = applyProperties_1;
51180
51181     var isWidget$2 = isWidget_1;
51182     var VPatch = vpatch;
51183
51184     var updateWidget = updateWidget_1;
51185
51186     var patchOp$1 = applyPatch$1;
51187
51188     function applyPatch$1(vpatch, domNode, renderOptions) {
51189         var type = vpatch.type;
51190         var vNode = vpatch.vNode;
51191         var patch = vpatch.patch;
51192
51193         switch (type) {
51194             case VPatch.REMOVE:
51195                 return removeNode$1(domNode, vNode)
51196             case VPatch.INSERT:
51197                 return insertNode$1(domNode, patch, renderOptions)
51198             case VPatch.VTEXT:
51199                 return stringPatch(domNode, vNode, patch, renderOptions)
51200             case VPatch.WIDGET:
51201                 return widgetPatch(domNode, vNode, patch, renderOptions)
51202             case VPatch.VNODE:
51203                 return vNodePatch(domNode, vNode, patch, renderOptions)
51204             case VPatch.ORDER:
51205                 reorderChildren(domNode, patch);
51206                 return domNode
51207             case VPatch.PROPS:
51208                 applyProperties(domNode, patch, vNode.properties);
51209                 return domNode
51210             case VPatch.THUNK:
51211                 return replaceRoot(domNode,
51212                     renderOptions.patch(domNode, patch, renderOptions))
51213             default:
51214                 return domNode
51215         }
51216     }
51217
51218     function removeNode$1(domNode, vNode) {
51219         var parentNode = domNode.parentNode;
51220
51221         if (parentNode) {
51222             parentNode.removeChild(domNode);
51223         }
51224
51225         destroyWidget(domNode, vNode);
51226
51227         return null
51228     }
51229
51230     function insertNode$1(parentNode, vNode, renderOptions) {
51231         var newNode = renderOptions.render(vNode, renderOptions);
51232
51233         if (parentNode) {
51234             parentNode.appendChild(newNode);
51235         }
51236
51237         return parentNode
51238     }
51239
51240     function stringPatch(domNode, leftVNode, vText, renderOptions) {
51241         var newNode;
51242
51243         if (domNode.nodeType === 3) {
51244             domNode.replaceData(0, domNode.length, vText.text);
51245             newNode = domNode;
51246         } else {
51247             var parentNode = domNode.parentNode;
51248             newNode = renderOptions.render(vText, renderOptions);
51249
51250             if (parentNode && newNode !== domNode) {
51251                 parentNode.replaceChild(newNode, domNode);
51252             }
51253         }
51254
51255         return newNode
51256     }
51257
51258     function widgetPatch(domNode, leftVNode, widget, renderOptions) {
51259         var updating = updateWidget(leftVNode, widget);
51260         var newNode;
51261
51262         if (updating) {
51263             newNode = widget.update(leftVNode, domNode) || domNode;
51264         } else {
51265             newNode = renderOptions.render(widget, renderOptions);
51266         }
51267
51268         var parentNode = domNode.parentNode;
51269
51270         if (parentNode && newNode !== domNode) {
51271             parentNode.replaceChild(newNode, domNode);
51272         }
51273
51274         if (!updating) {
51275             destroyWidget(domNode, leftVNode);
51276         }
51277
51278         return newNode
51279     }
51280
51281     function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
51282         var parentNode = domNode.parentNode;
51283         var newNode = renderOptions.render(vNode, renderOptions);
51284
51285         if (parentNode && newNode !== domNode) {
51286             parentNode.replaceChild(newNode, domNode);
51287         }
51288
51289         return newNode
51290     }
51291
51292     function destroyWidget(domNode, w) {
51293         if (typeof w.destroy === "function" && isWidget$2(w)) {
51294             w.destroy(domNode);
51295         }
51296     }
51297
51298     function reorderChildren(domNode, moves) {
51299         var childNodes = domNode.childNodes;
51300         var keyMap = {};
51301         var node;
51302         var remove;
51303         var insert;
51304
51305         for (var i = 0; i < moves.removes.length; i++) {
51306             remove = moves.removes[i];
51307             node = childNodes[remove.from];
51308             if (remove.key) {
51309                 keyMap[remove.key] = node;
51310             }
51311             domNode.removeChild(node);
51312         }
51313
51314         var length = childNodes.length;
51315         for (var j = 0; j < moves.inserts.length; j++) {
51316             insert = moves.inserts[j];
51317             node = keyMap[insert.key];
51318             // this is the weirdest bug i've ever seen in webkit
51319             domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]);
51320         }
51321     }
51322
51323     function replaceRoot(oldRoot, newRoot) {
51324         if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) {
51325             oldRoot.parentNode.replaceChild(newRoot, oldRoot);
51326         }
51327
51328         return newRoot;
51329     }
51330
51331     var document$1 = document_1;
51332     var isArray$1 = xIsArray;
51333
51334     var render = createElement_1$1;
51335     var domIndex = domIndex_1;
51336     var patchOp = patchOp$1;
51337     var patch_1$1 = patch$2;
51338
51339     function patch$2(rootNode, patches, renderOptions) {
51340         renderOptions = renderOptions || {};
51341         renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch$2
51342             ? renderOptions.patch
51343             : patchRecursive;
51344         renderOptions.render = renderOptions.render || render;
51345
51346         return renderOptions.patch(rootNode, patches, renderOptions)
51347     }
51348
51349     function patchRecursive(rootNode, patches, renderOptions) {
51350         var indices = patchIndices(patches);
51351
51352         if (indices.length === 0) {
51353             return rootNode
51354         }
51355
51356         var index = domIndex(rootNode, patches.a, indices);
51357         var ownerDocument = rootNode.ownerDocument;
51358
51359         if (!renderOptions.document && ownerDocument !== document$1) {
51360             renderOptions.document = ownerDocument;
51361         }
51362
51363         for (var i = 0; i < indices.length; i++) {
51364             var nodeIndex = indices[i];
51365             rootNode = applyPatch(rootNode,
51366                 index[nodeIndex],
51367                 patches[nodeIndex],
51368                 renderOptions);
51369         }
51370
51371         return rootNode
51372     }
51373
51374     function applyPatch(rootNode, domNode, patchList, renderOptions) {
51375         if (!domNode) {
51376             return rootNode
51377         }
51378
51379         var newNode;
51380
51381         if (isArray$1(patchList)) {
51382             for (var i = 0; i < patchList.length; i++) {
51383                 newNode = patchOp(patchList[i], domNode, renderOptions);
51384
51385                 if (domNode === rootNode) {
51386                     rootNode = newNode;
51387                 }
51388             }
51389         } else {
51390             newNode = patchOp(patchList, domNode, renderOptions);
51391
51392             if (domNode === rootNode) {
51393                 rootNode = newNode;
51394             }
51395         }
51396
51397         return rootNode
51398     }
51399
51400     function patchIndices(patches) {
51401         var indices = [];
51402
51403         for (var key in patches) {
51404             if (key !== "a") {
51405                 indices.push(Number(key));
51406             }
51407         }
51408
51409         return indices
51410     }
51411
51412     var patch$1 = patch_1$1;
51413
51414     var patch_1 = patch$1;
51415
51416     var version$1 = version$5;
51417     var isVNode$1 = isVnode;
51418     var isWidget$1 = isWidget_1;
51419     var isThunk = isThunk_1;
51420     var isVHook = isVhook;
51421
51422     var vnode = VirtualNode;
51423
51424     var noProperties = {};
51425     var noChildren = [];
51426
51427     function VirtualNode(tagName, properties, children, key, namespace) {
51428         this.tagName = tagName;
51429         this.properties = properties || noProperties;
51430         this.children = children || noChildren;
51431         this.key = key != null ? String(key) : undefined;
51432         this.namespace = (typeof namespace === "string") ? namespace : null;
51433
51434         var count = (children && children.length) || 0;
51435         var descendants = 0;
51436         var hasWidgets = false;
51437         var hasThunks = false;
51438         var descendantHooks = false;
51439         var hooks;
51440
51441         for (var propName in properties) {
51442             if (properties.hasOwnProperty(propName)) {
51443                 var property = properties[propName];
51444                 if (isVHook(property) && property.unhook) {
51445                     if (!hooks) {
51446                         hooks = {};
51447                     }
51448
51449                     hooks[propName] = property;
51450                 }
51451             }
51452         }
51453
51454         for (var i = 0; i < count; i++) {
51455             var child = children[i];
51456             if (isVNode$1(child)) {
51457                 descendants += child.count || 0;
51458
51459                 if (!hasWidgets && child.hasWidgets) {
51460                     hasWidgets = true;
51461                 }
51462
51463                 if (!hasThunks && child.hasThunks) {
51464                     hasThunks = true;
51465                 }
51466
51467                 if (!descendantHooks && (child.hooks || child.descendantHooks)) {
51468                     descendantHooks = true;
51469                 }
51470             } else if (!hasWidgets && isWidget$1(child)) {
51471                 if (typeof child.destroy === "function") {
51472                     hasWidgets = true;
51473                 }
51474             } else if (!hasThunks && isThunk(child)) {
51475                 hasThunks = true;
51476             }
51477         }
51478
51479         this.count = count + descendants;
51480         this.hasWidgets = hasWidgets;
51481         this.hasThunks = hasThunks;
51482         this.hooks = hooks;
51483         this.descendantHooks = descendantHooks;
51484     }
51485
51486     VirtualNode.prototype.version = version$1;
51487     VirtualNode.prototype.type = "VirtualNode";
51488
51489     var version = version$5;
51490
51491     var vtext = VirtualText;
51492
51493     function VirtualText(text) {
51494         this.text = String(text);
51495     }
51496
51497     VirtualText.prototype.version = version;
51498     VirtualText.prototype.type = "VirtualText";
51499
51500     /*!
51501      * Cross-Browser Split 1.1.1
51502      * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
51503      * Available under the MIT License
51504      * ECMAScript compliant, uniform cross-browser split method
51505      */
51506
51507     /**
51508      * Splits a string into an array of strings using a regex or string separator. Matches of the
51509      * separator are not included in the result array. However, if `separator` is a regex that contains
51510      * capturing groups, backreferences are spliced into the result each time `separator` is matched.
51511      * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
51512      * cross-browser.
51513      * @param {String} str String to split.
51514      * @param {RegExp|String} separator Regex or string to use for separating the string.
51515      * @param {Number} [limit] Maximum number of items to include in the result array.
51516      * @returns {Array} Array of substrings.
51517      * @example
51518      *
51519      * // Basic use
51520      * split('a b c d', ' ');
51521      * // -> ['a', 'b', 'c', 'd']
51522      *
51523      * // With limit
51524      * split('a b c d', ' ', 2);
51525      * // -> ['a', 'b']
51526      *
51527      * // Backreferences in result array
51528      * split('..word1 word2..', /([a-z]+)(\d+)/i);
51529      * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
51530      */
51531     var browserSplit = (function split(undef) {
51532
51533       var nativeSplit = String.prototype.split,
51534         compliantExecNpcg = /()??/.exec("")[1] === undef,
51535         // NPCG: nonparticipating capturing group
51536         self;
51537
51538       self = function(str, separator, limit) {
51539         // If `separator` is not a regex, use `nativeSplit`
51540         if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
51541           return nativeSplit.call(str, separator, limit);
51542         }
51543         var output = [],
51544           flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6
51545           (separator.sticky ? "y" : ""),
51546           // Firefox 3+
51547           lastLastIndex = 0,
51548           // Make `global` and avoid `lastIndex` issues by working with a copy
51549           separator = new RegExp(separator.source, flags + "g"),
51550           separator2, match, lastIndex, lastLength;
51551         str += ""; // Type-convert
51552         if (!compliantExecNpcg) {
51553           // Doesn't need flags gy, but they don't hurt
51554           separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
51555         }
51556         /* Values for `limit`, per the spec:
51557          * If undefined: 4294967295 // Math.pow(2, 32) - 1
51558          * If 0, Infinity, or NaN: 0
51559          * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
51560          * If negative number: 4294967296 - Math.floor(Math.abs(limit))
51561          * If other: Type-convert, then use the above rules
51562          */
51563         limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1
51564         limit >>> 0; // ToUint32(limit)
51565         while (match = separator.exec(str)) {
51566           // `separator.lastIndex` is not reliable cross-browser
51567           lastIndex = match.index + match[0].length;
51568           if (lastIndex > lastLastIndex) {
51569             output.push(str.slice(lastLastIndex, match.index));
51570             // Fix browsers whose `exec` methods don't consistently return `undefined` for
51571             // nonparticipating capturing groups
51572             if (!compliantExecNpcg && match.length > 1) {
51573               match[0].replace(separator2, function() {
51574                 for (var i = 1; i < arguments.length - 2; i++) {
51575                   if (arguments[i] === undef) {
51576                     match[i] = undef;
51577                   }
51578                 }
51579               });
51580             }
51581             if (match.length > 1 && match.index < str.length) {
51582               Array.prototype.push.apply(output, match.slice(1));
51583             }
51584             lastLength = match[0].length;
51585             lastLastIndex = lastIndex;
51586             if (output.length >= limit) {
51587               break;
51588             }
51589           }
51590           if (separator.lastIndex === match.index) {
51591             separator.lastIndex++; // Avoid an infinite loop
51592           }
51593         }
51594         if (lastLastIndex === str.length) {
51595           if (lastLength || !separator.test("")) {
51596             output.push("");
51597           }
51598         } else {
51599           output.push(str.slice(lastLastIndex));
51600         }
51601         return output.length > limit ? output.slice(0, limit) : output;
51602       };
51603
51604       return self;
51605     })();
51606
51607     var split = browserSplit;
51608
51609     var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/;
51610     var notClassId = /^\.|#/;
51611
51612     var parseTag_1 = parseTag$1;
51613
51614     function parseTag$1(tag, props) {
51615         if (!tag) {
51616             return 'DIV';
51617         }
51618
51619         var noId = !(props.hasOwnProperty('id'));
51620
51621         var tagParts = split(tag, classIdSplit);
51622         var tagName = null;
51623
51624         if (notClassId.test(tagParts[1])) {
51625             tagName = 'DIV';
51626         }
51627
51628         var classes, part, type, i;
51629
51630         for (i = 0; i < tagParts.length; i++) {
51631             part = tagParts[i];
51632
51633             if (!part) {
51634                 continue;
51635             }
51636
51637             type = part.charAt(0);
51638
51639             if (!tagName) {
51640                 tagName = part;
51641             } else if (type === '.') {
51642                 classes = classes || [];
51643                 classes.push(part.substring(1, part.length));
51644             } else if (type === '#' && noId) {
51645                 props.id = part.substring(1, part.length);
51646             }
51647         }
51648
51649         if (classes) {
51650             if (props.className) {
51651                 classes.push(props.className);
51652             }
51653
51654             props.className = classes.join(' ');
51655         }
51656
51657         return props.namespace ? tagName : tagName.toUpperCase();
51658     }
51659
51660     var softSetHook$1 = SoftSetHook;
51661
51662     function SoftSetHook(value) {
51663         if (!(this instanceof SoftSetHook)) {
51664             return new SoftSetHook(value);
51665         }
51666
51667         this.value = value;
51668     }
51669
51670     SoftSetHook.prototype.hook = function (node, propertyName) {
51671         if (node[propertyName] !== this.value) {
51672             node[propertyName] = this.value;
51673         }
51674     };
51675
51676     /*global window, global*/
51677
51678     var root = typeof window !== 'undefined' ?
51679         window : typeof commonjsGlobal !== 'undefined' ?
51680         commonjsGlobal : {};
51681
51682     var individual = Individual$1;
51683
51684     function Individual$1(key, value) {
51685         if (key in root) {
51686             return root[key];
51687         }
51688
51689         root[key] = value;
51690
51691         return value;
51692     }
51693
51694     var Individual = individual;
51695
51696     var oneVersion = OneVersion;
51697
51698     function OneVersion(moduleName, version, defaultValue) {
51699         var key = '__INDIVIDUAL_ONE_VERSION_' + moduleName;
51700         var enforceKey = key + '_ENFORCE_SINGLETON';
51701
51702         var versionValue = Individual(enforceKey, version);
51703
51704         if (versionValue !== version) {
51705             throw new Error('Can only have one copy of ' +
51706                 moduleName + '.\n' +
51707                 'You already have version ' + versionValue +
51708                 ' installed.\n' +
51709                 'This means you cannot install version ' + version);
51710         }
51711
51712         return Individual(key, defaultValue);
51713     }
51714
51715     var OneVersionConstraint = oneVersion;
51716
51717     var MY_VERSION = '7';
51718     OneVersionConstraint('ev-store', MY_VERSION);
51719
51720     var hashKey = '__EV_STORE_KEY@' + MY_VERSION;
51721
51722     var evStore = EvStore$1;
51723
51724     function EvStore$1(elem) {
51725         var hash = elem[hashKey];
51726
51727         if (!hash) {
51728             hash = elem[hashKey] = {};
51729         }
51730
51731         return hash;
51732     }
51733
51734     var EvStore = evStore;
51735
51736     var evHook$1 = EvHook;
51737
51738     function EvHook(value) {
51739         if (!(this instanceof EvHook)) {
51740             return new EvHook(value);
51741         }
51742
51743         this.value = value;
51744     }
51745
51746     EvHook.prototype.hook = function (node, propertyName) {
51747         var es = EvStore(node);
51748         var propName = propertyName.substr(3);
51749
51750         es[propName] = this.value;
51751     };
51752
51753     EvHook.prototype.unhook = function(node, propertyName) {
51754         var es = EvStore(node);
51755         var propName = propertyName.substr(3);
51756
51757         es[propName] = undefined;
51758     };
51759
51760     var isArray = xIsArray;
51761
51762     var VNode$1 = vnode;
51763     var VText$1 = vtext;
51764     var isVNode = isVnode;
51765     var isVText = isVtext;
51766     var isWidget = isWidget_1;
51767     var isHook = isVhook;
51768     var isVThunk = isThunk_1;
51769
51770     var parseTag = parseTag_1;
51771     var softSetHook = softSetHook$1;
51772     var evHook = evHook$1;
51773
51774     var virtualHyperscript = h$2;
51775
51776     function h$2(tagName, properties, children) {
51777         var childNodes = [];
51778         var tag, props, key, namespace;
51779
51780         if (!children && isChildren(properties)) {
51781             children = properties;
51782             props = {};
51783         }
51784
51785         props = props || properties || {};
51786         tag = parseTag(tagName, props);
51787
51788         // support keys
51789         if (props.hasOwnProperty('key')) {
51790             key = props.key;
51791             props.key = undefined;
51792         }
51793
51794         // support namespace
51795         if (props.hasOwnProperty('namespace')) {
51796             namespace = props.namespace;
51797             props.namespace = undefined;
51798         }
51799
51800         // fix cursor bug
51801         if (tag === 'INPUT' &&
51802             !namespace &&
51803             props.hasOwnProperty('value') &&
51804             props.value !== undefined &&
51805             !isHook(props.value)
51806         ) {
51807             props.value = softSetHook(props.value);
51808         }
51809
51810         transformProperties(props);
51811
51812         if (children !== undefined && children !== null) {
51813             addChild(children, childNodes, tag, props);
51814         }
51815
51816
51817         return new VNode$1(tag, props, childNodes, key, namespace);
51818     }
51819
51820     function addChild(c, childNodes, tag, props) {
51821         if (typeof c === 'string') {
51822             childNodes.push(new VText$1(c));
51823         } else if (typeof c === 'number') {
51824             childNodes.push(new VText$1(String(c)));
51825         } else if (isChild(c)) {
51826             childNodes.push(c);
51827         } else if (isArray(c)) {
51828             for (var i = 0; i < c.length; i++) {
51829                 addChild(c[i], childNodes, tag, props);
51830             }
51831         } else if (c === null || c === undefined) {
51832             return;
51833         } else {
51834             throw UnexpectedVirtualElement({
51835                 foreignObject: c,
51836                 parentVnode: {
51837                     tagName: tag,
51838                     properties: props
51839                 }
51840             });
51841         }
51842     }
51843
51844     function transformProperties(props) {
51845         for (var propName in props) {
51846             if (props.hasOwnProperty(propName)) {
51847                 var value = props[propName];
51848
51849                 if (isHook(value)) {
51850                     continue;
51851                 }
51852
51853                 if (propName.substr(0, 3) === 'ev-') {
51854                     // add ev-foo support
51855                     props[propName] = evHook(value);
51856                 }
51857             }
51858         }
51859     }
51860
51861     function isChild(x) {
51862         return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x);
51863     }
51864
51865     function isChildren(x) {
51866         return typeof x === 'string' || isArray(x) || isChild(x);
51867     }
51868
51869     function UnexpectedVirtualElement(data) {
51870         var err = new Error();
51871
51872         err.type = 'virtual-hyperscript.unexpected.virtual-element';
51873         err.message = 'Unexpected virtual child passed to h().\n' +
51874             'Expected a VNode / Vthunk / VWidget / string but:\n' +
51875             'got:\n' +
51876             errorString(data.foreignObject) +
51877             '.\n' +
51878             'The parent vnode is:\n' +
51879             errorString(data.parentVnode);
51880         err.foreignObject = data.foreignObject;
51881         err.parentVnode = data.parentVnode;
51882
51883         return err;
51884     }
51885
51886     function errorString(obj) {
51887         try {
51888             return JSON.stringify(obj, null, '    ');
51889         } catch (e) {
51890             return String(obj);
51891         }
51892     }
51893
51894     var h$1 = virtualHyperscript;
51895
51896     var h_1 = h$1;
51897
51898     var createElement = createElement_1$1;
51899
51900     var createElement_1 = createElement;
51901
51902     var diff = diff_1;
51903     var patch = patch_1;
51904     var h = h_1;
51905     var create = createElement_1;
51906     var VNode = vnode;
51907     var VText = vtext;
51908
51909     var virtualDom = {
51910         diff: diff,
51911         patch: patch,
51912         h: h,
51913         create: create,
51914         VNode: VNode,
51915         VText: VText
51916     };
51917
51918     class EventEmitter {
51919         constructor() { this._events = {}; }
51920         /**
51921          * @ignore
51922          */
51923         fire(type, event) {
51924             if (!this._listens(type)) {
51925                 return;
51926             }
51927             for (const handler of this._events[type]) {
51928                 handler(event);
51929             }
51930         }
51931         /**
51932          * Unsubscribe from an event by its name.
51933          * @param {string} type - The name of the event
51934          * to unsubscribe from.
51935          * @param {(event: T) => void} handler - The
51936          * handler to remove.
51937          */
51938         off(type, handler) {
51939             if (!type) {
51940                 this._events = {};
51941                 return;
51942             }
51943             if (this._listens(type)) {
51944                 const index = this._events[type].indexOf(handler);
51945                 if (index >= 0) {
51946                     this._events[type].splice(index, 1);
51947                 }
51948                 if (!this._events[type].length) {
51949                     delete this._events[type];
51950                 }
51951             }
51952         }
51953         /**
51954          * Subscribe to an event by its name.
51955          * @param {string} type - The name of the event
51956          * to subscribe to.
51957          * @param {(event: T) => void} handler - The
51958          * handler called when the event occurs.
51959          */
51960         on(type, handler) {
51961             this._events[type] = this._events[type] || [];
51962             this._events[type].push(handler);
51963         }
51964         _listens(eventType) {
51965             return eventType in this._events;
51966         }
51967     }
51968
51969     class SubscriptionHolder {
51970         constructor() {
51971             this._subscriptions = [];
51972         }
51973         push(subscription) {
51974             this._subscriptions.push(subscription);
51975         }
51976         unsubscribe() {
51977             for (const sub of this._subscriptions) {
51978                 sub.unsubscribe();
51979             }
51980             this._subscriptions = [];
51981         }
51982     }
51983
51984     class Component extends EventEmitter {
51985         constructor(name, container, navigator) {
51986             super();
51987             this._activated$ = new BehaviorSubject(false);
51988             this._configurationSubject$ = new Subject();
51989             this._activated = false;
51990             this._container = container;
51991             this._name = name;
51992             this._navigator = navigator;
51993             this._subscriptions = new SubscriptionHolder();
51994             this._configuration$ =
51995                 this._configurationSubject$.pipe(startWith(this.defaultConfiguration), scan((conf, newConf) => {
51996                     for (let key in newConf) {
51997                         if (newConf.hasOwnProperty(key)) {
51998                             conf[key] = newConf[key];
51999                         }
52000                     }
52001                     return conf;
52002                 }), publishReplay(1), refCount());
52003             this._configuration$.subscribe(() => { });
52004         }
52005         /**
52006          * Get activated.
52007          *
52008          * @returns {boolean} Value indicating if the component is
52009          * currently active.
52010          */
52011         get activated() {
52012             return this._activated;
52013         }
52014         /** @ignore */
52015         get activated$() {
52016             return this._activated$;
52017         }
52018         /**
52019          * Get default configuration.
52020          *
52021          * @returns {TConfiguration} Default configuration for component.
52022          */
52023         get defaultConfiguration() {
52024             return this._getDefaultConfiguration();
52025         }
52026         /** @ignore */
52027         get configuration$() {
52028             return this._configuration$;
52029         }
52030         /**
52031          * Get name.
52032          *
52033          * @description The name of the component. Used when interacting with the
52034          * component through the Viewer's API.
52035          */
52036         get name() {
52037             return this._name;
52038         }
52039         /** @ignore */
52040         activate(conf) {
52041             if (this._activated) {
52042                 return;
52043             }
52044             if (conf !== undefined) {
52045                 this._configurationSubject$.next(conf);
52046             }
52047             this._activated = true;
52048             this._activate();
52049             this._activated$.next(true);
52050         }
52051         /**
52052          * Configure the component.
52053          *
52054          * @param configuration Component configuration.
52055          */
52056         configure(configuration) {
52057             this._configurationSubject$.next(configuration);
52058         }
52059         /** @ignore */
52060         deactivate() {
52061             if (!this._activated) {
52062                 return;
52063             }
52064             this._activated = false;
52065             this._deactivate();
52066             this._container.domRenderer.clear(this._name);
52067             this._container.glRenderer.clear(this._name);
52068             this._activated$.next(false);
52069         }
52070         /** @inheritdoc */
52071         fire(type, event) {
52072             super.fire(type, event);
52073         }
52074         /** @inheritdoc */
52075         off(type, handler) {
52076             super.off(type, handler);
52077         }
52078         /** @inheritdoc */
52079         on(type, handler) {
52080             super.on(type, handler);
52081         }
52082         /**
52083          * Detect the viewer's new width and height and resize the component's
52084          * rendered elements accordingly if applicable.
52085          *
52086          * @ignore
52087          */
52088         resize() { return; }
52089     }
52090
52091     var CoverState;
52092     (function (CoverState) {
52093         CoverState[CoverState["Hidden"] = 0] = "Hidden";
52094         CoverState[CoverState["Loading"] = 1] = "Loading";
52095         CoverState[CoverState["Visible"] = 2] = "Visible";
52096     })(CoverState || (CoverState = {}));
52097
52098     class CoverComponent extends Component {
52099         constructor(name, container, navigator) {
52100             super(name, container, navigator);
52101         }
52102         _activate() {
52103             const originalSrc$ = this.configuration$.pipe(first((c) => {
52104                 return !!c.id;
52105             }), filter((c) => {
52106                 return !c.src;
52107             }), switchMap((c) => {
52108                 return this._getImageSrc$(c.id).pipe(catchError((error) => {
52109                     console.error(error);
52110                     return empty();
52111                 }));
52112             }), publishReplay(1), refCount());
52113             const subs = this._subscriptions;
52114             subs.push(originalSrc$.pipe(map((src) => {
52115                 return { src: src };
52116             }))
52117                 .subscribe((c) => {
52118                 this._configurationSubject$.next(c);
52119             }));
52120             subs.push(combineLatest(this.configuration$, originalSrc$).pipe(filter(([c, src]) => {
52121                 return !!c.src && c.src !== src;
52122             }), first())
52123                 .subscribe(([, src]) => {
52124                 window.URL.revokeObjectURL(src);
52125             }));
52126             subs.push(this._configuration$.pipe(distinctUntilChanged(undefined, (configuration) => {
52127                 return configuration.state;
52128             }), switchMap((configuration) => {
52129                 return combineLatest(of(configuration.state), this._navigator.stateService.currentImage$);
52130             }), switchMap(([state, image]) => {
52131                 const keySrc$ = combineLatest(of(image.id), image.image$.pipe(filter((imageElement) => {
52132                     return !!imageElement;
52133                 }), map((imageElement) => {
52134                     return imageElement.src;
52135                 })));
52136                 return state === CoverState.Visible ? keySrc$.pipe(first()) : keySrc$;
52137             }), distinctUntilChanged(([k1, s1], [k2, s2]) => {
52138                 return k1 === k2 && s1 === s2;
52139             }), map(([key, src]) => {
52140                 return { id: key, src: src };
52141             }))
52142                 .subscribe(this._configurationSubject$));
52143             subs.push(combineLatest(this._configuration$, this._container.configurationService.exploreUrl$, this._container.renderService.size$).pipe(map(([configuration, exploreUrl, size]) => {
52144                 if (!configuration.src) {
52145                     return { name: this._name, vNode: virtualDom.h("div", []) };
52146                 }
52147                 const compactClass = size.width <= 640 || size.height <= 480 ? ".mapillary-cover-compact" : "";
52148                 if (configuration.state === CoverState.Hidden) {
52149                     const doneContainer = virtualDom.h("div.mapillary-cover-container.mapillary-cover-done" + compactClass, [this._getCoverBackgroundVNode(configuration)]);
52150                     return { name: this._name, vNode: doneContainer };
52151                 }
52152                 const container = virtualDom.h("div.mapillary-cover-container" + compactClass, [this._getCoverButtonVNode(configuration, exploreUrl)]);
52153                 return { name: this._name, vNode: container };
52154             }))
52155                 .subscribe(this._container.domRenderer.render$));
52156         }
52157         _deactivate() {
52158             this._subscriptions.unsubscribe();
52159         }
52160         _getDefaultConfiguration() {
52161             return { state: CoverState.Visible };
52162         }
52163         _getCoverButtonVNode(configuration, exploreUrl) {
52164             const cover = configuration.state === CoverState.Loading ? "div.mapillary-cover.mapillary-cover-loading" : "div.mapillary-cover";
52165             const coverButton = virtualDom.h("div.mapillary-cover-button", [virtualDom.h("div.mapillary-cover-button-icon", [])]);
52166             const coverLogo = virtualDom.h("a.mapillary-cover-logo", { href: exploreUrl, target: "_blank" }, []);
52167             const coverIndicator = virtualDom.h("div.mapillary-cover-indicator", { onclick: () => { this.configure({ state: CoverState.Loading }); } }, []);
52168             return virtualDom.h(cover, [
52169                 this._getCoverBackgroundVNode(configuration),
52170                 coverIndicator,
52171                 coverButton,
52172                 coverLogo,
52173             ]);
52174         }
52175         _getCoverBackgroundVNode(conf) {
52176             const properties = {
52177                 style: { backgroundImage: `url(${conf.src})` },
52178             };
52179             const children = [];
52180             if (conf.state === CoverState.Loading) {
52181                 children.push(virtualDom.h("div.mapillary-cover-spinner", {}, []));
52182             }
52183             return virtualDom.h("div.mapillary-cover-background", properties, children);
52184         }
52185         _getImageSrc$(id) {
52186             return Observable.create((subscriber) => {
52187                 this._navigator.api.getImages$([id])
52188                     .subscribe((items) => {
52189                     for (const item of items) {
52190                         const imageId = typeof id === "number" ?
52191                             id.toString() : id;
52192                         if (item.node_id !== imageId) {
52193                             continue;
52194                         }
52195                         this._navigator.api.data
52196                             .getImageBuffer(item.node.thumb.url)
52197                             .then((buffer) => {
52198                             const image = new Image();
52199                             image.crossOrigin = "Anonymous";
52200                             image.onload = () => {
52201                                 subscriber.next(image.src);
52202                                 subscriber.complete();
52203                             };
52204                             image.onerror = () => {
52205                                 subscriber.error(new Error(`Failed to load cover ` +
52206                                     `image (${id})`));
52207                             };
52208                             const blob = new Blob([buffer]);
52209                             image.src = window.URL
52210                                 .createObjectURL(blob);
52211                         }, (error) => {
52212                             subscriber.error(error);
52213                         });
52214                         return;
52215                     }
52216                     subscriber.error(new MapillaryError(`Non existent cover key: ${id}`));
52217                 }, (error) => {
52218                     subscriber.error(error);
52219                 });
52220             });
52221         }
52222     }
52223     CoverComponent.componentName = "cover";
52224
52225     class AttributionComponent extends Component {
52226         _activate() {
52227             this._subscriptions.push(combineLatest(this._container.configurationService.exploreUrl$, this._navigator.stateService.currentImage$, this._container.renderService.size$).pipe(map(([exploreUrl, image, size]) => {
52228                 const attribution = this._makeAttribution(image.creatorUsername, exploreUrl, image.id, image.capturedAt, size.width);
52229                 return {
52230                     name: this._name,
52231                     vNode: attribution,
52232                 };
52233             }))
52234                 .subscribe(this._container.domRenderer.render$));
52235         }
52236         _deactivate() {
52237             this._subscriptions.unsubscribe();
52238         }
52239         _getDefaultConfiguration() {
52240             return {};
52241         }
52242         makeImageUrl(exploreUrl, id) {
52243             return `${exploreUrl}/app/?pKey=${id}&focus=photo`;
52244         }
52245         _makeAttribution(creatorUsername, exploreUrl, imageId, capturedAt, viewportWidth) {
52246             const compact = viewportWidth <= 640;
52247             const date = this._makeDate(capturedAt, compact);
52248             const by = this._makeBy(creatorUsername, exploreUrl, imageId, compact);
52249             const compactClass = compact ?
52250                 ".mapillary-attribution-compact" : "";
52251             return virtualDom.h("div.mapillary-attribution-container" + compactClass, {}, [...by, date]);
52252         }
52253         _makeBy(creatorUsername, exploreUrl, imageId, compact) {
52254             const icon = virtualDom.h("div.mapillary-attribution-logo", []);
52255             return creatorUsername ?
52256                 this._makeCreatorBy(icon, creatorUsername, exploreUrl, imageId, compact) :
52257                 this._makeGeneralBy(icon, exploreUrl, imageId, compact);
52258         }
52259         _makeCreatorBy(icon, creatorUsername, exploreUrl, imageId, compact) {
52260             const mapillary = virtualDom.h("a.mapillary-attribution-icon-container", { href: exploreUrl, rel: "noreferrer", target: "_blank" }, [icon]);
52261             const content = compact ?
52262                 `${creatorUsername}` : `image by ${creatorUsername}`;
52263             const imageBy = virtualDom.h("div.mapillary-attribution-username", { textContent: content }, []);
52264             const image = virtualDom.h("a.mapillary-attribution-image-container", {
52265                 href: this.makeImageUrl(exploreUrl, imageId),
52266                 rel: "noreferrer",
52267                 target: "_blank",
52268             }, [imageBy]);
52269             return [mapillary, image];
52270         }
52271         _makeGeneralBy(icon, exploreUrl, imageId, compact) {
52272             const imagesBy = virtualDom.h("div.mapillary-attribution-username", { textContent: 'images by' }, []);
52273             const mapillary = virtualDom.h("div.mapillary-attribution-icon-container", {}, [icon]);
52274             const contributors = virtualDom.h("div.mapillary-attribution-username", { textContent: 'contributors' }, []);
52275             const children = [mapillary, contributors];
52276             if (!compact) {
52277                 children.unshift(imagesBy);
52278             }
52279             const image = virtualDom.h("a.mapillary-attribution-image-container", {
52280                 href: this.makeImageUrl(exploreUrl, imageId),
52281                 rel: "noreferrer",
52282                 target: "_blank",
52283             }, children);
52284             return [image];
52285         }
52286         _makeDate(capturedAt, compact) {
52287             const date = new Date(capturedAt)
52288                 .toDateString()
52289                 .split(" ");
52290             const formatted = (date.length > 3 ?
52291                 compact ?
52292                     [date[3]] :
52293                     [date[1], date[2] + ",", date[3]] :
52294                 date).join(" ");
52295             return virtualDom.h("div.mapillary-attribution-date", { textContent: formatted }, []);
52296         }
52297     }
52298     AttributionComponent.componentName = "attribution";
52299
52300     /**
52301      * @class ViewportCoords
52302      *
52303      * @classdesc Provides methods for calculating 2D coordinate conversions
52304      * as well as 3D projection and unprojection.
52305      *
52306      * Basic coordinates are 2D coordinates on the [0, 1] interval and
52307      * have the origin point, (0, 0), at the top left corner and the
52308      * maximum value, (1, 1), at the bottom right corner of the original
52309      * image.
52310      *
52311      * Viewport coordinates are 2D coordinates on the [-1, 1] interval and
52312      * have the origin point in the center. The bottom left corner point is
52313      * (-1, -1) and the top right corner point is (1, 1).
52314      *
52315      * Canvas coordiantes are 2D pixel coordinates on the [0, canvasWidth] and
52316      * [0, canvasHeight] intervals. The origin point (0, 0) is in the top left
52317      * corner and the maximum value is (canvasWidth, canvasHeight) is in the
52318      * bottom right corner.
52319      *
52320      * 3D coordinates are in the topocentric world reference frame.
52321      */
52322     class ViewportCoords {
52323         constructor() {
52324             this._unprojectDepth = 200;
52325         }
52326         /**
52327          * Convert basic coordinates to canvas coordinates.
52328          *
52329          * @description Transform origin and camera position needs to be the
52330          * equal for reliable return value.
52331          *
52332          * @param {number} basicX - Basic X coordinate.
52333          * @param {number} basicY - Basic Y coordinate.
52334          * @param {HTMLElement} container - The viewer container.
52335          * @param {Transform} transform - Transform of the image to unproject from.
52336          * @param {THREE.Camera} camera - Camera used in rendering.
52337          * @returns {Array<number>} 2D canvas coordinates.
52338          */
52339         basicToCanvas(basicX, basicY, container, transform, camera) {
52340             const point3d = transform.unprojectBasic([basicX, basicY], this._unprojectDepth);
52341             const canvas = this.projectToCanvas(point3d, container, camera);
52342             return canvas;
52343         }
52344         /**
52345          * Convert basic coordinates to canvas coordinates safely. If 3D point is
52346          * behind camera null will be returned.
52347          *
52348          * @description Transform origin and camera position needs to be the
52349          * equal for reliable return value.
52350          *
52351          * @param {number} basicX - Basic X coordinate.
52352          * @param {number} basicY - Basic Y coordinate.
52353          * @param {HTMLElement} container - The viewer container.
52354          * @param {Transform} transform - Transform of the image to unproject from.
52355          * @param {THREE.Camera} camera - Camera used in rendering.
52356          * @returns {Array<number>} 2D canvas coordinates if the basic point represents a 3D point
52357          * in front of the camera, otherwise null.
52358          */
52359         basicToCanvasSafe(basicX, basicY, container, transform, camera) {
52360             const viewport = this.basicToViewportSafe(basicX, basicY, transform, camera);
52361             if (viewport === null) {
52362                 return null;
52363             }
52364             const canvas = this.viewportToCanvas(viewport[0], viewport[1], container);
52365             return canvas;
52366         }
52367         /**
52368          * Convert basic coordinates to viewport coordinates.
52369          *
52370          * @description Transform origin and camera position needs to be the
52371          * equal for reliable return value.
52372          *
52373          * @param {number} basicX - Basic X coordinate.
52374          * @param {number} basicY - Basic Y coordinate.
52375          * @param {Transform} transform - Transform of the image to unproject from.
52376          * @param {THREE.Camera} camera - Camera used in rendering.
52377          * @returns {Array<number>} 2D viewport coordinates.
52378          */
52379         basicToViewport(basicX, basicY, transform, camera) {
52380             const point3d = transform.unprojectBasic([basicX, basicY], this._unprojectDepth);
52381             const viewport = this.projectToViewport(point3d, camera);
52382             return viewport;
52383         }
52384         /**
52385          * Convert basic coordinates to viewport coordinates safely. If 3D point is
52386          * behind camera null will be returned.
52387          *
52388          * @description Transform origin and camera position needs to be the
52389          * equal for reliable return value.
52390          *
52391          * @param {number} basicX - Basic X coordinate.
52392          * @param {number} basicY - Basic Y coordinate.
52393          * @param {Transform} transform - Transform of the image to unproject from.
52394          * @param {THREE.Camera} camera - Camera used in rendering.
52395          * @returns {Array<number>} 2D viewport coordinates.
52396          */
52397         basicToViewportSafe(basicX, basicY, transform, camera) {
52398             const point3d = transform.unprojectBasic([basicX, basicY], this._unprojectDepth);
52399             const pointCamera = this.worldToCamera(point3d, camera);
52400             if (pointCamera[2] > 0) {
52401                 return null;
52402             }
52403             const viewport = this.projectToViewport(point3d, camera);
52404             return viewport;
52405         }
52406         /**
52407          * Convert camera 3D coordinates to viewport coordinates.
52408          *
52409          * @param {number} pointCamera - 3D point in camera coordinate system.
52410          * @param {THREE.Camera} camera - Camera used in rendering.
52411          * @returns {Array<number>} 2D viewport coordinates.
52412          */
52413         cameraToViewport(pointCamera, camera) {
52414             const viewport = new Vector3().fromArray(pointCamera)
52415                 .applyMatrix4(camera.projectionMatrix);
52416             return [viewport.x, viewport.y];
52417         }
52418         /**
52419          * Get canvas pixel position from event.
52420          *
52421          * @param {Event} event - Event containing clientX and clientY properties.
52422          * @param {HTMLElement} element - HTML element.
52423          * @returns {Array<number>} 2D canvas coordinates.
52424          */
52425         canvasPosition(event, element) {
52426             const clientRect = element.getBoundingClientRect();
52427             const canvasX = event.clientX - clientRect.left - element.clientLeft;
52428             const canvasY = event.clientY - clientRect.top - element.clientTop;
52429             return [canvasX, canvasY];
52430         }
52431         /**
52432          * Convert canvas coordinates to basic coordinates.
52433          *
52434          * @description Transform origin and camera position needs to be the
52435          * equal for reliable return value.
52436          *
52437          * @param {number} canvasX - Canvas X coordinate.
52438          * @param {number} canvasY - Canvas Y coordinate.
52439          * @param {HTMLElement} container - The viewer container.
52440          * @param {Transform} transform - Transform of the image to unproject from.
52441          * @param {THREE.Camera} camera - Camera used in rendering.
52442          * @returns {Array<number>} 2D basic coordinates.
52443          */
52444         canvasToBasic(canvasX, canvasY, container, transform, camera) {
52445             const point3d = this.unprojectFromCanvas(canvasX, canvasY, container, camera)
52446                 .toArray();
52447             const basic = transform.projectBasic(point3d);
52448             return basic;
52449         }
52450         /**
52451          * Convert canvas coordinates to viewport coordinates.
52452          *
52453          * @param {number} canvasX - Canvas X coordinate.
52454          * @param {number} canvasY - Canvas Y coordinate.
52455          * @param {HTMLElement} container - The viewer container.
52456          * @returns {Array<number>} 2D viewport coordinates.
52457          */
52458         canvasToViewport(canvasX, canvasY, container) {
52459             const [canvasWidth, canvasHeight] = this.containerToCanvas(container);
52460             const viewportX = 2 * canvasX / canvasWidth - 1;
52461             const viewportY = 1 - 2 * canvasY / canvasHeight;
52462             return [viewportX, viewportY];
52463         }
52464         /**
52465          * Determines the width and height of the container in canvas coordinates.
52466          *
52467          * @param {HTMLElement} container - The viewer container.
52468          * @returns {Array<number>} 2D canvas coordinates.
52469          */
52470         containerToCanvas(container) {
52471             return [container.offsetWidth, container.offsetHeight];
52472         }
52473         /**
52474          * Determine basic distances from image to canvas corners.
52475          *
52476          * @description Transform origin and camera position needs to be the
52477          * equal for reliable return value.
52478          *
52479          * Determines the smallest basic distance for every side of the canvas.
52480          *
52481          * @param {Transform} transform - Transform of the image to unproject from.
52482          * @param {THREE.Camera} camera - Camera used in rendering.
52483          * @returns {Array<number>} Array of basic distances as [top, right, bottom, left].
52484          */
52485         getBasicDistances(transform, camera) {
52486             const topLeftBasic = this.viewportToBasic(-1, 1, transform, camera);
52487             const topRightBasic = this.viewportToBasic(1, 1, transform, camera);
52488             const bottomRightBasic = this.viewportToBasic(1, -1, transform, camera);
52489             const bottomLeftBasic = this.viewportToBasic(-1, -1, transform, camera);
52490             let topBasicDistance = 0;
52491             let rightBasicDistance = 0;
52492             let bottomBasicDistance = 0;
52493             let leftBasicDistance = 0;
52494             if (topLeftBasic[1] < 0 && topRightBasic[1] < 0) {
52495                 topBasicDistance = topLeftBasic[1] > topRightBasic[1] ?
52496                     -topLeftBasic[1] :
52497                     -topRightBasic[1];
52498             }
52499             if (topRightBasic[0] > 1 && bottomRightBasic[0] > 1) {
52500                 rightBasicDistance = topRightBasic[0] < bottomRightBasic[0] ?
52501                     topRightBasic[0] - 1 :
52502                     bottomRightBasic[0] - 1;
52503             }
52504             if (bottomRightBasic[1] > 1 && bottomLeftBasic[1] > 1) {
52505                 bottomBasicDistance = bottomRightBasic[1] < bottomLeftBasic[1] ?
52506                     bottomRightBasic[1] - 1 :
52507                     bottomLeftBasic[1] - 1;
52508             }
52509             if (bottomLeftBasic[0] < 0 && topLeftBasic[0] < 0) {
52510                 leftBasicDistance = bottomLeftBasic[0] > topLeftBasic[0] ?
52511                     -bottomLeftBasic[0] :
52512                     -topLeftBasic[0];
52513             }
52514             return [topBasicDistance, rightBasicDistance, bottomBasicDistance, leftBasicDistance];
52515         }
52516         /**
52517          * Determine pixel distances from image to canvas corners.
52518          *
52519          * @description Transform origin and camera position needs to be the
52520          * equal for reliable return value.
52521          *
52522          * Determines the smallest pixel distance for every side of the canvas.
52523          *
52524          * @param {HTMLElement} container - The viewer container.
52525          * @param {Transform} transform - Transform of the image to unproject from.
52526          * @param {THREE.Camera} camera - Camera used in rendering.
52527          * @returns {Array<number>} Array of pixel distances as [top, right, bottom, left].
52528          */
52529         getPixelDistances(container, transform, camera) {
52530             const topLeftBasic = this.viewportToBasic(-1, 1, transform, camera);
52531             const topRightBasic = this.viewportToBasic(1, 1, transform, camera);
52532             const bottomRightBasic = this.viewportToBasic(1, -1, transform, camera);
52533             const bottomLeftBasic = this.viewportToBasic(-1, -1, transform, camera);
52534             let topPixelDistance = 0;
52535             let rightPixelDistance = 0;
52536             let bottomPixelDistance = 0;
52537             let leftPixelDistance = 0;
52538             const [canvasWidth, canvasHeight] = this.containerToCanvas(container);
52539             if (topLeftBasic[1] < 0 && topRightBasic[1] < 0) {
52540                 const basicX = topLeftBasic[1] > topRightBasic[1] ?
52541                     topLeftBasic[0] :
52542                     topRightBasic[0];
52543                 const canvas = this.basicToCanvas(basicX, 0, container, transform, camera);
52544                 topPixelDistance = canvas[1] > 0 ? canvas[1] : 0;
52545             }
52546             if (topRightBasic[0] > 1 && bottomRightBasic[0] > 1) {
52547                 const basicY = topRightBasic[0] < bottomRightBasic[0] ?
52548                     topRightBasic[1] :
52549                     bottomRightBasic[1];
52550                 const canvas = this.basicToCanvas(1, basicY, container, transform, camera);
52551                 rightPixelDistance = canvas[0] < canvasWidth ? canvasWidth - canvas[0] : 0;
52552             }
52553             if (bottomRightBasic[1] > 1 && bottomLeftBasic[1] > 1) {
52554                 const basicX = bottomRightBasic[1] < bottomLeftBasic[1] ?
52555                     bottomRightBasic[0] :
52556                     bottomLeftBasic[0];
52557                 const canvas = this.basicToCanvas(basicX, 1, container, transform, camera);
52558                 bottomPixelDistance = canvas[1] < canvasHeight ? canvasHeight - canvas[1] : 0;
52559             }
52560             if (bottomLeftBasic[0] < 0 && topLeftBasic[0] < 0) {
52561                 const basicY = bottomLeftBasic[0] > topLeftBasic[0] ?
52562                     bottomLeftBasic[1] :
52563                     topLeftBasic[1];
52564                 const canvas = this.basicToCanvas(0, basicY, container, transform, camera);
52565                 leftPixelDistance = canvas[0] > 0 ? canvas[0] : 0;
52566             }
52567             return [topPixelDistance, rightPixelDistance, bottomPixelDistance, leftPixelDistance];
52568         }
52569         /**
52570          * Determine if an event occured inside an element.
52571          *
52572          * @param {Event} event - Event containing clientX and clientY properties.
52573          * @param {HTMLElement} element - HTML element.
52574          * @returns {boolean} Value indicating if the event occured inside the element or not.
52575          */
52576         insideElement(event, element) {
52577             const clientRect = element.getBoundingClientRect();
52578             const minX = clientRect.left + element.clientLeft;
52579             const maxX = minX + element.clientWidth;
52580             const minY = clientRect.top + element.clientTop;
52581             const maxY = minY + element.clientHeight;
52582             return event.clientX > minX &&
52583                 event.clientX < maxX &&
52584                 event.clientY > minY &&
52585                 event.clientY < maxY;
52586         }
52587         /**
52588          * Project 3D world coordinates to canvas coordinates.
52589          *
52590          * @param {Array<number>} point3D - 3D world coordinates.
52591          * @param {HTMLElement} container - The viewer container.
52592          * @param {THREE.Camera} camera - Camera used in rendering.
52593          * @returns {Array<number>} 2D canvas coordinates.
52594          */
52595         projectToCanvas(point3d, container, camera) {
52596             const viewport = this.projectToViewport(point3d, camera);
52597             const canvas = this.viewportToCanvas(viewport[0], viewport[1], container);
52598             return canvas;
52599         }
52600         /**
52601          * Project 3D world coordinates to canvas coordinates safely. If 3D
52602          * point is behind camera null will be returned.
52603          *
52604          * @param {Array<number>} point3D - 3D world coordinates.
52605          * @param {HTMLElement} container - The viewer container.
52606          * @param {THREE.Camera} camera - Camera used in rendering.
52607          * @returns {Array<number>} 2D canvas coordinates.
52608          */
52609         projectToCanvasSafe(point3d, container, camera) {
52610             const pointCamera = this.worldToCamera(point3d, camera);
52611             if (pointCamera[2] > 0) {
52612                 return null;
52613             }
52614             const viewport = this.projectToViewport(point3d, camera);
52615             const canvas = this.viewportToCanvas(viewport[0], viewport[1], container);
52616             return canvas;
52617         }
52618         /**
52619          * Project 3D world coordinates to viewport coordinates.
52620          *
52621          * @param {Array<number>} point3D - 3D world coordinates.
52622          * @param {THREE.Camera} camera - Camera used in rendering.
52623          * @returns {Array<number>} 2D viewport coordinates.
52624          */
52625         projectToViewport(point3d, camera) {
52626             const viewport = new Vector3(point3d[0], point3d[1], point3d[2])
52627                 .project(camera);
52628             return [viewport.x, viewport.y];
52629         }
52630         /**
52631          * Uproject canvas coordinates to 3D world coordinates.
52632          *
52633          * @param {number} canvasX - Canvas X coordinate.
52634          * @param {number} canvasY - Canvas Y coordinate.
52635          * @param {HTMLElement} container - The viewer container.
52636          * @param {THREE.Camera} camera - Camera used in rendering.
52637          * @returns {Array<number>} 3D world coordinates.
52638          */
52639         unprojectFromCanvas(canvasX, canvasY, container, camera) {
52640             const viewport = this.canvasToViewport(canvasX, canvasY, container);
52641             const point3d = this.unprojectFromViewport(viewport[0], viewport[1], camera);
52642             return point3d;
52643         }
52644         /**
52645          * Unproject viewport coordinates to 3D world coordinates.
52646          *
52647          * @param {number} viewportX - Viewport X coordinate.
52648          * @param {number} viewportY - Viewport Y coordinate.
52649          * @param {THREE.Camera} camera - Camera used in rendering.
52650          * @returns {Array<number>} 3D world coordinates.
52651          */
52652         unprojectFromViewport(viewportX, viewportY, camera) {
52653             const point3d = new Vector3(viewportX, viewportY, 1)
52654                 .unproject(camera);
52655             return point3d;
52656         }
52657         /**
52658          * Convert viewport coordinates to basic coordinates.
52659          *
52660          * @description Transform origin and camera position needs to be the
52661          * equal for reliable return value.
52662          *
52663          * @param {number} viewportX - Viewport X coordinate.
52664          * @param {number} viewportY - Viewport Y coordinate.
52665          * @param {Transform} transform - Transform of the image to unproject from.
52666          * @param {THREE.Camera} camera - Camera used in rendering.
52667          * @returns {Array<number>} 2D basic coordinates.
52668          */
52669         viewportToBasic(viewportX, viewportY, transform, camera) {
52670             const point3d = new Vector3(viewportX, viewportY, 1)
52671                 .unproject(camera)
52672                 .toArray();
52673             const basic = transform.projectBasic(point3d);
52674             return basic;
52675         }
52676         /**
52677          * Convert viewport coordinates to canvas coordinates.
52678          *
52679          * @param {number} viewportX - Viewport X coordinate.
52680          * @param {number} viewportY - Viewport Y coordinate.
52681          * @param {HTMLElement} container - The viewer container.
52682          * @returns {Array<number>} 2D canvas coordinates.
52683          */
52684         viewportToCanvas(viewportX, viewportY, container) {
52685             const [canvasWidth, canvasHeight] = this.containerToCanvas(container);
52686             const canvasX = canvasWidth * (viewportX + 1) / 2;
52687             const canvasY = -canvasHeight * (viewportY - 1) / 2;
52688             return [canvasX, canvasY];
52689         }
52690         /**
52691          * Convert 3D world coordinates to 3D camera coordinates.
52692          *
52693          * @param {number} point3D - 3D point in world coordinate system.
52694          * @param {THREE.Camera} camera - Camera used in rendering.
52695          * @returns {Array<number>} 3D camera coordinates.
52696          */
52697         worldToCamera(point3d, camera) {
52698             const pointCamera = new Vector3(point3d[0], point3d[1], point3d[2])
52699                 .applyMatrix4(camera.matrixWorldInverse);
52700             return pointCamera.toArray();
52701         }
52702     }
52703
52704     /**
52705      * Enumeration for component size.
52706      * @enum {number}
52707      * @readonly
52708      * @description May be used by a component to allow for resizing
52709      * of the UI elements rendered by the component.
52710      */
52711     exports.ComponentSize = void 0;
52712     (function (ComponentSize) {
52713         /**
52714          * Automatic size. The size of the elements will automatically
52715          * change at a predefined threshold.
52716          */
52717         ComponentSize[ComponentSize["Automatic"] = 0] = "Automatic";
52718         /**
52719          * Large size. The size of the elements will be fixed until another
52720          * component size is configured.
52721          */
52722         ComponentSize[ComponentSize["Large"] = 1] = "Large";
52723         /**
52724          * Small size. The size of the elements will be fixed until another
52725          * component size is configured.
52726          */
52727         ComponentSize[ComponentSize["Small"] = 2] = "Small";
52728     })(exports.ComponentSize || (exports.ComponentSize = {}));
52729
52730     /**
52731      * @class BearingComponent
52732      *
52733      * @classdesc Component for indicating bearing and field of view.
52734      *
52735      * @example
52736      * ```js
52737      * var viewer = new Viewer({ ... });
52738      * var bearingComponent = viewer.getComponent("bearing");
52739      * bearingComponent.configure({ size: ComponentSize.Small });
52740      * ```
52741      */
52742     class BearingComponent extends Component {
52743         /** @ignore */
52744         constructor(name, container, navigator) {
52745             super(name, container, navigator);
52746             this._spatial = new Spatial();
52747             this._viewportCoords = new ViewportCoords();
52748             this._svgNamespace = "http://www.w3.org/2000/svg";
52749             this._distinctThreshold = Math.PI / 360;
52750             this._animationSpeed = 0.075;
52751         }
52752         _activate() {
52753             const subs = this._subscriptions;
52754             const cameraBearingFov$ = this._container.renderService.renderCamera$.pipe(map((rc) => {
52755                 let vFov = this._spatial.degToRad(rc.perspective.fov);
52756                 let hFov = rc.perspective.aspect === Number.POSITIVE_INFINITY ?
52757                     Math.PI :
52758                     Math.atan(rc.perspective.aspect * Math.tan(0.5 * vFov)) * 2;
52759                 return [this._spatial.azimuthalToBearing(rc.rotation.phi), hFov];
52760             }), distinctUntilChanged((a1, a2) => {
52761                 return Math.abs(a2[0] - a1[0]) < this._distinctThreshold &&
52762                     Math.abs(a2[1] - a1[1]) < this._distinctThreshold;
52763             }));
52764             const imageFov$ = combineLatest(this._navigator.stateService.currentState$.pipe(distinctUntilChanged(undefined, (frame) => {
52765                 return frame.state.currentImage.id;
52766             })), this._navigator.panService.panImages$).pipe(map(([frame, panImages]) => {
52767                 const image = frame.state.currentImage;
52768                 const transform = frame.state.currentTransform;
52769                 if (isSpherical(image.cameraType)) {
52770                     return [Math.PI, Math.PI];
52771                 }
52772                 const currentProjectedPoints = this._computeProjectedPoints(transform);
52773                 const hFov = this._spatial
52774                     .degToRad(this._computeHorizontalFov(currentProjectedPoints));
52775                 let hFovLeft = hFov / 2;
52776                 let hFovRight = hFov / 2;
52777                 for (const [n, , f] of panImages) {
52778                     const diff = this._spatial.wrap(n.compassAngle - image.compassAngle, -180, 180);
52779                     if (diff < 0) {
52780                         hFovLeft = this._spatial.degToRad(Math.abs(diff)) + f / 2;
52781                     }
52782                     else {
52783                         hFovRight = this._spatial.degToRad(Math.abs(diff)) + f / 2;
52784                     }
52785                 }
52786                 return [hFovLeft, hFovRight];
52787             }), distinctUntilChanged(([hFovLeft1, hFovRight1], [hFovLeft2, hFovRight2]) => {
52788                 return Math.abs(hFovLeft2 - hFovLeft1) < this._distinctThreshold &&
52789                     Math.abs(hFovRight2 - hFovRight1) < this._distinctThreshold;
52790             }));
52791             const offset$ = combineLatest(this._navigator.stateService.currentState$.pipe(distinctUntilChanged(undefined, (frame) => {
52792                 return frame.state.currentImage.id;
52793             })), this._container.renderService.bearing$).pipe(map(([frame, bearing]) => {
52794                 const offset = this._spatial.degToRad(frame.state.currentImage.compassAngle - bearing);
52795                 return offset;
52796             }));
52797             const imageFovOperation$ = new Subject();
52798             const smoothImageFov$ = imageFovOperation$.pipe(scan((state, operation) => {
52799                 return operation(state);
52800             }, { alpha: 0, curr: [0, 0, 0], prev: [0, 0, 0] }), map((state) => {
52801                 const alpha = MathUtils.smootherstep(state.alpha, 0, 1);
52802                 const curr = state.curr;
52803                 const prev = state.prev;
52804                 return [
52805                     this._interpolate(prev[0], curr[0], alpha),
52806                     this._interpolate(prev[1], curr[1], alpha),
52807                 ];
52808             }));
52809             subs.push(imageFov$.pipe(map((nbf) => {
52810                 return (state) => {
52811                     const a = MathUtils.smootherstep(state.alpha, 0, 1);
52812                     const c = state.curr;
52813                     const p = state.prev;
52814                     const prev = [
52815                         this._interpolate(p[0], c[0], a),
52816                         this._interpolate(p[1], c[1], a),
52817                     ];
52818                     const curr = nbf.slice();
52819                     return {
52820                         alpha: 0,
52821                         curr: curr,
52822                         prev: prev,
52823                     };
52824                 };
52825             }))
52826                 .subscribe(imageFovOperation$));
52827             subs.push(imageFov$.pipe(switchMap(() => {
52828                 return this._container.renderService.renderCameraFrame$.pipe(skip(1), scan((alpha) => {
52829                     return alpha + this._animationSpeed;
52830                 }, 0), takeWhile((alpha) => {
52831                     return alpha <= 1 + this._animationSpeed;
52832                 }), map((alpha) => {
52833                     return Math.min(alpha, 1);
52834                 }));
52835             }), map((alpha) => {
52836                 return (nbfState) => {
52837                     return {
52838                         alpha: alpha,
52839                         curr: nbfState.curr.slice(),
52840                         prev: nbfState.prev.slice(),
52841                     };
52842                 };
52843             }))
52844                 .subscribe(imageFovOperation$));
52845             const imageBearingFov$ = combineLatest(offset$, smoothImageFov$).pipe(map(([offset, fov]) => {
52846                 return [offset, fov[0], fov[1]];
52847             }));
52848             subs.push(combineLatest(cameraBearingFov$, imageBearingFov$, this._configuration$, this._container.renderService.size$).pipe(map(([[cb, cf], [no, nfl, nfr], configuration, size]) => {
52849                 const background = this._createBackground(cb);
52850                 const fovIndicator = this._createFovIndicator(nfl, nfr, no);
52851                 const north = this._createNorth(cb);
52852                 const cameraSector = this._createCircleSectorCompass(this._createCircleSector(Math.max(Math.PI / 20, cf), "#FFF"));
52853                 const compact = configuration.size === exports.ComponentSize.Small ||
52854                     configuration.size === exports.ComponentSize.Automatic && size.width < 640 ?
52855                     ".mapillary-bearing-compact" : "";
52856                 return {
52857                     name: this._name,
52858                     vNode: virtualDom.h("div.mapillary-bearing-indicator-container" + compact, { oncontextmenu: (event) => { event.preventDefault(); } }, [
52859                         background,
52860                         fovIndicator,
52861                         north,
52862                         cameraSector,
52863                     ]),
52864                 };
52865             }))
52866                 .subscribe(this._container.domRenderer.render$));
52867         }
52868         _deactivate() {
52869             this._subscriptions.unsubscribe();
52870         }
52871         _getDefaultConfiguration() {
52872             return { size: exports.ComponentSize.Automatic };
52873         }
52874         _createFovIndicator(fovLeft, fovRigth, offset) {
52875             const arc = this._createFovArc(fovLeft, fovRigth);
52876             const group = virtualDom.h("g", {
52877                 attributes: { transform: "translate(18,18)" },
52878                 namespace: this._svgNamespace,
52879             }, [arc]);
52880             const svg = virtualDom.h("svg", {
52881                 attributes: { viewBox: "0 0 36 36" },
52882                 namespace: this._svgNamespace,
52883                 style: {
52884                     height: "36px",
52885                     left: "2px",
52886                     position: "absolute",
52887                     top: "2px",
52888                     transform: `rotateZ(${this._spatial.radToDeg(offset)}deg)`,
52889                     width: "36px",
52890                 },
52891             }, [group]);
52892             return svg;
52893         }
52894         _createFovArc(fovLeft, fovRigth) {
52895             const radius = 16.75;
52896             const strokeWidth = 2.5;
52897             const fov = fovLeft + fovRigth;
52898             if (fov > 2 * Math.PI - Math.PI / 90) {
52899                 return virtualDom.h("circle", {
52900                     attributes: {
52901                         cx: "0",
52902                         cy: "0",
52903                         "fill-opacity": "0",
52904                         r: `${radius}`,
52905                         stroke: "#FFF",
52906                         "stroke-width": `${strokeWidth}`,
52907                     },
52908                     namespace: this._svgNamespace,
52909                 }, []);
52910             }
52911             let arcStart = -Math.PI / 2 - fovLeft;
52912             let arcEnd = arcStart + fov;
52913             let startX = radius * Math.cos(arcStart);
52914             let startY = radius * Math.sin(arcStart);
52915             let endX = radius * Math.cos(arcEnd);
52916             let endY = radius * Math.sin(arcEnd);
52917             let largeArc = fov >= Math.PI ? 1 : 0;
52918             let description = `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArc} 1 ${endX} ${endY}`;
52919             return virtualDom.h("path", {
52920                 attributes: {
52921                     d: description,
52922                     "fill-opacity": "0",
52923                     stroke: "#FFF",
52924                     "stroke-width": `${strokeWidth}`,
52925                 },
52926                 namespace: this._svgNamespace,
52927             }, []);
52928         }
52929         _createCircleSectorCompass(cameraSector) {
52930             let group = virtualDom.h("g", {
52931                 attributes: { transform: "translate(1,1)" },
52932                 namespace: this._svgNamespace,
52933             }, [cameraSector]);
52934             let svg = virtualDom.h("svg", {
52935                 attributes: { viewBox: "0 0 2 2" },
52936                 namespace: this._svgNamespace,
52937                 style: {
52938                     height: "26px",
52939                     left: "7px",
52940                     position: "absolute",
52941                     top: "7px",
52942                     width: "26px",
52943                 },
52944             }, [group]);
52945             return svg;
52946         }
52947         _createCircleSector(fov, fill) {
52948             if (fov > 2 * Math.PI - Math.PI / 90) {
52949                 return virtualDom.h("circle", {
52950                     attributes: { cx: "0", cy: "0", fill: fill, r: "1" },
52951                     namespace: this._svgNamespace,
52952                 }, []);
52953             }
52954             let arcStart = -Math.PI / 2 - fov / 2;
52955             let arcEnd = arcStart + fov;
52956             let startX = Math.cos(arcStart);
52957             let startY = Math.sin(arcStart);
52958             let endX = Math.cos(arcEnd);
52959             let endY = Math.sin(arcEnd);
52960             let largeArc = fov >= Math.PI ? 1 : 0;
52961             let description = `M 0 0 ${startX} ${startY} A 1 1 0 ${largeArc} 1 ${endX} ${endY}`;
52962             return virtualDom.h("path", {
52963                 attributes: { d: description, fill: fill },
52964                 namespace: this._svgNamespace,
52965             }, []);
52966         }
52967         _createNorth(bearing) {
52968             const north = virtualDom.h("div.mapillary-bearing-north", []);
52969             const container = virtualDom.h("div.mapillary-bearing-north-container", { style: { transform: `rotateZ(${this._spatial.radToDeg(-bearing)}deg)` } }, [north]);
52970             return container;
52971         }
52972         _createBackground(bearing) {
52973             return virtualDom.h("div.mapillary-bearing-indicator-background", { style: { transform: `rotateZ(${this._spatial.radToDeg(-bearing)}deg)` } }, [
52974                 virtualDom.h("div.mapillary-bearing-indicator-background-circle", []),
52975                 virtualDom.h("div.mapillary-bearing-indicator-background-arrow-container", [
52976                     virtualDom.h("div.mapillary-bearing-indicator-background-arrow", []),
52977                 ]),
52978             ]);
52979         }
52980         _computeProjectedPoints(transform) {
52981             const vertices = [[1, 0]];
52982             const directions = [[0, 0.5]];
52983             const pointsPerLine = 12;
52984             return computeProjectedPoints(transform, vertices, directions, pointsPerLine, this._viewportCoords);
52985         }
52986         _computeHorizontalFov(projectedPoints) {
52987             const fovs = projectedPoints
52988                 .map((projectedPoint) => {
52989                 return this._coordToFov(projectedPoint[0]);
52990             });
52991             const fov = Math.min(...fovs);
52992             return fov;
52993         }
52994         _coordToFov(x) {
52995             return this._spatial.radToDeg(2 * Math.atan(x));
52996         }
52997         _interpolate(x1, x2, alpha) {
52998             return (1 - alpha) * x1 + alpha * x2;
52999         }
53000     }
53001     BearingComponent.componentName = "bearing";
53002
53003     class CacheComponent extends Component {
53004         /** @ignore */
53005         constructor(name, container, navigator) {
53006             super(name, container, navigator);
53007         }
53008         _activate() {
53009             const subs = this._subscriptions;
53010             subs.push(combineLatest(this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
53011                 return image.sequenceEdges$;
53012             }), filter((status) => {
53013                 return status.cached;
53014             })), this._configuration$).pipe(switchMap((nc) => {
53015                 let status = nc[0];
53016                 let configuration = nc[1];
53017                 let sequenceDepth = Math.max(0, Math.min(4, configuration.depth.sequence));
53018                 let next$ = this._cache$(status.edges, exports.NavigationDirection.Next, sequenceDepth);
53019                 let prev$ = this._cache$(status.edges, exports.NavigationDirection.Prev, sequenceDepth);
53020                 return merge(next$, prev$).pipe(catchError((error) => {
53021                     console.error("Failed to cache sequence edges.", error);
53022                     return empty();
53023                 }));
53024             }))
53025                 .subscribe(() => { }));
53026             subs.push(combineLatest(this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
53027                 return combineLatest(of(image), image.spatialEdges$.pipe(filter((status) => {
53028                     return status.cached;
53029                 })));
53030             })), this._configuration$).pipe(switchMap(([[image, edgeStatus], configuration]) => {
53031                 let edges = edgeStatus.edges;
53032                 let depth = configuration.depth;
53033                 let sphericalDepth = Math.max(0, Math.min(2, depth.spherical));
53034                 let stepDepth = isSpherical(image.cameraType) ?
53035                     0 : Math.max(0, Math.min(3, depth.step));
53036                 let turnDepth = isSpherical(image.cameraType) ?
53037                     0 : Math.max(0, Math.min(1, depth.turn));
53038                 let spherical$ = this._cache$(edges, exports.NavigationDirection.Spherical, sphericalDepth);
53039                 let forward$ = this._cache$(edges, exports.NavigationDirection.StepForward, stepDepth);
53040                 let backward$ = this._cache$(edges, exports.NavigationDirection.StepBackward, stepDepth);
53041                 let left$ = this._cache$(edges, exports.NavigationDirection.StepLeft, stepDepth);
53042                 let right$ = this._cache$(edges, exports.NavigationDirection.StepRight, stepDepth);
53043                 let turnLeft$ = this._cache$(edges, exports.NavigationDirection.TurnLeft, turnDepth);
53044                 let turnRight$ = this._cache$(edges, exports.NavigationDirection.TurnRight, turnDepth);
53045                 let turnU$ = this._cache$(edges, exports.NavigationDirection.TurnU, turnDepth);
53046                 return merge(forward$, backward$, left$, right$, spherical$, turnLeft$, turnRight$, turnU$).pipe(catchError((error) => {
53047                     console.error("Failed to cache spatial edges.", error);
53048                     return empty();
53049                 }));
53050             }))
53051                 .subscribe(() => { }));
53052         }
53053         _deactivate() {
53054             this._subscriptions.unsubscribe();
53055         }
53056         _getDefaultConfiguration() {
53057             return { depth: { spherical: 1, sequence: 2, step: 1, turn: 0 } };
53058         }
53059         _cache$(edges, direction, depth) {
53060             return zip(of(edges), of(depth)).pipe(expand((ed) => {
53061                 let es = ed[0];
53062                 let d = ed[1];
53063                 let edgesDepths$ = [];
53064                 if (d > 0) {
53065                     for (let edge of es) {
53066                         if (edge.data.direction === direction) {
53067                             edgesDepths$.push(zip(this._navigator.graphService.cacheImage$(edge.target).pipe(mergeMap((n) => {
53068                                 return this._imageToEdges$(n, direction);
53069                             })), of(d - 1)));
53070                         }
53071                     }
53072                 }
53073                 return from(edgesDepths$).pipe(mergeAll());
53074             }), skip(1));
53075         }
53076         _imageToEdges$(image, direction) {
53077             return ([exports.NavigationDirection.Next, exports.NavigationDirection.Prev].indexOf(direction) > -1 ?
53078                 image.sequenceEdges$ :
53079                 image.spatialEdges$).pipe(first((status) => {
53080                 return status.cached;
53081             }), map((status) => {
53082                 return status.edges;
53083             }));
53084         }
53085     }
53086     CacheComponent.componentName = "cache";
53087
53088     /**
53089      * @class CancelMapillaryError
53090      *
53091      * @classdesc Error thrown when a move to request has been
53092      * cancelled before completing because of a subsequent request.
53093      */
53094     class CancelMapillaryError extends MapillaryError {
53095         constructor(message) {
53096             super(message != null ? message : "The request was cancelled.");
53097             Object.setPrototypeOf(this, CancelMapillaryError.prototype);
53098             this.name = "CancelMapillaryError";
53099         }
53100     }
53101
53102     /**
53103      * @class DirectionDOMCalculator
53104      * @classdesc Helper class for calculating DOM CSS properties.
53105      */
53106     class DirectionDOMCalculator {
53107         constructor(configuration, size) {
53108             this._spatial = new Spatial();
53109             this._minThresholdWidth = 320;
53110             this._maxThresholdWidth = 1480;
53111             this._minThresholdHeight = 240;
53112             this._maxThresholdHeight = 820;
53113             this._configure(configuration);
53114             this._resize(size);
53115             this._reset();
53116         }
53117         get minWidth() {
53118             return this._minWidth;
53119         }
53120         get maxWidth() {
53121             return this._maxWidth;
53122         }
53123         get containerWidth() {
53124             return this._containerWidth;
53125         }
53126         get containerWidthCss() {
53127             return this._containerWidthCss;
53128         }
53129         get containerMarginCss() {
53130             return this._containerMarginCss;
53131         }
53132         get containerLeftCss() {
53133             return this._containerLeftCss;
53134         }
53135         get containerHeight() {
53136             return this._containerHeight;
53137         }
53138         get containerHeightCss() {
53139             return this._containerHeightCss;
53140         }
53141         get containerBottomCss() {
53142             return this._containerBottomCss;
53143         }
53144         get stepCircleSize() {
53145             return this._stepCircleSize;
53146         }
53147         get stepCircleSizeCss() {
53148             return this._stepCircleSizeCss;
53149         }
53150         get stepCircleMarginCss() {
53151             return this._stepCircleMarginCss;
53152         }
53153         get turnCircleSize() {
53154             return this._turnCircleSize;
53155         }
53156         get turnCircleSizeCss() {
53157             return this._turnCircleSizeCss;
53158         }
53159         get outerRadius() {
53160             return this._outerRadius;
53161         }
53162         get innerRadius() {
53163             return this._innerRadius;
53164         }
53165         get shadowOffset() {
53166             return this._shadowOffset;
53167         }
53168         /**
53169          * Configures the min and max width values.
53170          *
53171          * @param {DirectionConfiguration} configuration Configuration
53172          * with min and max width values.
53173          */
53174         configure(configuration) {
53175             this._configure(configuration);
53176             this._reset();
53177         }
53178         /**
53179          * Resizes all properties according to the width and height
53180          * of the size object.
53181          *
53182          * @param {ViewportSize} size The size of the container element.
53183          */
53184         resize(size) {
53185             this._resize(size);
53186             this._reset();
53187         }
53188         /**
53189          * Calculates the coordinates on the unit circle for an angle.
53190          *
53191          * @param {number} angle Angle in radians.
53192          * @returns {Array<number>} The x and y coordinates on the unit circle.
53193          */
53194         angleToCoordinates(angle) {
53195             return [Math.cos(angle), Math.sin(angle)];
53196         }
53197         /**
53198          * Calculates the coordinates on the unit circle for the
53199          * relative angle between the first and second angle.
53200          *
53201          * @param {number} first Angle in radians.
53202          * @param {number} second Angle in radians.
53203          * @returns {Array<number>} The x and y coordinates on the unit circle
53204          * for the relative angle between the first and second angle.
53205          */
53206         relativeAngleToCoordiantes(first, second) {
53207             let relativeAngle = this._spatial.wrapAngle(first - second);
53208             return this.angleToCoordinates(relativeAngle);
53209         }
53210         _configure(configuration) {
53211             this._minWidth = configuration.minWidth;
53212             this._maxWidth = this._getMaxWidth(configuration.minWidth, configuration.maxWidth);
53213         }
53214         _resize(size) {
53215             this._elementWidth = size.width;
53216             this._elementHeight = size.height;
53217         }
53218         _reset() {
53219             this._containerWidth = this._getContainerWidth(this._elementWidth, this._elementHeight);
53220             this._containerHeight = this._getContainerHeight(this.containerWidth);
53221             this._stepCircleSize = this._getStepCircleDiameter(this._containerHeight);
53222             this._turnCircleSize = this._getTurnCircleDiameter(this.containerHeight);
53223             this._outerRadius = this._getOuterRadius(this._containerHeight);
53224             this._innerRadius = this._getInnerRadius(this._containerHeight);
53225             this._shadowOffset = 3;
53226             this._containerWidthCss = this._numberToCssPixels(this._containerWidth);
53227             this._containerMarginCss = this._numberToCssPixels(-0.5 * this._containerWidth);
53228             this._containerLeftCss = this._numberToCssPixels(Math.floor(0.5 * this._elementWidth));
53229             this._containerHeightCss = this._numberToCssPixels(this._containerHeight);
53230             this._containerBottomCss = this._numberToCssPixels(Math.floor(-0.08 * this._containerHeight));
53231             this._stepCircleSizeCss = this._numberToCssPixels(this._stepCircleSize);
53232             this._stepCircleMarginCss = this._numberToCssPixels(-0.5 * this._stepCircleSize);
53233             this._turnCircleSizeCss = this._numberToCssPixels(this._turnCircleSize);
53234         }
53235         _getContainerWidth(elementWidth, elementHeight) {
53236             let relativeWidth = (elementWidth - this._minThresholdWidth) / (this._maxThresholdWidth - this._minThresholdWidth);
53237             let relativeHeight = (elementHeight - this._minThresholdHeight) / (this._maxThresholdHeight - this._minThresholdHeight);
53238             let coeff = Math.max(0, Math.min(1, Math.min(relativeWidth, relativeHeight)));
53239             coeff = 0.04 * Math.round(25 * coeff);
53240             return this._minWidth + coeff * (this._maxWidth - this._minWidth);
53241         }
53242         _getContainerHeight(containerWidth) {
53243             return 0.77 * containerWidth;
53244         }
53245         _getStepCircleDiameter(containerHeight) {
53246             return 0.34 * containerHeight;
53247         }
53248         _getTurnCircleDiameter(containerHeight) {
53249             return 0.3 * containerHeight;
53250         }
53251         _getOuterRadius(containerHeight) {
53252             return 0.31 * containerHeight;
53253         }
53254         _getInnerRadius(containerHeight) {
53255             return 0.125 * containerHeight;
53256         }
53257         _numberToCssPixels(value) {
53258             return value + "px";
53259         }
53260         _getMaxWidth(value, minWidth) {
53261             return value > minWidth ? value : minWidth;
53262         }
53263     }
53264
53265     /**
53266      * @class DirectionDOMRenderer
53267      * @classdesc DOM renderer for direction arrows.
53268      */
53269     class DirectionDOMRenderer {
53270         constructor(configuration, size) {
53271             this._isEdge = false;
53272             this._spatial = new Spatial();
53273             this._calculator = new DirectionDOMCalculator(configuration, size);
53274             this._image = null;
53275             this._rotation = { phi: 0, theta: 0 };
53276             this._epsilon = 0.5 * Math.PI / 180;
53277             this._highlightKey = null;
53278             this._distinguishSequence = false;
53279             this._needsRender = false;
53280             this._stepEdges = [];
53281             this._turnEdges = [];
53282             this._sphericalEdges = [];
53283             this._sequenceEdgeKeys = [];
53284             this._stepDirections = [
53285                 exports.NavigationDirection.StepForward,
53286                 exports.NavigationDirection.StepBackward,
53287                 exports.NavigationDirection.StepLeft,
53288                 exports.NavigationDirection.StepRight,
53289             ];
53290             this._turnDirections = [
53291                 exports.NavigationDirection.TurnLeft,
53292                 exports.NavigationDirection.TurnRight,
53293                 exports.NavigationDirection.TurnU,
53294             ];
53295             this._turnNames = {};
53296             this._turnNames[exports.NavigationDirection.TurnLeft] = "mapillary-direction-turn-left";
53297             this._turnNames[exports.NavigationDirection.TurnRight] = "mapillary-direction-turn-right";
53298             this._turnNames[exports.NavigationDirection.TurnU] = "mapillary-direction-turn-around";
53299             // detects IE 8-11, then Edge 20+.
53300             let isIE = !!document.documentMode;
53301             this._isEdge = !isIE && !!window.StyleMedia;
53302         }
53303         /**
53304          * Get needs render.
53305          *
53306          * @returns {boolean} Value indicating whether render should be called.
53307          */
53308         get needsRender() {
53309             return this._needsRender;
53310         }
53311         /**
53312          * Renders virtual DOM elements.
53313          *
53314          * @description Calling render resets the needs render property.
53315          */
53316         render(navigator) {
53317             this._needsRender = false;
53318             let rotation = this._rotation;
53319             let steps = [];
53320             let turns = [];
53321             if (isSpherical(this._image.cameraType)) {
53322                 steps = steps.concat(this._createSphericalArrows(navigator, rotation));
53323             }
53324             else {
53325                 steps = steps.concat(this._createPerspectiveToSphericalArrows(navigator, rotation));
53326                 steps = steps.concat(this._createStepArrows(navigator, rotation));
53327                 turns = turns.concat(this._createTurnArrows(navigator));
53328             }
53329             return this._getContainer(steps, turns, rotation);
53330         }
53331         setEdges(edgeStatus, sequence) {
53332             this._setEdges(edgeStatus, sequence);
53333             this._setNeedsRender();
53334         }
53335         /**
53336          * Set image for which to show edges.
53337          *
53338          * @param {Image} image
53339          */
53340         setImage(image) {
53341             this._image = image;
53342             this._clearEdges();
53343             this._setNeedsRender();
53344         }
53345         /**
53346          * Set the render camera to use for calculating rotations.
53347          *
53348          * @param {RenderCamera} renderCamera
53349          */
53350         setRenderCamera(renderCamera) {
53351             let rotation = renderCamera.rotation;
53352             if (Math.abs(rotation.phi - this._rotation.phi) < this._epsilon) {
53353                 return;
53354             }
53355             this._rotation = rotation;
53356             this._setNeedsRender();
53357         }
53358         /**
53359          * Set configuration values.
53360          *
53361          * @param {DirectionConfiguration} configuration
53362          */
53363         setConfiguration(configuration) {
53364             let needsRender = false;
53365             if (this._highlightKey !== configuration.highlightId ||
53366                 this._distinguishSequence !== configuration.distinguishSequence) {
53367                 this._highlightKey = configuration.highlightId;
53368                 this._distinguishSequence = configuration.distinguishSequence;
53369                 needsRender = true;
53370             }
53371             if (this._calculator.minWidth !== configuration.minWidth ||
53372                 this._calculator.maxWidth !== configuration.maxWidth) {
53373                 this._calculator.configure(configuration);
53374                 needsRender = true;
53375             }
53376             if (needsRender) {
53377                 this._setNeedsRender();
53378             }
53379         }
53380         /**
53381          * Detect the element's width and height and resize
53382          * elements accordingly.
53383          *
53384          * @param {ViewportSize} size Size of vßiewer container element.
53385          */
53386         resize(size) {
53387             this._calculator.resize(size);
53388             this._setNeedsRender();
53389         }
53390         _setNeedsRender() {
53391             if (this._image != null) {
53392                 this._needsRender = true;
53393             }
53394         }
53395         _clearEdges() {
53396             this._stepEdges = [];
53397             this._turnEdges = [];
53398             this._sphericalEdges = [];
53399             this._sequenceEdgeKeys = [];
53400         }
53401         _setEdges(edgeStatus, sequence) {
53402             this._stepEdges = [];
53403             this._turnEdges = [];
53404             this._sphericalEdges = [];
53405             this._sequenceEdgeKeys = [];
53406             for (let edge of edgeStatus.edges) {
53407                 let direction = edge.data.direction;
53408                 if (this._stepDirections.indexOf(direction) > -1) {
53409                     this._stepEdges.push(edge);
53410                     continue;
53411                 }
53412                 if (this._turnDirections.indexOf(direction) > -1) {
53413                     this._turnEdges.push(edge);
53414                     continue;
53415                 }
53416                 if (edge.data.direction === exports.NavigationDirection.Spherical) {
53417                     this._sphericalEdges.push(edge);
53418                 }
53419             }
53420             if (this._distinguishSequence && sequence != null) {
53421                 let edges = this._sphericalEdges
53422                     .concat(this._stepEdges)
53423                     .concat(this._turnEdges);
53424                 for (let edge of edges) {
53425                     let edgeKey = edge.target;
53426                     for (let sequenceKey of sequence.imageIds) {
53427                         if (sequenceKey === edgeKey) {
53428                             this._sequenceEdgeKeys.push(edgeKey);
53429                             break;
53430                         }
53431                     }
53432                 }
53433             }
53434         }
53435         _createSphericalArrows(navigator, rotation) {
53436             let arrows = [];
53437             for (let sphericalEdge of this._sphericalEdges) {
53438                 arrows.push(this._createVNodeByKey(navigator, sphericalEdge.target, sphericalEdge.data.worldMotionAzimuth, rotation, this._calculator.outerRadius, "mapillary-direction-arrow-spherical"));
53439             }
53440             for (let stepEdge of this._stepEdges) {
53441                 arrows.push(this._createSphericalToPerspectiveArrow(navigator, stepEdge.target, stepEdge.data.worldMotionAzimuth, rotation, stepEdge.data.direction));
53442             }
53443             return arrows;
53444         }
53445         _createSphericalToPerspectiveArrow(navigator, key, azimuth, rotation, direction) {
53446             let threshold = Math.PI / 8;
53447             let relativePhi = rotation.phi;
53448             switch (direction) {
53449                 case exports.NavigationDirection.StepBackward:
53450                     relativePhi = rotation.phi - Math.PI;
53451                     break;
53452                 case exports.NavigationDirection.StepLeft:
53453                     relativePhi = rotation.phi + Math.PI / 2;
53454                     break;
53455                 case exports.NavigationDirection.StepRight:
53456                     relativePhi = rotation.phi - Math.PI / 2;
53457                     break;
53458             }
53459             if (Math.abs(this._spatial.wrapAngle(azimuth - relativePhi)) < threshold) {
53460                 return this._createVNodeByKey(navigator, key, azimuth, rotation, this._calculator.outerRadius, "mapillary-direction-arrow-step");
53461             }
53462             return this._createVNodeInactive(key, azimuth, rotation);
53463         }
53464         _createPerspectiveToSphericalArrows(navigator, rotation) {
53465             let arrows = [];
53466             for (let sphericalEdge of this._sphericalEdges) {
53467                 arrows.push(this._createVNodeByKey(navigator, sphericalEdge.target, sphericalEdge.data.worldMotionAzimuth, rotation, this._calculator.innerRadius, "mapillary-direction-arrow-spherical", true));
53468             }
53469             return arrows;
53470         }
53471         _createStepArrows(navigator, rotation) {
53472             let arrows = [];
53473             for (let stepEdge of this._stepEdges) {
53474                 arrows.push(this._createVNodeByDirection(navigator, stepEdge.target, stepEdge.data.worldMotionAzimuth, rotation, stepEdge.data.direction));
53475             }
53476             return arrows;
53477         }
53478         _createTurnArrows(navigator) {
53479             let turns = [];
53480             for (let turnEdge of this._turnEdges) {
53481                 let direction = turnEdge.data.direction;
53482                 let name = this._turnNames[direction];
53483                 turns.push(this._createVNodeByTurn(navigator, turnEdge.target, name, direction));
53484             }
53485             return turns;
53486         }
53487         _createVNodeByKey(navigator, key, azimuth, rotation, offset, className, shiftVertically) {
53488             let onClick = (e) => {
53489                 navigator.moveTo$(key)
53490                     .subscribe(undefined, (error) => {
53491                     if (!(error instanceof CancelMapillaryError)) {
53492                         console.error(error);
53493                     }
53494                 });
53495             };
53496             return this._createVNode(key, azimuth, rotation, offset, className, "mapillary-direction-circle", onClick, shiftVertically);
53497         }
53498         _createVNodeByDirection(navigator, key, azimuth, rotation, direction) {
53499             let onClick = (e) => {
53500                 navigator.moveDir$(direction)
53501                     .subscribe(undefined, (error) => {
53502                     if (!(error instanceof CancelMapillaryError)) {
53503                         console.error(error);
53504                     }
53505                 });
53506             };
53507             return this._createVNode(key, azimuth, rotation, this._calculator.outerRadius, "mapillary-direction-arrow-step", "mapillary-direction-circle", onClick);
53508         }
53509         _createVNodeByTurn(navigator, key, className, direction) {
53510             let onClick = (e) => {
53511                 navigator.moveDir$(direction)
53512                     .subscribe(undefined, (error) => {
53513                     if (!(error instanceof CancelMapillaryError)) {
53514                         console.error(error);
53515                     }
53516                 });
53517             };
53518             let style = {
53519                 height: this._calculator.turnCircleSizeCss,
53520                 transform: "rotate(0)",
53521                 width: this._calculator.turnCircleSizeCss,
53522             };
53523             switch (direction) {
53524                 case exports.NavigationDirection.TurnLeft:
53525                     style.left = "5px";
53526                     style.top = "5px";
53527                     break;
53528                 case exports.NavigationDirection.TurnRight:
53529                     style.right = "5px";
53530                     style.top = "5px";
53531                     break;
53532                 case exports.NavigationDirection.TurnU:
53533                     style.left = "5px";
53534                     style.bottom = "5px";
53535                     break;
53536             }
53537             let circleProperties = {
53538                 attributes: {
53539                     "data-id": key,
53540                 },
53541                 onclick: onClick,
53542                 style: style,
53543             };
53544             let circleClassName = "mapillary-direction-turn-circle";
53545             if (this._sequenceEdgeKeys.indexOf(key) > -1) {
53546                 circleClassName += "-sequence";
53547             }
53548             if (this._highlightKey === key) {
53549                 circleClassName += "-highlight";
53550             }
53551             let turn = virtualDom.h(`div.${className}`, {}, []);
53552             return virtualDom.h("div." + circleClassName, circleProperties, [turn]);
53553         }
53554         _createVNodeInactive(key, azimuth, rotation) {
53555             return this._createVNode(key, azimuth, rotation, this._calculator.outerRadius, "mapillary-direction-arrow-inactive", "mapillary-direction-circle-inactive");
53556         }
53557         _createVNode(key, azimuth, rotation, radius, className, circleClassName, onClick, shiftVertically) {
53558             let translation = this._calculator.angleToCoordinates(azimuth - rotation.phi);
53559             // rotate 90 degrees clockwise and flip over X-axis
53560             let translationX = Math.round(-radius * translation[1] + 0.5 * this._calculator.containerWidth);
53561             let translationY = Math.round(-radius * translation[0] + 0.5 * this._calculator.containerHeight);
53562             let shadowTranslation = this._calculator.relativeAngleToCoordiantes(azimuth, rotation.phi);
53563             let shadowOffset = this._calculator.shadowOffset;
53564             let shadowTranslationX = -shadowOffset * shadowTranslation[1];
53565             let shadowTranslationY = shadowOffset * shadowTranslation[0];
53566             let filter = `drop-shadow(${shadowTranslationX}px ${shadowTranslationY}px 1px rgba(0,0,0,0.8))`;
53567             let properties = {
53568                 style: {
53569                     "-webkit-filter": filter,
53570                     filter: filter,
53571                 },
53572             };
53573             let chevron = virtualDom.h("div." + className, properties, []);
53574             let azimuthDeg = -this._spatial.radToDeg(azimuth - rotation.phi);
53575             let circleTransform = shiftVertically ?
53576                 `translate(${translationX}px, ${translationY}px) rotate(${azimuthDeg}deg) translateZ(-0.01px)` :
53577                 `translate(${translationX}px, ${translationY}px) rotate(${azimuthDeg}deg)`;
53578             let circleProperties = {
53579                 attributes: { "data-id": key },
53580                 onclick: onClick,
53581                 style: {
53582                     height: this._calculator.stepCircleSizeCss,
53583                     marginLeft: this._calculator.stepCircleMarginCss,
53584                     marginTop: this._calculator.stepCircleMarginCss,
53585                     transform: circleTransform,
53586                     width: this._calculator.stepCircleSizeCss,
53587                 },
53588             };
53589             if (this._sequenceEdgeKeys.indexOf(key) > -1) {
53590                 circleClassName += "-sequence";
53591             }
53592             if (this._highlightKey === key) {
53593                 circleClassName += "-highlight";
53594             }
53595             return virtualDom.h("div." + circleClassName, circleProperties, [chevron]);
53596         }
53597         _getContainer(steps, turns, rotation) {
53598             // edge does not handle hover on perspective transforms.
53599             let transform = this._isEdge ?
53600                 "rotateX(60deg)" :
53601                 `perspective(${this._calculator.containerWidthCss}) rotateX(60deg)`;
53602             let properties = {
53603                 oncontextmenu: (event) => { event.preventDefault(); },
53604                 style: {
53605                     bottom: this._calculator.containerBottomCss,
53606                     height: this._calculator.containerHeightCss,
53607                     left: this._calculator.containerLeftCss,
53608                     marginLeft: this._calculator.containerMarginCss,
53609                     transform: transform,
53610                     width: this._calculator.containerWidthCss,
53611                 },
53612             };
53613             return virtualDom.h("div.mapillary-direction-perspective", properties, turns.concat(steps));
53614         }
53615     }
53616
53617     /**
53618      * @class DirectionComponent
53619      * @classdesc Component showing navigation arrows for steps and turns.
53620      */
53621     class DirectionComponent extends Component {
53622         /** @ignore */
53623         constructor(name, container, navigator, directionDOMRenderer) {
53624             super(name, container, navigator);
53625             this._renderer = !!directionDOMRenderer ?
53626                 directionDOMRenderer :
53627                 new DirectionDOMRenderer(this.defaultConfiguration, { height: container.container.offsetHeight, width: container.container.offsetWidth });
53628             this._hoveredIdSubject$ = new Subject();
53629             this._hoveredId$ = this._hoveredIdSubject$.pipe(share());
53630         }
53631         fire(type, event) {
53632             super.fire(type, event);
53633         }
53634         off(type, handler) {
53635             super.off(type, handler);
53636         }
53637         on(type, handler) {
53638             super.on(type, handler);
53639         }
53640         _activate() {
53641             const subs = this._subscriptions;
53642             subs.push(this._configuration$
53643                 .subscribe((configuration) => {
53644                 this._renderer.setConfiguration(configuration);
53645             }));
53646             subs.push(this._container.renderService.size$
53647                 .subscribe((size) => {
53648                 this._renderer.resize(size);
53649             }));
53650             subs.push(this._navigator.stateService.currentImage$.pipe(tap((image) => {
53651                 this._container.domRenderer.render$.next({ name: this._name, vNode: virtualDom.h("div", {}, []) });
53652                 this._renderer.setImage(image);
53653             }), withLatestFrom(this._configuration$), switchMap(([image, configuration]) => {
53654                 return combineLatest(image.spatialEdges$, configuration.distinguishSequence ?
53655                     this._navigator.graphService
53656                         .cacheSequence$(image.sequenceId).pipe(catchError((error) => {
53657                         console.error(`Failed to cache sequence (${image.sequenceId})`, error);
53658                         return of(null);
53659                     })) :
53660                     of(null));
53661             }))
53662                 .subscribe(([edgeStatus, sequence]) => {
53663                 this._renderer.setEdges(edgeStatus, sequence);
53664             }));
53665             subs.push(this._container.renderService.renderCameraFrame$.pipe(tap((renderCamera) => {
53666                 this._renderer.setRenderCamera(renderCamera);
53667             }), map(() => {
53668                 return this._renderer;
53669             }), filter((renderer) => {
53670                 return renderer.needsRender;
53671             }), map((renderer) => {
53672                 return { name: this._name, vNode: renderer.render(this._navigator) };
53673             }))
53674                 .subscribe(this._container.domRenderer.render$));
53675             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]) => {
53676                 let elements = element.getElementsByClassName("mapillary-direction-perspective");
53677                 for (let i = 0; i < elements.length; i++) {
53678                     let hovered = elements.item(i).querySelector(":hover");
53679                     if (hovered != null && hovered.hasAttribute("data-id")) {
53680                         return hovered.getAttribute("data-id");
53681                     }
53682                 }
53683                 return null;
53684             }), distinctUntilChanged())
53685                 .subscribe(this._hoveredIdSubject$));
53686             subs.push(this._hoveredId$
53687                 .subscribe((id) => {
53688                 const type = "hover";
53689                 const event = {
53690                     id,
53691                     target: this,
53692                     type,
53693                 };
53694                 this.fire(type, event);
53695             }));
53696         }
53697         _deactivate() {
53698             this._subscriptions.unsubscribe();
53699         }
53700         _getDefaultConfiguration() {
53701             return {
53702                 distinguishSequence: false,
53703                 maxWidth: 460,
53704                 minWidth: 260,
53705             };
53706         }
53707     }
53708     /** @inheritdoc */
53709     DirectionComponent.componentName = "direction";
53710
53711     const sphericalFrag = `
53712 #ifdef GL_FRAGMENT_PRECISION_HIGH
53713 precision highp float;
53714 #else
53715 precision mediump float;
53716 #endif
53717
53718 #define tau 6.28318530718
53719
53720 uniform sampler2D projectorTex;
53721 uniform float opacity;
53722
53723 varying vec4 vRstq;
53724
53725 void main()
53726 {
53727     vec3 b = normalize(vRstq.xyz);
53728     float lat = -asin(b.y);
53729     float lng = atan(b.x, b.z);
53730     float x = lng / tau + 0.5;
53731     float y = lat / tau * 2.0 + 0.5;
53732     vec4 baseColor = texture2D(projectorTex, vec2(x, y));
53733     baseColor.a = opacity;
53734     gl_FragColor = baseColor;
53735 }
53736 `;
53737
53738     const sphericalVert = `
53739 #ifdef GL_ES
53740 precision highp float;
53741 #endif
53742
53743 uniform mat4 projectorMat;
53744
53745 varying vec4 vRstq;
53746
53747 void main()
53748 {
53749     vRstq = projectorMat * vec4(position, 1.0);
53750     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
53751 }
53752 `;
53753
53754     const sphericalCurtainFrag = `
53755 #ifdef GL_FRAGMENT_PRECISION_HIGH
53756 precision highp float;
53757 #else
53758 precision mediump float;
53759 #endif
53760
53761 #define tau 6.28318530718
53762
53763 uniform sampler2D projectorTex;
53764 uniform float curtain;
53765 uniform float opacity;
53766
53767 varying vec4 vRstq;
53768
53769 void main()
53770 {
53771     vec3 b = normalize(vRstq.xyz);
53772     float lat = -asin(b.y);
53773     float lng = atan(b.x, b.z);
53774     float x = lng / tau + 0.5;
53775     float y = lat / tau * 2.0 + 0.5;
53776
53777     bool inverted = curtain < 0.5;
53778
53779     float curtainMin = inverted ? curtain + 0.5 : curtain - 0.5;
53780     float curtainMax = curtain;
53781
53782     bool insideCurtain = inverted ?
53783         x > curtainMin || x < curtainMax :
53784         x > curtainMin && x < curtainMax;
53785
53786     vec4 baseColor;
53787     if (insideCurtain) {
53788         baseColor = texture2D(projectorTex, vec2(x, y));
53789         baseColor.a = opacity;
53790     } else {
53791         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
53792     }
53793
53794     gl_FragColor = baseColor;
53795 }
53796 `;
53797
53798     const sphericalCurtainVert = `
53799 #ifdef GL_ES
53800 precision highp float;
53801 #endif
53802
53803 uniform mat4 projectorMat;
53804
53805 varying vec4 vRstq;
53806
53807 void main()
53808 {
53809     vRstq = projectorMat * vec4(position, 1.0);
53810     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
53811 }
53812 `;
53813
53814     const fisheyeFrag = `
53815 #ifdef GL_FRAGMENT_PRECISION_HIGH
53816 precision highp float;
53817 #else
53818 precision mediump float;
53819 #endif
53820
53821 uniform sampler2D projectorTex;
53822 uniform float opacity;
53823 uniform float focal;
53824 uniform float k1;
53825 uniform float k2;
53826 uniform float scale_x;
53827 uniform float scale_y;
53828 uniform float radial_peak;
53829
53830 varying vec4 vRstq;
53831
53832 void main()
53833 {
53834     float x = vRstq.x;
53835     float y = vRstq.y;
53836     float z = vRstq.z;
53837
53838     float r = sqrt(x * x + y * y);
53839     float theta = atan(r, z);
53840
53841     if (radial_peak > 0. && theta > radial_peak) {
53842         theta = radial_peak;
53843     }
53844
53845     float theta2 = theta * theta;
53846     float theta_d = theta * (1.0 + theta2 * (k1 + theta2 * k2));
53847     float s = focal * theta_d / r;
53848
53849     float u = scale_x * s * x + 0.5;
53850     float v = -scale_y * s * y + 0.5;
53851
53852     vec4 baseColor;
53853     if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
53854         baseColor = texture2D(projectorTex, vec2(u, v));
53855         baseColor.a = opacity;
53856     } else {
53857         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
53858     }
53859
53860     gl_FragColor = baseColor;
53861 }
53862 `;
53863
53864     const fisheyeVert = `
53865 #ifdef GL_ES
53866 precision highp float;
53867 #endif
53868
53869 uniform mat4 projectorMat;
53870
53871 varying vec4 vRstq;
53872
53873 void main()
53874 {
53875     vRstq = projectorMat * vec4(position, 1.0);
53876     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
53877 }
53878 `;
53879
53880     const fisheyeCurtainFrag = `
53881 #ifdef GL_FRAGMENT_PRECISION_HIGH
53882 precision highp float;
53883 #else
53884 precision mediump float;
53885 #endif
53886
53887 uniform sampler2D projectorTex;
53888 uniform float opacity;
53889 uniform float focal;
53890 uniform float k1;
53891 uniform float k2;
53892 uniform float scale_x;
53893 uniform float scale_y;
53894 uniform float radial_peak;
53895 uniform float curtain;
53896
53897 varying vec4 vRstq;
53898
53899 void main()
53900 {
53901     float x = vRstq.x;
53902     float y = vRstq.y;
53903     float z = vRstq.z;
53904
53905     float r2 = sqrt(x * x + y * y);
53906     float theta = atan(r2, z);
53907
53908     if (radial_peak > 0. && theta > radial_peak) {
53909         theta = radial_peak;
53910     }
53911
53912     float theta2 = theta * theta;
53913     float theta_d = theta * (1.0 + theta2 * (k1 + theta2 * k2));
53914     float s = focal * theta_d / r2;
53915
53916     float u = scale_x * s * x + 0.5;
53917     float v = -scale_y * s * y + 0.5;
53918
53919     vec4 baseColor;
53920     if ((u < curtain || curtain >= 1.0) && u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
53921         baseColor = texture2D(projectorTex, vec2(u, v));
53922         baseColor.a = opacity;
53923     } else {
53924         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
53925     }
53926
53927     gl_FragColor = baseColor;
53928 }
53929 `;
53930
53931     const fisheyeCurtainVert = `
53932 #ifdef GL_ES
53933 precision highp float;
53934 #endif
53935
53936 uniform mat4 projectorMat;
53937
53938 varying vec4 vRstq;
53939
53940 void main()
53941 {
53942     vRstq = projectorMat * vec4(position, 1.0);
53943     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
53944 }
53945 `;
53946
53947     const perspectiveFrag = `
53948 #ifdef GL_FRAGMENT_PRECISION_HIGH
53949 precision highp float;
53950 #else
53951 precision mediump float;
53952 #endif
53953
53954 uniform sampler2D projectorTex;
53955 uniform float opacity;
53956 uniform float focal;
53957 uniform float k1;
53958 uniform float k2;
53959 uniform float scale_x;
53960 uniform float scale_y;
53961 uniform float radial_peak;
53962
53963 varying vec4 vRstq;
53964
53965 void main()
53966 {
53967     float x = vRstq.x / vRstq.z;
53968     float y = vRstq.y / vRstq.z;
53969     float r2 = x * x + y * y;
53970
53971     if (radial_peak > 0. && r2 > radial_peak * sqrt(r2)) {
53972         r2 = radial_peak * radial_peak;
53973     }
53974
53975     float d = 1.0 + k1 * r2 + k2 * r2 * r2;
53976     float u = scale_x * focal * d * x + 0.5;
53977     float v = - scale_y * focal * d * y + 0.5;
53978
53979     vec4 baseColor;
53980     if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
53981         baseColor = texture2D(projectorTex, vec2(u, v));
53982         baseColor.a = opacity;
53983     } else {
53984         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
53985     }
53986
53987     gl_FragColor = baseColor;
53988 }
53989 `;
53990
53991     const perspectiveVert = `
53992 #ifdef GL_ES
53993 precision highp float;
53994 #endif
53995
53996 uniform mat4 projectorMat;
53997
53998 varying vec4 vRstq;
53999
54000 void main()
54001 {
54002     vRstq = projectorMat * vec4(position, 1.0);
54003     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
54004 }
54005 `;
54006
54007     const perspectiveCurtainFrag = `
54008 #ifdef GL_FRAGMENT_PRECISION_HIGH
54009 precision highp float;
54010 #else
54011 precision mediump float;
54012 #endif
54013
54014 uniform sampler2D projectorTex;
54015 uniform float opacity;
54016 uniform float focal;
54017 uniform float k1;
54018 uniform float k2;
54019 uniform float scale_x;
54020 uniform float scale_y;
54021 uniform float radial_peak;
54022 uniform float curtain;
54023
54024 varying vec4 vRstq;
54025
54026 void main()
54027 {
54028     float x = vRstq.x / vRstq.z;
54029     float y = vRstq.y / vRstq.z;
54030     float r2 = x * x + y * y;
54031
54032     if (radial_peak > 0. && r2 > radial_peak * sqrt(r2)) {
54033         r2 = radial_peak * radial_peak;
54034     }
54035
54036     float d = 1.0 + k1 * r2 + k2 * r2 * r2;
54037     float u = scale_x * focal * d * x + 0.5;
54038     float v = - scale_y * focal * d * y + 0.5;
54039
54040     vec4 baseColor;
54041     if ((u < curtain || curtain >= 1.0) && u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
54042         baseColor = texture2D(projectorTex, vec2(u, v));
54043         baseColor.a = opacity;
54044     } else {
54045         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
54046     }
54047
54048     gl_FragColor = baseColor;
54049 }
54050 `;
54051
54052     const perspectiveCurtainVert = `
54053 #ifdef GL_ES
54054 precision highp float;
54055 #endif
54056
54057 uniform mat4 projectorMat;
54058
54059 varying vec4 vRstq;
54060
54061 void main()
54062 {
54063     vRstq = projectorMat * vec4(position, 1.0);
54064     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
54065 }
54066 `;
54067
54068     const perspectiveDistortedFrag = `
54069 #ifdef GL_FRAGMENT_PRECISION_HIGH
54070 precision highp float;
54071 #else
54072 precision mediump float;
54073 #endif
54074
54075 uniform sampler2D projectorTex;
54076 uniform float opacity;
54077
54078 varying vec4 vRstq;
54079
54080 void main()
54081 {
54082     float u = vRstq.x / vRstq.w;
54083     float v = vRstq.y / vRstq.w;
54084
54085     vec4 baseColor;
54086     if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
54087         baseColor = texture2D(projectorTex, vec2(u, v));
54088         baseColor.a = opacity;
54089     } else {
54090         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
54091     }
54092
54093     gl_FragColor = baseColor;
54094 }
54095 `;
54096
54097     const perspectiveDistortedVert = `
54098 #ifdef GL_ES
54099 precision highp float;
54100 #endif
54101
54102 uniform mat4 projectorMat;
54103
54104 varying vec4 vRstq;
54105
54106 void main()
54107 {
54108     vRstq = projectorMat * vec4(position, 1.0);
54109     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
54110 }
54111 `;
54112
54113     const perspectiveDistortedCurtainFrag = `
54114 #ifdef GL_FRAGMENT_PRECISION_HIGH
54115 precision highp float;
54116 #else
54117 precision mediump float;
54118 #endif
54119
54120 uniform sampler2D projectorTex;
54121 uniform float opacity;
54122 uniform float curtain;
54123
54124 varying vec4 vRstq;
54125
54126 void main()
54127 {
54128     float u = vRstq.x / vRstq.w;
54129     float v = vRstq.y / vRstq.w;
54130
54131     vec4 baseColor;
54132     if ((u < curtain || curtain >= 1.0) && u >= 0. && u <= 1. && v >= 0. && v <= 1.) {
54133         baseColor = texture2D(projectorTex, vec2(u, v));
54134         baseColor.a = opacity;
54135     } else {
54136         baseColor = vec4(0.0, 0.0, 0.0, 0.0);
54137     }
54138
54139     gl_FragColor = baseColor;
54140 }
54141 `;
54142
54143     const perspectiveDistortedCurtainVert = `
54144 #ifdef GL_ES
54145 precision highp float;
54146 #endif
54147
54148 uniform mat4 projectorMat;
54149
54150 varying vec4 vRstq;
54151
54152 void main()
54153 {
54154     vRstq = projectorMat * vec4(position, 1.0);
54155     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
54156 }
54157 `;
54158
54159     class Shaders {
54160     }
54161     Shaders.fisheye = {
54162         fragment: fisheyeFrag,
54163         vertex: fisheyeVert,
54164     };
54165     Shaders.fisheyeCurtain = {
54166         fragment: fisheyeCurtainFrag,
54167         vertex: fisheyeCurtainVert,
54168     };
54169     Shaders.perspective = {
54170         fragment: perspectiveFrag,
54171         vertex: perspectiveVert,
54172     };
54173     Shaders.perspectiveCurtain = {
54174         fragment: perspectiveCurtainFrag,
54175         vertex: perspectiveCurtainVert,
54176     };
54177     Shaders.perspectiveDistorted = {
54178         fragment: perspectiveDistortedFrag,
54179         vertex: perspectiveDistortedVert,
54180     };
54181     Shaders.perspectiveDistortedCurtain = {
54182         fragment: perspectiveDistortedCurtainFrag,
54183         vertex: perspectiveDistortedCurtainVert,
54184     };
54185     Shaders.spherical = {
54186         fragment: sphericalFrag,
54187         vertex: sphericalVert,
54188     };
54189     Shaders.sphericalCurtain = {
54190         fragment: sphericalCurtainFrag,
54191         vertex: sphericalCurtainVert,
54192     };
54193
54194     class MeshFactory {
54195         constructor(imagePlaneDepth, imageSphereRadius) {
54196             this._imagePlaneDepth = imagePlaneDepth != null ? imagePlaneDepth : 200;
54197             this._imageSphereRadius = imageSphereRadius != null ? imageSphereRadius : 200;
54198         }
54199         createMesh(image, transform) {
54200             if (isSpherical(transform.cameraType)) {
54201                 return this._createImageSphere(image, transform);
54202             }
54203             else if (isFisheye(transform.cameraType)) {
54204                 return this._createImagePlaneFisheye(image, transform);
54205             }
54206             else {
54207                 return this._createImagePlane(image, transform);
54208             }
54209         }
54210         createFlatMesh(image, transform, basicX0, basicX1, basicY0, basicY1) {
54211             let texture = this._createTexture(image.image);
54212             let materialParameters = this._createDistortedPlaneMaterialParameters(transform, texture);
54213             let material = new ShaderMaterial(materialParameters);
54214             let geometry = this._getFlatImagePlaneGeoFromBasic(transform, basicX0, basicX1, basicY0, basicY1);
54215             return new Mesh(geometry, material);
54216         }
54217         createCurtainMesh(image, transform) {
54218             if (isSpherical(transform.cameraType)) {
54219                 return this._createSphereCurtainMesh(image, transform);
54220             }
54221             else if (isFisheye(transform.cameraType)) {
54222                 return this._createCurtainMeshFisheye(image, transform);
54223             }
54224             else {
54225                 return this._createCurtainMesh(image, transform);
54226             }
54227         }
54228         createDistortedCurtainMesh(image, transform) {
54229             return this._createDistortedCurtainMesh(image, transform);
54230         }
54231         _createCurtainMesh(image, transform) {
54232             let texture = this._createTexture(image.image);
54233             let materialParameters = this._createCurtainPlaneMaterialParameters(transform, texture);
54234             let material = new ShaderMaterial(materialParameters);
54235             let geometry = this._useMesh(transform, image) ?
54236                 this._getImagePlaneGeo(transform, image) :
54237                 this._getRegularFlatImagePlaneGeo(transform);
54238             return new Mesh(geometry, material);
54239         }
54240         _createCurtainMeshFisheye(image, transform) {
54241             let texture = this._createTexture(image.image);
54242             let materialParameters = this._createCurtainPlaneMaterialParametersFisheye(transform, texture);
54243             let material = new ShaderMaterial(materialParameters);
54244             let geometry = this._useMesh(transform, image) ?
54245                 this._getImagePlaneGeoFisheye(transform, image) :
54246                 this._getRegularFlatImagePlaneGeo(transform);
54247             return new Mesh(geometry, material);
54248         }
54249         _createDistortedCurtainMesh(image, transform) {
54250             let texture = this._createTexture(image.image);
54251             let materialParameters = this._createDistortedCurtainPlaneMaterialParameters(transform, texture);
54252             let material = new ShaderMaterial(materialParameters);
54253             let geometry = this._getRegularFlatImagePlaneGeo(transform);
54254             return new Mesh(geometry, material);
54255         }
54256         _createSphereCurtainMesh(image, transform) {
54257             let texture = this._createTexture(image.image);
54258             let materialParameters = this._createCurtainSphereMaterialParameters(transform, texture);
54259             let material = new ShaderMaterial(materialParameters);
54260             return this._useMesh(transform, image) ?
54261                 new Mesh(this._getImageSphereGeo(transform, image), material) :
54262                 new Mesh(this._getFlatImageSphereGeo(transform), material);
54263         }
54264         _createImageSphere(image, transform) {
54265             let texture = this._createTexture(image.image);
54266             let materialParameters = this._createSphereMaterialParameters(transform, texture);
54267             let material = new ShaderMaterial(materialParameters);
54268             let mesh = this._useMesh(transform, image) ?
54269                 new Mesh(this._getImageSphereGeo(transform, image), material) :
54270                 new Mesh(this._getFlatImageSphereGeo(transform), material);
54271             return mesh;
54272         }
54273         _createImagePlane(image, transform) {
54274             let texture = this._createTexture(image.image);
54275             let materialParameters = this._createPlaneMaterialParameters(transform, texture);
54276             let material = new ShaderMaterial(materialParameters);
54277             let geometry = this._useMesh(transform, image) ?
54278                 this._getImagePlaneGeo(transform, image) :
54279                 this._getRegularFlatImagePlaneGeo(transform);
54280             return new Mesh(geometry, material);
54281         }
54282         _createImagePlaneFisheye(image, transform) {
54283             let texture = this._createTexture(image.image);
54284             let materialParameters = this._createPlaneMaterialParametersFisheye(transform, texture);
54285             let material = new ShaderMaterial(materialParameters);
54286             let geometry = this._useMesh(transform, image) ?
54287                 this._getImagePlaneGeoFisheye(transform, image) :
54288                 this._getRegularFlatImagePlaneGeoFisheye(transform);
54289             return new Mesh(geometry, material);
54290         }
54291         _createSphereMaterialParameters(transform, texture) {
54292             let materialParameters = {
54293                 depthWrite: false,
54294                 fragmentShader: Shaders.spherical.fragment,
54295                 side: DoubleSide,
54296                 transparent: true,
54297                 uniforms: {
54298                     opacity: { value: 1.0 },
54299                     projectorMat: { value: transform.rt },
54300                     projectorTex: { value: texture },
54301                 },
54302                 vertexShader: Shaders.spherical.vertex,
54303             };
54304             return materialParameters;
54305         }
54306         _createCurtainSphereMaterialParameters(transform, texture) {
54307             let materialParameters = {
54308                 depthWrite: false,
54309                 fragmentShader: Shaders.sphericalCurtain.fragment,
54310                 side: DoubleSide,
54311                 transparent: true,
54312                 uniforms: {
54313                     curtain: { value: 1.0 },
54314                     opacity: { value: 1.0 },
54315                     projectorMat: { value: transform.rt },
54316                     projectorTex: { value: texture },
54317                 },
54318                 vertexShader: Shaders.sphericalCurtain.vertex,
54319             };
54320             return materialParameters;
54321         }
54322         _createPlaneMaterialParameters(transform, texture) {
54323             let materialParameters = {
54324                 depthWrite: false,
54325                 fragmentShader: Shaders.perspective.fragment,
54326                 side: DoubleSide,
54327                 transparent: true,
54328                 uniforms: {
54329                     focal: { value: transform.focal },
54330                     k1: { value: transform.ck1 },
54331                     k2: { value: transform.ck2 },
54332                     opacity: { value: 1.0 },
54333                     projectorMat: { value: transform.basicRt },
54334                     projectorTex: { value: texture },
54335                     radial_peak: { value: !!transform.radialPeak ? transform.radialPeak : 0.0 },
54336                     scale_x: { value: Math.max(transform.basicHeight, transform.basicWidth) / transform.basicWidth },
54337                     scale_y: { value: Math.max(transform.basicWidth, transform.basicHeight) / transform.basicHeight },
54338                 },
54339                 vertexShader: Shaders.perspective.vertex,
54340             };
54341             return materialParameters;
54342         }
54343         _createPlaneMaterialParametersFisheye(transform, texture) {
54344             let materialParameters = {
54345                 depthWrite: false,
54346                 fragmentShader: Shaders.fisheye.fragment,
54347                 side: DoubleSide,
54348                 transparent: true,
54349                 uniforms: {
54350                     focal: { value: transform.focal },
54351                     k1: { value: transform.ck1 },
54352                     k2: { value: transform.ck2 },
54353                     opacity: { value: 1.0 },
54354                     projectorMat: { value: transform.basicRt },
54355                     projectorTex: { value: texture },
54356                     radial_peak: { value: !!transform.radialPeak ? transform.radialPeak : 0.0 },
54357                     scale_x: { value: Math.max(transform.basicHeight, transform.basicWidth) / transform.basicWidth },
54358                     scale_y: { value: Math.max(transform.basicWidth, transform.basicHeight) / transform.basicHeight },
54359                 },
54360                 vertexShader: Shaders.fisheye.vertex,
54361             };
54362             return materialParameters;
54363         }
54364         _createCurtainPlaneMaterialParametersFisheye(transform, texture) {
54365             let materialParameters = {
54366                 depthWrite: false,
54367                 fragmentShader: Shaders.fisheyeCurtain.fragment,
54368                 side: DoubleSide,
54369                 transparent: true,
54370                 uniforms: {
54371                     curtain: { value: 1.0 },
54372                     focal: { value: transform.focal },
54373                     k1: { value: transform.ck1 },
54374                     k2: { value: transform.ck2 },
54375                     opacity: { value: 1.0 },
54376                     projectorMat: { value: transform.basicRt },
54377                     projectorTex: { value: texture },
54378                     radial_peak: { value: !!transform.radialPeak ? transform.radialPeak : 0.0 },
54379                     scale_x: { value: Math.max(transform.basicHeight, transform.basicWidth) / transform.basicWidth },
54380                     scale_y: { value: Math.max(transform.basicWidth, transform.basicHeight) / transform.basicHeight },
54381                 },
54382                 vertexShader: Shaders.fisheyeCurtain.vertex,
54383             };
54384             return materialParameters;
54385         }
54386         _createCurtainPlaneMaterialParameters(transform, texture) {
54387             let materialParameters = {
54388                 depthWrite: false,
54389                 fragmentShader: Shaders.perspectiveCurtain.fragment,
54390                 side: DoubleSide,
54391                 transparent: true,
54392                 uniforms: {
54393                     curtain: { value: 1.0 },
54394                     focal: { value: transform.focal },
54395                     k1: { value: transform.ck1 },
54396                     k2: { value: transform.ck2 },
54397                     opacity: { value: 1.0 },
54398                     projectorMat: { value: transform.basicRt },
54399                     projectorTex: { value: texture },
54400                     radial_peak: { value: !!transform.radialPeak ? transform.radialPeak : 0.0 },
54401                     scale_x: { value: Math.max(transform.basicHeight, transform.basicWidth) / transform.basicWidth },
54402                     scale_y: { value: Math.max(transform.basicWidth, transform.basicHeight) / transform.basicHeight },
54403                 },
54404                 vertexShader: Shaders.perspectiveCurtain.vertex,
54405             };
54406             return materialParameters;
54407         }
54408         _createDistortedCurtainPlaneMaterialParameters(transform, texture) {
54409             let materialParameters = {
54410                 depthWrite: false,
54411                 fragmentShader: Shaders.perspectiveDistortedCurtain.fragment,
54412                 side: DoubleSide,
54413                 transparent: true,
54414                 uniforms: {
54415                     curtain: { value: 1.0 },
54416                     opacity: { value: 1.0 },
54417                     projectorMat: { value: transform.projectorMatrix() },
54418                     projectorTex: { value: texture },
54419                 },
54420                 vertexShader: Shaders.perspectiveDistortedCurtain.vertex,
54421             };
54422             return materialParameters;
54423         }
54424         _createDistortedPlaneMaterialParameters(transform, texture) {
54425             let materialParameters = {
54426                 depthWrite: false,
54427                 fragmentShader: Shaders.perspectiveDistorted.fragment,
54428                 side: DoubleSide,
54429                 transparent: true,
54430                 uniforms: {
54431                     opacity: { value: 1.0 },
54432                     projectorMat: { value: transform.projectorMatrix() },
54433                     projectorTex: { value: texture },
54434                 },
54435                 vertexShader: Shaders.perspectiveDistorted.vertex,
54436             };
54437             return materialParameters;
54438         }
54439         _createTexture(image) {
54440             let texture = new Texture(image);
54441             texture.minFilter = LinearFilter;
54442             texture.needsUpdate = true;
54443             return texture;
54444         }
54445         _useMesh(transform, image) {
54446             return image.mesh.vertices.length && transform.hasValidScale;
54447         }
54448         _getImageSphereGeo(transform, image) {
54449             const t = transform.srtInverse;
54450             // push everything at least 5 meters in front of the camera
54451             let minZ = 5.0 * transform.scale;
54452             let maxZ = this._imageSphereRadius * transform.scale;
54453             let vertices = image.mesh.vertices;
54454             let numVertices = vertices.length / 3;
54455             let positions = new Float32Array(vertices.length);
54456             for (let i = 0; i < numVertices; ++i) {
54457                 let index = 3 * i;
54458                 let x = vertices[index + 0];
54459                 let y = vertices[index + 1];
54460                 let z = vertices[index + 2];
54461                 let l = Math.sqrt(x * x + y * y + z * z);
54462                 let boundedL = Math.max(minZ, Math.min(l, maxZ));
54463                 let factor = boundedL / l;
54464                 let p = new Vector3(x * factor, y * factor, z * factor);
54465                 p.applyMatrix4(t);
54466                 positions[index + 0] = p.x;
54467                 positions[index + 1] = p.y;
54468                 positions[index + 2] = p.z;
54469             }
54470             let faces = image.mesh.faces;
54471             let indices = new Uint16Array(faces.length);
54472             for (let i = 0; i < faces.length; ++i) {
54473                 indices[i] = faces[i];
54474             }
54475             let geometry = new BufferGeometry();
54476             geometry.setAttribute("position", new BufferAttribute(positions, 3));
54477             geometry.setIndex(new BufferAttribute(indices, 1));
54478             return geometry;
54479         }
54480         _getImagePlaneGeo(transform, image) {
54481             const undistortionMarginFactor = 3;
54482             const t = transform.srtInverse;
54483             // push everything at least 5 meters in front of the camera
54484             let minZ = 5.0 * transform.scale;
54485             let maxZ = this._imagePlaneDepth * transform.scale;
54486             let vertices = image.mesh.vertices;
54487             let numVertices = vertices.length / 3;
54488             let positions = new Float32Array(vertices.length);
54489             for (let i = 0; i < numVertices; ++i) {
54490                 let index = 3 * i;
54491                 let x = vertices[index + 0];
54492                 let y = vertices[index + 1];
54493                 let z = vertices[index + 2];
54494                 if (i < 4) {
54495                     x *= undistortionMarginFactor;
54496                     y *= undistortionMarginFactor;
54497                 }
54498                 let boundedZ = Math.max(minZ, Math.min(z, maxZ));
54499                 let factor = boundedZ / z;
54500                 let p = new Vector3(x * factor, y * factor, boundedZ);
54501                 p.applyMatrix4(t);
54502                 positions[index + 0] = p.x;
54503                 positions[index + 1] = p.y;
54504                 positions[index + 2] = p.z;
54505             }
54506             let faces = image.mesh.faces;
54507             let indices = new Uint16Array(faces.length);
54508             for (let i = 0; i < faces.length; ++i) {
54509                 indices[i] = faces[i];
54510             }
54511             let geometry = new BufferGeometry();
54512             geometry.setAttribute("position", new BufferAttribute(positions, 3));
54513             geometry.setIndex(new BufferAttribute(indices, 1));
54514             return geometry;
54515         }
54516         _getImagePlaneGeoFisheye(transform, image) {
54517             const t = transform.srtInverse;
54518             // push everything at least 5 meters in front of the camera
54519             let minZ = 5.0 * transform.scale;
54520             let maxZ = this._imagePlaneDepth * transform.scale;
54521             let vertices = image.mesh.vertices;
54522             let numVertices = vertices.length / 3;
54523             let positions = new Float32Array(vertices.length);
54524             for (let i = 0; i < numVertices; ++i) {
54525                 let index = 3 * i;
54526                 let x = vertices[index + 0];
54527                 let y = vertices[index + 1];
54528                 let z = vertices[index + 2];
54529                 let l = Math.sqrt(x * x + y * y + z * z);
54530                 let boundedL = Math.max(minZ, Math.min(l, maxZ));
54531                 let factor = boundedL / l;
54532                 let p = new Vector3(x * factor, y * factor, z * factor);
54533                 p.applyMatrix4(t);
54534                 positions[index + 0] = p.x;
54535                 positions[index + 1] = p.y;
54536                 positions[index + 2] = p.z;
54537             }
54538             let faces = image.mesh.faces;
54539             let indices = new Uint16Array(faces.length);
54540             for (let i = 0; i < faces.length; ++i) {
54541                 indices[i] = faces[i];
54542             }
54543             let geometry = new BufferGeometry();
54544             geometry.setAttribute("position", new BufferAttribute(positions, 3));
54545             geometry.setIndex(new BufferAttribute(indices, 1));
54546             return geometry;
54547         }
54548         _getFlatImageSphereGeo(transform) {
54549             const geometry = new SphereGeometry(this._imageSphereRadius, 20, 40);
54550             const t = transform.rt
54551                 .clone()
54552                 .invert();
54553             geometry.applyMatrix4(t);
54554             return geometry;
54555         }
54556         _getRegularFlatImagePlaneGeo(transform) {
54557             let width = transform.width;
54558             let height = transform.height;
54559             let size = Math.max(width, height);
54560             let dx = width / 2.0 / size;
54561             let dy = height / 2.0 / size;
54562             return this._getFlatImagePlaneGeo(transform, dx, dy);
54563         }
54564         _getFlatImagePlaneGeo(transform, dx, dy) {
54565             let vertices = [];
54566             vertices.push(transform.unprojectSfM([-dx, -dy], this._imagePlaneDepth));
54567             vertices.push(transform.unprojectSfM([dx, -dy], this._imagePlaneDepth));
54568             vertices.push(transform.unprojectSfM([dx, dy], this._imagePlaneDepth));
54569             vertices.push(transform.unprojectSfM([-dx, dy], this._imagePlaneDepth));
54570             return this._createFlatGeometry(vertices);
54571         }
54572         _getRegularFlatImagePlaneGeoFisheye(transform) {
54573             let width = transform.width;
54574             let height = transform.height;
54575             let size = Math.max(width, height);
54576             let dx = width / 2.0 / size;
54577             let dy = height / 2.0 / size;
54578             return this._getFlatImagePlaneGeoFisheye(transform, dx, dy);
54579         }
54580         _getFlatImagePlaneGeoFisheye(transform, dx, dy) {
54581             let vertices = [];
54582             vertices.push(transform.unprojectSfM([-dx, -dy], this._imagePlaneDepth));
54583             vertices.push(transform.unprojectSfM([dx, -dy], this._imagePlaneDepth));
54584             vertices.push(transform.unprojectSfM([dx, dy], this._imagePlaneDepth));
54585             vertices.push(transform.unprojectSfM([-dx, dy], this._imagePlaneDepth));
54586             return this._createFlatGeometry(vertices);
54587         }
54588         _getFlatImagePlaneGeoFromBasic(transform, basicX0, basicX1, basicY0, basicY1) {
54589             let vertices = [];
54590             vertices.push(transform.unprojectBasic([basicX0, basicY0], this._imagePlaneDepth));
54591             vertices.push(transform.unprojectBasic([basicX1, basicY0], this._imagePlaneDepth));
54592             vertices.push(transform.unprojectBasic([basicX1, basicY1], this._imagePlaneDepth));
54593             vertices.push(transform.unprojectBasic([basicX0, basicY1], this._imagePlaneDepth));
54594             return this._createFlatGeometry(vertices);
54595         }
54596         _createFlatGeometry(vertices) {
54597             let positions = new Float32Array(12);
54598             for (let i = 0; i < vertices.length; i++) {
54599                 let index = 3 * i;
54600                 positions[index + 0] = vertices[i][0];
54601                 positions[index + 1] = vertices[i][1];
54602                 positions[index + 2] = vertices[i][2];
54603             }
54604             let indices = new Uint16Array(6);
54605             indices[0] = 0;
54606             indices[1] = 1;
54607             indices[2] = 3;
54608             indices[3] = 1;
54609             indices[4] = 2;
54610             indices[5] = 3;
54611             let geometry = new BufferGeometry();
54612             geometry.setAttribute("position", new BufferAttribute(positions, 3));
54613             geometry.setIndex(new BufferAttribute(indices, 1));
54614             return geometry;
54615         }
54616     }
54617
54618     class MeshScene {
54619         constructor() {
54620             this._planes = {};
54621             this._planesOld = {};
54622             this._planesPeriphery = {};
54623             this._scene = new Scene();
54624             this._sceneOld = new Scene();
54625             this._scenePeriphery = new Scene();
54626         }
54627         get planes() {
54628             return this._planes;
54629         }
54630         get planesOld() {
54631             return this._planesOld;
54632         }
54633         get planesPeriphery() {
54634             return this._planesPeriphery;
54635         }
54636         get scene() {
54637             return this._scene;
54638         }
54639         get sceneOld() {
54640             return this._sceneOld;
54641         }
54642         get scenePeriphery() {
54643             return this._scenePeriphery;
54644         }
54645         updateImagePlanes(planes) {
54646             this._dispose(this._planesOld, this.sceneOld);
54647             for (const key in this._planes) {
54648                 if (!this._planes.hasOwnProperty(key)) {
54649                     continue;
54650                 }
54651                 const plane = this._planes[key];
54652                 this._scene.remove(plane);
54653                 this._sceneOld.add(plane);
54654             }
54655             for (const key in planes) {
54656                 if (!planes.hasOwnProperty(key)) {
54657                     continue;
54658                 }
54659                 this._scene.add(planes[key]);
54660             }
54661             this._planesOld = this._planes;
54662             this._planes = planes;
54663         }
54664         addImagePlanes(planes) {
54665             for (const key in planes) {
54666                 if (!planes.hasOwnProperty(key)) {
54667                     continue;
54668                 }
54669                 const plane = planes[key];
54670                 this._scene.add(plane);
54671                 this._planes[key] = plane;
54672             }
54673         }
54674         addImagePlanesOld(planes) {
54675             for (const key in planes) {
54676                 if (!planes.hasOwnProperty(key)) {
54677                     continue;
54678                 }
54679                 const plane = planes[key];
54680                 this._sceneOld.add(plane);
54681                 this._planesOld[key] = plane;
54682             }
54683         }
54684         setImagePlanes(planes) {
54685             this._clear();
54686             this.addImagePlanes(planes);
54687         }
54688         addPeripheryPlanes(planes) {
54689             for (const key in planes) {
54690                 if (!planes.hasOwnProperty(key)) {
54691                     continue;
54692                 }
54693                 const plane = planes[key];
54694                 this._scenePeriphery.add(plane);
54695                 this._planesPeriphery[key] = plane;
54696             }
54697         }
54698         setPeripheryPlanes(planes) {
54699             this._clearPeriphery();
54700             this.addPeripheryPlanes(planes);
54701         }
54702         setImagePlanesOld(planes) {
54703             this._clearOld();
54704             this.addImagePlanesOld(planes);
54705         }
54706         clear() {
54707             this._clear();
54708             this._clearOld();
54709         }
54710         _clear() {
54711             this._dispose(this._planes, this._scene);
54712             this._planes = {};
54713         }
54714         _clearOld() {
54715             this._dispose(this._planesOld, this._sceneOld);
54716             this._planesOld = {};
54717         }
54718         _clearPeriphery() {
54719             this._dispose(this._planesPeriphery, this._scenePeriphery);
54720             this._planesPeriphery = {};
54721         }
54722         _dispose(planes, scene) {
54723             for (const key in planes) {
54724                 if (!planes.hasOwnProperty(key)) {
54725                     continue;
54726                 }
54727                 const plane = planes[key];
54728                 scene.remove(plane);
54729                 plane.geometry.dispose();
54730                 plane.material.dispose();
54731                 let texture = plane.material.uniforms.projectorTex.value;
54732                 if (texture != null) {
54733                     texture.dispose();
54734                 }
54735             }
54736         }
54737     }
54738
54739     class ImageGLRenderer {
54740         constructor() {
54741             this._factory = new MeshFactory();
54742             this._scene = new MeshScene();
54743             this._alpha = 0;
54744             this._alphaOld = 0;
54745             this._fadeOutSpeed = 0.05;
54746             this._currentKey = null;
54747             this._previousKey = null;
54748             this._providerDisposers = {};
54749             this._frameId = 0;
54750             this._needsRender = false;
54751         }
54752         get frameId() {
54753             return this._frameId;
54754         }
54755         get needsRender() {
54756             return this._needsRender;
54757         }
54758         indicateNeedsRender() {
54759             this._needsRender = true;
54760         }
54761         addPeripheryPlane(image, transform) {
54762             const mesh = this._factory.createMesh(image, transform);
54763             const planes = {};
54764             planes[image.id] = mesh;
54765             this._scene.addPeripheryPlanes(planes);
54766             this._needsRender = true;
54767         }
54768         clearPeripheryPlanes() {
54769             this._scene.setPeripheryPlanes({});
54770             this._needsRender = true;
54771         }
54772         updateFrame(frame) {
54773             this._updateFrameId(frame.id);
54774             this._needsRender = this._updateAlpha(frame.state.alpha) || this._needsRender;
54775             this._needsRender = this._updateAlphaOld(frame.state.alpha) || this._needsRender;
54776             this._needsRender = this._updateImagePlanes(frame.state) || this._needsRender;
54777         }
54778         setTextureProvider(key, provider) {
54779             if (key !== this._currentKey) {
54780                 return;
54781             }
54782             let createdSubscription = provider.textureCreated$
54783                 .subscribe((texture) => {
54784                 this._updateTexture(texture);
54785             });
54786             let updatedSubscription = provider.textureUpdated$
54787                 .subscribe((updated) => {
54788                 this._needsRender = true;
54789             });
54790             let dispose = () => {
54791                 createdSubscription.unsubscribe();
54792                 updatedSubscription.unsubscribe();
54793                 provider.dispose();
54794             };
54795             if (key in this._providerDisposers) {
54796                 let disposeProvider = this._providerDisposers[key];
54797                 disposeProvider();
54798                 delete this._providerDisposers[key];
54799             }
54800             this._providerDisposers[key] = dispose;
54801         }
54802         updateTextureImage(imageElement, image) {
54803             this._needsRender = true;
54804             const planes = this._extend({}, this._scene.planes, this._scene.planesOld, this._scene.planesPeriphery);
54805             for (const key in planes) {
54806                 if (!planes.hasOwnProperty(key)) {
54807                     continue;
54808                 }
54809                 if (key !== image.id) {
54810                     continue;
54811                 }
54812                 const plane = planes[key];
54813                 let material = plane.material;
54814                 let texture = material.uniforms.projectorTex.value;
54815                 texture.image = imageElement;
54816                 texture.needsUpdate = true;
54817             }
54818         }
54819         render(perspectiveCamera, renderer) {
54820             const planes = this._scene.planes;
54821             const planesOld = this._scene.planesOld;
54822             const planesPeriphery = this._scene.planesPeriphery;
54823             const planeAlpha = Object.keys(planesOld).length ? 1 : this._alpha;
54824             const peripheryAlpha = Object.keys(planesOld).length ? 1 : Math.floor(this._alpha);
54825             for (const key in planes) {
54826                 if (!planes.hasOwnProperty(key)) {
54827                     continue;
54828                 }
54829                 const plane = planes[key];
54830                 plane.material.uniforms.opacity.value = planeAlpha;
54831             }
54832             for (const key in planesOld) {
54833                 if (!planesOld.hasOwnProperty(key)) {
54834                     continue;
54835                 }
54836                 const plane = planesOld[key];
54837                 plane.material.uniforms.opacity.value = this._alphaOld;
54838             }
54839             for (const key in planesPeriphery) {
54840                 if (!planesPeriphery.hasOwnProperty(key)) {
54841                     continue;
54842                 }
54843                 const plane = planesPeriphery[key];
54844                 plane.material.uniforms.opacity.value = peripheryAlpha;
54845             }
54846             renderer.render(this._scene.scenePeriphery, perspectiveCamera);
54847             renderer.render(this._scene.scene, perspectiveCamera);
54848             renderer.render(this._scene.sceneOld, perspectiveCamera);
54849             for (const key in planes) {
54850                 if (!planes.hasOwnProperty(key)) {
54851                     continue;
54852                 }
54853                 const plane = planes[key];
54854                 plane.material.uniforms.opacity.value = this._alpha;
54855             }
54856             renderer.render(this._scene.scene, perspectiveCamera);
54857         }
54858         clearNeedsRender() {
54859             this._needsRender = false;
54860         }
54861         dispose() {
54862             this._scene.clear();
54863         }
54864         _updateFrameId(frameId) {
54865             this._frameId = frameId;
54866         }
54867         _updateAlpha(alpha) {
54868             if (alpha === this._alpha) {
54869                 return false;
54870             }
54871             this._alpha = alpha;
54872             return true;
54873         }
54874         _updateAlphaOld(alpha) {
54875             if (alpha < 1 || this._alphaOld === 0) {
54876                 return false;
54877             }
54878             this._alphaOld = Math.max(0, this._alphaOld - this._fadeOutSpeed);
54879             return true;
54880         }
54881         _updateImagePlanes(state) {
54882             if (state.currentImage == null ||
54883                 state.currentImage.id === this._currentKey) {
54884                 return false;
54885             }
54886             let previousKey = state.previousImage != null ? state.previousImage.id : null;
54887             let currentKey = state.currentImage.id;
54888             if (this._previousKey !== previousKey &&
54889                 this._previousKey !== currentKey &&
54890                 this._previousKey in this._providerDisposers) {
54891                 let disposeProvider = this._providerDisposers[this._previousKey];
54892                 disposeProvider();
54893                 delete this._providerDisposers[this._previousKey];
54894             }
54895             if (previousKey != null) {
54896                 if (previousKey !== this._currentKey && previousKey !== this._previousKey) {
54897                     let previousMesh = this._factory.createMesh(state.previousImage, state.previousTransform);
54898                     const previousPlanes = {};
54899                     previousPlanes[previousKey] = previousMesh;
54900                     this._scene.updateImagePlanes(previousPlanes);
54901                 }
54902                 this._previousKey = previousKey;
54903             }
54904             this._currentKey = currentKey;
54905             let currentMesh = this._factory.createMesh(state.currentImage, state.currentTransform);
54906             const planes = {};
54907             planes[currentKey] = currentMesh;
54908             this._scene.updateImagePlanes(planes);
54909             this._alphaOld = 1;
54910             return true;
54911         }
54912         _updateTexture(texture) {
54913             this._needsRender = true;
54914             const planes = this._scene.planes;
54915             for (const key in planes) {
54916                 if (!planes.hasOwnProperty(key)) {
54917                     continue;
54918                 }
54919                 const plane = planes[key];
54920                 let material = plane.material;
54921                 let oldTexture = material.uniforms.projectorTex.value;
54922                 material.uniforms.projectorTex.value = null;
54923                 oldTexture.dispose();
54924                 material.uniforms.projectorTex.value = texture;
54925             }
54926         }
54927         _extend(dest, ...sources) {
54928             for (const src of sources) {
54929                 for (const k in src) {
54930                     if (!src.hasOwnProperty(k)) {
54931                         continue;
54932                     }
54933                     dest[k] = src[k];
54934                 }
54935             }
54936             return dest;
54937         }
54938     }
54939
54940     var RenderPass;
54941     (function (RenderPass) {
54942         RenderPass[RenderPass["Background"] = 0] = "Background";
54943         RenderPass[RenderPass["Opaque"] = 1] = "Opaque";
54944     })(RenderPass || (RenderPass = {}));
54945
54946     /**
54947      * @class ImageTileLoader
54948      *
54949      * @classdesc Represents a loader of image tiles.
54950      */
54951     class TileLoader {
54952         /**
54953          * Create a new image image tile loader instance.
54954          *
54955          * @param {APIWrapper} _api - API wrapper.
54956          */
54957         constructor(_api) {
54958             this._api = _api;
54959             this._urls$ = new Map();
54960         }
54961         /**
54962          * Retrieve an image tile.
54963          *
54964          * @param {string} url - URL to the image tile resource
54965          */
54966         getImage$(url) {
54967             let aborter;
54968             const abort = new Promise((_, reject) => {
54969                 aborter = reject;
54970             });
54971             return [Observable.create((subscriber) => {
54972                     this._api.data
54973                         .getImageBuffer(url, abort)
54974                         .then((buffer) => {
54975                         aborter = null;
54976                         const image = new Image();
54977                         image.crossOrigin = "Anonymous";
54978                         image.onload = () => {
54979                             window.URL.revokeObjectURL(image.src);
54980                             subscriber.next(image);
54981                             subscriber.complete();
54982                         };
54983                         image.onerror = () => {
54984                             aborter = null;
54985                             window.URL.revokeObjectURL(image.src);
54986                             subscriber.error(new Error(`Failed to load image tile`));
54987                         };
54988                         const blob = new Blob([buffer]);
54989                         image.src = window.URL.createObjectURL(blob);
54990                     }, (error) => {
54991                         aborter = null;
54992                         subscriber.error(error);
54993                     });
54994                 }),
54995                 () => {
54996                     if (!!aborter) {
54997                         aborter();
54998                     }
54999                 }];
55000         }
55001         getURLs$(imageId, level) {
55002             const uniqueId = this._inventId(imageId, level);
55003             if (this._urls$.has(uniqueId)) {
55004                 return this._urls$.get(uniqueId);
55005             }
55006             const request = { imageId, z: level };
55007             const urls$ = this._api
55008                 .getImageTiles$(request)
55009                 .pipe(map(contract => contract.node), finalize(() => {
55010                 this._urls$.delete(uniqueId);
55011             }), publish(), refCount());
55012             this._urls$.set(uniqueId, urls$);
55013             return urls$;
55014         }
55015         _inventId(imageId, level) {
55016             return `${imageId}-${level}`;
55017         }
55018     }
55019
55020     /**
55021      * @class ImageTileStore
55022      *
55023      * @classdesc Represents a store for image tiles.
55024      */
55025     class TileStore {
55026         /**
55027          * Create a new image image tile store instance.
55028          */
55029         constructor() {
55030             this._tiles = new Map();
55031             this._urlLevels = new Set();
55032             this._urls = new Map();
55033         }
55034         /**
55035          * Add an image tile to the store.
55036          *
55037          * @param {string} id - The identifier for the image tile.
55038          * @param {HTMLImageElement} image - The image tile.
55039          */
55040         add(id, image) {
55041             if (this._tiles.has(id)) {
55042                 throw new Error(`Image tile already stored (${id})`);
55043             }
55044             this._tiles.set(id, image);
55045         }
55046         addURLs(level, ents) {
55047             const urls = this._urls;
55048             for (const ent of ents) {
55049                 const id = this.inventId(ent);
55050                 if (this._urls.has(id)) {
55051                     throw new Error(`URL already stored (${id})`);
55052                 }
55053                 urls.set(id, ent.url);
55054             }
55055             this._urlLevels.add(level);
55056         }
55057         /**
55058          * Dispose the store.
55059          *
55060          * @description Disposes all cached assets.
55061          */
55062         dispose() {
55063             this._tiles
55064                 .forEach(image => window.URL.revokeObjectURL(image.src));
55065             this._tiles.clear();
55066             this._urls.clear();
55067             this._urlLevels.clear();
55068         }
55069         /**
55070          * Get an image tile from the store.
55071          *
55072          * @param {string} id - The identifier for the tile.
55073          * @param {number} level - The level of the tile.
55074          */
55075         get(id) {
55076             return this._tiles.get(id);
55077         }
55078         getURL(id) {
55079             return this._urls.get(id);
55080         }
55081         /**
55082          * Check if an image tile exist in the store.
55083          *
55084          * @param {string} id - The identifier for the tile.
55085          * @param {number} level - The level of the tile.
55086          */
55087         has(id) {
55088             return this._tiles.has(id);
55089         }
55090         hasURL(id) {
55091             return this._urls.has(id);
55092         }
55093         hasURLLevel(level) {
55094             return this._urlLevels.has(level);
55095         }
55096         /**
55097          * Create a unique tile id from a tile.
55098          *
55099          * @description Tile ids are used as a hash for
55100          * storing the tile in a dictionary.
55101          *
55102          * @param {ImageTileEnt} tile - The tile.
55103          * @returns {string} Unique id.
55104          */
55105         inventId(tile) {
55106             return `${tile.z}-${tile.x}-${tile.y}`;
55107         }
55108     }
55109
55110     /**
55111      * @class RegionOfInterestCalculator
55112      *
55113      * @classdesc Represents a calculator for regions of interest.
55114      */
55115     class RegionOfInterestCalculator {
55116         constructor() {
55117             this._viewportCoords = new ViewportCoords();
55118         }
55119         /**
55120          * Compute a region of interest based on the current render camera
55121          * and the viewport size.
55122          *
55123          * @param {RenderCamera} renderCamera - Render camera used for unprojections.
55124          * @param {ViewportSize} size - Viewport size in pixels.
55125          * @param {Transform} transform - Transform used for projections.
55126          *
55127          * @returns {TileRegionOfInterest} A region of interest.
55128          */
55129         computeRegionOfInterest(renderCamera, size, transform) {
55130             const viewportBoundaryPoints = this._viewportBoundaryPoints(4);
55131             const bbox = this._viewportPointsBoundingBox(viewportBoundaryPoints, renderCamera, transform);
55132             this._clipBoundingBox(bbox);
55133             const viewportPixelWidth = 2 / size.width;
55134             const viewportPixelHeight = 2 / size.height;
55135             const centralViewportPixel = [
55136                 [-0.5 * viewportPixelWidth, 0.5 * viewportPixelHeight],
55137                 [0.5 * viewportPixelWidth, 0.5 * viewportPixelHeight],
55138                 [0.5 * viewportPixelWidth, -0.5 * viewportPixelHeight],
55139                 [-0.5 * viewportPixelWidth, -0.5 * viewportPixelHeight],
55140             ];
55141             const cpbox = this._viewportPointsBoundingBox(centralViewportPixel, renderCamera, transform);
55142             const inverted = cpbox.minX < cpbox.maxX;
55143             return {
55144                 bbox: bbox,
55145                 pixelHeight: cpbox.maxY - cpbox.minY,
55146                 pixelWidth: cpbox.maxX - cpbox.minX + (inverted ? 0 : 1),
55147             };
55148         }
55149         _viewportBoundaryPoints(pointsPerSide) {
55150             const points = [];
55151             const os = [[-1, 1], [1, 1], [1, -1], [-1, -1]];
55152             const ds = [[2, 0], [0, -2], [-2, 0], [0, 2]];
55153             for (let side = 0; side < 4; ++side) {
55154                 const o = os[side];
55155                 const d = ds[side];
55156                 for (let i = 0; i < pointsPerSide; ++i) {
55157                     points.push([o[0] + d[0] * i / pointsPerSide,
55158                         o[1] + d[1] * i / pointsPerSide]);
55159                 }
55160             }
55161             return points;
55162         }
55163         _viewportPointsBoundingBox(viewportPoints, renderCamera, transform) {
55164             const basicPoints = viewportPoints
55165                 .map((point) => {
55166                 return this._viewportCoords
55167                     .viewportToBasic(point[0], point[1], transform, renderCamera.perspective);
55168             });
55169             if (isSpherical(transform.cameraType)) {
55170                 return this._boundingBoxSpherical(basicPoints);
55171             }
55172             else {
55173                 return this._boundingBox(basicPoints);
55174             }
55175         }
55176         _boundingBox(points) {
55177             const bbox = {
55178                 maxX: Number.NEGATIVE_INFINITY,
55179                 maxY: Number.NEGATIVE_INFINITY,
55180                 minX: Number.POSITIVE_INFINITY,
55181                 minY: Number.POSITIVE_INFINITY,
55182             };
55183             for (let i = 0; i < points.length; ++i) {
55184                 bbox.minX = Math.min(bbox.minX, points[i][0]);
55185                 bbox.maxX = Math.max(bbox.maxX, points[i][0]);
55186                 bbox.minY = Math.min(bbox.minY, points[i][1]);
55187                 bbox.maxY = Math.max(bbox.maxY, points[i][1]);
55188             }
55189             return bbox;
55190         }
55191         _boundingBoxSpherical(points) {
55192             const xs = [];
55193             const ys = [];
55194             for (let i = 0; i < points.length; ++i) {
55195                 xs.push(points[i][0]);
55196                 ys.push(points[i][1]);
55197             }
55198             xs.sort((a, b) => { return this._sign(a - b); });
55199             ys.sort((a, b) => { return this._sign(a - b); });
55200             const intervalX = this._intervalSpherical(xs);
55201             return {
55202                 maxX: intervalX[1],
55203                 maxY: ys[ys.length - 1],
55204                 minX: intervalX[0],
55205                 minY: ys[0],
55206             };
55207         }
55208         /**
55209          * Find the max interval between consecutive numbers.
55210          * Assumes numbers are between 0 and 1, sorted and that
55211          * x is equivalent to x + 1.
55212          */
55213         _intervalSpherical(xs) {
55214             let maxdx = 0;
55215             let maxi = -1;
55216             for (let i = 0; i < xs.length - 1; ++i) {
55217                 const dx = xs[i + 1] - xs[i];
55218                 if (dx > maxdx) {
55219                     maxdx = dx;
55220                     maxi = i;
55221                 }
55222             }
55223             const loopdx = xs[0] + 1 - xs[xs.length - 1];
55224             if (loopdx > maxdx) {
55225                 return [xs[0], xs[xs.length - 1]];
55226             }
55227             else {
55228                 return [xs[maxi + 1], xs[maxi]];
55229             }
55230         }
55231         _clipBoundingBox(bbox) {
55232             bbox.minX = Math.max(0, Math.min(1, bbox.minX));
55233             bbox.maxX = Math.max(0, Math.min(1, bbox.maxX));
55234             bbox.minY = Math.max(0, Math.min(1, bbox.minY));
55235             bbox.maxY = Math.max(0, Math.min(1, bbox.maxY));
55236         }
55237         _sign(n) {
55238             return n > 0 ? 1 : n < 0 ? -1 : 0;
55239         }
55240     }
55241
55242     const TILE_MIN_REQUEST_LEVEL = 11;
55243     const TILE_SIZE = 1024;
55244
55245     function clamp(value, min, max) {
55246         return Math.max(min, Math.min(max, value));
55247     }
55248     function levelTilePixelSize(level) {
55249         return TILE_SIZE / levelScale(level);
55250     }
55251     function levelScale(level) {
55252         return Math.pow(2, level.z - level.max);
55253     }
55254     function rawImageLevel(size) {
55255         const s = Math.max(size.w, size.h);
55256         return Math.log(s) / Math.log(2);
55257     }
55258     function baseImageLevel(size) {
55259         return Math.ceil(rawImageLevel(size));
55260     }
55261     function clampedImageLevel(size, min, max) {
55262         return Math.max(min, Math.min(max, baseImageLevel(size)));
55263     }
55264     function basicToTileCoords2D(basic, size, level) {
55265         const tilePixelSize = levelTilePixelSize(level);
55266         const w = size.w;
55267         const h = size.h;
55268         const maxX = Math.ceil(w / tilePixelSize) - 1;
55269         const maxY = Math.ceil(h / tilePixelSize) - 1;
55270         const x = clamp(Math.floor(w * basic[0] / tilePixelSize), 0, maxX);
55271         const y = clamp(Math.floor(h * basic[1] / tilePixelSize), 0, maxY);
55272         return { x, y };
55273     }
55274     function tileToPixelCoords2D(tile, size, level) {
55275         const scale = 1 / levelScale(level);
55276         const scaledTS = scale * TILE_SIZE;
55277         const x = scaledTS * tile.x;
55278         const y = scaledTS * tile.y;
55279         const w = Math.min(scaledTS, size.w - x);
55280         const h = Math.min(scaledTS, size.h - y);
55281         return { h, x, y, w };
55282     }
55283     function hasOverlap1D(low, base, scale) {
55284         return (scale * low <= base &&
55285             base < scale * (low + 1));
55286     }
55287     function hasOverlap2D(tile1, tile2) {
55288         if (tile1.z === tile2.z) {
55289             return tile1.x === tile2.x && tile1.y === tile2.y;
55290         }
55291         const low = tile1.z < tile2.z ? tile1 : tile2;
55292         const base = tile1.z < tile2.z ? tile2 : tile1;
55293         const scale = 1 / levelScale({ max: base.z, z: low.z });
55294         const overlapX = hasOverlap1D(low.x, base.x, scale);
55295         const overlapY = hasOverlap1D(low.y, base.y, scale);
55296         return overlapX && overlapY;
55297     }
55298     function cornersToTilesCoords2D(topLeft, bottomRight, size, level) {
55299         const xs = [];
55300         if (topLeft.x > bottomRight.x) {
55301             const tilePixelSize = levelTilePixelSize(level);
55302             const maxX = Math.ceil(size.w / tilePixelSize) - 1;
55303             for (let x = topLeft.x; x <= maxX; x++) {
55304                 xs.push(x);
55305             }
55306             for (let x = 0; x <= bottomRight.x; x++) {
55307                 xs.push(x);
55308             }
55309         }
55310         else {
55311             for (let x = topLeft.x; x <= bottomRight.x; x++) {
55312                 xs.push(x);
55313             }
55314         }
55315         const tiles = [];
55316         for (const x of xs) {
55317             for (let y = topLeft.y; y <= bottomRight.y; y++) {
55318                 tiles.push({ x, y });
55319             }
55320         }
55321         return tiles;
55322     }
55323     function verifySize(size) {
55324         return size.w > 0 && size.h > 0;
55325     }
55326
55327     /**
55328      * @class TextureProvider
55329      *
55330      * @classdesc Represents a provider of textures.
55331      */
55332     class TextureProvider {
55333         /**
55334          * Create a new image texture provider instance.
55335          *
55336          * @param {string} imageId - The identifier of the image for which to request tiles.
55337          * @param {number} width - The full width of the original image.
55338          * @param {number} height - The full height of the original image.
55339          * @param {HTMLImageElement} background - Image to use as background.
55340          * @param {TileLoader} loader - Loader for retrieving tiles.
55341          * @param {TileStore} store - Store for saving tiles.
55342          * @param {THREE.WebGLRenderer} renderer - Renderer used for rendering tiles to texture.
55343          */
55344         constructor(imageId, width, height, background, loader, store, renderer) {
55345             const size = { h: height, w: width };
55346             if (!verifySize(size)) {
55347                 console.warn(`Original image size (${width}, ${height}) ` +
55348                     `is invalid (${imageId}). Tiles will not be loaded.`);
55349             }
55350             this._imageId = imageId;
55351             this._size = size;
55352             this._level = {
55353                 max: baseImageLevel(this._size),
55354                 z: -1,
55355             };
55356             this._holder = new SubscriptionHolder();
55357             this._updated$ = new Subject();
55358             this._createdSubject$ = new Subject();
55359             this._created$ = this._createdSubject$
55360                 .pipe(publishReplay(1), refCount());
55361             this._holder.push(this._created$.subscribe(() => { }));
55362             this._hasSubject$ = new Subject();
55363             this._has$ = this._hasSubject$
55364                 .pipe(startWith(false), publishReplay(1), refCount());
55365             this._holder.push(this._has$.subscribe(() => { }));
55366             this._renderedLevel = new Set();
55367             this._rendered = new Map();
55368             this._subscriptions = new Map();
55369             this._urlSubscriptions = new Map();
55370             this._loader = loader;
55371             this._store = store;
55372             this._background = background;
55373             this._renderer = renderer;
55374             this._aborts = [];
55375             this._render = null;
55376             this._disposed = false;
55377         }
55378         /**
55379          * Get disposed.
55380          *
55381          * @returns {boolean} Value indicating whether provider has
55382          * been disposed.
55383          */
55384         get disposed() {
55385             return this._disposed;
55386         }
55387         /**
55388          * Get hasTexture$.
55389          *
55390          * @returns {Observable<boolean>} Observable emitting
55391          * values indicating when the existance of a texture
55392          * changes.
55393          */
55394         get hasTexture$() {
55395             return this._has$;
55396         }
55397         /**
55398          * Get id.
55399          *
55400          * @returns {boolean} The identifier of the image for
55401          * which to render textures.
55402          */
55403         get id() {
55404             return this._imageId;
55405         }
55406         /**
55407          * Get textureUpdated$.
55408          *
55409          * @returns {Observable<boolean>} Observable emitting
55410          * values when an existing texture has been updated.
55411          */
55412         get textureUpdated$() {
55413             return this._updated$;
55414         }
55415         /**
55416          * Get textureCreated$.
55417          *
55418          * @returns {Observable<boolean>} Observable emitting
55419          * values when a new texture has been created.
55420          */
55421         get textureCreated$() {
55422             return this._created$;
55423         }
55424         /**
55425          * Abort all outstanding image tile requests.
55426          */
55427         abort() {
55428             this._subscriptions.forEach(sub => sub.unsubscribe());
55429             this._subscriptions.clear();
55430             for (const abort of this._aborts) {
55431                 abort();
55432             }
55433             this._aborts = [];
55434         }
55435         /**
55436          * Dispose the provider.
55437          *
55438          * @description Disposes all cached assets and
55439          * aborts all outstanding image tile requests.
55440          */
55441         dispose() {
55442             if (this._disposed) {
55443                 console.warn(`Texture already disposed (${this._imageId})`);
55444                 return;
55445             }
55446             this._urlSubscriptions.forEach(sub => sub.unsubscribe());
55447             this._urlSubscriptions.clear();
55448             this.abort();
55449             if (this._render != null) {
55450                 this._render.target.dispose();
55451                 this._render.target = null;
55452                 this._render.camera = null;
55453                 this._render = null;
55454             }
55455             this._store.dispose();
55456             this._holder.unsubscribe();
55457             this._renderedLevel.clear();
55458             this._background = null;
55459             this._renderer = null;
55460             this._disposed = true;
55461         }
55462         /**
55463          * Set the region of interest.
55464          *
55465          * @description When the region of interest is set the
55466          * the tile level is determined and tiles for the region
55467          * are fetched from the store or the loader and renderedLevel
55468          * to the texture.
55469          *
55470          * @param {TileRegionOfInterest} roi - Spatial edges to cache.
55471          */
55472         setRegionOfInterest(roi) {
55473             if (!verifySize(this._size)) {
55474                 return;
55475             }
55476             const virtualWidth = 1 / roi.pixelWidth;
55477             const virtualHeight = 1 / roi.pixelHeight;
55478             const level = clampedImageLevel({ h: virtualHeight, w: virtualWidth }, TILE_MIN_REQUEST_LEVEL, this._level.max);
55479             if (level !== this._level.z) {
55480                 this.abort();
55481                 this._level.z = level;
55482                 this._renderedLevel.clear();
55483                 this._rendered
55484                     .forEach((tile, id) => {
55485                     if (tile.z !== level) {
55486                         return;
55487                     }
55488                     this._renderedLevel.add(id);
55489                 });
55490             }
55491             if (this._render == null) {
55492                 this._initRender();
55493             }
55494             const topLeft = basicToTileCoords2D([roi.bbox.minX, roi.bbox.minY], this._size, this._level);
55495             const bottomRight = basicToTileCoords2D([roi.bbox.maxX, roi.bbox.maxY], this._size, this._level);
55496             const tiles = cornersToTilesCoords2D(topLeft, bottomRight, this._size, this._level);
55497             this._fetchTiles(level, tiles);
55498         }
55499         /**
55500          * Retrieve an image tile.
55501          *
55502          * @description Retrieve an image tile and render it to the
55503          * texture. Add the tile to the store and emit to the updated
55504          * observable.
55505          *
55506          * @param {ImageTileEnt} tile - The tile ent.
55507          */
55508         _fetchTile(tile) {
55509             const getTile = this._loader.getImage$(tile.url);
55510             const tile$ = getTile[0];
55511             const abort = getTile[1];
55512             this._aborts.push(abort);
55513             const tileId = this._store.inventId(tile);
55514             const subscription = tile$.subscribe((image) => {
55515                 const pixels = tileToPixelCoords2D(tile, this._size, this._level);
55516                 this._renderToTarget(pixels, image);
55517                 this._subscriptions.delete(tileId);
55518                 this._removeFromArray(abort, this._aborts);
55519                 this._markRendered(tile);
55520                 this._store.add(tileId, image);
55521                 this._updated$.next(true);
55522             }, (error) => {
55523                 this._subscriptions.delete(tileId);
55524                 this._removeFromArray(abort, this._aborts);
55525                 console.error(error);
55526             });
55527             if (!subscription.closed) {
55528                 this._subscriptions.set(tileId, subscription);
55529             }
55530         }
55531         /**
55532          * Fetch image tiles.
55533          *
55534          * @description Retrieve a image tiles and render them to the
55535          * texture. Retrieve from store if it exists, otherwise retrieve
55536          * from loader.
55537          *
55538          * @param {Array<TileCoords2D>} tiles - Array of tile coordinates to
55539          * retrieve.
55540          */
55541         _fetchTiles(level, tiles) {
55542             const urls$ = this._store.hasURLLevel(level) ?
55543                 of(undefined) :
55544                 this._loader
55545                     .getURLs$(this._imageId, level)
55546                     .pipe(tap(ents => {
55547                     if (!this._store.hasURLLevel(level)) {
55548                         this._store.addURLs(level, ents);
55549                     }
55550                 }));
55551             const subscription = urls$.subscribe(() => {
55552                 if (level !== this._level.z) {
55553                     return;
55554                 }
55555                 for (const tile of tiles) {
55556                     const ent = {
55557                         x: tile.x,
55558                         y: tile.y,
55559                         z: level,
55560                         url: null,
55561                     };
55562                     const id = this._store.inventId(ent);
55563                     if (this._renderedLevel.has(id) ||
55564                         this._subscriptions.has(id)) {
55565                         continue;
55566                     }
55567                     if (this._store.has(id)) {
55568                         const pixels = tileToPixelCoords2D(tile, this._size, this._level);
55569                         this._renderToTarget(pixels, this._store.get(id));
55570                         this._markRendered(ent);
55571                         this._updated$.next(true);
55572                         continue;
55573                     }
55574                     ent.url = this._store.getURL(id);
55575                     this._fetchTile(ent);
55576                 }
55577                 this._urlSubscriptions.delete(level);
55578             }, (error) => {
55579                 this._urlSubscriptions.delete(level);
55580                 console.error(error);
55581             });
55582             if (!subscription.closed) {
55583                 this._urlSubscriptions.set(level, subscription);
55584             }
55585         }
55586         _initRender() {
55587             const dx = this._size.w / 2;
55588             const dy = this._size.h / 2;
55589             const near = -1;
55590             const far = 1;
55591             const camera = new OrthographicCamera(-dx, dx, dy, -dy, near, far);
55592             camera.position.z = 1;
55593             const gl = this._renderer.getContext();
55594             const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
55595             const backgroundSize = Math.max(this._size.w, this._size.h);
55596             const scale = maxTextureSize > backgroundSize ?
55597                 1 : maxTextureSize / backgroundSize;
55598             const targetWidth = Math.floor(scale * this._size.w);
55599             const targetHeight = Math.floor(scale * this._size.h);
55600             const target = new WebGLRenderTarget(targetWidth, targetHeight, {
55601                 depthBuffer: false,
55602                 format: RGBFormat,
55603                 magFilter: LinearFilter,
55604                 minFilter: LinearFilter,
55605                 stencilBuffer: false,
55606             });
55607             this._render = { camera, target };
55608             const pixels = tileToPixelCoords2D({ x: 0, y: 0 }, this._size, { max: this._level.max, z: 0 });
55609             this._renderToTarget(pixels, this._background);
55610             this._createdSubject$.next(target.texture);
55611             this._hasSubject$.next(true);
55612         }
55613         /**
55614          * Mark a tile as rendered.
55615          *
55616          * @description Clears tiles marked as rendered in other
55617          * levels of the tile pyramid if they overlap the
55618          * newly rendered tile.
55619          *
55620          * @param {Arrary<number>} tile - The tile ent.
55621          */
55622         _markRendered(tile) {
55623             const others = Array.from(this._rendered.entries())
55624                 .filter(([_, t]) => {
55625                 return t.z !== tile.z;
55626             });
55627             for (const [otherId, other] of others) {
55628                 if (hasOverlap2D(tile, other)) {
55629                     this._rendered.delete(otherId);
55630                 }
55631             }
55632             const id = this._store.inventId(tile);
55633             this._rendered.set(id, tile);
55634             this._renderedLevel.add(id);
55635         }
55636         /**
55637          * Remove an item from an array if it exists in array.
55638          *
55639          * @param {T} item - Item to remove.
55640          * @param {Array<T>} array - Array from which item should be removed.
55641          */
55642         _removeFromArray(item, array) {
55643             const index = array.indexOf(item);
55644             if (index !== -1) {
55645                 array.splice(index, 1);
55646             }
55647         }
55648         /**
55649          * Render an image tile to the target texture.
55650          *
55651          * @param {ImageTileEnt} tile - Tile ent.
55652          * @param {HTMLImageElement} image - The image tile to render.
55653          */
55654         _renderToTarget(pixel, image) {
55655             const texture = new Texture(image);
55656             texture.minFilter = LinearFilter;
55657             texture.needsUpdate = true;
55658             const geometry = new PlaneGeometry(pixel.w, pixel.h);
55659             const material = new MeshBasicMaterial({
55660                 map: texture,
55661                 side: FrontSide,
55662             });
55663             const mesh = new Mesh(geometry, material);
55664             mesh.position.x = -this._size.w / 2 + pixel.x + pixel.w / 2;
55665             mesh.position.y = this._size.h / 2 - pixel.y - pixel.h / 2;
55666             const scene = new Scene();
55667             scene.add(mesh);
55668             const target = this._renderer.getRenderTarget();
55669             this._renderer.resetState();
55670             this._renderer.setRenderTarget(this._render.target);
55671             this._renderer.render(scene, this._render.camera);
55672             this._renderer.setRenderTarget(target);
55673             scene.remove(mesh);
55674             geometry.dispose();
55675             material.dispose();
55676             texture.dispose();
55677         }
55678     }
55679
55680     var State;
55681     (function (State) {
55682         State[State["Custom"] = 0] = "Custom";
55683         State[State["Earth"] = 1] = "Earth";
55684         State[State["Traversing"] = 2] = "Traversing";
55685         State[State["Waiting"] = 3] = "Waiting";
55686         State[State["WaitingInteractively"] = 4] = "WaitingInteractively";
55687     })(State || (State = {}));
55688
55689     class ImageComponent extends Component {
55690         constructor(name, container, navigator) {
55691             super(name, container, navigator);
55692             this._imageTileLoader = new TileLoader(navigator.api);
55693             this._roiCalculator = new RegionOfInterestCalculator();
55694             this._rendererOperation$ = new Subject();
55695             this._rendererCreator$ = new Subject();
55696             this._rendererDisposer$ = new Subject();
55697             this._renderer$ = this._rendererOperation$.pipe(scan((renderer, operation) => {
55698                 return operation(renderer);
55699             }, null), filter((renderer) => {
55700                 return renderer != null;
55701             }), distinctUntilChanged(undefined, (renderer) => {
55702                 return renderer.frameId;
55703             }));
55704             this._rendererCreator$.pipe(map(() => {
55705                 return (renderer) => {
55706                     if (renderer != null) {
55707                         throw new Error("Multiple image plane states can not be created at the same time");
55708                     }
55709                     return new ImageGLRenderer();
55710                 };
55711             }))
55712                 .subscribe(this._rendererOperation$);
55713             this._rendererDisposer$.pipe(map(() => {
55714                 return (renderer) => {
55715                     renderer.dispose();
55716                     return null;
55717                 };
55718             }))
55719                 .subscribe(this._rendererOperation$);
55720         }
55721         _activate() {
55722             const subs = this._subscriptions;
55723             subs.push(this._renderer$.pipe(map((renderer) => {
55724                 const renderHash = {
55725                     name: this._name,
55726                     renderer: {
55727                         frameId: renderer.frameId,
55728                         needsRender: renderer.needsRender,
55729                         render: renderer.render.bind(renderer),
55730                         pass: RenderPass.Background,
55731                     },
55732                 };
55733                 renderer.clearNeedsRender();
55734                 return renderHash;
55735             }))
55736                 .subscribe(this._container.glRenderer.render$));
55737             this._rendererCreator$.next(null);
55738             subs.push(this._navigator.stateService.currentState$.pipe(map((frame) => {
55739                 return (renderer) => {
55740                     renderer.updateFrame(frame);
55741                     return renderer;
55742                 };
55743             }))
55744                 .subscribe(this._rendererOperation$));
55745             const textureProvider$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
55746                 return active ?
55747                     this._navigator.stateService.currentState$ :
55748                     new Subject();
55749             }), distinctUntilChanged(undefined, (frame) => {
55750                 return frame.state.currentImage.id;
55751             }), withLatestFrom(this._container.glRenderer.webGLRenderer$), map(([frame, renderer]) => {
55752                 const state = frame.state;
55753                 const currentNode = state.currentImage;
55754                 const currentTransform = state.currentTransform;
55755                 return new TextureProvider(currentNode.id, currentTransform.basicWidth, currentTransform.basicHeight, currentNode.image, this._imageTileLoader, new TileStore(), renderer);
55756             }), publishReplay(1), refCount());
55757             subs.push(textureProvider$.subscribe(() => { }));
55758             subs.push(textureProvider$.pipe(map((provider) => {
55759                 return (renderer) => {
55760                     renderer.setTextureProvider(provider.id, provider);
55761                     return renderer;
55762                 };
55763             }))
55764                 .subscribe(this._rendererOperation$));
55765             subs.push(textureProvider$.pipe(pairwise())
55766                 .subscribe((pair) => {
55767                 const previous = pair[0];
55768                 previous.abort();
55769             }));
55770             const roiTrigger$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
55771                 return active ?
55772                     combineLatest(this._navigator.stateService.state$, this._navigator.stateService.inTranslation$) :
55773                     new Subject();
55774             }), switchMap(([state, inTranslation]) => {
55775                 const streetState = state === State.Traversing ||
55776                     state === State.Waiting ||
55777                     state === State.WaitingInteractively;
55778                 const active = streetState && !inTranslation;
55779                 return active ?
55780                     this._container.renderService.renderCameraFrame$ :
55781                     empty();
55782             }), map((camera) => {
55783                 return {
55784                     camera,
55785                     height: camera.size.height.valueOf(),
55786                     lookat: camera.camera.lookat.clone(),
55787                     width: camera.size.width.valueOf(),
55788                     zoom: camera.zoom.valueOf(),
55789                 };
55790             }), pairwise(), map(([pl0, pl1]) => {
55791                 const stalled = pl0.width === pl1.width &&
55792                     pl0.height === pl1.height &&
55793                     pl0.zoom === pl1.zoom &&
55794                     pl0.lookat.equals(pl1.lookat);
55795                 return { camera: pl1.camera, stalled };
55796             }), distinctUntilChanged((x, y) => {
55797                 return x.stalled === y.stalled;
55798             }), filter((camera) => {
55799                 return camera.stalled;
55800             }), withLatestFrom(this._container.renderService.size$, this._navigator.stateService.currentTransform$));
55801             subs.push(textureProvider$.pipe(switchMap((provider) => {
55802                 return roiTrigger$.pipe(map(([stalled, size, transform]) => {
55803                     const camera = stalled.camera;
55804                     const basic = new ViewportCoords()
55805                         .viewportToBasic(0, 0, transform, camera.perspective);
55806                     if (basic[0] < 0 ||
55807                         basic[1] < 0 ||
55808                         basic[0] > 1 ||
55809                         basic[1] > 1) {
55810                         return undefined;
55811                     }
55812                     return [
55813                         this._roiCalculator
55814                             .computeRegionOfInterest(camera, size, transform),
55815                         provider,
55816                     ];
55817                 }), filter((args) => {
55818                     return !!args;
55819                 }));
55820             }), filter((args) => {
55821                 return !args[1].disposed;
55822             }))
55823                 .subscribe(([roi, provider]) => {
55824                 provider.setRegionOfInterest(roi);
55825             }));
55826             const hasTexture$ = textureProvider$
55827                 .pipe(switchMap((provider) => {
55828                 return provider.hasTexture$;
55829             }), startWith(false), publishReplay(1), refCount());
55830             subs.push(hasTexture$.subscribe(() => { }));
55831             subs.push(this._navigator.panService.panImages$.pipe(filter((panNodes) => {
55832                 return panNodes.length === 0;
55833             }), map(() => {
55834                 return (renderer) => {
55835                     renderer.clearPeripheryPlanes();
55836                     return renderer;
55837                 };
55838             }))
55839                 .subscribe(this._rendererOperation$));
55840             const cachedPanNodes$ = this._navigator.panService.panImages$.pipe(switchMap((nts) => {
55841                 return from(nts).pipe(mergeMap(([n, t]) => {
55842                     return combineLatest(this._navigator.graphService.cacheImage$(n.id).pipe(catchError((error) => {
55843                         console.error(`Failed to cache periphery image (${n.id})`, error);
55844                         return empty();
55845                     })), of(t));
55846                 }));
55847             }), share());
55848             subs.push(cachedPanNodes$.pipe(map(([n, t]) => {
55849                 return (renderer) => {
55850                     renderer.addPeripheryPlane(n, t);
55851                     return renderer;
55852                 };
55853             }))
55854                 .subscribe(this._rendererOperation$));
55855             subs.push(cachedPanNodes$.pipe(mergeMap(([n]) => {
55856                 return n.cacheImage$().pipe(catchError(() => {
55857                     return empty();
55858                 }));
55859             }), map((n) => {
55860                 return (renderer) => {
55861                     renderer.updateTextureImage(n.image, n);
55862                     return renderer;
55863                 };
55864             }))
55865                 .subscribe(this._rendererOperation$));
55866             const inTransition$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
55867                 return frame.state.alpha < 1;
55868             }), distinctUntilChanged());
55869             const panTrigger$ = combineLatest(this._container.mouseService.active$, this._container.touchService.active$, this._navigator.stateService.inMotion$, inTransition$).pipe(map(([mouseActive, touchActive, inMotion, inTransition]) => {
55870                 return !(mouseActive || touchActive || inMotion || inTransition);
55871             }), filter((trigger) => {
55872                 return trigger;
55873             }));
55874             subs.push(this._navigator.stateService.state$
55875                 .pipe(switchMap(state => {
55876                 return state === State.Traversing ?
55877                     this._navigator.panService.panImages$ :
55878                     empty();
55879             }), switchMap((nts) => {
55880                 return panTrigger$.pipe(withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentImage$, this._navigator.stateService.currentTransform$), mergeMap(([, renderCamera, currentNode, currentTransform]) => {
55881                     return of([
55882                         renderCamera,
55883                         currentNode,
55884                         currentTransform,
55885                         nts,
55886                     ]);
55887                 }));
55888             }), switchMap(([camera, cn, ct, nts]) => {
55889                 const direction = camera.camera.lookat.clone().sub(camera.camera.position);
55890                 const cd = new Spatial().viewingDirection(cn.rotation);
55891                 const ca = cd.angleTo(direction);
55892                 const closest = [ca, undefined];
55893                 const basic = new ViewportCoords().viewportToBasic(0, 0, ct, camera.perspective);
55894                 if (basic[0] >= 0 && basic[0] <= 1 && basic[1] >= 0 && basic[1] <= 1) {
55895                     closest[0] = Number.NEGATIVE_INFINITY;
55896                 }
55897                 for (const [n] of nts) {
55898                     const d = new Spatial().viewingDirection(n.rotation);
55899                     const a = d.angleTo(direction);
55900                     if (a < closest[0]) {
55901                         closest[0] = a;
55902                         closest[1] = n.id;
55903                     }
55904                 }
55905                 if (!closest[1]) {
55906                     return empty();
55907                 }
55908                 return this._navigator.moveTo$(closest[1]).pipe(catchError(() => {
55909                     return empty();
55910                 }));
55911             }))
55912                 .subscribe());
55913         }
55914         _deactivate() {
55915             this._rendererDisposer$.next(null);
55916             this._subscriptions.unsubscribe();
55917         }
55918         _getDefaultConfiguration() {
55919             return {};
55920         }
55921     }
55922     ImageComponent.componentName = "image";
55923
55924     class HandlerBase {
55925         /** @ignore */
55926         constructor(component, container, navigator) {
55927             this._component = component;
55928             this._container = container;
55929             this._navigator = navigator;
55930             this._enabled = false;
55931         }
55932         /**
55933          * Returns a Boolean indicating whether the interaction is enabled.
55934          *
55935          * @returns {boolean} `true` if the interaction is enabled.
55936          */
55937         get isEnabled() {
55938             return this._enabled;
55939         }
55940         /**
55941          * Enables the interaction.
55942          *
55943          * @example
55944          * ```js
55945          * <component-name>.<handler-name>.enable();
55946          * ```
55947          */
55948         enable() {
55949             if (this._enabled || !this._component.activated) {
55950                 return;
55951             }
55952             this._enable();
55953             this._enabled = true;
55954             this._component.configure(this._getConfiguration(true));
55955         }
55956         /**
55957          * Disables the interaction.
55958          *
55959          * @example
55960          * ```js
55961          * <component-name>.<handler-name>.disable();
55962          * ```
55963          */
55964         disable() {
55965             if (!this._enabled) {
55966                 return;
55967             }
55968             this._disable();
55969             this._enabled = false;
55970             if (this._component.activated) {
55971                 this._component.configure(this._getConfiguration(false));
55972             }
55973         }
55974     }
55975
55976     /**
55977      * The `KeySequenceNavigationHandler` allows the user to navigate through a sequence using the
55978      * following key commands:
55979      *
55980      * `ALT` + `Up Arrow`: Navigate to next image in the sequence.
55981      * `ALT` + `Down Arrow`: Navigate to previous image in sequence.
55982      *
55983      * @example
55984      * ```js
55985      * var keyboardComponent = viewer.getComponent("keyboard");
55986      *
55987      * keyboardComponent.keySequenceNavigation.disable();
55988      * keyboardComponent.keySequenceNavigation.enable();
55989      *
55990      * var isEnabled = keyboardComponent.keySequenceNavigation.isEnabled;
55991      * ```
55992      */
55993     class KeySequenceNavigationHandler extends HandlerBase {
55994         _enable() {
55995             const sequenceEdges$ = this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
55996                 return image.sequenceEdges$;
55997             }));
55998             this._keyDownSubscription = this._container.keyboardService.keyDown$.pipe(withLatestFrom(sequenceEdges$))
55999                 .subscribe(([event, edgeStatus]) => {
56000                 let direction = null;
56001                 switch (event.keyCode) {
56002                     case 38: // up
56003                         direction = exports.NavigationDirection.Next;
56004                         break;
56005                     case 40: // down
56006                         direction = exports.NavigationDirection.Prev;
56007                         break;
56008                     default:
56009                         return;
56010                 }
56011                 event.preventDefault();
56012                 if (!event.altKey || event.shiftKey || !edgeStatus.cached) {
56013                     return;
56014                 }
56015                 for (const edge of edgeStatus.edges) {
56016                     if (edge.data.direction === direction) {
56017                         this._navigator.moveTo$(edge.target)
56018                             .subscribe(undefined, (error) => {
56019                             if (!(error instanceof CancelMapillaryError)) {
56020                                 console.error(error);
56021                             }
56022                         });
56023                         return;
56024                     }
56025                 }
56026             });
56027         }
56028         _disable() {
56029             this._keyDownSubscription.unsubscribe();
56030         }
56031         _getConfiguration(enable) {
56032             return { keySequenceNavigation: enable };
56033         }
56034     }
56035
56036     /**
56037      * The `KeySpatialNavigationHandler` allows the user to navigate through a sequence using the
56038      * following key commands:
56039      *
56040      * `Up Arrow`: Step forward.
56041      * `Down Arrow`: Step backward.
56042      * `Left Arrow`: Step to the left.
56043      * `Rigth Arrow`: Step to the right.
56044      * `SHIFT` + `Down Arrow`: Turn around.
56045      * `SHIFT` + `Left Arrow`: Turn to the left.
56046      * `SHIFT` + `Rigth Arrow`: Turn to the right.
56047      *
56048      * @example
56049      * ```js
56050      * var keyboardComponent = viewer.getComponent("keyboard");
56051      *
56052      * keyboardComponent.keySpatialNavigation.disable();
56053      * keyboardComponent.keySpatialNavigation.enable();
56054      *
56055      * var isEnabled = keyboardComponent.keySpatialNavigation.isEnabled;
56056      * ```
56057      */
56058     class KeySpatialNavigationHandler extends HandlerBase {
56059         /** @ignore */
56060         constructor(component, container, navigator, spatial) {
56061             super(component, container, navigator);
56062             this._spatial = spatial;
56063         }
56064         _enable() {
56065             const spatialEdges$ = this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
56066                 return image.spatialEdges$;
56067             }));
56068             this._keyDownSubscription = this._container.keyboardService.keyDown$.pipe(withLatestFrom(spatialEdges$, this._navigator.stateService.currentState$))
56069                 .subscribe(([event, edgeStatus, frame]) => {
56070                 let spherical = isSpherical(frame.state.currentImage.cameraType);
56071                 let direction = null;
56072                 switch (event.keyCode) {
56073                     case 37: // left
56074                         direction = event.shiftKey && !spherical ? exports.NavigationDirection.TurnLeft : exports.NavigationDirection.StepLeft;
56075                         break;
56076                     case 38: // up
56077                         direction = event.shiftKey && !spherical ? exports.NavigationDirection.Spherical : exports.NavigationDirection.StepForward;
56078                         break;
56079                     case 39: // right
56080                         direction = event.shiftKey && !spherical ? exports.NavigationDirection.TurnRight : exports.NavigationDirection.StepRight;
56081                         break;
56082                     case 40: // down
56083                         direction = event.shiftKey && !spherical ? exports.NavigationDirection.TurnU : exports.NavigationDirection.StepBackward;
56084                         break;
56085                     default:
56086                         return;
56087                 }
56088                 event.preventDefault();
56089                 if (event.altKey || !edgeStatus.cached ||
56090                     (event.shiftKey && spherical)) {
56091                     return;
56092                 }
56093                 if (!spherical) {
56094                     this._moveDir(direction, edgeStatus);
56095                 }
56096                 else {
56097                     const shifts = {};
56098                     shifts[exports.NavigationDirection.StepBackward] = Math.PI;
56099                     shifts[exports.NavigationDirection.StepForward] = 0;
56100                     shifts[exports.NavigationDirection.StepLeft] = Math.PI / 2;
56101                     shifts[exports.NavigationDirection.StepRight] = -Math.PI / 2;
56102                     const phi = this._rotationFromCamera(frame.state.camera).phi;
56103                     const navigationAngle = this._spatial.wrapAngle(phi + shifts[direction]);
56104                     const threshold = Math.PI / 4;
56105                     const edges = edgeStatus.edges.filter((e) => {
56106                         return e.data.direction === exports.NavigationDirection.Spherical || e.data.direction === direction;
56107                     });
56108                     let smallestAngle = Number.MAX_VALUE;
56109                     let toKey = null;
56110                     for (const edge of edges) {
56111                         const angle = Math.abs(this._spatial.wrapAngle(edge.data.worldMotionAzimuth - navigationAngle));
56112                         if (angle < Math.min(smallestAngle, threshold)) {
56113                             smallestAngle = angle;
56114                             toKey = edge.target;
56115                         }
56116                     }
56117                     if (toKey == null) {
56118                         return;
56119                     }
56120                     this._moveTo(toKey);
56121                 }
56122             });
56123         }
56124         _disable() {
56125             this._keyDownSubscription.unsubscribe();
56126         }
56127         _getConfiguration(enable) {
56128             return { keySpatialNavigation: enable };
56129         }
56130         _moveDir(direction, edgeStatus) {
56131             for (const edge of edgeStatus.edges) {
56132                 if (edge.data.direction === direction) {
56133                     this._moveTo(edge.target);
56134                     return;
56135                 }
56136             }
56137         }
56138         _moveTo(id) {
56139             this._navigator.moveTo$(id)
56140                 .subscribe(undefined, (error) => {
56141                 if (!(error instanceof CancelMapillaryError)) {
56142                     console.error(error);
56143                 }
56144             });
56145         }
56146         _rotationFromCamera(camera) {
56147             let direction = camera.lookat.clone().sub(camera.position);
56148             let upProjection = direction.clone().dot(camera.up);
56149             let planeProjection = direction.clone().sub(camera.up.clone().multiplyScalar(upProjection));
56150             let phi = Math.atan2(planeProjection.y, planeProjection.x);
56151             let theta = Math.PI / 2 - this._spatial.angleToPlane(direction.toArray(), [0, 0, 1]);
56152             return { phi: phi, theta: theta };
56153         }
56154     }
56155
56156     /**
56157      * The `KeyZoomHandler` allows the user to zoom in and out using the
56158      * following key commands:
56159      *
56160      * `+`: Zoom in.
56161      * `-`: Zoom out.
56162      *
56163      * @example
56164      * ```js
56165      * var keyboardComponent = viewer.getComponent("keyboard");
56166      *
56167      * keyboardComponent.keyZoom.disable();
56168      * keyboardComponent.keyZoom.enable();
56169      *
56170      * var isEnabled = keyboardComponent.keyZoom.isEnabled;
56171      * ```
56172      */
56173     class KeyZoomHandler extends HandlerBase {
56174         /** @ignore */
56175         constructor(component, container, navigator, viewportCoords) {
56176             super(component, container, navigator);
56177             this._viewportCoords = viewportCoords;
56178         }
56179         _enable() {
56180             this._keyDownSubscription = this._container.keyboardService.keyDown$.pipe(withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$))
56181                 .subscribe(([event, render, transform]) => {
56182                 if (event.altKey || event.ctrlKey || event.metaKey) {
56183                     return;
56184                 }
56185                 let delta = 0;
56186                 switch (event.key) {
56187                     case "+":
56188                         delta = 1;
56189                         break;
56190                     case "-":
56191                         delta = -1;
56192                         break;
56193                     default:
56194                         return;
56195                 }
56196                 event.preventDefault();
56197                 const unprojected = this._viewportCoords.unprojectFromViewport(0, 0, render.perspective);
56198                 const reference = transform.projectBasic(unprojected.toArray());
56199                 this._navigator.stateService.zoomIn(delta, reference);
56200             });
56201         }
56202         _disable() {
56203             this._keyDownSubscription.unsubscribe();
56204         }
56205         _getConfiguration(enable) {
56206             return { keyZoom: enable };
56207         }
56208     }
56209
56210     /**
56211      * The `KeyPlayHandler` allows the user to control the play behavior
56212      * using the following key commands:
56213      *
56214      * `Spacebar`: Start or stop playing.
56215      * `SHIFT` + `D`: Switch direction.
56216      * `<`: Decrease speed.
56217      * `>`: Increase speed.
56218      *
56219      * @example
56220      * ```js
56221      * var keyboardComponent = viewer.getComponent("keyboard");
56222      *
56223      * keyboardComponent.keyPlay.disable();
56224      * keyboardComponent.keyPlay.enable();
56225      *
56226      * var isEnabled = keyboardComponent.keyPlay.isEnabled;
56227      * ```
56228      */
56229     class KeyPlayHandler extends HandlerBase {
56230         _enable() {
56231             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) => {
56232                 return image.sequenceEdges$;
56233             })), this._navigator.stateService.state$.pipe(map((state) => {
56234                 return state === State.Earth;
56235             }), distinctUntilChanged())))
56236                 .subscribe(([event, playing, direction, speed, status, earth]) => {
56237                 if (event.altKey || event.ctrlKey || event.metaKey) {
56238                     return;
56239                 }
56240                 switch (event.key) {
56241                     case "D":
56242                         if (!event.shiftKey) {
56243                             return;
56244                         }
56245                         const newDirection = playing ?
56246                             null : direction === exports.NavigationDirection.Next ?
56247                             exports.NavigationDirection.Prev : direction === exports.NavigationDirection.Prev ?
56248                             exports.NavigationDirection.Next : null;
56249                         if (newDirection != null) {
56250                             this._navigator.playService.setDirection(newDirection);
56251                         }
56252                         break;
56253                     case " ":
56254                         if (event.shiftKey) {
56255                             return;
56256                         }
56257                         if (!earth) {
56258                             if (playing) {
56259                                 this._navigator.playService.stop();
56260                             }
56261                             else {
56262                                 for (let edge of status.edges) {
56263                                     if (edge.data.direction === direction) {
56264                                         this._navigator.playService.play();
56265                                     }
56266                                 }
56267                             }
56268                         }
56269                         break;
56270                     case "<":
56271                         this._navigator.playService.setSpeed(speed - 0.05);
56272                         break;
56273                     case ">":
56274                         this._navigator.playService.setSpeed(speed + 0.05);
56275                         break;
56276                     default:
56277                         return;
56278                 }
56279                 event.preventDefault();
56280             });
56281         }
56282         _disable() {
56283             this._keyDownSubscription.unsubscribe();
56284         }
56285         _getConfiguration(enable) {
56286             return { keyPlay: enable };
56287         }
56288     }
56289
56290     /**
56291      * @class KeyboardComponent
56292      *
56293      * @classdesc Component for keyboard event handling.
56294      *
56295      * To retrive and use the keyboard component
56296      *
56297      * @example
56298      * ```js
56299      * var viewer = new Viewer({ ... });
56300      *
56301      * var keyboardComponent = viewer.getComponent("keyboard");
56302      * ```
56303      */
56304     class KeyboardComponent extends Component {
56305         /** @ignore */
56306         constructor(name, container, navigator) {
56307             super(name, container, navigator);
56308             this._keyPlayHandler =
56309                 new KeyPlayHandler(this, container, navigator);
56310             this._keySequenceNavigationHandler =
56311                 new KeySequenceNavigationHandler(this, container, navigator);
56312             this._keySpatialNavigationHandler =
56313                 new KeySpatialNavigationHandler(this, container, navigator, new Spatial());
56314             this._keyZoomHandler =
56315                 new KeyZoomHandler(this, container, navigator, new ViewportCoords());
56316         }
56317         /**
56318          * Get key play.
56319          *
56320          * @returns {KeyPlayHandler} The key play handler.
56321          */
56322         get keyPlay() {
56323             return this._keyPlayHandler;
56324         }
56325         /**
56326          * Get key sequence navigation.
56327          *
56328          * @returns {KeySequenceNavigationHandler} The key sequence navigation handler.
56329          */
56330         get keySequenceNavigation() {
56331             return this._keySequenceNavigationHandler;
56332         }
56333         /**
56334          * Get spatial.
56335          *
56336          * @returns {KeySpatialNavigationHandler} The spatial handler.
56337          */
56338         get keySpatialNavigation() {
56339             return this._keySpatialNavigationHandler;
56340         }
56341         /**
56342          * Get key zoom.
56343          *
56344          * @returns {KeyZoomHandler} The key zoom handler.
56345          */
56346         get keyZoom() {
56347             return this._keyZoomHandler;
56348         }
56349         _activate() {
56350             this._subscriptions.push(this._configuration$
56351                 .subscribe((configuration) => {
56352                 if (configuration.keyPlay) {
56353                     this._keyPlayHandler.enable();
56354                 }
56355                 else {
56356                     this._keyPlayHandler.disable();
56357                 }
56358                 if (configuration.keySequenceNavigation) {
56359                     this._keySequenceNavigationHandler.enable();
56360                 }
56361                 else {
56362                     this._keySequenceNavigationHandler.disable();
56363                 }
56364                 if (configuration.keySpatialNavigation) {
56365                     this._keySpatialNavigationHandler.enable();
56366                 }
56367                 else {
56368                     this._keySpatialNavigationHandler.disable();
56369                 }
56370                 if (configuration.keyZoom) {
56371                     this._keyZoomHandler.enable();
56372                 }
56373                 else {
56374                     this._keyZoomHandler.disable();
56375                 }
56376             }));
56377         }
56378         _deactivate() {
56379             this._subscriptions.unsubscribe();
56380             this._keyPlayHandler.disable();
56381             this._keySequenceNavigationHandler.disable();
56382             this._keySpatialNavigationHandler.disable();
56383             this._keyZoomHandler.disable();
56384         }
56385         _getDefaultConfiguration() {
56386             return { keyPlay: true, keySequenceNavigation: true, keySpatialNavigation: true, keyZoom: true };
56387         }
56388     }
56389     KeyboardComponent.componentName = "keyboard";
56390
56391     class MarkerScene {
56392         constructor(scene, raycaster) {
56393             this._needsRender = false;
56394             this._interactiveObjects = [];
56395             this._markers = {};
56396             this._objectMarkers = {};
56397             this._raycaster = !!raycaster ? raycaster : new Raycaster();
56398             this._scene = !!scene ? scene : new Scene();
56399         }
56400         get markers() {
56401             return this._markers;
56402         }
56403         get needsRender() {
56404             return this._needsRender;
56405         }
56406         add(marker, position) {
56407             if (marker.id in this._markers) {
56408                 this._dispose(marker.id);
56409             }
56410             marker.createGeometry(position);
56411             this._scene.add(marker.geometry);
56412             this._markers[marker.id] = marker;
56413             for (let interactiveObject of marker.getInteractiveObjects()) {
56414                 this._interactiveObjects.push(interactiveObject);
56415                 this._objectMarkers[interactiveObject.uuid] = marker.id;
56416             }
56417             this._needsRender = true;
56418         }
56419         clear() {
56420             for (const id in this._markers) {
56421                 if (!this._markers.hasOwnProperty) {
56422                     continue;
56423                 }
56424                 this._dispose(id);
56425             }
56426             this._needsRender = true;
56427         }
56428         get(id) {
56429             return this._markers[id];
56430         }
56431         getAll() {
56432             return Object
56433                 .keys(this._markers)
56434                 .map((id) => { return this._markers[id]; });
56435         }
56436         has(id) {
56437             return id in this._markers;
56438         }
56439         intersectObjects([viewportX, viewportY], camera) {
56440             this._raycaster.setFromCamera(new Vector2(viewportX, viewportY), camera);
56441             const intersects = this._raycaster.intersectObjects(this._interactiveObjects);
56442             for (const intersect of intersects) {
56443                 if (intersect.object.uuid in this._objectMarkers) {
56444                     return this._objectMarkers[intersect.object.uuid];
56445                 }
56446             }
56447             return null;
56448         }
56449         lerpAltitude(id, alt, alpha) {
56450             if (!(id in this._markers)) {
56451                 return;
56452             }
56453             this._markers[id].lerpAltitude(alt, alpha);
56454             this._needsRender = true;
56455         }
56456         remove(id) {
56457             if (!(id in this._markers)) {
56458                 return;
56459             }
56460             this._dispose(id);
56461             this._needsRender = true;
56462         }
56463         render(perspectiveCamera, renderer) {
56464             renderer.render(this._scene, perspectiveCamera);
56465             this._needsRender = false;
56466         }
56467         update(id, position, lngLat) {
56468             if (!(id in this._markers)) {
56469                 return;
56470             }
56471             const marker = this._markers[id];
56472             marker.updatePosition(position, lngLat);
56473             this._needsRender = true;
56474         }
56475         _dispose(id) {
56476             const marker = this._markers[id];
56477             this._scene.remove(marker.geometry);
56478             for (let interactiveObject of marker.getInteractiveObjects()) {
56479                 const index = this._interactiveObjects.indexOf(interactiveObject);
56480                 if (index !== -1) {
56481                     this._interactiveObjects.splice(index, 1);
56482                 }
56483                 else {
56484                     console.warn(`Object does not exist (${interactiveObject.id}) for ${id}`);
56485                 }
56486                 delete this._objectMarkers[interactiveObject.uuid];
56487             }
56488             marker.disposeGeometry();
56489             delete this._markers[id];
56490         }
56491     }
56492
56493     /**
56494      * @class MarkerComponent
56495      *
56496      * @classdesc Component for showing and editing 3D marker objects.
56497      *
56498      * The `add` method is used for adding new markers or replacing
56499      * markers already in the set.
56500      *
56501      * If a marker already in the set has the same
56502      * id as one of the markers added, the old marker will be removed and
56503      * the added marker will take its place.
56504      *
56505      * It is not possible to update markers in the set by updating any properties
56506      * directly on the marker object. Markers need to be replaced by
56507      * re-adding them for updates to geographic position or configuration
56508      * to be reflected.
56509      *
56510      * Markers added to the marker component can be either interactive
56511      * or non-interactive. Different marker types define their behavior.
56512      * Markers with interaction support can be configured with options
56513      * to respond to dragging inside the viewer and be detected when
56514      * retrieving markers from pixel points with the `getMarkerIdAt` method.
56515      *
56516      * To retrive and use the marker component
56517      *
56518      * @example
56519      * ```js
56520      * var viewer = new Viewer({ component: { marker: true }, ... });
56521      *
56522      * var markerComponent = viewer.getComponent("marker");
56523      * ```
56524      */
56525     class MarkerComponent extends Component {
56526         /** @ignore */
56527         constructor(name, container, navigator) {
56528             super(name, container, navigator);
56529             this._graphCalculator = new GraphCalculator();
56530             this._markerScene = new MarkerScene();
56531             this._markerSet = new MarkerSet();
56532             this._viewportCoords = new ViewportCoords();
56533             this._relativeGroundAltitude = -2;
56534         }
56535         /**
56536          * Add markers to the marker set or replace markers in the marker set.
56537          *
56538          * @description If a marker already in the set has the same
56539          * id as one of the markers added, the old marker will be removed
56540          * the added marker will take its place.
56541          *
56542          * Any marker inside the visible bounding bbox
56543          * will be initialized and placed in the viewer.
56544          *
56545          * @param {Array<Marker>} markers - Markers to add.
56546          *
56547          * @example
56548          * ```js
56549          * markerComponent.add([marker1, marker2]);
56550          * ```
56551          */
56552         add(markers) {
56553             this._markerSet.add(markers);
56554         }
56555         fire(type, event) {
56556             super.fire(type, event);
56557         }
56558         /**
56559          * Returns the marker in the marker set with the specified id, or
56560          * undefined if the id matches no marker.
56561          *
56562          * @param {string} markerId - Id of the marker.
56563          *
56564          * @example
56565          * ```js
56566          * var marker = markerComponent.get("markerId");
56567          * ```
56568          *
56569          */
56570         get(markerId) {
56571             return this._markerSet.get(markerId);
56572         }
56573         /**
56574          * Returns an array of all markers.
56575          *
56576          * @example
56577          * ```js
56578          * var markers = markerComponent.getAll();
56579          * ```
56580          */
56581         getAll() {
56582             return this._markerSet.getAll();
56583         }
56584         /**
56585          * Returns the id of the interactive marker closest to the current camera
56586          * position at the specified point.
56587          *
56588          * @description Notice that the pixelPoint argument requires x, y
56589          * coordinates from pixel space.
56590          *
56591          * With this function, you can use the coordinates provided by mouse
56592          * events to get information out of the marker component.
56593          *
56594          * If no interactive geometry of an interactive marker exist at the pixel
56595          * point, `null` will be returned.
56596          *
56597          * @param {Array<number>} pixelPoint - Pixel coordinates on the viewer element.
56598          * @returns {string} Id of the interactive marker closest to the camera. If no
56599          * interactive marker exist at the pixel point, `null` will be returned.
56600          *
56601          * @example
56602          * ```js
56603          * markerComponent.getMarkerIdAt([100, 100])
56604          *     .then((markerId) => { console.log(markerId); });
56605          * ```
56606          */
56607         getMarkerIdAt(pixelPoint) {
56608             return new Promise((resolve, reject) => {
56609                 this._container.renderService.renderCamera$.pipe(first(), map((render) => {
56610                     const viewport = this._viewportCoords
56611                         .canvasToViewport(pixelPoint[0], pixelPoint[1], this._container.container);
56612                     const id = this._markerScene.intersectObjects(viewport, render.perspective);
56613                     return id;
56614                 }))
56615                     .subscribe((id) => {
56616                     resolve(id);
56617                 }, (error) => {
56618                     reject(error);
56619                 });
56620             });
56621         }
56622         /**
56623          * Check if a marker exist in the marker set.
56624          *
56625          * @param {string} markerId - Id of the marker.
56626          *
56627          * @example
56628          * ```js
56629          * var markerExists = markerComponent.has("markerId");
56630          * ```
56631          */
56632         has(markerId) {
56633             return this._markerSet.has(markerId);
56634         }
56635         off(type, handler) {
56636             super.off(type, handler);
56637         }
56638         on(type, handler) {
56639             super.on(type, handler);
56640         }
56641         /**
56642          * Remove markers with the specified ids from the marker set.
56643          *
56644          * @param {Array<string>} markerIds - Ids for markers to remove.
56645          *
56646          * @example
56647          * ```js
56648          * markerComponent.remove(["id-1", "id-2"]);
56649          * ```
56650          */
56651         remove(markerIds) {
56652             this._markerSet.remove(markerIds);
56653         }
56654         /**
56655          * Remove all markers from the marker set.
56656          *
56657          * @example
56658          * ```js
56659          * markerComponent.removeAll();
56660          * ```
56661          */
56662         removeAll() {
56663             this._markerSet.removeAll();
56664         }
56665         _activate() {
56666             const groundAltitude$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
56667                 return frame.state.camera.position.z + this._relativeGroundAltitude;
56668             }), distinctUntilChanged((a1, a2) => {
56669                 return Math.abs(a1 - a2) < 0.01;
56670             }), publishReplay(1), refCount());
56671             const geoInitiated$ = combineLatest(groundAltitude$, this._navigator.stateService.reference$).pipe(first(), map(() => { }), publishReplay(1), refCount());
56672             const clampedConfiguration$ = this._configuration$.pipe(map((configuration) => {
56673                 return { visibleBBoxSize: Math.max(1, Math.min(200, configuration.visibleBBoxSize)) };
56674             }));
56675             const currentLngLat$ = this._navigator.stateService.currentImage$.pipe(map((image) => { return image.lngLat; }), publishReplay(1), refCount());
56676             const visibleBBox$ = combineLatest(clampedConfiguration$, currentLngLat$).pipe(map(([configuration, lngLat]) => {
56677                 return this._graphCalculator
56678                     .boundingBoxCorners(lngLat, configuration.visibleBBoxSize / 2);
56679             }), publishReplay(1), refCount());
56680             const visibleMarkers$ = combineLatest(concat(of(this._markerSet), this._markerSet.changed$), visibleBBox$).pipe(map(([set, bbox]) => {
56681                 return set.search(bbox);
56682             }));
56683             const subs = this._subscriptions;
56684             subs.push(geoInitiated$.pipe(switchMap(() => {
56685                 return visibleMarkers$.pipe(withLatestFrom(this._navigator.stateService.reference$, groundAltitude$));
56686             }))
56687                 .subscribe(([markers, reference, alt]) => {
56688                 const markerScene = this._markerScene;
56689                 const sceneMarkers = markerScene.markers;
56690                 const markersToRemove = Object.assign({}, sceneMarkers);
56691                 for (const marker of markers) {
56692                     if (marker.id in sceneMarkers) {
56693                         delete markersToRemove[marker.id];
56694                     }
56695                     else {
56696                         const point3d = geodeticToEnu(marker.lngLat.lng, marker.lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
56697                         markerScene.add(marker, point3d);
56698                     }
56699                 }
56700                 for (const id in markersToRemove) {
56701                     if (!markersToRemove.hasOwnProperty(id)) {
56702                         continue;
56703                     }
56704                     markerScene.remove(id);
56705                 }
56706             }));
56707             subs.push(geoInitiated$.pipe(switchMap(() => {
56708                 return this._markerSet.updated$.pipe(withLatestFrom(visibleBBox$, this._navigator.stateService.reference$, groundAltitude$));
56709             }))
56710                 .subscribe(([markers, [sw, ne], reference, alt]) => {
56711                 const markerScene = this._markerScene;
56712                 for (const marker of markers) {
56713                     const exists = markerScene.has(marker.id);
56714                     const visible = marker.lngLat.lat > sw.lat &&
56715                         marker.lngLat.lat < ne.lat &&
56716                         marker.lngLat.lng > sw.lng &&
56717                         marker.lngLat.lng < ne.lng;
56718                     if (visible) {
56719                         const point3d = geodeticToEnu(marker.lngLat.lng, marker.lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
56720                         markerScene.add(marker, point3d);
56721                     }
56722                     else if (!visible && exists) {
56723                         markerScene.remove(marker.id);
56724                     }
56725                 }
56726             }));
56727             subs.push(this._navigator.stateService.reference$.pipe(skip(1), withLatestFrom(groundAltitude$))
56728                 .subscribe(([reference, alt]) => {
56729                 const markerScene = this._markerScene;
56730                 for (const marker of markerScene.getAll()) {
56731                     const point3d = geodeticToEnu(marker.lngLat.lng, marker.lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
56732                     markerScene.update(marker.id, point3d);
56733                 }
56734             }));
56735             subs.push(groundAltitude$.pipe(skip(1), withLatestFrom(this._navigator.stateService.reference$, currentLngLat$))
56736                 .subscribe(([alt, reference, lngLat]) => {
56737                 const markerScene = this._markerScene;
56738                 const position = geodeticToEnu(lngLat.lng, lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
56739                 for (const marker of markerScene.getAll()) {
56740                     const point3d = geodeticToEnu(marker.lngLat.lng, marker.lngLat.lat, reference.alt + alt, reference.lng, reference.lat, reference.alt);
56741                     const distanceX = point3d[0] - position[0];
56742                     const distanceY = point3d[1] - position[1];
56743                     const groundDistance = Math
56744                         .sqrt(distanceX * distanceX + distanceY * distanceY);
56745                     if (groundDistance > 50) {
56746                         continue;
56747                     }
56748                     markerScene.lerpAltitude(marker.id, alt, Math.min(1, Math.max(0, 1.2 - 1.2 * groundDistance / 50)));
56749                 }
56750             }));
56751             subs.push(this._navigator.stateService.currentState$
56752                 .pipe(map((frame) => {
56753                 const scene = this._markerScene;
56754                 return {
56755                     name: this._name,
56756                     renderer: {
56757                         frameId: frame.id,
56758                         needsRender: scene.needsRender,
56759                         render: scene.render.bind(scene),
56760                         pass: RenderPass.Opaque,
56761                     },
56762                 };
56763             }))
56764                 .subscribe(this._container.glRenderer.render$));
56765             const hoveredMarkerId$ = combineLatest(this._container.renderService.renderCamera$, this._container.mouseService.mouseMove$)
56766                 .pipe(map(([render, event]) => {
56767                 const element = this._container.container;
56768                 const [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
56769                 const viewport = this._viewportCoords
56770                     .canvasToViewport(canvasX, canvasY, element);
56771                 const markerId = this._markerScene.intersectObjects(viewport, render.perspective);
56772                 return markerId;
56773             }), publishReplay(1), refCount());
56774             const draggingStarted$ = this._container.mouseService
56775                 .filtered$(this._name, this._container.mouseService.mouseDragStart$).pipe(map(() => {
56776                 return true;
56777             }));
56778             const draggingStopped$ = this._container.mouseService
56779                 .filtered$(this._name, this._container.mouseService.mouseDragEnd$).pipe(map(() => {
56780                 return false;
56781             }));
56782             const filteredDragging$ = merge(draggingStarted$, draggingStopped$)
56783                 .pipe(startWith(false));
56784             subs.push(merge(draggingStarted$.pipe(withLatestFrom(hoveredMarkerId$)), combineLatest(draggingStopped$, of(null))).pipe(startWith([false, null]), pairwise())
56785                 .subscribe(([previous, current]) => {
56786                 const dragging = current[0];
56787                 const type = dragging ?
56788                     "markerdragstart" :
56789                     "markerdragend";
56790                 const id = dragging ? current[1] : previous[1];
56791                 const marker = this._markerScene.get(id);
56792                 const event = {
56793                     marker,
56794                     target: this,
56795                     type,
56796                 };
56797                 this.fire(type, event);
56798             }));
56799             const mouseDown$ = merge(this._container.mouseService.mouseDown$.pipe(map(() => { return true; })), this._container.mouseService.documentMouseUp$.pipe(map(() => { return false; }))).pipe(startWith(false));
56800             subs.push(combineLatest(this._container.mouseService.active$, hoveredMarkerId$.pipe(distinctUntilChanged()), mouseDown$, filteredDragging$)
56801                 .pipe(map(([active, markerId, mouseDown, filteredDragging]) => {
56802                 return (!active && markerId != null && mouseDown) ||
56803                     filteredDragging;
56804             }), distinctUntilChanged())
56805                 .subscribe((claim) => {
56806                 if (claim) {
56807                     this._container.mouseService.claimMouse(this._name, 1);
56808                     this._container.mouseService.claimWheel(this._name, 1);
56809                 }
56810                 else {
56811                     this._container.mouseService.unclaimMouse(this._name);
56812                     this._container.mouseService.unclaimWheel(this._name);
56813                 }
56814             }));
56815             const offset$ = this._container.mouseService
56816                 .filtered$(this._name, this._container.mouseService.mouseDragStart$).pipe(withLatestFrom(hoveredMarkerId$, this._container.renderService.renderCamera$), map(([e, id, r]) => {
56817                 const marker = this._markerScene.get(id);
56818                 const element = this._container.container;
56819                 const [groundCanvasX, groundCanvasY] = this._viewportCoords
56820                     .projectToCanvas(marker.geometry.position
56821                     .toArray(), element, r.perspective);
56822                 const [canvasX, canvasY] = this._viewportCoords
56823                     .canvasPosition(e, element);
56824                 const offset = [canvasX - groundCanvasX, canvasY - groundCanvasY];
56825                 return [marker, offset, r];
56826             }), publishReplay(1), refCount());
56827             subs.push(this._container.mouseService
56828                 .filtered$(this._name, this._container.mouseService.mouseDrag$)
56829                 .pipe(withLatestFrom(offset$, this._navigator.stateService.reference$, clampedConfiguration$))
56830                 .subscribe(([event, [marker, offset, render], reference, configuration]) => {
56831                 if (!this._markerScene.has(marker.id)) {
56832                     return;
56833                 }
56834                 const element = this._container.container;
56835                 const [canvasX, canvasY] = this._viewportCoords
56836                     .canvasPosition(event, element);
56837                 const groundX = canvasX - offset[0];
56838                 const groundY = canvasY - offset[1];
56839                 const [viewportX, viewportY] = this._viewportCoords
56840                     .canvasToViewport(groundX, groundY, element);
56841                 const direction = new Vector3(viewportX, viewportY, 1)
56842                     .unproject(render.perspective)
56843                     .sub(render.perspective.position)
56844                     .normalize();
56845                 const distance = Math.min(this._relativeGroundAltitude / direction.z, configuration.visibleBBoxSize / 2 - 0.1);
56846                 if (distance < 0) {
56847                     return;
56848                 }
56849                 const intersection = direction
56850                     .clone()
56851                     .multiplyScalar(distance)
56852                     .add(render.perspective.position);
56853                 intersection.z =
56854                     render.perspective.position.z
56855                         + this._relativeGroundAltitude;
56856                 const [lng, lat] = enuToGeodetic(intersection.x, intersection.y, intersection.z, reference.lng, reference.lat, reference.alt);
56857                 this._markerScene
56858                     .update(marker.id, intersection.toArray(), { lat, lng });
56859                 this._markerSet.update(marker);
56860                 const type = "markerposition";
56861                 const markerEvent = {
56862                     marker,
56863                     target: this,
56864                     type,
56865                 };
56866                 this.fire(type, markerEvent);
56867             }));
56868         }
56869         _deactivate() {
56870             this._subscriptions.unsubscribe();
56871             this._markerScene.clear();
56872         }
56873         _getDefaultConfiguration() {
56874             return { visibleBBoxSize: 100 };
56875         }
56876     }
56877     MarkerComponent.componentName = "marker";
56878
56879     function sign$1(n) {
56880         return n > 0 ? 1 : n < 0 ? -1 : 0;
56881     }
56882     function colinearPointOnSegment(p, s) {
56883         return p.x <= Math.max(s.p1.x, s.p2.x) &&
56884             p.x >= Math.min(s.p1.x, s.p2.x) &&
56885             p.y >= Math.max(s.p1.y, s.p2.y) &&
56886             p.y >= Math.min(s.p1.y, s.p2.y);
56887     }
56888     function parallel(s1, s2) {
56889         const ux = s1.p2.x - s1.p1.x;
56890         const uy = s1.p2.y - s1.p1.y;
56891         const vx = s2.p2.x - s2.p1.x;
56892         const vy = s2.p2.y - s2.p1.y;
56893         const cross = ux * vy - uy * vx;
56894         const u2 = ux * ux + uy * uy;
56895         const v2 = vx * vx + vy * vy;
56896         const epsilon2 = 1e-10;
56897         return cross * cross < epsilon2 * u2 * v2;
56898     }
56899     function tripletOrientation(p1, p2, p3) {
56900         const orientation = (p2.y - p1.y) * (p3.x - p2.x) -
56901             (p3.y - p2.y) * (p2.x - p1.x);
56902         return sign$1(orientation);
56903     }
56904     function segmentsIntersect(s1, s2) {
56905         if (parallel(s1, s2)) {
56906             return false;
56907         }
56908         const o1 = tripletOrientation(s1.p1, s1.p2, s2.p1);
56909         const o2 = tripletOrientation(s1.p1, s1.p2, s2.p2);
56910         const o3 = tripletOrientation(s2.p1, s2.p2, s1.p1);
56911         const o4 = tripletOrientation(s2.p1, s2.p2, s1.p2);
56912         if (o1 !== o2 && o3 !== o4) {
56913             return true;
56914         }
56915         if (o1 === 0 && colinearPointOnSegment(s2.p1, s1)) {
56916             return true;
56917         }
56918         if (o2 === 0 && colinearPointOnSegment(s2.p2, s1)) {
56919             return true;
56920         }
56921         if (o3 === 0 && colinearPointOnSegment(s1.p1, s2)) {
56922             return true;
56923         }
56924         if (o4 === 0 && colinearPointOnSegment(s1.p2, s2)) {
56925             return true;
56926         }
56927         return false;
56928     }
56929     function segmentIntersection(s1, s2) {
56930         if (parallel(s1, s2)) {
56931             return undefined;
56932         }
56933         const x1 = s1.p1.x;
56934         const x2 = s1.p2.x;
56935         const y1 = s1.p1.y;
56936         const y2 = s1.p2.y;
56937         const x3 = s2.p1.x;
56938         const x4 = s2.p2.x;
56939         const y3 = s2.p1.y;
56940         const y4 = s2.p2.y;
56941         const den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
56942         const xNum = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
56943         const yNum = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
56944         return { x: xNum / den, y: yNum / den };
56945     }
56946
56947     function basicBoundaryPoints(pointsPerSide) {
56948         let points = [];
56949         let os = [[0, 0], [1, 0], [1, 1], [0, 1]];
56950         let ds = [[1, 0], [0, 1], [-1, 0], [0, -1]];
56951         for (let side = 0; side < 4; ++side) {
56952             let o = os[side];
56953             let d = ds[side];
56954             for (let i = 0; i < pointsPerSide; ++i) {
56955                 points.push([o[0] + d[0] * i / pointsPerSide,
56956                     o[1] + d[1] * i / pointsPerSide]);
56957             }
56958         }
56959         return points;
56960     }
56961     function insideViewport(x, y) {
56962         return x >= -1 && x <= 1 && y >= -1 && y <= 1;
56963     }
56964     function insideBasic(x, y) {
56965         return x >= 0 && x <= 1 && y >= 0 && y <= 1;
56966     }
56967     function viewportDistances(transform, perspective, viewportCoords) {
56968         const boundaryPointsBasic = basicBoundaryPoints(100);
56969         const boundaryPointsViewport = boundaryPointsBasic
56970             .map((basic) => {
56971             return viewportCoords.basicToViewportSafe(basic[0], basic[1], transform, perspective);
56972         });
56973         const visibleBoundaryPoints = [];
56974         const viewportSides = [
56975             { x: -1, y: 1 },
56976             { x: 1, y: 1 },
56977             { x: 1, y: -1 },
56978             { x: -1, y: -1 }
56979         ];
56980         const intersections = [false, false, false, false];
56981         for (let i = 0; i < boundaryPointsViewport.length; i++) {
56982             const p1 = boundaryPointsViewport[i];
56983             const p2 = boundaryPointsViewport[(i + 1) % boundaryPointsViewport.length];
56984             if (p1 === null) {
56985                 continue;
56986             }
56987             if (p2 === null) {
56988                 if (insideViewport(p1[0], p1[1])) {
56989                     visibleBoundaryPoints.push(p1);
56990                 }
56991                 continue;
56992             }
56993             const [x1, y1] = p1;
56994             const [x2, y2] = p2;
56995             if (insideViewport(x1, y1)) {
56996                 if (insideViewport(x2, y2)) {
56997                     visibleBoundaryPoints.push(p1);
56998                 }
56999                 else {
57000                     for (let side = 0; side < 4; side++) {
57001                         const s1 = { p1: { x: x1, y: y1 }, p2: { x: x2, y: y2 } };
57002                         const s2 = { p1: viewportSides[side], p2: viewportSides[(side + 1) % 4] };
57003                         const intersecting = segmentsIntersect(s1, s2);
57004                         if (intersecting) {
57005                             const intersection = segmentIntersection(s1, s2);
57006                             visibleBoundaryPoints.push(p1, [intersection.x, intersection.y]);
57007                             intersections[side] = true;
57008                         }
57009                     }
57010                 }
57011             }
57012         }
57013         const [topLeftBasicX, topLeftBasicY] = viewportCoords.viewportToBasic(-1, 1, transform, perspective);
57014         const [topRightBasicX, topRightBasicY] = viewportCoords.viewportToBasic(1, 1, transform, perspective);
57015         const [bottomRightBasicX, bottomRightBasicY] = viewportCoords.viewportToBasic(1, -1, transform, perspective);
57016         const [bottomLeftBasicX, bottomLeftBasicY] = viewportCoords.viewportToBasic(-1, -1, transform, perspective);
57017         if (insideBasic(topLeftBasicX, topLeftBasicY)) {
57018             intersections[3] = intersections[0] = true;
57019         }
57020         if (insideBasic(topRightBasicX, topRightBasicY)) {
57021             intersections[0] = intersections[1] = true;
57022         }
57023         if (insideBasic(bottomRightBasicX, bottomRightBasicY)) {
57024             intersections[1] = intersections[2] = true;
57025         }
57026         if (insideBasic(bottomLeftBasicX, bottomLeftBasicY)) {
57027             intersections[2] = intersections[3] = true;
57028         }
57029         const maximums = [-1, -1, 1, 1];
57030         for (let visibleBoundaryPoint of visibleBoundaryPoints) {
57031             const x = visibleBoundaryPoint[0];
57032             const y = visibleBoundaryPoint[1];
57033             if (x > maximums[1]) {
57034                 maximums[1] = x;
57035             }
57036             if (x < maximums[3]) {
57037                 maximums[3] = x;
57038             }
57039             if (y > maximums[0]) {
57040                 maximums[0] = y;
57041             }
57042             if (y < maximums[2]) {
57043                 maximums[2] = y;
57044             }
57045         }
57046         const boundary = [1, 1, -1, -1];
57047         const distances = [];
57048         for (let side = 0; side < 4; side++) {
57049             if (intersections[side]) {
57050                 distances.push(0);
57051                 continue;
57052             }
57053             distances.push(Math.abs(boundary[side] - maximums[side]));
57054         }
57055         return distances;
57056     }
57057
57058     /**
57059      * The `BounceHandler` ensures that the viewer bounces back to the image
57060      * when drag panning outside of the image edge.
57061      */
57062     class BounceHandler extends HandlerBase {
57063         constructor(component, container, navigator, viewportCoords, spatial) {
57064             super(component, container, navigator);
57065             this._spatial = spatial;
57066             this._viewportCoords = viewportCoords;
57067         }
57068         _enable() {
57069             const inTransition$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
57070                 return frame.state.alpha < 1;
57071             }), distinctUntilChanged());
57072             this._bounceSubscription = combineLatest(inTransition$, this._navigator.stateService.inTranslation$, this._container.mouseService.active$, this._container.touchService.active$).pipe(map((noForce) => {
57073                 return noForce[0] || noForce[1] || noForce[2] || noForce[3];
57074             }), distinctUntilChanged(), switchMap((noForce) => {
57075                 return noForce ?
57076                     empty() :
57077                     combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$.pipe(first()));
57078             }), withLatestFrom(this._navigator.panService.panImages$))
57079                 .subscribe(([[render, transform], nts]) => {
57080                 if (!transform.hasValidScale && render.camera.focal < 0.1) {
57081                     return;
57082                 }
57083                 if (render.perspective.aspect === 0 || render.perspective.aspect === Number.POSITIVE_INFINITY) {
57084                     return;
57085                 }
57086                 const distances = viewportDistances(transform, render.perspective, this._viewportCoords);
57087                 const basic = this._viewportCoords.viewportToBasic(0, 0, transform, render.perspective);
57088                 if ((basic[0] < 0 || basic[0] > 1) && nts.length > 0) {
57089                     distances[0] = distances[2] = 0;
57090                 }
57091                 for (const [, t] of nts) {
57092                     const d = viewportDistances(t, render.perspective, this._viewportCoords);
57093                     for (let i = 1; i < distances.length; i += 2) {
57094                         if (d[i] < distances[i]) {
57095                             distances[i] = d[i];
57096                         }
57097                     }
57098                 }
57099                 if (Math.max(...distances) < 0.01) {
57100                     return;
57101                 }
57102                 const horizontalDistance = distances[1] - distances[3];
57103                 const verticalDistance = distances[0] - distances[2];
57104                 const currentDirection = this._viewportCoords
57105                     .unprojectFromViewport(0, 0, render.perspective)
57106                     .sub(render.perspective.position);
57107                 const directionPhi = this._viewportCoords
57108                     .unprojectFromViewport(horizontalDistance, 0, render.perspective)
57109                     .sub(render.perspective.position);
57110                 const directionTheta = this._viewportCoords
57111                     .unprojectFromViewport(0, verticalDistance, render.perspective)
57112                     .sub(render.perspective.position);
57113                 let phi = (horizontalDistance > 0 ? 1 : -1) * directionPhi.angleTo(currentDirection);
57114                 let theta = (verticalDistance > 0 ? 1 : -1) * directionTheta.angleTo(currentDirection);
57115                 const threshold = Math.PI / 60;
57116                 const coeff = 1e-1;
57117                 phi = this._spatial.clamp(coeff * phi, -threshold, threshold);
57118                 theta = this._spatial.clamp(coeff * theta, -threshold, threshold);
57119                 this._navigator.stateService.rotateUnbounded({ phi: phi, theta: theta });
57120             });
57121         }
57122         _disable() {
57123             this._bounceSubscription.unsubscribe();
57124         }
57125         _getConfiguration() {
57126             return {};
57127         }
57128     }
57129
57130     class MouseOperator {
57131         static filteredPairwiseMouseDrag$(name, mouseService) {
57132             return this._filteredPairwiseMouseDrag$(name, mouseService, mouseService.mouseDragStart$, mouseService.mouseDrag$, mouseService.mouseDragEnd$);
57133         }
57134         static filteredPairwiseMouseRightDrag$(name, mouseService) {
57135             return this._filteredPairwiseMouseDrag$(name, mouseService, mouseService.mouseRightDragStart$, mouseService.mouseRightDrag$, mouseService.mouseRightDragEnd$);
57136         }
57137         static _filteredPairwiseMouseDrag$(name, mouseService, mouseDragStart$, mouseDrag$, mouseDragEnd$) {
57138             return mouseService
57139                 .filtered$(name, mouseDragStart$).pipe(switchMap((mouseDragStart) => {
57140                 const dragging$ = concat(of(mouseDragStart), mouseService
57141                     .filtered$(name, mouseDrag$));
57142                 const dragEnd$ = mouseService
57143                     .filtered$(name, mouseDragEnd$).pipe(map(() => {
57144                     return null;
57145                 }));
57146                 return merge(dragging$, dragEnd$).pipe(takeWhile((e) => {
57147                     return !!e;
57148                 }), startWith(null));
57149             }), pairwise(), filter((pair) => {
57150                 return pair[0] != null && pair[1] != null;
57151             }));
57152         }
57153     }
57154
57155     /**
57156      * The `DragPanHandler` allows the user to pan the viewer image by clicking and dragging the cursor.
57157      *
57158      * @example
57159      * ```js
57160      * var pointerComponent = viewer.getComponent("pointer");
57161      *
57162      * pointerComponent.dragPan.disable();
57163      * pointerComponent.dragPan.enable();
57164      *
57165      * var isEnabled = pointerComponent.dragPan.isEnabled;
57166      * ```
57167      */
57168     class DragPanHandler extends HandlerBase {
57169         /** @ignore */
57170         constructor(component, container, navigator, viewportCoords, spatial) {
57171             super(component, container, navigator);
57172             this._spatial = spatial;
57173             this._viewportCoords = viewportCoords;
57174         }
57175         _enable() {
57176             let draggingStarted$ = this._container.mouseService
57177                 .filtered$(this._component.name, this._container.mouseService.mouseDragStart$).pipe(map(() => {
57178                 return true;
57179             }), share());
57180             let draggingStopped$ = this._container.mouseService
57181                 .filtered$(this._component.name, this._container.mouseService.mouseDragEnd$).pipe(map(() => {
57182                 return false;
57183             }), share());
57184             this._activeMouseSubscription = merge(draggingStarted$, draggingStopped$)
57185                 .subscribe(this._container.mouseService.activate$);
57186             const documentMouseMove$ = merge(draggingStarted$, draggingStopped$).pipe(switchMap((dragging) => {
57187                 return dragging ?
57188                     this._container.mouseService.documentMouseMove$ :
57189                     empty();
57190             }));
57191             this._preventDefaultSubscription = merge(documentMouseMove$, this._container.touchService.touchMove$)
57192                 .subscribe((event) => {
57193                 event.preventDefault(); // prevent selection of content outside the viewer
57194             });
57195             let touchMovingStarted$ = this._container.touchService.singleTouchDragStart$.pipe(map(() => {
57196                 return true;
57197             }));
57198             let touchMovingStopped$ = this._container.touchService.singleTouchDragEnd$.pipe(map(() => {
57199                 return false;
57200             }));
57201             this._activeTouchSubscription = merge(touchMovingStarted$, touchMovingStopped$)
57202                 .subscribe(this._container.touchService.activate$);
57203             const rotation$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
57204                 return isSpherical(frame.state.currentImage.cameraType) ||
57205                     frame.state.imagesAhead < 1;
57206             }), distinctUntilChanged(), switchMap((enable) => {
57207                 if (!enable) {
57208                     return empty();
57209                 }
57210                 const mouseDrag$ = MouseOperator.filteredPairwiseMouseDrag$(this._component.name, this._container.mouseService);
57211                 const singleTouchDrag$ = merge(this._container.touchService.singleTouchDragStart$, this._container.touchService.singleTouchDrag$, this._container.touchService.singleTouchDragEnd$.pipe(map(() => { return null; }))).pipe(map((event) => {
57212                     return event != null && event.touches.length > 0 ?
57213                         event.touches[0] : null;
57214                 }), pairwise(), filter((pair) => {
57215                     return pair[0] != null && pair[1] != null;
57216                 }));
57217                 return merge(mouseDrag$, singleTouchDrag$);
57218             }), withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$, this._navigator.panService.panImages$), map(([events, render, transform, nts]) => {
57219                 let previousEvent = events[0];
57220                 let event = events[1];
57221                 let movementX = event.clientX - previousEvent.clientX;
57222                 let movementY = event.clientY - previousEvent.clientY;
57223                 let element = this._container.container;
57224                 let [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
57225                 let currentDirection = this._viewportCoords.unprojectFromCanvas(canvasX, canvasY, element, render.perspective)
57226                     .sub(render.perspective.position);
57227                 let directionX = this._viewportCoords.unprojectFromCanvas(canvasX - movementX, canvasY, element, render.perspective)
57228                     .sub(render.perspective.position);
57229                 let directionY = this._viewportCoords.unprojectFromCanvas(canvasX, canvasY - movementY, element, render.perspective)
57230                     .sub(render.perspective.position);
57231                 let phi = (movementX > 0 ? 1 : -1) * directionX.angleTo(currentDirection);
57232                 let theta = (movementY > 0 ? -1 : 1) * directionY.angleTo(currentDirection);
57233                 const distances = viewportDistances(transform, render.perspective, this._viewportCoords);
57234                 for (const [, t] of nts) {
57235                     const d = viewportDistances(t, render.perspective, this._viewportCoords);
57236                     for (let i = 0; i < distances.length; i++) {
57237                         if (d[i] < distances[i]) {
57238                             distances[i] = d[i];
57239                         }
57240                     }
57241                 }
57242                 if (distances[0] > 0 && theta < 0) {
57243                     theta /= Math.max(1, 2e2 * distances[0]);
57244                 }
57245                 if (distances[2] > 0 && theta > 0) {
57246                     theta /= Math.max(1, 2e2 * distances[2]);
57247                 }
57248                 if (distances[1] > 0 && phi < 0) {
57249                     phi /= Math.max(1, 2e2 * distances[1]);
57250                 }
57251                 if (distances[3] > 0 && phi > 0) {
57252                     phi /= Math.max(1, 2e2 * distances[3]);
57253                 }
57254                 return { phi: phi, theta: theta };
57255             }), share());
57256             this._rotateWithoutInertiaSubscription = rotation$
57257                 .subscribe((rotation) => {
57258                 this._navigator.stateService.rotateWithoutInertia(rotation);
57259             });
57260             this._rotateSubscription = rotation$.pipe(scan((rotationBuffer, rotation) => {
57261                 this._drainBuffer(rotationBuffer);
57262                 rotationBuffer.push([Date.now(), rotation]);
57263                 return rotationBuffer;
57264             }, []), sample(merge(this._container.mouseService.filtered$(this._component.name, this._container.mouseService.mouseDragEnd$), this._container.touchService.singleTouchDragEnd$)), map((rotationBuffer) => {
57265                 const drainedBuffer = this._drainBuffer(rotationBuffer.slice());
57266                 const rotation = { phi: 0, theta: 0 };
57267                 for (const bufferedRotation of drainedBuffer) {
57268                     rotation.phi += bufferedRotation[1].phi;
57269                     rotation.theta += bufferedRotation[1].theta;
57270                 }
57271                 const count = drainedBuffer.length;
57272                 if (count > 0) {
57273                     rotation.phi /= count;
57274                     rotation.theta /= count;
57275                 }
57276                 const threshold = Math.PI / 18;
57277                 rotation.phi = this._spatial.clamp(rotation.phi, -threshold, threshold);
57278                 rotation.theta = this._spatial.clamp(rotation.theta, -threshold, threshold);
57279                 return rotation;
57280             }))
57281                 .subscribe((rotation) => {
57282                 this._navigator.stateService.rotate(rotation);
57283             });
57284         }
57285         _disable() {
57286             this._activeMouseSubscription.unsubscribe();
57287             this._activeTouchSubscription.unsubscribe();
57288             this._preventDefaultSubscription.unsubscribe();
57289             this._rotateSubscription.unsubscribe();
57290             this._rotateWithoutInertiaSubscription.unsubscribe();
57291             this._activeMouseSubscription = null;
57292             this._activeTouchSubscription = null;
57293             this._preventDefaultSubscription = null;
57294             this._rotateSubscription = null;
57295         }
57296         _getConfiguration(enable) {
57297             return { dragPan: enable };
57298         }
57299         _drainBuffer(buffer) {
57300             const cutoff = 50;
57301             const now = Date.now();
57302             while (buffer.length > 0 && now - buffer[0][0] > cutoff) {
57303                 buffer.shift();
57304             }
57305             return buffer;
57306         }
57307     }
57308
57309     class EarthControlHandler extends HandlerBase {
57310         /** @ignore */
57311         constructor(component, container, navigator, viewportCoords, spatial) {
57312             super(component, container, navigator);
57313             this._spatial = spatial;
57314             this._viewportCoords = viewportCoords;
57315             this._subscriptions = new SubscriptionHolder();
57316         }
57317         _enable() {
57318             const earth$ = this._navigator.stateService.state$.pipe(map((state) => {
57319                 return state === State.Earth;
57320             }), publishReplay(1), refCount());
57321             const subs = this._subscriptions;
57322             subs.push(earth$.pipe(switchMap((earth) => {
57323                 return earth ?
57324                     this._container.mouseService.mouseWheel$ :
57325                     empty();
57326             }))
57327                 .subscribe((event) => {
57328                 event.preventDefault();
57329             }));
57330             subs.push(earth$.pipe(switchMap((earth) => {
57331                 if (!earth) {
57332                     return empty();
57333                 }
57334                 return MouseOperator.filteredPairwiseMouseDrag$(this._component.name, this._container.mouseService).pipe(filter(([e1, e2]) => {
57335                     return !(e1.ctrlKey && e2.ctrlKey);
57336                 }));
57337             }), withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$), map(([[previous, current], render, transform]) => {
57338                 const planeNormal = [0, 0, 1];
57339                 const planePoint = [0, 0, -2];
57340                 const currentIntersection = this._planeIntersection(current, planeNormal, planePoint, render.perspective, this._container.container);
57341                 const previousIntersection = this._planeIntersection(previous, planeNormal, planePoint, render.perspective, this._container.container);
57342                 if (!currentIntersection || !previousIntersection) {
57343                     return null;
57344                 }
57345                 const direction = new Vector3()
57346                     .subVectors(currentIntersection, previousIntersection)
57347                     .multiplyScalar(-1)
57348                     .toArray();
57349                 return direction;
57350             }), filter((direction) => {
57351                 return !!direction;
57352             }))
57353                 .subscribe((direction) => {
57354                 this._navigator.stateService.truck(direction);
57355             }));
57356             subs.push(earth$.pipe(switchMap((earth) => {
57357                 if (!earth) {
57358                     return empty();
57359                 }
57360                 return MouseOperator.filteredPairwiseMouseDrag$(this._component.name, this._container.mouseService).pipe(filter(([e1, e2]) => {
57361                     return e1.ctrlKey && e2.ctrlKey;
57362                 }));
57363             }), map(([previous, current]) => {
57364                 return this._mousePairToRotation(previous, current);
57365             }))
57366                 .subscribe((rotation) => {
57367                 this._navigator.stateService.orbit(rotation);
57368             }));
57369             subs.push(earth$.pipe(switchMap((earth) => {
57370                 if (!earth) {
57371                     return empty();
57372                 }
57373                 return MouseOperator.filteredPairwiseMouseRightDrag$(this._component.name, this._container.mouseService).pipe(filter(([e1, e2]) => {
57374                     return !e1.ctrlKey && !e2.ctrlKey;
57375                 }));
57376             }), map(([previous, current]) => {
57377                 return this._mousePairToRotation(previous, current);
57378             }))
57379                 .subscribe((rotation) => {
57380                 this._navigator.stateService.orbit(rotation);
57381             }));
57382             subs.push(earth$.pipe(switchMap((earth) => {
57383                 if (!earth) {
57384                     return empty();
57385                 }
57386                 return this._container.mouseService
57387                     .filteredWheel$(this._component.name, this._container.mouseService.mouseWheel$);
57388             }), map((event) => {
57389                 let delta = event.deltaY;
57390                 if (event.deltaMode === 1) {
57391                     delta = 40 * delta;
57392                 }
57393                 else if (event.deltaMode === 2) {
57394                     delta = 800 * delta;
57395                 }
57396                 const canvasSize = this._viewportCoords.containerToCanvas(this._container.container);
57397                 return -delta / canvasSize[1];
57398             }))
57399                 .subscribe((delta) => {
57400                 this._navigator.stateService.dolly(delta);
57401             }));
57402         }
57403         _disable() {
57404             this._subscriptions.unsubscribe();
57405         }
57406         _getConfiguration() {
57407             return {};
57408         }
57409         _eventToViewport(event, element) {
57410             const previousCanvas = this._viewportCoords.canvasPosition(event, element);
57411             return this._viewportCoords.canvasToViewport(previousCanvas[0], previousCanvas[1], element);
57412         }
57413         _mousePairToRotation(previous, current) {
57414             const [currentX, currentY] = this._eventToViewport(current, this._container.container);
57415             const [previousX, previousY] = this._eventToViewport(previous, this._container.container);
57416             const phi = (previousX - currentX) * Math.PI;
57417             const theta = (currentY - previousY) * Math.PI / 2;
57418             return { phi: phi, theta: theta };
57419         }
57420         _planeIntersection(event, planeNormal, planePoint, camera, element) {
57421             const [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
57422             const direction = this._viewportCoords
57423                 .unprojectFromCanvas(canvasX, canvasY, element, camera)
57424                 .sub(camera.position)
57425                 .normalize();
57426             if (Math.abs(this._spatial.angleToPlane(direction.toArray(), planeNormal)) < Math.PI / 90) {
57427                 return null;
57428             }
57429             const l0 = camera.position.clone();
57430             const n = new Vector3().fromArray(planeNormal);
57431             const p0 = new Vector3().fromArray(planePoint);
57432             const d = new Vector3().subVectors(p0, l0).dot(n) / direction.clone().dot(n);
57433             const intersection = new Vector3().addVectors(l0, direction.multiplyScalar(d));
57434             if (this._viewportCoords.worldToCamera(intersection.toArray(), camera)[2] > 0) {
57435                 return null;
57436             }
57437             return intersection;
57438         }
57439     }
57440
57441     /**
57442      * The `ScrollZoomHandler` allows the user to zoom the viewer image by scrolling.
57443      *
57444      * @example
57445      * ```js
57446      * var pointerComponent = viewer.getComponent("pointer");
57447      *
57448      * pointerComponent.scrollZoom.disable();
57449      * pointerComponent.scrollZoom.enable();
57450      *
57451      * var isEnabled = pointerComponent.scrollZoom.isEnabled;
57452      * ```
57453      */
57454     class ScrollZoomHandler extends HandlerBase {
57455         /** @ignore */
57456         constructor(component, container, navigator, viewportCoords) {
57457             super(component, container, navigator);
57458             this._viewportCoords = viewportCoords;
57459         }
57460         _enable() {
57461             this._container.mouseService.claimWheel(this._component.name, 0);
57462             this._preventDefaultSubscription = this._container.mouseService.mouseWheel$
57463                 .subscribe((event) => {
57464                 event.preventDefault();
57465             });
57466             this._zoomSubscription = this._container.mouseService
57467                 .filteredWheel$(this._component.name, this._container.mouseService.mouseWheel$).pipe(withLatestFrom(this._navigator.stateService.currentState$, (w, f) => {
57468                 return [w, f];
57469             }), filter((args) => {
57470                 let state = args[1].state;
57471                 return isSpherical(state.currentImage.cameraType) ||
57472                     state.imagesAhead < 1;
57473             }), map((args) => {
57474                 return args[0];
57475             }), withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$, (w, r, t) => {
57476                 return [w, r, t];
57477             }))
57478                 .subscribe((args) => {
57479                 let event = args[0];
57480                 let render = args[1];
57481                 let transform = args[2];
57482                 let element = this._container.container;
57483                 let [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
57484                 let unprojected = this._viewportCoords.unprojectFromCanvas(canvasX, canvasY, element, render.perspective);
57485                 let reference = transform.projectBasic(unprojected.toArray());
57486                 let deltaY = event.deltaY;
57487                 if (event.deltaMode === 1) {
57488                     deltaY = 40 * deltaY;
57489                 }
57490                 else if (event.deltaMode === 2) {
57491                     deltaY = 800 * deltaY;
57492                 }
57493                 const canvasSize = this._viewportCoords.containerToCanvas(element);
57494                 let zoom = -3 * deltaY / canvasSize[1];
57495                 this._navigator.stateService.zoomIn(zoom, reference);
57496             });
57497         }
57498         _disable() {
57499             this._container.mouseService.unclaimWheel(this._component.name);
57500             this._preventDefaultSubscription.unsubscribe();
57501             this._zoomSubscription.unsubscribe();
57502             this._preventDefaultSubscription = null;
57503             this._zoomSubscription = null;
57504         }
57505         _getConfiguration(enable) {
57506             return { scrollZoom: enable };
57507         }
57508     }
57509
57510     /**
57511      * The `TouchZoomHandler` allows the user to zoom the viewer image by pinching on a touchscreen.
57512      *
57513      * @example
57514      * ```js
57515      * var pointerComponent = viewer.getComponent("pointer");
57516      *
57517      * pointerComponent.touchZoom.disable();
57518      * pointerComponent.touchZoom.enable();
57519      *
57520      * var isEnabled = pointerComponent.touchZoom.isEnabled;
57521      * ```
57522      */
57523     class TouchZoomHandler extends HandlerBase {
57524         /** @ignore */
57525         constructor(component, container, navigator, viewportCoords) {
57526             super(component, container, navigator);
57527             this._viewportCoords = viewportCoords;
57528         }
57529         _enable() {
57530             this._preventDefaultSubscription = this._container.touchService.pinch$
57531                 .subscribe((pinch) => {
57532                 pinch.originalEvent.preventDefault();
57533             });
57534             let pinchStarted$ = this._container.touchService.pinchStart$.pipe(map((event) => {
57535                 return true;
57536             }));
57537             let pinchStopped$ = this._container.touchService.pinchEnd$.pipe(map((event) => {
57538                 return false;
57539             }));
57540             this._activeSubscription = merge(pinchStarted$, pinchStopped$)
57541                 .subscribe(this._container.touchService.activate$);
57542             this._zoomSubscription = this._container.touchService.pinch$.pipe(withLatestFrom(this._navigator.stateService.currentState$), filter((args) => {
57543                 let state = args[1].state;
57544                 return isSpherical(state.currentImage.cameraType) ||
57545                     state.imagesAhead < 1;
57546             }), map((args) => {
57547                 return args[0];
57548             }), withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$))
57549                 .subscribe(([pinch, render, transform]) => {
57550                 let element = this._container.container;
57551                 let [canvasX, canvasY] = this._viewportCoords.canvasPosition(pinch, element);
57552                 let unprojected = this._viewportCoords.unprojectFromCanvas(canvasX, canvasY, element, render.perspective);
57553                 let reference = transform.projectBasic(unprojected.toArray());
57554                 const [canvasWidth, canvasHeight] = this._viewportCoords.containerToCanvas(element);
57555                 let zoom = 3 * pinch.distanceChange / Math.min(canvasWidth, canvasHeight);
57556                 this._navigator.stateService.zoomIn(zoom, reference);
57557             });
57558         }
57559         _disable() {
57560             this._activeSubscription.unsubscribe();
57561             this._preventDefaultSubscription.unsubscribe();
57562             this._zoomSubscription.unsubscribe();
57563             this._preventDefaultSubscription = null;
57564             this._zoomSubscription = null;
57565         }
57566         _getConfiguration(enable) {
57567             return { touchZoom: enable };
57568         }
57569     }
57570
57571     /**
57572      * @class PointerComponent
57573      *
57574      * @classdesc Component handling mouse, pen, and touch events for camera movement.
57575      *
57576      * To retrive and use the mouse component
57577      *
57578      * @example
57579      * ```js
57580      * var viewer = new Viewer({ ... });
57581      *
57582      * var pointerComponent = viewer.getComponent("pointer");
57583      * ```
57584      */
57585     class PointerComponent extends Component {
57586         /** @ignore */
57587         constructor(name, container, navigator) {
57588             super(name, container, navigator);
57589             const spatial = new Spatial();
57590             const viewportCoords = new ViewportCoords();
57591             this._bounceHandler =
57592                 new BounceHandler(this, container, navigator, viewportCoords, spatial);
57593             this._dragPanHandler =
57594                 new DragPanHandler(this, container, navigator, viewportCoords, spatial);
57595             this._earthControlHandler =
57596                 new EarthControlHandler(this, container, navigator, viewportCoords, spatial);
57597             this._scrollZoomHandler =
57598                 new ScrollZoomHandler(this, container, navigator, viewportCoords);
57599             this._touchZoomHandler =
57600                 new TouchZoomHandler(this, container, navigator, viewportCoords);
57601         }
57602         /**
57603          * Get drag pan.
57604          *
57605          * @returns {DragPanHandler} The drag pan handler.
57606          */
57607         get dragPan() {
57608             return this._dragPanHandler;
57609         }
57610         /**
57611          * Get earth control.
57612          *
57613          * @returns {EarthControlHandler} The earth control handler.
57614          */
57615         get earthControl() {
57616             return this._earthControlHandler;
57617         }
57618         /**
57619          * Get scroll zoom.
57620          *
57621          * @returns {ScrollZoomHandler} The scroll zoom handler.
57622          */
57623         get scrollZoom() {
57624             return this._scrollZoomHandler;
57625         }
57626         /**
57627          * Get touch zoom.
57628          *
57629          * @returns {TouchZoomHandler} The touch zoom handler.
57630          */
57631         get touchZoom() {
57632             return this._touchZoomHandler;
57633         }
57634         _activate() {
57635             this._bounceHandler.enable();
57636             this._subscriptions.push(this._configuration$
57637                 .subscribe((configuration) => {
57638                 if (configuration.dragPan) {
57639                     this._dragPanHandler.enable();
57640                 }
57641                 else {
57642                     this._dragPanHandler.disable();
57643                 }
57644                 if (configuration.earthControl) {
57645                     this._earthControlHandler.enable();
57646                 }
57647                 else {
57648                     this._earthControlHandler.disable();
57649                 }
57650                 if (configuration.scrollZoom) {
57651                     this._scrollZoomHandler.enable();
57652                 }
57653                 else {
57654                     this._scrollZoomHandler.disable();
57655                 }
57656                 if (configuration.touchZoom) {
57657                     this._touchZoomHandler.enable();
57658                 }
57659                 else {
57660                     this._touchZoomHandler.disable();
57661                 }
57662             }));
57663             this._container.mouseService.claimMouse(this._name, 0);
57664         }
57665         _deactivate() {
57666             this._container.mouseService.unclaimMouse(this._name);
57667             this._subscriptions.unsubscribe();
57668             this._bounceHandler.disable();
57669             this._dragPanHandler.disable();
57670             this._earthControlHandler.disable();
57671             this._scrollZoomHandler.disable();
57672             this._touchZoomHandler.disable();
57673         }
57674         _getDefaultConfiguration() {
57675             return {
57676                 dragPan: true,
57677                 earthControl: true,
57678                 scrollZoom: true,
57679                 touchZoom: true,
57680             };
57681         }
57682     }
57683     /** @inheritdoc */
57684     PointerComponent.componentName = "pointer";
57685
57686     class DOM {
57687         constructor(doc) {
57688             this._document = !!doc ? doc : document;
57689         }
57690         get document() {
57691             return this._document;
57692         }
57693         createElement(tagName, className, container) {
57694             const element = this._document.createElement(tagName);
57695             if (!!className) {
57696                 element.className = className;
57697             }
57698             if (!!container) {
57699                 container.appendChild(element);
57700             }
57701             return element;
57702         }
57703     }
57704
57705     /**
57706      * @class PopupComponent
57707      *
57708      * @classdesc Component for showing HTML popup objects.
57709      *
57710      * The `add` method is used for adding new popups. Popups are removed by reference.
57711      *
57712      * It is not possible to update popups in the set by updating any properties
57713      * directly on the popup object. Popups need to be replaced by
57714      * removing them and creating new ones with relevant changed properties and
57715      * adding those instead.
57716      *
57717      * Popups are only relevant to a single image because they are based on
57718      * 2D basic image coordinates. Popups related to a certain image should
57719      * be removed when the viewer is moved to another image.
57720      *
57721      * To retrive and use the popup component
57722      *
57723      * @example
57724      * ```js
57725      * var viewer = new Viewer({ component: { popup: true }, ... });
57726      *
57727      * var popupComponent = viewer.getComponent("popup");
57728      * ```
57729      */
57730     class PopupComponent extends Component {
57731         /** @ignore */
57732         constructor(name, container, navigator, dom) {
57733             super(name, container, navigator);
57734             this._dom = !!dom ? dom : new DOM();
57735             this._popups = [];
57736             this._added$ = new Subject();
57737             this._popups$ = new Subject();
57738         }
57739         /**
57740          * Add popups to the popups set.
57741          *
57742          * @description Adding a new popup never replaces an old one
57743          * because they are stored by reference. Adding an already
57744          * existing popup has no effect.
57745          *
57746          * @param {Array<Popup>} popups - Popups to add.
57747          *
57748          * @example
57749          * ```js
57750          * popupComponent.add([popup1, popup2]);
57751          * ```
57752          */
57753         add(popups) {
57754             for (const popup of popups) {
57755                 if (this._popups.indexOf(popup) !== -1) {
57756                     continue;
57757                 }
57758                 this._popups.push(popup);
57759                 if (this._activated) {
57760                     popup.setParentContainer(this._popupContainer);
57761                 }
57762             }
57763             this._added$.next(popups);
57764             this._popups$.next(this._popups);
57765         }
57766         /**
57767          * Returns an array of all popups.
57768          *
57769          * @example
57770          * ```js
57771          * var popups = popupComponent.getAll();
57772          * ```
57773          */
57774         getAll() {
57775             return this._popups.slice();
57776         }
57777         /**
57778          * Remove popups based on reference from the popup set.
57779          *
57780          * @param {Array<Popup>} popups - Popups to remove.
57781          *
57782          * @example
57783          * ```js
57784          * popupComponent.remove([popup1, popup2]);
57785          * ```
57786          */
57787         remove(popups) {
57788             for (const popup of popups) {
57789                 this._remove(popup);
57790             }
57791             this._popups$.next(this._popups);
57792         }
57793         /**
57794          * Remove all popups from the popup set.
57795          *
57796          * @example
57797          * ```js
57798          * popupComponent.removeAll();
57799          * ```
57800          */
57801         removeAll() {
57802             for (const popup of this._popups.slice()) {
57803                 this._remove(popup);
57804             }
57805             this._popups$.next(this._popups);
57806         }
57807         _activate() {
57808             this._popupContainer = this._dom.createElement("div", "mapillary-popup-container", this._container.container);
57809             for (const popup of this._popups) {
57810                 popup.setParentContainer(this._popupContainer);
57811             }
57812             const subs = this._subscriptions;
57813             subs.push(combineLatest(this._container.renderService.renderCamera$, this._container.renderService.size$, this._navigator.stateService.currentTransform$)
57814                 .subscribe(([renderCamera, size, transform]) => {
57815                 for (const popup of this._popups) {
57816                     popup.update(renderCamera, size, transform);
57817                 }
57818             }));
57819             const changed$ = this._popups$.pipe(startWith(this._popups), switchMap((popups) => {
57820                 return from(popups).pipe(mergeMap((popup) => {
57821                     return popup.changed$;
57822                 }));
57823             }), map((popup) => {
57824                 return [popup];
57825             }));
57826             subs.push(merge(this._added$, changed$).pipe(withLatestFrom(this._container.renderService.renderCamera$, this._container.renderService.size$, this._navigator.stateService.currentTransform$))
57827                 .subscribe(([popups, renderCamera, size, transform]) => {
57828                 for (const popup of popups) {
57829                     popup.update(renderCamera, size, transform);
57830                 }
57831             }));
57832         }
57833         _deactivate() {
57834             this._subscriptions.unsubscribe();
57835             for (const popup of this._popups) {
57836                 popup.remove();
57837             }
57838             this._container.container.removeChild(this._popupContainer);
57839             delete this._popupContainer;
57840         }
57841         _getDefaultConfiguration() {
57842             return {};
57843         }
57844         _remove(popup) {
57845             const index = this._popups.indexOf(popup);
57846             if (index === -1) {
57847                 return;
57848             }
57849             const removed = this._popups.splice(index, 1)[0];
57850             if (this._activated) {
57851                 removed.remove();
57852             }
57853         }
57854     }
57855     PopupComponent.componentName = "popup";
57856
57857     /**
57858      * Enumeration for graph modes.
57859      * @enum {number}
57860      * @readonly
57861      * @description Modes for the retrieval and caching performed
57862      * by the graph service on the graph.
57863      */
57864     var GraphMode;
57865     (function (GraphMode) {
57866         /**
57867          * Caching is performed on sequences only and sequence edges are
57868          * calculated. Spatial tiles
57869          * are not retrieved and spatial edges are not calculated when
57870          * caching nodes. Complete sequences are being cached for requested
57871          * nodes within the graph.
57872          */
57873         GraphMode[GraphMode["Sequence"] = 0] = "Sequence";
57874         /**
57875          * Caching is performed with emphasis on spatial data. Sequence edges
57876          * as well as spatial edges are cached. Sequence data
57877          * is still requested but complete sequences are not being cached
57878          * for requested nodes.
57879          *
57880          * This is the initial mode of the graph service.
57881          */
57882         GraphMode[GraphMode["Spatial"] = 1] = "Spatial";
57883     })(GraphMode || (GraphMode = {}));
57884
57885     var SequenceMode;
57886     (function (SequenceMode) {
57887         SequenceMode[SequenceMode["Default"] = 0] = "Default";
57888         SequenceMode[SequenceMode["Playback"] = 1] = "Playback";
57889         SequenceMode[SequenceMode["Timeline"] = 2] = "Timeline";
57890     })(SequenceMode || (SequenceMode = {}));
57891
57892     class SequenceDOMRenderer {
57893         constructor(container) {
57894             this._container = container;
57895             this._minThresholdWidth = 320;
57896             this._maxThresholdWidth = 1480;
57897             this._minThresholdHeight = 240;
57898             this._maxThresholdHeight = 820;
57899             this._stepperDefaultWidth = 108;
57900             this._controlsDefaultWidth = 88;
57901             this._defaultHeight = 30;
57902             this._expandControls = false;
57903             this._mode = SequenceMode.Default;
57904             this._speed = 0.5;
57905             this._changingSpeed = false;
57906             this._index = null;
57907             this._changingPosition = false;
57908             this._mouseEnterDirection$ = new Subject();
57909             this._mouseLeaveDirection$ = new Subject();
57910             this._notifyChanged$ = new Subject();
57911             this._notifyChangingPositionChanged$ = new Subject();
57912             this._notifySpeedChanged$ = new Subject();
57913             this._notifyIndexChanged$ = new Subject();
57914         }
57915         get changed$() {
57916             return this._notifyChanged$;
57917         }
57918         get changingPositionChanged$() {
57919             return this._notifyChangingPositionChanged$;
57920         }
57921         get speed$() {
57922             return this._notifySpeedChanged$;
57923         }
57924         get index$() {
57925             return this._notifyIndexChanged$;
57926         }
57927         get mouseEnterDirection$() {
57928             return this._mouseEnterDirection$;
57929         }
57930         get mouseLeaveDirection$() {
57931             return this._mouseLeaveDirection$;
57932         }
57933         activate() {
57934             if (!!this._changingSubscription) {
57935                 return;
57936             }
57937             this._changingSubscription = merge(this._container.mouseService.documentMouseUp$, this._container.touchService.touchEnd$.pipe(filter((touchEvent) => {
57938                 return touchEvent.touches.length === 0;
57939             })))
57940                 .subscribe(() => {
57941                 if (this._changingSpeed) {
57942                     this._changingSpeed = false;
57943                 }
57944                 if (this._changingPosition) {
57945                     this._setChangingPosition(false);
57946                 }
57947             });
57948         }
57949         deactivate() {
57950             if (!this._changingSubscription) {
57951                 return;
57952             }
57953             this._changingSpeed = false;
57954             this._changingPosition = false;
57955             this._expandControls = false;
57956             this._mode = SequenceMode.Default;
57957             this._changingSubscription.unsubscribe();
57958             this._changingSubscription = null;
57959         }
57960         render(edgeStatus, configuration, containerWidth, speed, index, max, playEnabled, component, navigator) {
57961             if (configuration.visible === false) {
57962                 return virtualDom.h("div.mapillary-sequence-container", {}, []);
57963             }
57964             const stepper = this._createStepper(edgeStatus, configuration, playEnabled, containerWidth, component, navigator);
57965             const controls = this._createSequenceControls(containerWidth);
57966             const playback = this._createPlaybackControls(containerWidth, speed, component, configuration);
57967             const timeline = this._createTimelineControls(containerWidth, index, max);
57968             return virtualDom.h("div.mapillary-sequence-container", [stepper, controls, playback, timeline]);
57969         }
57970         getContainerWidth(size, configuration) {
57971             let minWidth = configuration.minWidth;
57972             let maxWidth = configuration.maxWidth;
57973             if (maxWidth < minWidth) {
57974                 maxWidth = minWidth;
57975             }
57976             let relativeWidth = (size.width - this._minThresholdWidth) / (this._maxThresholdWidth - this._minThresholdWidth);
57977             let relativeHeight = (size.height - this._minThresholdHeight) / (this._maxThresholdHeight - this._minThresholdHeight);
57978             let coeff = Math.max(0, Math.min(1, Math.min(relativeWidth, relativeHeight)));
57979             return minWidth + coeff * (maxWidth - minWidth);
57980         }
57981         _createPositionInput(index, max) {
57982             this._index = index;
57983             const onPosition = (e) => {
57984                 this._index = Number(e.target.value);
57985                 this._notifyIndexChanged$.next(this._index);
57986             };
57987             const boundingRect = this._container.domContainer.getBoundingClientRect();
57988             const width = Math.max(276, Math.min(410, 5 + 0.8 * boundingRect.width)) - 65;
57989             const onStart = (e) => {
57990                 e.stopPropagation();
57991                 this._setChangingPosition(true);
57992             };
57993             const onMove = (e) => {
57994                 if (this._changingPosition === true) {
57995                     e.stopPropagation();
57996                 }
57997             };
57998             const onKeyDown = (e) => {
57999                 if (e.key === "ArrowDown" || e.key === "ArrowLeft" ||
58000                     e.key === "ArrowRight" || e.key === "ArrowUp") {
58001                     e.preventDefault();
58002                 }
58003             };
58004             const positionInputProperties = {
58005                 max: max != null ? max : 1,
58006                 min: 0,
58007                 onchange: onPosition,
58008                 oninput: onPosition,
58009                 onkeydown: onKeyDown,
58010                 onpointerdown: onStart,
58011                 onpointermove: onMove,
58012                 ontouchmove: onMove,
58013                 ontouchstart: onStart,
58014                 style: {
58015                     width: `${width}px`,
58016                 },
58017                 type: "range",
58018                 value: index != null ? index : 0,
58019             };
58020             const disabled = index == null || max == null || max <= 1;
58021             if (disabled) {
58022                 positionInputProperties.disabled = "true";
58023             }
58024             const positionInput = virtualDom.h("input.mapillary-sequence-position", positionInputProperties, []);
58025             const positionContainerClass = disabled ? ".mapillary-sequence-position-container-inactive" : ".mapillary-sequence-position-container";
58026             return virtualDom.h("div" + positionContainerClass, [positionInput]);
58027         }
58028         _createSpeedInput(speed) {
58029             this._speed = speed;
58030             const onSpeed = (e) => {
58031                 this._speed = Number(e.target.value) / 1000;
58032                 this._notifySpeedChanged$.next(this._speed);
58033             };
58034             const boundingRect = this._container.domContainer.getBoundingClientRect();
58035             const width = Math.max(276, Math.min(410, 5 + 0.8 * boundingRect.width)) - 160;
58036             const onStart = (e) => {
58037                 this._changingSpeed = true;
58038                 e.stopPropagation();
58039             };
58040             const onMove = (e) => {
58041                 if (this._changingSpeed === true) {
58042                     e.stopPropagation();
58043                 }
58044             };
58045             const onKeyDown = (e) => {
58046                 if (e.key === "ArrowDown" || e.key === "ArrowLeft" ||
58047                     e.key === "ArrowRight" || e.key === "ArrowUp") {
58048                     e.preventDefault();
58049                 }
58050             };
58051             const speedInput = virtualDom.h("input.mapillary-sequence-speed", {
58052                 max: 1000,
58053                 min: 0,
58054                 onchange: onSpeed,
58055                 oninput: onSpeed,
58056                 onkeydown: onKeyDown,
58057                 onpointerdown: onStart,
58058                 onpointermove: onMove,
58059                 ontouchmove: onMove,
58060                 ontouchstart: onStart,
58061                 style: {
58062                     width: `${width}px`,
58063                 },
58064                 type: "range",
58065                 value: 1000 * speed,
58066             }, []);
58067             return virtualDom.h("div.mapillary-sequence-speed-container", [speedInput]);
58068         }
58069         _createPlaybackControls(containerWidth, speed, component, configuration) {
58070             if (this._mode !== SequenceMode.Playback) {
58071                 return virtualDom.h("div.mapillary-sequence-playback", []);
58072             }
58073             const switchIcon = virtualDom.h("div.mapillary-sequence-switch-icon.mapillary-sequence-icon-visible", []);
58074             const direction = configuration.direction === exports.NavigationDirection.Next ?
58075                 exports.NavigationDirection.Prev : exports.NavigationDirection.Next;
58076             const playing = configuration.playing;
58077             const switchButtonProperties = {
58078                 onclick: () => {
58079                     if (!playing) {
58080                         component.configure({ direction });
58081                     }
58082                 },
58083             };
58084             const switchButtonClassName = configuration.playing ? ".mapillary-sequence-switch-button-inactive" : ".mapillary-sequence-switch-button";
58085             const switchButton = virtualDom.h("div" + switchButtonClassName, switchButtonProperties, [switchIcon]);
58086             const slowIcon = virtualDom.h("div.mapillary-sequence-slow-icon.mapillary-sequence-icon-visible", []);
58087             const slowContainer = virtualDom.h("div.mapillary-sequence-slow-container", [slowIcon]);
58088             const fastIcon = virtualDom.h("div.mapillary-sequence-fast-icon.mapillary-sequence-icon-visible", []);
58089             const fastContainer = virtualDom.h("div.mapillary-sequence-fast-container", [fastIcon]);
58090             const closeIcon = virtualDom.h("div.mapillary-sequence-close-icon.mapillary-sequence-icon-visible", []);
58091             const closeButtonProperties = {
58092                 onclick: () => {
58093                     this._mode = SequenceMode.Default;
58094                     this._notifyChanged$.next(this);
58095                 },
58096             };
58097             const closeButton = virtualDom.h("div.mapillary-sequence-close-button", closeButtonProperties, [closeIcon]);
58098             const speedInput = this._createSpeedInput(speed);
58099             const playbackChildren = [switchButton, slowContainer, speedInput, fastContainer, closeButton];
58100             const top = Math.round(containerWidth / this._stepperDefaultWidth * this._defaultHeight + 10);
58101             const playbackProperties = { style: { top: `${top}px` } };
58102             return virtualDom.h("div.mapillary-sequence-playback", playbackProperties, playbackChildren);
58103         }
58104         _createPlayingButton(nextId, prevId, playEnabled, configuration, component) {
58105             let canPlay = (configuration.direction === exports.NavigationDirection.Next && nextId != null) ||
58106                 (configuration.direction === exports.NavigationDirection.Prev && prevId != null);
58107             canPlay = canPlay && playEnabled;
58108             let onclick = configuration.playing ?
58109                 () => { component.stop(); } :
58110                 canPlay ? () => { component.play(); } : null;
58111             let buttonProperties = { onclick: onclick };
58112             let iconProperties = {};
58113             if (configuration.direction === exports.NavigationDirection.Prev) {
58114                 iconProperties.style = {
58115                     transform: "rotate(180deg) translate(50%, 50%)",
58116                 };
58117             }
58118             let icon = virtualDom.h("div.mapillary-sequence-icon", iconProperties, []);
58119             let buttonClass = configuration.playing ?
58120                 "mapillary-sequence-stop" :
58121                 canPlay ?
58122                     "mapillary-sequence-play" :
58123                     "mapillary-sequence-play-inactive";
58124             return virtualDom.h("div." + buttonClass, buttonProperties, [icon]);
58125         }
58126         _createSequenceControls(containerWidth) {
58127             const borderRadius = Math.round(8 / this._stepperDefaultWidth * containerWidth);
58128             const expanderProperties = {
58129                 onclick: () => {
58130                     this._expandControls = !this._expandControls;
58131                     this._mode = SequenceMode.Default;
58132                     this._notifyChanged$.next(this);
58133                 },
58134                 style: {
58135                     "border-bottom-right-radius": `${borderRadius}px`,
58136                     "border-top-right-radius": `${borderRadius}px`,
58137                 },
58138             };
58139             const expanderBar = virtualDom.h("div.mapillary-sequence-expander-bar", []);
58140             const expander = virtualDom.h("div.mapillary-sequence-expander-button", expanderProperties, [expanderBar]);
58141             const fastIconClassName = this._mode === SequenceMode.Playback ?
58142                 ".mapillary-sequence-fast-icon-gray.mapillary-sequence-icon-visible" : ".mapillary-sequence-fast-icon";
58143             const fastIcon = virtualDom.h("div" + fastIconClassName, []);
58144             const playbackProperties = {
58145                 onclick: () => {
58146                     this._mode = this._mode === SequenceMode.Playback ?
58147                         SequenceMode.Default :
58148                         SequenceMode.Playback;
58149                     this._notifyChanged$.next(this);
58150                 },
58151             };
58152             const playback = virtualDom.h("div.mapillary-sequence-playback-button", playbackProperties, [fastIcon]);
58153             const timelineIconClassName = this._mode === SequenceMode.Timeline ?
58154                 ".mapillary-sequence-timeline-icon-gray.mapillary-sequence-icon-visible" : ".mapillary-sequence-timeline-icon";
58155             const timelineIcon = virtualDom.h("div" + timelineIconClassName, []);
58156             const timelineProperties = {
58157                 onclick: () => {
58158                     this._mode = this._mode === SequenceMode.Timeline ?
58159                         SequenceMode.Default :
58160                         SequenceMode.Timeline;
58161                     this._notifyChanged$.next(this);
58162                 },
58163             };
58164             const timeline = virtualDom.h("div.mapillary-sequence-timeline-button", timelineProperties, [timelineIcon]);
58165             const properties = {
58166                 style: {
58167                     height: (this._defaultHeight / this._stepperDefaultWidth * containerWidth) + "px",
58168                     transform: `translate(${containerWidth / 2 + 2}px, 0)`,
58169                     width: (this._controlsDefaultWidth / this._stepperDefaultWidth * containerWidth) + "px",
58170                 },
58171             };
58172             const className = ".mapillary-sequence-controls" +
58173                 (this._expandControls ? ".mapillary-sequence-controls-expanded" : "");
58174             return virtualDom.h("div" + className, properties, [playback, timeline, expander]);
58175         }
58176         _createSequenceArrows(nextId, prevId, containerWidth, configuration, navigator) {
58177             let nextProperties = {
58178                 onclick: nextId != null ?
58179                     () => {
58180                         navigator.moveDir$(exports.NavigationDirection.Next)
58181                             .subscribe(undefined, (error) => {
58182                             if (!(error instanceof CancelMapillaryError)) {
58183                                 console.error(error);
58184                             }
58185                         });
58186                     } :
58187                     null,
58188                 onpointerenter: () => { this._mouseEnterDirection$.next(exports.NavigationDirection.Next); },
58189                 onpointerleave: () => { this._mouseLeaveDirection$.next(exports.NavigationDirection.Next); },
58190             };
58191             const borderRadius = Math.round(8 / this._stepperDefaultWidth * containerWidth);
58192             let prevProperties = {
58193                 onclick: prevId != null ?
58194                     () => {
58195                         navigator.moveDir$(exports.NavigationDirection.Prev)
58196                             .subscribe(undefined, (error) => {
58197                             if (!(error instanceof CancelMapillaryError)) {
58198                                 console.error(error);
58199                             }
58200                         });
58201                     } :
58202                     null,
58203                 onpointerenter: () => { this._mouseEnterDirection$.next(exports.NavigationDirection.Prev); },
58204                 onpointerleave: () => { this._mouseLeaveDirection$.next(exports.NavigationDirection.Prev); },
58205                 style: {
58206                     "border-bottom-left-radius": `${borderRadius}px`,
58207                     "border-top-left-radius": `${borderRadius}px`,
58208                 },
58209             };
58210             let nextClass = this._getStepClassName(exports.NavigationDirection.Next, nextId, configuration.highlightId);
58211             let prevClass = this._getStepClassName(exports.NavigationDirection.Prev, prevId, configuration.highlightId);
58212             let nextIcon = virtualDom.h("div.mapillary-sequence-icon", []);
58213             let prevIcon = virtualDom.h("div.mapillary-sequence-icon", []);
58214             return [
58215                 virtualDom.h("div." + prevClass, prevProperties, [prevIcon]),
58216                 virtualDom.h("div." + nextClass, nextProperties, [nextIcon]),
58217             ];
58218         }
58219         _createStepper(edgeStatus, configuration, playEnabled, containerWidth, component, navigator) {
58220             let nextId = null;
58221             let prevId = null;
58222             for (let edge of edgeStatus.edges) {
58223                 if (edge.data.direction === exports.NavigationDirection.Next) {
58224                     nextId = edge.target;
58225                 }
58226                 if (edge.data.direction === exports.NavigationDirection.Prev) {
58227                     prevId = edge.target;
58228                 }
58229             }
58230             const playingButton = this._createPlayingButton(nextId, prevId, playEnabled, configuration, component);
58231             const buttons = this._createSequenceArrows(nextId, prevId, containerWidth, configuration, navigator);
58232             buttons.splice(1, 0, playingButton);
58233             const containerProperties = {
58234                 oncontextmenu: (event) => { event.preventDefault(); },
58235                 style: {
58236                     height: (this._defaultHeight / this._stepperDefaultWidth * containerWidth) + "px",
58237                     width: containerWidth + "px",
58238                 },
58239             };
58240             return virtualDom.h("div.mapillary-sequence-stepper", containerProperties, buttons);
58241         }
58242         _createTimelineControls(containerWidth, index, max) {
58243             if (this._mode !== SequenceMode.Timeline) {
58244                 return virtualDom.h("div.mapillary-sequence-timeline", []);
58245             }
58246             const positionInput = this._createPositionInput(index, max);
58247             const closeIcon = virtualDom.h("div.mapillary-sequence-close-icon.mapillary-sequence-icon-visible", []);
58248             const closeButtonProperties = {
58249                 onclick: () => {
58250                     this._mode = SequenceMode.Default;
58251                     this._notifyChanged$.next(this);
58252                 },
58253             };
58254             const closeButton = virtualDom.h("div.mapillary-sequence-close-button", closeButtonProperties, [closeIcon]);
58255             const top = Math.round(containerWidth / this._stepperDefaultWidth * this._defaultHeight + 10);
58256             const playbackProperties = { style: { top: `${top}px` } };
58257             return virtualDom.h("div.mapillary-sequence-timeline", playbackProperties, [positionInput, closeButton]);
58258         }
58259         _getStepClassName(direction, imageId, highlightId) {
58260             let className = direction === exports.NavigationDirection.Next ?
58261                 "mapillary-sequence-step-next" :
58262                 "mapillary-sequence-step-prev";
58263             if (imageId == null) {
58264                 className += "-inactive";
58265             }
58266             else {
58267                 if (highlightId === imageId) {
58268                     className += "-highlight";
58269                 }
58270             }
58271             return className;
58272         }
58273         _setChangingPosition(value) {
58274             this._changingPosition = value;
58275             this._notifyChangingPositionChanged$.next(value);
58276         }
58277     }
58278
58279     /**
58280      * @class SequenceComponent
58281      * @classdesc Component showing navigation arrows for sequence directions
58282      * as well as playing button. Exposes an API to start and stop play.
58283      */
58284     class SequenceComponent extends Component {
58285         constructor(name, container, navigator, renderer, scheduler) {
58286             super(name, container, navigator);
58287             this._sequenceDOMRenderer = !!renderer ? renderer : new SequenceDOMRenderer(container);
58288             this._scheduler = scheduler;
58289             this._containerWidth$ = new Subject();
58290             this._hoveredIdSubject$ = new Subject();
58291             this._hoveredId$ = this._hoveredIdSubject$.pipe(share());
58292             this._navigator.playService.playing$.pipe(skip(1), withLatestFrom(this._configuration$))
58293                 .subscribe(([playing, configuration]) => {
58294                 const type = "playing";
58295                 const event = {
58296                     playing,
58297                     target: this,
58298                     type,
58299                 };
58300                 this.fire(type, event);
58301                 if (playing === configuration.playing) {
58302                     return;
58303                 }
58304                 if (playing) {
58305                     this.play();
58306                 }
58307                 else {
58308                     this.stop();
58309                 }
58310             });
58311             this._navigator.playService.direction$.pipe(skip(1), withLatestFrom(this._configuration$))
58312                 .subscribe(([direction, configuration]) => {
58313                 if (direction !== configuration.direction) {
58314                     this.configure({ direction });
58315                 }
58316             });
58317         }
58318         fire(type, event) {
58319             super.fire(type, event);
58320         }
58321         off(type, handler) {
58322             super.off(type, handler);
58323         }
58324         on(type, handler) {
58325             super.on(type, handler);
58326         }
58327         /**
58328          * Start playing.
58329          *
58330          * @fires playing
58331          */
58332         play() { this.configure({ playing: true }); }
58333         /**
58334          * Stop playing.
58335          *
58336          * @fires playing
58337          */
58338         stop() { this.configure({ playing: false }); }
58339         _activate() {
58340             this._sequenceDOMRenderer.activate();
58341             const edgeStatus$ = this._navigator.stateService.currentImage$.pipe(switchMap((image) => {
58342                 return image.sequenceEdges$;
58343             }), publishReplay(1), refCount());
58344             const sequence$ = this._navigator.stateService.currentImage$.pipe(distinctUntilChanged(undefined, (image) => {
58345                 return image.sequenceId;
58346             }), switchMap((image) => {
58347                 return concat(of(null), this._navigator.graphService.cacheSequence$(image.sequenceId).pipe(retry(3), catchError((e) => {
58348                     console.error("Failed to cache sequence", e);
58349                     return of(null);
58350                 })));
58351             }), startWith(null), publishReplay(1), refCount());
58352             const subs = this._subscriptions;
58353             subs.push(sequence$.subscribe());
58354             const rendererId$ = this._sequenceDOMRenderer.index$.pipe(withLatestFrom(sequence$), map(([index, sequence]) => {
58355                 return sequence != null ? sequence.imageIds[index] : null;
58356             }), filter((id) => {
58357                 return !!id;
58358             }), distinctUntilChanged(), publish(), refCount());
58359             subs.push(merge(rendererId$.pipe(debounceTime(100, this._scheduler)), rendererId$.pipe(auditTime(400, this._scheduler))).pipe(distinctUntilChanged(), switchMap((id) => {
58360                 return this._navigator.moveTo$(id).pipe(catchError(() => {
58361                     return empty();
58362                 }));
58363             }))
58364                 .subscribe());
58365             subs.push(this._sequenceDOMRenderer.changingPositionChanged$.pipe(filter((changing) => {
58366                 return changing;
58367             }))
58368                 .subscribe(() => {
58369                 this._navigator.graphService.setGraphMode(GraphMode.Sequence);
58370             }));
58371             subs.push(this._sequenceDOMRenderer.changingPositionChanged$.pipe(filter((changing) => {
58372                 return !changing;
58373             }))
58374                 .subscribe(() => {
58375                 this._navigator.graphService.setGraphMode(GraphMode.Spatial);
58376             }));
58377             this._navigator.graphService.graphMode$.pipe(switchMap((mode) => {
58378                 return mode === GraphMode.Spatial ?
58379                     this._navigator.stateService.currentImage$.pipe(take(2)) :
58380                     empty();
58381             }), filter((image) => {
58382                 return !image.spatialEdges.cached;
58383             }), switchMap((image) => {
58384                 return this._navigator.graphService.cacheImage$(image.id).pipe(catchError(() => {
58385                     return empty();
58386                 }));
58387             }))
58388                 .subscribe();
58389             subs.push(this._sequenceDOMRenderer.changingPositionChanged$.pipe(filter((changing) => {
58390                 return changing;
58391             }))
58392                 .subscribe(() => {
58393                 this._navigator.playService.stop();
58394             }));
58395             subs.push(combineLatest(this._navigator.graphService.graphMode$, this._sequenceDOMRenderer.changingPositionChanged$.pipe(startWith(false), distinctUntilChanged())).pipe(withLatestFrom(this._navigator.stateService.currentImage$), switchMap(([[mode, changing], image]) => {
58396                 return changing && mode === GraphMode.Sequence ?
58397                     this._navigator.graphService.cacheSequenceImages$(image.sequenceId, image.id).pipe(retry(3), catchError((error) => {
58398                         console.error("Failed to cache sequence images.", error);
58399                         return empty();
58400                     })) :
58401                     empty();
58402             }))
58403                 .subscribe());
58404             const position$ = sequence$.pipe(switchMap((sequence) => {
58405                 if (!sequence) {
58406                     return of({ index: null, max: null });
58407                 }
58408                 let firstCurrentId = true;
58409                 return this._sequenceDOMRenderer.changingPositionChanged$.pipe(startWith(false), distinctUntilChanged(), switchMap((changingPosition) => {
58410                     const skipCount = !changingPosition &&
58411                         firstCurrentId ?
58412                         0 : 1;
58413                     firstCurrentId = false;
58414                     return changingPosition ?
58415                         rendererId$ :
58416                         this._navigator.stateService.currentImage$.pipe(map((image) => {
58417                             return image.id;
58418                         }), distinctUntilChanged(), skip(skipCount));
58419                 }), map((imageId) => {
58420                     const index = sequence.imageIds.indexOf(imageId);
58421                     if (index === -1) {
58422                         return { index: null, max: null };
58423                     }
58424                     return { index: index, max: sequence.imageIds.length - 1 };
58425                 }));
58426             }));
58427             const earth$ = this._navigator.stateService.state$.pipe(map((state) => {
58428                 return state === State.Earth;
58429             }), distinctUntilChanged());
58430             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]) => {
58431                 const vNode = this._sequenceDOMRenderer
58432                     .render(edgeStatus, configuration, containerWidth, speed, position.index, position.max, !earth, this, this._navigator);
58433                 return { name: this._name, vNode: vNode };
58434             }))
58435                 .subscribe(this._container.domRenderer.render$));
58436             subs.push(this._sequenceDOMRenderer.speed$
58437                 .subscribe((speed) => {
58438                 this._navigator.playService.setSpeed(speed);
58439             }));
58440             subs.push(this._configuration$.pipe(map((configuration) => {
58441                 return configuration.direction;
58442             }), distinctUntilChanged())
58443                 .subscribe((direction) => {
58444                 this._navigator.playService.setDirection(direction);
58445             }));
58446             subs.push(combineLatest(this._container.renderService.size$, this._configuration$.pipe(distinctUntilChanged((value1, value2) => {
58447                 return value1[0] === value2[0] && value1[1] === value2[1];
58448             }, (configuration) => {
58449                 return [configuration.minWidth, configuration.maxWidth];
58450             }))).pipe(map(([size, configuration]) => {
58451                 return this._sequenceDOMRenderer.getContainerWidth(size, configuration);
58452             }))
58453                 .subscribe(this._containerWidth$));
58454             subs.push(this._configuration$.pipe(map((configuration) => {
58455                 return configuration.playing;
58456             }), distinctUntilChanged())
58457                 .subscribe((playing) => {
58458                 if (playing) {
58459                     this._navigator.playService.play();
58460                 }
58461                 else {
58462                     this._navigator.playService.stop();
58463                 }
58464             }));
58465             subs.push(this._sequenceDOMRenderer.mouseEnterDirection$.pipe(switchMap((direction) => {
58466                 const edgeTo$ = edgeStatus$.pipe(map((edgeStatus) => {
58467                     for (let edge of edgeStatus.edges) {
58468                         if (edge.data.direction === direction) {
58469                             return edge.target;
58470                         }
58471                     }
58472                     return null;
58473                 }), takeUntil(this._sequenceDOMRenderer.mouseLeaveDirection$));
58474                 return concat(edgeTo$, of(null));
58475             }), distinctUntilChanged())
58476                 .subscribe(this._hoveredIdSubject$));
58477             subs.push(this._hoveredId$
58478                 .subscribe((id) => {
58479                 const type = "hover";
58480                 const event = {
58481                     id,
58482                     target: this,
58483                     type,
58484                 };
58485                 this.fire(type, event);
58486             }));
58487         }
58488         _deactivate() {
58489             this._subscriptions.unsubscribe();
58490             this._sequenceDOMRenderer.deactivate();
58491         }
58492         _getDefaultConfiguration() {
58493             return {
58494                 direction: exports.NavigationDirection.Next,
58495                 maxWidth: 108,
58496                 minWidth: 70,
58497                 playing: false,
58498                 visible: true,
58499             };
58500         }
58501     }
58502     /** @inheritdoc */
58503     SequenceComponent.componentName = "sequence";
58504
58505     /**
58506      * Enumeration for slider mode.
58507      *
58508      * @enum {number}
58509      * @readonly
58510      *
58511      * @description Modes for specifying how transitions
58512      * between images are performed in slider mode. Only
58513      * applicable when the slider component determines
58514      * that transitions with motion is possilble. When it
58515      * is not, the stationary mode will be applied.
58516      */
58517     exports.SliderConfigurationMode = void 0;
58518     (function (SliderConfigurationMode) {
58519         /**
58520          * Transitions with motion.
58521          *
58522          * @description The slider component moves the
58523          * camera between the image origins.
58524          *
58525          * In this mode it is not possible to zoom or pan.
58526          *
58527          * The slider component falls back to stationary
58528          * mode when it determines that the pair of images
58529          * does not have a strong enough relation.
58530          */
58531         SliderConfigurationMode[SliderConfigurationMode["Motion"] = 0] = "Motion";
58532         /**
58533          * Stationary transitions.
58534          *
58535          * @description The camera is stationary.
58536          *
58537          * In this mode it is possible to zoom and pan.
58538          */
58539         SliderConfigurationMode[SliderConfigurationMode["Stationary"] = 1] = "Stationary";
58540     })(exports.SliderConfigurationMode || (exports.SliderConfigurationMode = {}));
58541
58542     const EPSILON = 1e-8;
58543     /**
58544      * @class Transform
58545      *
58546      * @classdesc Class used for calculating coordinate transformations
58547      * and projections.
58548      */
58549     class Transform {
58550         /**
58551          * Create a new transform instance.
58552          * @param {number} orientation - Image orientation.
58553          * @param {number} width - Image height.
58554          * @param {number} height - Image width.
58555          * @param {number} focal - Focal length.
58556          * @param {number} scale - Atomic scale.
58557          * @param {Array<number>} rotation - Rotation vector in three dimensions.
58558          * @param {Array<number>} translation - Translation vector in three dimensions.
58559          * @param {HTMLImageElement} image - Image for fallback size calculations.
58560          */
58561         constructor(orientation, width, height, scale, rotation, translation, image, textureScale, cameraParameters, cameraType) {
58562             this._orientation = this._getValue(orientation, 1);
58563             let imageWidth = image != null ? image.width : 4;
58564             let imageHeight = image != null ? image.height : 3;
58565             let keepOrientation = this._orientation < 5;
58566             this._width = this._getValue(width, keepOrientation ? imageWidth : imageHeight);
58567             this._height = this._getValue(height, keepOrientation ? imageHeight : imageWidth);
58568             this._basicAspect = keepOrientation ?
58569                 this._width / this._height :
58570                 this._height / this._width;
58571             this._basicWidth = keepOrientation ? width : height;
58572             this._basicHeight = keepOrientation ? height : width;
58573             const parameters = this._getCameraParameters(cameraParameters, cameraType);
58574             const focal = parameters[0];
58575             const ck1 = parameters[1];
58576             const ck2 = parameters[2];
58577             this._focal = this._getValue(focal, 1);
58578             this._scale = this._getValue(scale, 0);
58579             this._worldToCamera = this.createWorldToCamera(rotation, translation);
58580             this._worldToCameraInverse = new Matrix4()
58581                 .copy(this._worldToCamera)
58582                 .invert();
58583             this._scaledWorldToCamera =
58584                 this._createScaledWorldToCamera(this._worldToCamera, this._scale);
58585             this._scaledWorldToCameraInverse = new Matrix4()
58586                 .copy(this._scaledWorldToCamera)
58587                 .invert();
58588             this._basicWorldToCamera = this._createBasicWorldToCamera(this._worldToCamera, orientation);
58589             this._textureScale = !!textureScale ? textureScale : [1, 1];
58590             this._ck1 = !!ck1 ? ck1 : 0;
58591             this._ck2 = !!ck2 ? ck2 : 0;
58592             this._cameraType = !!cameraType ?
58593                 cameraType :
58594                 "perspective";
58595             this._radialPeak = this._getRadialPeak(this._ck1, this._ck2);
58596         }
58597         get ck1() {
58598             return this._ck1;
58599         }
58600         get ck2() {
58601             return this._ck2;
58602         }
58603         get cameraType() {
58604             return this._cameraType;
58605         }
58606         /**
58607          * Get basic aspect.
58608          * @returns {number} The orientation adjusted aspect ratio.
58609          */
58610         get basicAspect() {
58611             return this._basicAspect;
58612         }
58613         /**
58614          * Get basic height.
58615          *
58616          * @description Does not fall back to image image height but
58617          * uses original value from API so can be faulty.
58618          *
58619          * @returns {number} The height of the basic version image
58620          * (adjusted for orientation).
58621          */
58622         get basicHeight() {
58623             return this._basicHeight;
58624         }
58625         get basicRt() {
58626             return this._basicWorldToCamera;
58627         }
58628         /**
58629          * Get basic width.
58630          *
58631          * @description Does not fall back to image image width but
58632          * uses original value from API so can be faulty.
58633          *
58634          * @returns {number} The width of the basic version image
58635          * (adjusted for orientation).
58636          */
58637         get basicWidth() {
58638             return this._basicWidth;
58639         }
58640         /**
58641          * Get focal.
58642          * @returns {number} The image focal length.
58643          */
58644         get focal() {
58645             return this._focal;
58646         }
58647         /**
58648          * Get height.
58649          *
58650          * @description Falls back to the image image height if
58651          * the API data is faulty.
58652          *
58653          * @returns {number} The orientation adjusted image height.
58654          */
58655         get height() {
58656             return this._height;
58657         }
58658         /**
58659          * Get orientation.
58660          * @returns {number} The image orientation.
58661          */
58662         get orientation() {
58663             return this._orientation;
58664         }
58665         /**
58666          * Get rt.
58667          * @returns {THREE.Matrix4} The extrinsic camera matrix.
58668          */
58669         get rt() {
58670             return this._worldToCamera;
58671         }
58672         /**
58673          * Get srt.
58674          * @returns {THREE.Matrix4} The scaled extrinsic camera matrix.
58675          */
58676         get srt() {
58677             return this._scaledWorldToCamera;
58678         }
58679         /**
58680          * Get srtInverse.
58681          * @returns {THREE.Matrix4} The scaled extrinsic camera matrix.
58682          */
58683         get srtInverse() {
58684             return this._scaledWorldToCameraInverse;
58685         }
58686         /**
58687          * Get scale.
58688          * @returns {number} The image atomic reconstruction scale.
58689          */
58690         get scale() {
58691             return this._scale;
58692         }
58693         /**
58694          * Get has valid scale.
58695          * @returns {boolean} Value indicating if the scale of the transform is valid.
58696          */
58697         get hasValidScale() {
58698             return this._scale > 1e-2 && this._scale < 50;
58699         }
58700         /**
58701          * Get radial peak.
58702          * @returns {number} Value indicating the radius where the radial
58703          * undistortion function peaks.
58704          */
58705         get radialPeak() {
58706             return this._radialPeak;
58707         }
58708         /**
58709          * Get width.
58710          *
58711          * @description Falls back to the image image width if
58712          * the API data is faulty.
58713          *
58714          * @returns {number} The orientation adjusted image width.
58715          */
58716         get width() {
58717             return this._width;
58718         }
58719         /**
58720          * Calculate the up vector for the image transform.
58721          *
58722          * @returns {THREE.Vector3} Normalized and orientation adjusted up vector.
58723          */
58724         upVector() {
58725             let rte = this._worldToCamera.elements;
58726             switch (this._orientation) {
58727                 case 1:
58728                     return new Vector3(-rte[1], -rte[5], -rte[9]);
58729                 case 3:
58730                     return new Vector3(rte[1], rte[5], rte[9]);
58731                 case 6:
58732                     return new Vector3(-rte[0], -rte[4], -rte[8]);
58733                 case 8:
58734                     return new Vector3(rte[0], rte[4], rte[8]);
58735                 default:
58736                     return new Vector3(-rte[1], -rte[5], -rte[9]);
58737             }
58738         }
58739         /**
58740          * Calculate projector matrix for projecting 3D points to texture map
58741          * coordinates (u and v).
58742          *
58743          * @returns {THREE.Matrix4} Projection matrix for 3D point to texture
58744          * map coordinate calculations.
58745          */
58746         projectorMatrix() {
58747             let projector = this._normalizedToTextureMatrix();
58748             let f = this._focal;
58749             let projection = new Matrix4().set(f, 0, 0, 0, 0, f, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
58750             projector.multiply(projection);
58751             projector.multiply(this._worldToCamera);
58752             return projector;
58753         }
58754         /**
58755          * Project 3D world coordinates to basic coordinates.
58756          *
58757          * @param {Array<number>} point3d - 3D world coordinates.
58758          * @return {Array<number>} 2D basic coordinates.
58759          */
58760         projectBasic(point3d) {
58761             let sfm = this.projectSfM(point3d);
58762             return this._sfmToBasic(sfm);
58763         }
58764         /**
58765          * Unproject basic coordinates to 3D world coordinates.
58766          *
58767          * @param {Array<number>} basic - 2D basic coordinates.
58768          * @param {Array<number>} distance - Distance to unproject from camera center.
58769          * @param {boolean} [depth] - Treat the distance value as depth from camera center.
58770          *                            Only applicable for perspective images. Will be
58771          *                            ignored for spherical.
58772          * @returns {Array<number>} Unprojected 3D world coordinates.
58773          */
58774         unprojectBasic(basic, distance, depth) {
58775             let sfm = this._basicToSfm(basic);
58776             return this.unprojectSfM(sfm, distance, depth);
58777         }
58778         /**
58779          * Project 3D world coordinates to SfM coordinates.
58780          *
58781          * @param {Array<number>} point3d - 3D world coordinates.
58782          * @return {Array<number>} 2D SfM coordinates.
58783          */
58784         projectSfM(point3d) {
58785             let v = new Vector4(point3d[0], point3d[1], point3d[2], 1);
58786             v.applyMatrix4(this._worldToCamera);
58787             return this._bearingToSfm([v.x, v.y, v.z]);
58788         }
58789         /**
58790          * Unproject SfM coordinates to a 3D world coordinates.
58791          *
58792          * @param {Array<number>} sfm - 2D SfM coordinates.
58793          * @param {Array<number>} distance - Distance to unproject
58794          * from camera center.
58795          * @param {boolean} [depth] - Treat the distance value as
58796          * depth from camera center. Only applicable for perspective
58797          * images. Will be ignored for spherical.
58798          * @returns {Array<number>} Unprojected 3D world coordinates.
58799          */
58800         unprojectSfM(sfm, distance, depth) {
58801             const bearing = this._sfmToBearing(sfm);
58802             const unprojectedCamera = depth && !isSpherical(this._cameraType) ?
58803                 new Vector4(distance * bearing[0] / bearing[2], distance * bearing[1] / bearing[2], distance, 1) :
58804                 new Vector4(distance * bearing[0], distance * bearing[1], distance * bearing[2], 1);
58805             const unprojectedWorld = unprojectedCamera
58806                 .applyMatrix4(this._worldToCameraInverse);
58807             return [
58808                 unprojectedWorld.x / unprojectedWorld.w,
58809                 unprojectedWorld.y / unprojectedWorld.w,
58810                 unprojectedWorld.z / unprojectedWorld.w,
58811             ];
58812         }
58813         /**
58814          * Transform SfM coordinates to bearing vector (3D cartesian
58815          * coordinates on the unit sphere).
58816          *
58817          * @param {Array<number>} sfm - 2D SfM coordinates.
58818          * @returns {Array<number>} Bearing vector (3D cartesian coordinates
58819          * on the unit sphere).
58820          */
58821         _sfmToBearing(sfm) {
58822             if (isSpherical(this._cameraType)) {
58823                 let lng = sfm[0] * 2 * Math.PI;
58824                 let lat = -sfm[1] * 2 * Math.PI;
58825                 let x = Math.cos(lat) * Math.sin(lng);
58826                 let y = -Math.sin(lat);
58827                 let z = Math.cos(lat) * Math.cos(lng);
58828                 return [x, y, z];
58829             }
58830             else if (isFisheye(this._cameraType)) {
58831                 let [dxn, dyn] = [sfm[0] / this._focal, sfm[1] / this._focal];
58832                 const dTheta = Math.sqrt(dxn * dxn + dyn * dyn);
58833                 let d = this._distortionFromDistortedRadius(dTheta, this._ck1, this._ck2, this._radialPeak);
58834                 let theta = dTheta / d;
58835                 let z = Math.cos(theta);
58836                 let r = Math.sin(theta);
58837                 const denomTheta = dTheta > EPSILON ? 1 / dTheta : 1;
58838                 let x = r * dxn * denomTheta;
58839                 let y = r * dyn * denomTheta;
58840                 return [x, y, z];
58841             }
58842             else {
58843                 let [dxn, dyn] = [sfm[0] / this._focal, sfm[1] / this._focal];
58844                 const dr = Math.sqrt(dxn * dxn + dyn * dyn);
58845                 let d = this._distortionFromDistortedRadius(dr, this._ck1, this._ck2, this._radialPeak);
58846                 const xn = dxn / d;
58847                 const yn = dyn / d;
58848                 let v = new Vector3(xn, yn, 1);
58849                 v.normalize();
58850                 return [v.x, v.y, v.z];
58851             }
58852         }
58853         /** Compute distortion given the distorted radius.
58854          *
58855          *  Solves for d in the equation
58856          *    y = d(x, k1, k2) * x
58857          * given the distorted radius, y.
58858          */
58859         _distortionFromDistortedRadius(distortedRadius, k1, k2, radialPeak) {
58860             let d = 1.0;
58861             for (let i = 0; i < 10; i++) {
58862                 let radius = distortedRadius / d;
58863                 if (radius > radialPeak) {
58864                     radius = radialPeak;
58865                 }
58866                 d = 1 + k1 * Math.pow(radius, 2) + k2 * Math.pow(radius, 4);
58867             }
58868             return d;
58869         }
58870         /**
58871          * Transform bearing vector (3D cartesian coordiantes on the unit sphere) to
58872          * SfM coordinates.
58873          *
58874          * @param {Array<number>} bearing - Bearing vector (3D cartesian coordinates on the
58875          * unit sphere).
58876          * @returns {Array<number>} 2D SfM coordinates.
58877          */
58878         _bearingToSfm(bearing) {
58879             if (isSpherical(this._cameraType)) {
58880                 let x = bearing[0];
58881                 let y = bearing[1];
58882                 let z = bearing[2];
58883                 let lng = Math.atan2(x, z);
58884                 let lat = Math.atan2(-y, Math.sqrt(x * x + z * z));
58885                 return [lng / (2 * Math.PI), -lat / (2 * Math.PI)];
58886             }
58887             else if (isFisheye(this._cameraType)) {
58888                 if (bearing[2] > 0) {
58889                     const [x, y, z] = bearing;
58890                     const r = Math.sqrt(x * x + y * y);
58891                     let theta = Math.atan2(r, z);
58892                     if (theta > this._radialPeak) {
58893                         theta = this._radialPeak;
58894                     }
58895                     const distortion = 1.0 + Math.pow(theta, 2) * (this._ck1 + Math.pow(theta, 2) * this._ck2);
58896                     const s = this._focal * distortion * theta / r;
58897                     return [s * x, s * y];
58898                 }
58899                 else {
58900                     return [
58901                         bearing[0] < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
58902                         bearing[1] < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
58903                     ];
58904                 }
58905             }
58906             else {
58907                 if (bearing[2] > 0) {
58908                     let [xn, yn] = [bearing[0] / bearing[2], bearing[1] / bearing[2]];
58909                     let r2 = xn * xn + yn * yn;
58910                     const rp2 = Math.pow(this._radialPeak, 2);
58911                     if (r2 > rp2) {
58912                         r2 = rp2;
58913                     }
58914                     const d = 1 + this._ck1 * r2 + this._ck2 * Math.pow(r2, 2);
58915                     return [
58916                         this._focal * d * xn,
58917                         this._focal * d * yn,
58918                     ];
58919                 }
58920                 else {
58921                     return [
58922                         bearing[0] < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
58923                         bearing[1] < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
58924                     ];
58925                 }
58926             }
58927         }
58928         /**
58929          * Convert basic coordinates to SfM coordinates.
58930          *
58931          * @param {Array<number>} basic - 2D basic coordinates.
58932          * @returns {Array<number>} 2D SfM coordinates.
58933          */
58934         _basicToSfm(basic) {
58935             let rotatedX;
58936             let rotatedY;
58937             switch (this._orientation) {
58938                 case 1:
58939                     rotatedX = basic[0];
58940                     rotatedY = basic[1];
58941                     break;
58942                 case 3:
58943                     rotatedX = 1 - basic[0];
58944                     rotatedY = 1 - basic[1];
58945                     break;
58946                 case 6:
58947                     rotatedX = basic[1];
58948                     rotatedY = 1 - basic[0];
58949                     break;
58950                 case 8:
58951                     rotatedX = 1 - basic[1];
58952                     rotatedY = basic[0];
58953                     break;
58954                 default:
58955                     rotatedX = basic[0];
58956                     rotatedY = basic[1];
58957                     break;
58958             }
58959             let w = this._width;
58960             let h = this._height;
58961             let s = Math.max(w, h);
58962             let sfmX = rotatedX * w / s - w / s / 2;
58963             let sfmY = rotatedY * h / s - h / s / 2;
58964             return [sfmX, sfmY];
58965         }
58966         /**
58967          * Convert SfM coordinates to basic coordinates.
58968          *
58969          * @param {Array<number>} sfm - 2D SfM coordinates.
58970          * @returns {Array<number>} 2D basic coordinates.
58971          */
58972         _sfmToBasic(sfm) {
58973             let w = this._width;
58974             let h = this._height;
58975             let s = Math.max(w, h);
58976             let rotatedX = (sfm[0] + w / s / 2) / w * s;
58977             let rotatedY = (sfm[1] + h / s / 2) / h * s;
58978             let basicX;
58979             let basicY;
58980             switch (this._orientation) {
58981                 case 1:
58982                     basicX = rotatedX;
58983                     basicY = rotatedY;
58984                     break;
58985                 case 3:
58986                     basicX = 1 - rotatedX;
58987                     basicY = 1 - rotatedY;
58988                     break;
58989                 case 6:
58990                     basicX = 1 - rotatedY;
58991                     basicY = rotatedX;
58992                     break;
58993                 case 8:
58994                     basicX = rotatedY;
58995                     basicY = 1 - rotatedX;
58996                     break;
58997                 default:
58998                     basicX = rotatedX;
58999                     basicY = rotatedY;
59000                     break;
59001             }
59002             return [basicX, basicY];
59003         }
59004         /**
59005          * Checks a value and returns it if it exists and is larger than 0.
59006          * Fallbacks if it is null.
59007          *
59008          * @param {number} value - Value to check.
59009          * @param {number} fallback - Value to fall back to.
59010          * @returns {number} The value or its fallback value if it is not defined or negative.
59011          */
59012         _getValue(value, fallback) {
59013             return value != null && value > 0 ? value : fallback;
59014         }
59015         _getCameraParameters(value, cameraType) {
59016             if (isSpherical(cameraType)) {
59017                 return [];
59018             }
59019             if (!value || value.length === 0) {
59020                 return [1, 0, 0];
59021             }
59022             const padding = 3 - value.length;
59023             if (padding <= 0) {
59024                 return value;
59025             }
59026             return value
59027                 .concat(new Array(padding)
59028                 .fill(0));
59029         }
59030         /**
59031          * Creates the extrinsic camera matrix [ R | t ].
59032          *
59033          * @param {Array<number>} rotation - Rotation vector in angle axis representation.
59034          * @param {Array<number>} translation - Translation vector.
59035          * @returns {THREE.Matrix4} Extrisic camera matrix.
59036          */
59037         createWorldToCamera(rotation, translation) {
59038             const axis = new Vector3(rotation[0], rotation[1], rotation[2]);
59039             const angle = axis.length();
59040             if (angle > 0) {
59041                 axis.normalize();
59042             }
59043             const worldToCamera = new Matrix4();
59044             worldToCamera.makeRotationAxis(axis, angle);
59045             worldToCamera.setPosition(new Vector3(translation[0], translation[1], translation[2]));
59046             return worldToCamera;
59047         }
59048         /**
59049          * Calculates the scaled extrinsic camera matrix scale * [ R | t ].
59050          *
59051          * @param {THREE.Matrix4} worldToCamera - Extrisic camera matrix.
59052          * @param {number} scale - Scale factor.
59053          * @returns {THREE.Matrix4} Scaled extrisic camera matrix.
59054          */
59055         _createScaledWorldToCamera(worldToCamera, scale) {
59056             const scaledWorldToCamera = worldToCamera.clone();
59057             const elements = scaledWorldToCamera.elements;
59058             elements[12] = scale * elements[12];
59059             elements[13] = scale * elements[13];
59060             elements[14] = scale * elements[14];
59061             scaledWorldToCamera.scale(new Vector3(scale, scale, scale));
59062             return scaledWorldToCamera;
59063         }
59064         _createBasicWorldToCamera(rt, orientation) {
59065             const axis = new Vector3(0, 0, 1);
59066             let angle = 0;
59067             switch (orientation) {
59068                 case 3:
59069                     angle = Math.PI;
59070                     break;
59071                 case 6:
59072                     angle = Math.PI / 2;
59073                     break;
59074                 case 8:
59075                     angle = 3 * Math.PI / 2;
59076                     break;
59077             }
59078             return new Matrix4()
59079                 .makeRotationAxis(axis, angle)
59080                 .multiply(rt);
59081         }
59082         _getRadialPeak(k1, k2) {
59083             const a = 5 * k2;
59084             const b = 3 * k1;
59085             const c = 1;
59086             const d = Math.pow(b, 2) - 4 * a * c;
59087             if (d < 0) {
59088                 return undefined;
59089             }
59090             const root1 = (-b - Math.sqrt(d)) / 2 / a;
59091             const root2 = (-b + Math.sqrt(d)) / 2 / a;
59092             const minRoot = Math.min(root1, root2);
59093             const maxRoot = Math.max(root1, root2);
59094             return minRoot > 0 ?
59095                 Math.sqrt(minRoot) :
59096                 maxRoot > 0 ?
59097                     Math.sqrt(maxRoot) :
59098                     undefined;
59099         }
59100         /**
59101          * Calculate a transformation matrix from normalized coordinates for
59102          * texture map coordinates.
59103          *
59104          * @returns {THREE.Matrix4} Normalized coordinates to texture map
59105          * coordinates transformation matrix.
59106          */
59107         _normalizedToTextureMatrix() {
59108             const size = Math.max(this._width, this._height);
59109             const scaleX = this._orientation < 5 ? this._textureScale[0] : this._textureScale[1];
59110             const scaleY = this._orientation < 5 ? this._textureScale[1] : this._textureScale[0];
59111             const w = size / this._width * scaleX;
59112             const h = size / this._height * scaleY;
59113             switch (this._orientation) {
59114                 case 1:
59115                     return new Matrix4().set(w, 0, 0, 0.5, 0, -h, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
59116                 case 3:
59117                     return new Matrix4().set(-w, 0, 0, 0.5, 0, h, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
59118                 case 6:
59119                     return new Matrix4().set(0, -h, 0, 0.5, -w, 0, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
59120                 case 8:
59121                     return new Matrix4().set(0, h, 0, 0.5, w, 0, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
59122                 default:
59123                     return new Matrix4().set(w, 0, 0, 0.5, 0, -h, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1);
59124             }
59125         }
59126     }
59127
59128     class SliderGLRenderer {
59129         constructor() {
59130             this._factory = new MeshFactory();
59131             this._scene = new MeshScene();
59132             this._spatial = new Spatial();
59133             this._currentKey = null;
59134             this._previousKey = null;
59135             this._disabled = false;
59136             this._curtain = 1;
59137             this._frameId = 0;
59138             this._needsRender = false;
59139             this._mode = null;
59140             this._currentProviderDisposers = {};
59141             this._previousProviderDisposers = {};
59142         }
59143         get disabled() {
59144             return this._disabled;
59145         }
59146         get frameId() {
59147             return this._frameId;
59148         }
59149         get needsRender() {
59150             return this._needsRender;
59151         }
59152         setTextureProvider(key, provider) {
59153             this._setTextureProvider(key, this._currentKey, provider, this._currentProviderDisposers, this._updateTexture.bind(this));
59154         }
59155         setTextureProviderPrev(key, provider) {
59156             this._setTextureProvider(key, this._previousKey, provider, this._previousProviderDisposers, this._updateTexturePrev.bind(this));
59157         }
59158         update(frame, mode) {
59159             this._updateFrameId(frame.id);
59160             this._updateImagePlanes(frame.state, mode);
59161         }
59162         updateCurtain(curtain) {
59163             if (this._curtain === curtain) {
59164                 return;
59165             }
59166             this._curtain = curtain;
59167             this._updateCurtain();
59168             this._needsRender = true;
59169         }
59170         updateTexture(imageElement, image) {
59171             const planes = image.id === this._currentKey ?
59172                 this._scene.planes :
59173                 image.id === this._previousKey ?
59174                     this._scene.planesOld :
59175                     {};
59176             if (Object.keys(planes).length === 0) {
59177                 return;
59178             }
59179             this._needsRender = true;
59180             for (const key in planes) {
59181                 if (!planes.hasOwnProperty(key)) {
59182                     continue;
59183                 }
59184                 const plane = planes[key];
59185                 let material = plane.material;
59186                 let texture = material.uniforms.projectorTex.value;
59187                 texture.image = imageElement;
59188                 texture.needsUpdate = true;
59189             }
59190         }
59191         updateTextureImage(imageElement, image) {
59192             if (this._currentKey !== image.id) {
59193                 return;
59194             }
59195             this._needsRender = true;
59196             const planes = this._scene.planes;
59197             for (const key in planes) {
59198                 if (!planes.hasOwnProperty(key)) {
59199                     continue;
59200                 }
59201                 const plane = planes[key];
59202                 let material = plane.material;
59203                 let texture = material.uniforms.projectorTex.value;
59204                 texture.image = imageElement;
59205                 texture.needsUpdate = true;
59206             }
59207         }
59208         render(perspectiveCamera, renderer) {
59209             if (!this.disabled) {
59210                 renderer.render(this._scene.sceneOld, perspectiveCamera);
59211             }
59212             renderer.render(this._scene.scene, perspectiveCamera);
59213             this._needsRender = false;
59214         }
59215         dispose() {
59216             this._scene.clear();
59217             for (const key in this._currentProviderDisposers) {
59218                 if (!this._currentProviderDisposers.hasOwnProperty(key)) {
59219                     continue;
59220                 }
59221                 this._currentProviderDisposers[key]();
59222             }
59223             for (const key in this._previousProviderDisposers) {
59224                 if (!this._previousProviderDisposers.hasOwnProperty(key)) {
59225                     continue;
59226                 }
59227                 this._previousProviderDisposers[key]();
59228             }
59229             this._currentProviderDisposers = {};
59230             this._previousProviderDisposers = {};
59231         }
59232         _getBasicCorners(currentAspect, previousAspect) {
59233             let offsetX;
59234             let offsetY;
59235             if (currentAspect > previousAspect) {
59236                 offsetX = 0.5;
59237                 offsetY = 0.5 * currentAspect / previousAspect;
59238             }
59239             else {
59240                 offsetX = 0.5 * previousAspect / currentAspect;
59241                 offsetY = 0.5;
59242             }
59243             return [[0.5 - offsetX, 0.5 - offsetY], [0.5 + offsetX, 0.5 + offsetY]];
59244         }
59245         _setDisabled(state) {
59246             this._disabled = state.currentImage == null ||
59247                 state.previousImage == null ||
59248                 (isSpherical(state.currentImage.cameraType) &&
59249                     !isSpherical(state.previousImage.cameraType));
59250         }
59251         _setTextureProvider(key, originalKey, provider, providerDisposers, updateTexture) {
59252             if (key !== originalKey) {
59253                 return;
59254             }
59255             let createdSubscription = provider.textureCreated$
59256                 .subscribe(updateTexture);
59257             let updatedSubscription = provider.textureUpdated$
59258                 .subscribe((updated) => {
59259                 this._needsRender = true;
59260             });
59261             let dispose = () => {
59262                 createdSubscription.unsubscribe();
59263                 updatedSubscription.unsubscribe();
59264                 provider.dispose();
59265             };
59266             if (key in providerDisposers) {
59267                 let disposeProvider = providerDisposers[key];
59268                 disposeProvider();
59269                 delete providerDisposers[key];
59270             }
59271             providerDisposers[key] = dispose;
59272         }
59273         _updateCurtain() {
59274             const planes = this._scene.planes;
59275             for (const key in planes) {
59276                 if (!planes.hasOwnProperty(key)) {
59277                     continue;
59278                 }
59279                 const plane = planes[key];
59280                 let shaderMaterial = plane.material;
59281                 if (!!shaderMaterial.uniforms.curtain) {
59282                     shaderMaterial.uniforms.curtain.value = this._curtain;
59283                 }
59284             }
59285         }
59286         _updateFrameId(frameId) {
59287             this._frameId = frameId;
59288         }
59289         _updateImagePlanes(state, mode) {
59290             const currentChanged = state.currentImage != null && this._currentKey !== state.currentImage.id;
59291             const previousChanged = state.previousImage != null && this._previousKey !== state.previousImage.id;
59292             const modeChanged = this._mode !== mode;
59293             if (!(currentChanged || previousChanged || modeChanged)) {
59294                 return;
59295             }
59296             this._setDisabled(state);
59297             this._needsRender = true;
59298             this._mode = mode;
59299             const motionless = state.motionless ||
59300                 mode === exports.SliderConfigurationMode.Stationary ||
59301                 isSpherical(state.currentImage.cameraType);
59302             if (this.disabled || previousChanged) {
59303                 if (this._previousKey in this._previousProviderDisposers) {
59304                     this._previousProviderDisposers[this._previousKey]();
59305                     delete this._previousProviderDisposers[this._previousKey];
59306                 }
59307             }
59308             if (this.disabled) {
59309                 this._scene.setImagePlanesOld({});
59310             }
59311             else {
59312                 if (previousChanged || modeChanged) {
59313                     const previousNode = state.previousImage;
59314                     this._previousKey = previousNode.id;
59315                     const elements = state.currentTransform.rt.elements;
59316                     let translation = [elements[12], elements[13], elements[14]];
59317                     const currentAspect = state.currentTransform.basicAspect;
59318                     const previousAspect = state.previousTransform.basicAspect;
59319                     const textureScale = currentAspect > previousAspect ?
59320                         [1, previousAspect / currentAspect] :
59321                         [currentAspect / previousAspect, 1];
59322                     let rotation = state.currentImage.rotation;
59323                     let width = state.currentImage.width;
59324                     let height = state.currentImage.height;
59325                     if (isSpherical(previousNode.cameraType)) {
59326                         rotation = state.previousImage.rotation;
59327                         translation = this._spatial
59328                             .rotate(this._spatial
59329                             .opticalCenter(state.currentImage.rotation, translation)
59330                             .toArray(), rotation)
59331                             .multiplyScalar(-1)
59332                             .toArray();
59333                         width = state.previousImage.width;
59334                         height = state.previousImage.height;
59335                     }
59336                     const transform = new Transform(state.currentImage.exifOrientation, width, height, state.currentImage.scale, rotation, translation, previousNode.image, textureScale, state.currentImage.cameraParameters, state.currentImage.cameraType);
59337                     let mesh = undefined;
59338                     if (isSpherical(previousNode.cameraType)) {
59339                         mesh = this._factory.createMesh(previousNode, motionless ||
59340                             isSpherical(state.currentImage.cameraType) ?
59341                             transform : state.previousTransform);
59342                     }
59343                     else {
59344                         if (motionless) {
59345                             const [[basicX0, basicY0], [basicX1, basicY1]] = this._getBasicCorners(currentAspect, previousAspect);
59346                             mesh = this._factory.createFlatMesh(state.previousImage, transform, basicX0, basicX1, basicY0, basicY1);
59347                         }
59348                         else {
59349                             mesh = this._factory.createMesh(state.previousImage, state.previousTransform);
59350                         }
59351                     }
59352                     const previousPlanes = {};
59353                     previousPlanes[previousNode.id] = mesh;
59354                     this._scene.setImagePlanesOld(previousPlanes);
59355                 }
59356             }
59357             if (currentChanged || modeChanged) {
59358                 if (this._currentKey in this._currentProviderDisposers) {
59359                     this._currentProviderDisposers[this._currentKey]();
59360                     delete this._currentProviderDisposers[this._currentKey];
59361                 }
59362                 this._currentKey = state.currentImage.id;
59363                 const planes = {};
59364                 if (isSpherical(state.currentImage.cameraType)) {
59365                     planes[state.currentImage.id] =
59366                         this._factory.createCurtainMesh(state.currentImage, state.currentTransform);
59367                 }
59368                 else {
59369                     if (motionless) {
59370                         planes[state.currentImage.id] = this._factory.createDistortedCurtainMesh(state.currentImage, state.currentTransform);
59371                     }
59372                     else {
59373                         planes[state.currentImage.id] = this._factory.createCurtainMesh(state.currentImage, state.currentTransform);
59374                     }
59375                 }
59376                 this._scene.setImagePlanes(planes);
59377                 this._updateCurtain();
59378             }
59379         }
59380         _updateTexture(texture) {
59381             this._needsRender = true;
59382             const planes = this._scene.planes;
59383             for (const key in planes) {
59384                 if (!planes.hasOwnProperty(key)) {
59385                     continue;
59386                 }
59387                 const plane = planes[key];
59388                 let material = plane.material;
59389                 let oldTexture = material.uniforms.projectorTex.value;
59390                 material.uniforms.projectorTex.value = null;
59391                 oldTexture.dispose();
59392                 material.uniforms.projectorTex.value = texture;
59393             }
59394         }
59395         _updateTexturePrev(texture) {
59396             this._needsRender = true;
59397             const planes = this._scene.planesOld;
59398             for (const key in planes) {
59399                 if (!planes.hasOwnProperty(key)) {
59400                     continue;
59401                 }
59402                 const plane = planes[key];
59403                 let material = plane.material;
59404                 let oldTexture = material.uniforms.projectorTex.value;
59405                 material.uniforms.projectorTex.value = null;
59406                 oldTexture.dispose();
59407                 material.uniforms.projectorTex.value = texture;
59408             }
59409         }
59410     }
59411
59412     class SliderDOMRenderer {
59413         constructor(container) {
59414             this._container = container;
59415             this._interacting = false;
59416             this._notifyModeChanged$ = new Subject();
59417             this._notifyPositionChanged$ = new Subject();
59418             this._stopInteractionSubscription = null;
59419         }
59420         get mode$() {
59421             return this._notifyModeChanged$;
59422         }
59423         get position$() {
59424             return this._notifyPositionChanged$;
59425         }
59426         activate() {
59427             if (!!this._stopInteractionSubscription) {
59428                 return;
59429             }
59430             this._stopInteractionSubscription = merge(this._container.mouseService.documentMouseUp$, this._container.touchService.touchEnd$.pipe(filter((touchEvent) => {
59431                 return touchEvent.touches.length === 0;
59432             })))
59433                 .subscribe((event) => {
59434                 if (this._interacting) {
59435                     this._interacting = false;
59436                 }
59437             });
59438         }
59439         deactivate() {
59440             if (!this._stopInteractionSubscription) {
59441                 return;
59442             }
59443             this._interacting = false;
59444             this._stopInteractionSubscription.unsubscribe();
59445             this._stopInteractionSubscription = null;
59446         }
59447         render(position, mode, motionless, spherical, visible) {
59448             const children = [];
59449             if (visible) {
59450                 children.push(virtualDom.h("div.mapillary-slider-border", []));
59451                 const modeVisible = !(motionless || spherical);
59452                 if (modeVisible) {
59453                     children.push(this._createModeButton(mode));
59454                     children.push(this._createModeButton2d(mode));
59455                 }
59456                 children.push(this._createPositionInput(position, modeVisible));
59457             }
59458             const boundingRect = this._container.domContainer.getBoundingClientRect();
59459             const width = Math.max(215, Math.min(400, boundingRect.width - 100));
59460             return virtualDom.h("div.mapillary-slider-container", { style: { width: `${width}px` } }, children);
59461         }
59462         _createModeButton(mode) {
59463             const properties = {
59464                 onclick: () => {
59465                     if (mode === exports.SliderConfigurationMode.Motion) {
59466                         return;
59467                     }
59468                     this._notifyModeChanged$.next(exports.SliderConfigurationMode.Motion);
59469                 },
59470             };
59471             const className = mode === exports.SliderConfigurationMode.Stationary ?
59472                 "mapillary-slider-mode-button-inactive" :
59473                 "mapillary-slider-mode-button";
59474             return virtualDom.h("div." + className, properties, [virtualDom.h("div.mapillary-slider-mode-icon", [])]);
59475         }
59476         _createModeButton2d(mode) {
59477             const properties = {
59478                 onclick: () => {
59479                     if (mode === exports.SliderConfigurationMode.Stationary) {
59480                         return;
59481                     }
59482                     this._notifyModeChanged$.next(exports.SliderConfigurationMode.Stationary);
59483                 },
59484             };
59485             const className = mode === exports.SliderConfigurationMode.Motion ?
59486                 "mapillary-slider-mode-button-2d-inactive" :
59487                 "mapillary-slider-mode-button-2d";
59488             return virtualDom.h("div." + className, properties, [virtualDom.h("div.mapillary-slider-mode-icon-2d", [])]);
59489         }
59490         _createPositionInput(position, modeVisible) {
59491             const onChange = (e) => {
59492                 this._notifyPositionChanged$.next(Number(e.target.value) / 1000);
59493             };
59494             const onStart = (e) => {
59495                 this._interacting = true;
59496                 e.stopPropagation();
59497             };
59498             const onMove = (e) => {
59499                 if (this._interacting) {
59500                     e.stopPropagation();
59501                 }
59502             };
59503             const onKeyDown = (e) => {
59504                 if (e.key === "ArrowDown" || e.key === "ArrowLeft" ||
59505                     e.key === "ArrowRight" || e.key === "ArrowUp") {
59506                     e.preventDefault();
59507                 }
59508             };
59509             const boundingRect = this._container.domContainer.getBoundingClientRect();
59510             const width = Math.max(215, Math.min(400, boundingRect.width - 105)) - 84 + (modeVisible ? 0 : 52);
59511             const positionInput = virtualDom.h("input.mapillary-slider-position", {
59512                 max: 1000,
59513                 min: 0,
59514                 onchange: onChange,
59515                 oninput: onChange,
59516                 onkeydown: onKeyDown,
59517                 onpointerdown: onStart,
59518                 onpointermove: onMove,
59519                 ontouchmove: onMove,
59520                 ontouchstart: onStart,
59521                 style: {
59522                     width: `${width}px`,
59523                 },
59524                 type: "range",
59525                 value: 1000 * position,
59526             }, []);
59527             return virtualDom.h("div.mapillary-slider-position-container", [positionInput]);
59528         }
59529     }
59530
59531     /**
59532      * @class SliderComponent
59533      *
59534      * @classdesc Component for comparing pairs of images. Renders
59535      * a slider for adjusting the curtain of the first image.
59536      *
59537      * Deactivate the sequence, direction and image plane
59538      * components when activating the slider component to avoid
59539      * interfering UI elements.
59540      *
59541      * To retrive and use the slider component
59542      *
59543      * @example
59544      * ```js
59545      * var viewer = new Viewer({ ... });
59546      *
59547      * viewer.deactivateComponent("image");
59548      * viewer.deactivateComponent("direction");
59549      * viewer.deactivateComponent("sequence");
59550      *
59551      * viewer.activateComponent("slider");
59552      *
59553      * var sliderComponent = viewer.getComponent("slider");
59554      * ```
59555      */
59556     class SliderComponent extends Component {
59557         /** @ignore */
59558         constructor(name, container, navigator, viewportCoords) {
59559             super(name, container, navigator);
59560             this._viewportCoords = !!viewportCoords ? viewportCoords : new ViewportCoords();
59561             this._domRenderer = new SliderDOMRenderer(container);
59562             this._imageTileLoader = new TileLoader(navigator.api);
59563             this._roiCalculator = new RegionOfInterestCalculator();
59564             this._spatial = new Spatial();
59565             this._glRendererOperation$ = new Subject();
59566             this._glRendererCreator$ = new Subject();
59567             this._glRendererDisposer$ = new Subject();
59568             this._glRenderer$ = this._glRendererOperation$.pipe(scan((glRenderer, operation) => {
59569                 return operation(glRenderer);
59570             }, null), filter((glRenderer) => {
59571                 return glRenderer != null;
59572             }), distinctUntilChanged(undefined, (glRenderer) => {
59573                 return glRenderer.frameId;
59574             }));
59575             this._glRendererCreator$.pipe(map(() => {
59576                 return (glRenderer) => {
59577                     if (glRenderer != null) {
59578                         throw new Error("Multiple slider states can not be created at the same time");
59579                     }
59580                     return new SliderGLRenderer();
59581                 };
59582             }))
59583                 .subscribe(this._glRendererOperation$);
59584             this._glRendererDisposer$.pipe(map(() => {
59585                 return (glRenderer) => {
59586                     glRenderer.dispose();
59587                     return null;
59588                 };
59589             }))
59590                 .subscribe(this._glRendererOperation$);
59591         }
59592         _activate() {
59593             const subs = this._subscriptions;
59594             subs.push(this._domRenderer.mode$
59595                 .subscribe((mode) => {
59596                 this.configure({ mode });
59597             }));
59598             subs.push(this._glRenderer$.pipe(map((glRenderer) => {
59599                 let renderHash = {
59600                     name: this._name,
59601                     renderer: {
59602                         frameId: glRenderer.frameId,
59603                         needsRender: glRenderer.needsRender,
59604                         render: glRenderer.render.bind(glRenderer),
59605                         pass: RenderPass.Background,
59606                     },
59607                 };
59608                 return renderHash;
59609             }))
59610                 .subscribe(this._container.glRenderer.render$));
59611             const position$ = concat(this.configuration$.pipe(map((configuration) => {
59612                 return configuration.initialPosition != null ?
59613                     configuration.initialPosition : 1;
59614             }), first()), this._domRenderer.position$);
59615             const mode$ = this.configuration$.pipe(map((configuration) => {
59616                 return configuration.mode;
59617             }), distinctUntilChanged());
59618             const motionless$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
59619                 return frame.state.motionless;
59620             }), distinctUntilChanged());
59621             const spherical$ = this._navigator.stateService.currentState$.pipe(map((frame) => {
59622                 return isSpherical(frame.state.currentImage.cameraType);
59623             }), distinctUntilChanged());
59624             const sliderVisible$ = combineLatest(this._configuration$.pipe(map((configuration) => {
59625                 return configuration.sliderVisible;
59626             })), this._navigator.stateService.currentState$.pipe(map((frame) => {
59627                 return !(frame.state.currentImage == null ||
59628                     frame.state.previousImage == null ||
59629                     (isSpherical(frame.state.currentImage.cameraType) &&
59630                         !isSpherical(frame.state.previousImage.cameraType)));
59631             }), distinctUntilChanged())).pipe(map(([sliderVisible, enabledState]) => {
59632                 return sliderVisible && enabledState;
59633             }), distinctUntilChanged());
59634             this._waitSubscription = combineLatest(mode$, motionless$, spherical$, sliderVisible$).pipe(withLatestFrom(this._navigator.stateService.state$))
59635                 .subscribe(([[mode, motionless, spherical, sliderVisible], state]) => {
59636                 const interactive = sliderVisible &&
59637                     (motionless ||
59638                         mode === exports.SliderConfigurationMode.Stationary ||
59639                         spherical);
59640                 if (interactive && state !== State.WaitingInteractively) {
59641                     this._navigator.stateService.waitInteractively();
59642                 }
59643                 else if (!interactive && state !== State.Waiting) {
59644                     this._navigator.stateService.wait();
59645                 }
59646             });
59647             subs.push(combineLatest(position$, mode$, motionless$, spherical$, sliderVisible$)
59648                 .subscribe(([position, mode, motionless, spherical]) => {
59649                 if (motionless || mode === exports.SliderConfigurationMode.Stationary || spherical) {
59650                     this._navigator.stateService.moveTo(1);
59651                 }
59652                 else {
59653                     this._navigator.stateService.moveTo(position);
59654                 }
59655             }));
59656             subs.push(combineLatest(position$, mode$, motionless$, spherical$, sliderVisible$, this._container.renderService.size$).pipe(map(([position, mode, motionless, spherical, sliderVisible]) => {
59657                 return {
59658                     name: this._name,
59659                     vNode: this._domRenderer.render(position, mode, motionless, spherical, sliderVisible),
59660                 };
59661             }))
59662                 .subscribe(this._container.domRenderer.render$));
59663             this._glRendererCreator$.next(null);
59664             subs.push(combineLatest(position$, spherical$, sliderVisible$, this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$).pipe(map(([position, spherical, visible, render, transform]) => {
59665                 if (!spherical) {
59666                     return visible ? position : 1;
59667                 }
59668                 const basicMin = this._viewportCoords.viewportToBasic(-1.15, 0, transform, render.perspective);
59669                 const basicMax = this._viewportCoords.viewportToBasic(1.15, 0, transform, render.perspective);
59670                 const shiftedMax = basicMax[0] < basicMin[0] ? basicMax[0] + 1 : basicMax[0];
59671                 const basicPosition = basicMin[0] + position * (shiftedMax - basicMin[0]);
59672                 return basicPosition > 1 ? basicPosition - 1 : basicPosition;
59673             }), map((position) => {
59674                 return (glRenderer) => {
59675                     glRenderer.updateCurtain(position);
59676                     return glRenderer;
59677                 };
59678             }))
59679                 .subscribe(this._glRendererOperation$));
59680             subs.push(combineLatest(this._navigator.stateService.currentState$, mode$).pipe(map(([frame, mode]) => {
59681                 return (glRenderer) => {
59682                     glRenderer.update(frame, mode);
59683                     return glRenderer;
59684                 };
59685             }))
59686                 .subscribe(this._glRendererOperation$));
59687             subs.push(this._configuration$.pipe(filter((configuration) => {
59688                 return configuration.ids != null;
59689             }), switchMap((configuration) => {
59690                 return zip(zip(this._catchCacheImage$(configuration.ids.background), this._catchCacheImage$(configuration.ids.foreground)).pipe(map((images) => {
59691                     return { background: images[0], foreground: images[1] };
59692                 })), this._navigator.stateService.currentState$.pipe(first())).pipe(map((nf) => {
59693                     return { images: nf[0], state: nf[1].state };
59694                 }));
59695             }))
59696                 .subscribe((co) => {
59697                 if (co.state.currentImage != null &&
59698                     co.state.previousImage != null &&
59699                     co.state.currentImage.id === co.images.foreground.id &&
59700                     co.state.previousImage.id === co.images.background.id) {
59701                     return;
59702                 }
59703                 if (co.state.currentImage.id === co.images.background.id) {
59704                     this._navigator.stateService.setImages([co.images.foreground]);
59705                     return;
59706                 }
59707                 if (co.state.currentImage.id === co.images.foreground.id &&
59708                     co.state.trajectory.length === 1) {
59709                     this._navigator.stateService.prependImages([co.images.background]);
59710                     return;
59711                 }
59712                 this._navigator.stateService.setImages([co.images.background]);
59713                 this._navigator.stateService.setImages([co.images.foreground]);
59714             }, (e) => {
59715                 console.error(e);
59716             }));
59717             const textureProvider$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
59718                 return active ?
59719                     this._navigator.stateService.currentState$ :
59720                     new Subject();
59721             }), distinctUntilChanged(undefined, (frame) => {
59722                 return frame.state.currentImage.id;
59723             }), withLatestFrom(this._container.glRenderer.webGLRenderer$, this._container.renderService.size$), map(([frame, renderer, size]) => {
59724                 const state = frame.state;
59725                 Math.max(size.width, size.height);
59726                 const currentImage = state.currentImage;
59727                 const currentTransform = state.currentTransform;
59728                 return new TextureProvider(currentImage.id, currentTransform.basicWidth, currentTransform.basicHeight, currentImage.image, this._imageTileLoader, new TileStore(), renderer);
59729             }), publishReplay(1), refCount());
59730             subs.push(textureProvider$.subscribe(() => { }));
59731             subs.push(textureProvider$.pipe(map((provider) => {
59732                 return (renderer) => {
59733                     renderer.setTextureProvider(provider.id, provider);
59734                     return renderer;
59735                 };
59736             }))
59737                 .subscribe(this._glRendererOperation$));
59738             subs.push(textureProvider$.pipe(pairwise())
59739                 .subscribe((pair) => {
59740                 let previous = pair[0];
59741                 previous.abort();
59742             }));
59743             const roiTrigger$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
59744                 return active ?
59745                     combineLatest(this._container.renderService.renderCameraFrame$, this._container.renderService.size$.pipe(debounceTime(250))) :
59746                     new Subject();
59747             }), map(([camera, size]) => {
59748                 return [
59749                     camera.camera.position.clone(),
59750                     camera.camera.lookat.clone(),
59751                     camera.zoom.valueOf(),
59752                     size.height.valueOf(),
59753                     size.width.valueOf()
59754                 ];
59755             }), pairwise(), skipWhile((pls) => {
59756                 return pls[1][2] - pls[0][2] < 0 || pls[1][2] === 0;
59757             }), map((pls) => {
59758                 let samePosition = pls[0][0].equals(pls[1][0]);
59759                 let sameLookat = pls[0][1].equals(pls[1][1]);
59760                 let sameZoom = pls[0][2] === pls[1][2];
59761                 let sameHeight = pls[0][3] === pls[1][3];
59762                 let sameWidth = pls[0][4] === pls[1][4];
59763                 return samePosition && sameLookat && sameZoom && sameHeight && sameWidth;
59764             }), distinctUntilChanged(), filter((stalled) => {
59765                 return stalled;
59766             }), switchMap(() => {
59767                 return this._container.renderService.renderCameraFrame$.pipe(first());
59768             }), withLatestFrom(this._container.renderService.size$, this._navigator.stateService.currentTransform$));
59769             subs.push(textureProvider$.pipe(switchMap((provider) => {
59770                 return roiTrigger$.pipe(map(([camera, size, transform]) => {
59771                     return [
59772                         this._roiCalculator.computeRegionOfInterest(camera, size, transform),
59773                         provider,
59774                     ];
59775                 }));
59776             }), filter((args) => {
59777                 return !args[1].disposed;
59778             }))
59779                 .subscribe((args) => {
59780                 let roi = args[0];
59781                 let provider = args[1];
59782                 provider.setRegionOfInterest(roi);
59783             }));
59784             const hasTexture$ = textureProvider$.pipe(switchMap((provider) => {
59785                 return provider.hasTexture$;
59786             }), startWith(false), publishReplay(1), refCount());
59787             subs.push(hasTexture$.subscribe(() => { }));
59788             const textureProviderPrev$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
59789                 return active ?
59790                     this._navigator.stateService.currentState$ :
59791                     new Subject();
59792             }), filter((frame) => {
59793                 return !!frame.state.previousImage;
59794             }), distinctUntilChanged(undefined, (frame) => {
59795                 return frame.state.previousImage.id;
59796             }), withLatestFrom(this._container.glRenderer.webGLRenderer$, this._container.renderService.size$), map(([frame, renderer, size]) => {
59797                 const state = frame.state;
59798                 const previousImage = state.previousImage;
59799                 const previousTransform = state.previousTransform;
59800                 return new TextureProvider(previousImage.id, previousTransform.basicWidth, previousTransform.basicHeight, previousImage.image, this._imageTileLoader, new TileStore(), renderer);
59801             }), publishReplay(1), refCount());
59802             subs.push(textureProviderPrev$.subscribe(() => { }));
59803             subs.push(textureProviderPrev$.pipe(map((provider) => {
59804                 return (renderer) => {
59805                     renderer.setTextureProviderPrev(provider.id, provider);
59806                     return renderer;
59807                 };
59808             }))
59809                 .subscribe(this._glRendererOperation$));
59810             subs.push(textureProviderPrev$.pipe(pairwise())
59811                 .subscribe((pair) => {
59812                 let previous = pair[0];
59813                 previous.abort();
59814             }));
59815             const roiTriggerPrev$ = this._container.configurationService.imageTiling$.pipe(switchMap((active) => {
59816                 return active ?
59817                     combineLatest(this._container.renderService.renderCameraFrame$, this._container.renderService.size$.pipe(debounceTime(250))) :
59818                     new Subject();
59819             }), map(([camera, size]) => {
59820                 return [
59821                     camera.camera.position.clone(),
59822                     camera.camera.lookat.clone(),
59823                     camera.zoom.valueOf(),
59824                     size.height.valueOf(),
59825                     size.width.valueOf()
59826                 ];
59827             }), pairwise(), skipWhile((pls) => {
59828                 return pls[1][2] - pls[0][2] < 0 || pls[1][2] === 0;
59829             }), map((pls) => {
59830                 let samePosition = pls[0][0].equals(pls[1][0]);
59831                 let sameLookat = pls[0][1].equals(pls[1][1]);
59832                 let sameZoom = pls[0][2] === pls[1][2];
59833                 let sameHeight = pls[0][3] === pls[1][3];
59834                 let sameWidth = pls[0][4] === pls[1][4];
59835                 return samePosition && sameLookat && sameZoom && sameHeight && sameWidth;
59836             }), distinctUntilChanged(), filter((stalled) => {
59837                 return stalled;
59838             }), switchMap(() => {
59839                 return this._container.renderService.renderCameraFrame$.pipe(first());
59840             }), withLatestFrom(this._container.renderService.size$, this._navigator.stateService.currentTransform$));
59841             subs.push(textureProviderPrev$.pipe(switchMap((provider) => {
59842                 return roiTriggerPrev$.pipe(map(([camera, size, transform]) => {
59843                     return [
59844                         this._roiCalculator.computeRegionOfInterest(camera, size, transform),
59845                         provider,
59846                     ];
59847                 }));
59848             }), filter((args) => {
59849                 return !args[1].disposed;
59850             }), withLatestFrom(this._navigator.stateService.currentState$))
59851                 .subscribe(([[roi, provider], frame]) => {
59852                 let shiftedRoi = null;
59853                 if (isSpherical(frame.state.previousImage.cameraType)) {
59854                     if (isSpherical(frame.state.currentImage.cameraType)) {
59855                         const currentViewingDirection = this._spatial.viewingDirection(frame.state.currentImage.rotation);
59856                         const previousViewingDirection = this._spatial.viewingDirection(frame.state.previousImage.rotation);
59857                         const directionDiff = this._spatial.angleBetweenVector2(currentViewingDirection.x, currentViewingDirection.y, previousViewingDirection.x, previousViewingDirection.y);
59858                         const shift = directionDiff / (2 * Math.PI);
59859                         const bbox = {
59860                             maxX: this._spatial.wrap(roi.bbox.maxX + shift, 0, 1),
59861                             maxY: roi.bbox.maxY,
59862                             minX: this._spatial.wrap(roi.bbox.minX + shift, 0, 1),
59863                             minY: roi.bbox.minY,
59864                         };
59865                         shiftedRoi = {
59866                             bbox: bbox,
59867                             pixelHeight: roi.pixelHeight,
59868                             pixelWidth: roi.pixelWidth,
59869                         };
59870                     }
59871                     else {
59872                         const currentViewingDirection = this._spatial.viewingDirection(frame.state.currentImage.rotation);
59873                         const previousViewingDirection = this._spatial.viewingDirection(frame.state.previousImage.rotation);
59874                         const directionDiff = this._spatial.angleBetweenVector2(currentViewingDirection.x, currentViewingDirection.y, previousViewingDirection.x, previousViewingDirection.y);
59875                         const shiftX = directionDiff / (2 * Math.PI);
59876                         const a1 = this._spatial.angleToPlane(currentViewingDirection.toArray(), [0, 0, 1]);
59877                         const a2 = this._spatial.angleToPlane(previousViewingDirection.toArray(), [0, 0, 1]);
59878                         const shiftY = (a2 - a1) / (2 * Math.PI);
59879                         const currentTransform = frame.state.currentTransform;
59880                         const size = Math.max(currentTransform.basicWidth, currentTransform.basicHeight);
59881                         const hFov = size > 0 ?
59882                             2 * Math.atan(0.5 * currentTransform.basicWidth / (size * currentTransform.focal)) :
59883                             Math.PI / 3;
59884                         const vFov = size > 0 ?
59885                             2 * Math.atan(0.5 * currentTransform.basicHeight / (size * currentTransform.focal)) :
59886                             Math.PI / 3;
59887                         const spanningWidth = hFov / (2 * Math.PI);
59888                         const spanningHeight = vFov / Math.PI;
59889                         const basicWidth = (roi.bbox.maxX - roi.bbox.minX) * spanningWidth;
59890                         const basicHeight = (roi.bbox.maxY - roi.bbox.minY) * spanningHeight;
59891                         const pixelWidth = roi.pixelWidth * spanningWidth;
59892                         const pixelHeight = roi.pixelHeight * spanningHeight;
59893                         const zoomShiftX = (roi.bbox.minX + roi.bbox.maxX) / 2 - 0.5;
59894                         const zoomShiftY = (roi.bbox.minY + roi.bbox.maxY) / 2 - 0.5;
59895                         const minX = 0.5 + shiftX + spanningWidth * zoomShiftX - basicWidth / 2;
59896                         const maxX = 0.5 + shiftX + spanningWidth * zoomShiftX + basicWidth / 2;
59897                         const minY = 0.5 + shiftY + spanningHeight * zoomShiftY - basicHeight / 2;
59898                         const maxY = 0.5 + shiftY + spanningHeight * zoomShiftY + basicHeight / 2;
59899                         const bbox = {
59900                             maxX: this._spatial.wrap(maxX, 0, 1),
59901                             maxY: maxY,
59902                             minX: this._spatial.wrap(minX, 0, 1),
59903                             minY: minY,
59904                         };
59905                         shiftedRoi = {
59906                             bbox: bbox,
59907                             pixelHeight: pixelHeight,
59908                             pixelWidth: pixelWidth,
59909                         };
59910                     }
59911                 }
59912                 else {
59913                     const currentBasicAspect = frame.state.currentTransform.basicAspect;
59914                     const previousBasicAspect = frame.state.previousTransform.basicAspect;
59915                     const [[cornerMinX, cornerMinY], [cornerMaxX, cornerMaxY]] = this._getBasicCorners(currentBasicAspect, previousBasicAspect);
59916                     const basicWidth = cornerMaxX - cornerMinX;
59917                     const basicHeight = cornerMaxY - cornerMinY;
59918                     const pixelWidth = roi.pixelWidth / basicWidth;
59919                     const pixelHeight = roi.pixelHeight / basicHeight;
59920                     const minX = (basicWidth - 1) / (2 * basicWidth) + roi.bbox.minX / basicWidth;
59921                     const maxX = (basicWidth - 1) / (2 * basicWidth) + roi.bbox.maxX / basicWidth;
59922                     const minY = (basicHeight - 1) / (2 * basicHeight) + roi.bbox.minY / basicHeight;
59923                     const maxY = (basicHeight - 1) / (2 * basicHeight) + roi.bbox.maxY / basicHeight;
59924                     const bbox = {
59925                         maxX: maxX,
59926                         maxY: maxY,
59927                         minX: minX,
59928                         minY: minY,
59929                     };
59930                     this._clipBoundingBox(bbox);
59931                     shiftedRoi = {
59932                         bbox: bbox,
59933                         pixelHeight: pixelHeight,
59934                         pixelWidth: pixelWidth,
59935                     };
59936                 }
59937                 provider.setRegionOfInterest(shiftedRoi);
59938             }));
59939             const hasTexturePrev$ = textureProviderPrev$.pipe(switchMap((provider) => {
59940                 return provider.hasTexture$;
59941             }), startWith(false), publishReplay(1), refCount());
59942             subs.push(hasTexturePrev$.subscribe(() => { }));
59943         }
59944         _deactivate() {
59945             this._waitSubscription.unsubscribe();
59946             this._navigator.stateService.state$.pipe(first())
59947                 .subscribe((state) => {
59948                 if (state !== State.Traversing) {
59949                     this._navigator.stateService.traverse();
59950                 }
59951             });
59952             this._glRendererDisposer$.next(null);
59953             this._domRenderer.deactivate();
59954             this._subscriptions.unsubscribe();
59955             this.configure({ ids: null });
59956         }
59957         _getDefaultConfiguration() {
59958             return {
59959                 initialPosition: 1,
59960                 mode: exports.SliderConfigurationMode.Motion,
59961                 sliderVisible: true,
59962             };
59963         }
59964         _catchCacheImage$(imageId) {
59965             return this._navigator.graphService.cacheImage$(imageId).pipe(catchError((error) => {
59966                 console.error(`Failed to cache slider image (${imageId})`, error);
59967                 return empty();
59968             }));
59969         }
59970         _getBasicCorners(currentAspect, previousAspect) {
59971             let offsetX;
59972             let offsetY;
59973             if (currentAspect > previousAspect) {
59974                 offsetX = 0.5;
59975                 offsetY = 0.5 * currentAspect / previousAspect;
59976             }
59977             else {
59978                 offsetX = 0.5 * previousAspect / currentAspect;
59979                 offsetY = 0.5;
59980             }
59981             return [[0.5 - offsetX, 0.5 - offsetY], [0.5 + offsetX, 0.5 + offsetY]];
59982         }
59983         _clipBoundingBox(bbox) {
59984             bbox.minX = Math.max(0, Math.min(1, bbox.minX));
59985             bbox.maxX = Math.max(0, Math.min(1, bbox.maxX));
59986             bbox.minY = Math.max(0, Math.min(1, bbox.minY));
59987             bbox.maxY = Math.max(0, Math.min(1, bbox.maxY));
59988         }
59989     }
59990     SliderComponent.componentName = "slider";
59991
59992     class PlayService {
59993         constructor(graphService, stateService) {
59994             this._subscriptions = new SubscriptionHolder();
59995             this._graphService = graphService;
59996             this._stateService = stateService;
59997             const subs = this._subscriptions;
59998             this._directionSubject$ = new Subject();
59999             this._direction$ = this._directionSubject$.pipe(startWith(exports.NavigationDirection.Next), publishReplay(1), refCount());
60000             subs.push(this._direction$.subscribe());
60001             this._playing = false;
60002             this._playingSubject$ = new Subject();
60003             this._playing$ = this._playingSubject$.pipe(startWith(this._playing), publishReplay(1), refCount());
60004             subs.push(this._playing$.subscribe());
60005             this._speed = 0.5;
60006             this._speedSubject$ = new Subject();
60007             this._speed$ = this._speedSubject$.pipe(startWith(this._speed), publishReplay(1), refCount());
60008             subs.push(this._speed$.subscribe());
60009             this._imagesAhead = this._mapImagesAhead(this._mapSpeed(this._speed));
60010             this._bridging$ = null;
60011         }
60012         get playing() {
60013             return this._playing;
60014         }
60015         get direction$() {
60016             return this._direction$;
60017         }
60018         get playing$() {
60019             return this._playing$;
60020         }
60021         get speed$() {
60022             return this._speed$;
60023         }
60024         play() {
60025             if (this._playing) {
60026                 return;
60027             }
60028             this._stateService.cutImages();
60029             const stateSpeed = this._setSpeed(this._speed);
60030             this._stateService.setSpeed(stateSpeed);
60031             this._graphModeSubscription = this._speed$.pipe(map((speed) => {
60032                 return speed > PlayService.sequenceSpeed ? GraphMode.Sequence : GraphMode.Spatial;
60033             }), distinctUntilChanged())
60034                 .subscribe((mode) => {
60035                 this._graphService.setGraphMode(mode);
60036             });
60037             this._cacheSubscription = combineLatest(this._stateService.currentImage$.pipe(map((image) => {
60038                 return [image.sequenceId, image.id];
60039             }), distinctUntilChanged(undefined, ([sequenceId]) => {
60040                 return sequenceId;
60041             })), this._graphService.graphMode$, this._direction$).pipe(switchMap(([[sequenceId, imageId], mode, direction]) => {
60042                 if (direction !== exports.NavigationDirection.Next && direction !== exports.NavigationDirection.Prev) {
60043                     return of([undefined, direction]);
60044                 }
60045                 const sequence$ = (mode === GraphMode.Sequence ?
60046                     this._graphService.cacheSequenceImages$(sequenceId, imageId) :
60047                     this._graphService.cacheSequence$(sequenceId)).pipe(retry(3), catchError((error) => {
60048                     console.error(error);
60049                     return of(undefined);
60050                 }));
60051                 return combineLatest(sequence$, of(direction));
60052             }), switchMap(([sequence, direction]) => {
60053                 if (sequence === undefined) {
60054                     return empty();
60055                 }
60056                 const imageIds = sequence.imageIds.slice();
60057                 if (direction === exports.NavigationDirection.Prev) {
60058                     imageIds.reverse();
60059                 }
60060                 return this._stateService.currentState$.pipe(map((frame) => {
60061                     return [frame.state.trajectory[frame.state.trajectory.length - 1].id, frame.state.imagesAhead];
60062                 }), scan(([lastRequestKey, previousRequestKeys], [lastTrajectoryKey, imagesAhead]) => {
60063                     if (lastRequestKey === undefined) {
60064                         lastRequestKey = lastTrajectoryKey;
60065                     }
60066                     const lastIndex = imageIds.length - 1;
60067                     if (imagesAhead >= this._imagesAhead || imageIds[lastIndex] === lastRequestKey) {
60068                         return [lastRequestKey, []];
60069                     }
60070                     const current = imageIds.indexOf(lastTrajectoryKey);
60071                     const start = imageIds.indexOf(lastRequestKey) + 1;
60072                     const end = Math.min(lastIndex, current + this._imagesAhead - imagesAhead) + 1;
60073                     if (end <= start) {
60074                         return [lastRequestKey, []];
60075                     }
60076                     return [imageIds[end - 1], imageIds.slice(start, end)];
60077                 }, [undefined, []]), mergeMap(([lastRequestKey, newRequestKeys]) => {
60078                     return from(newRequestKeys);
60079                 }));
60080             }), mergeMap((key) => {
60081                 return this._graphService.cacheImage$(key).pipe(catchError(() => {
60082                     return empty();
60083                 }));
60084             }, 6))
60085                 .subscribe();
60086             this._playingSubscription = this._stateService.currentState$.pipe(filter((frame) => {
60087                 return frame.state.imagesAhead < this._imagesAhead;
60088             }), distinctUntilChanged(undefined, (frame) => {
60089                 return frame.state.lastImage.id;
60090             }), map((frame) => {
60091                 const lastImage = frame.state.lastImage;
60092                 const trajectory = frame.state.trajectory;
60093                 let increasingTime = undefined;
60094                 for (let i = trajectory.length - 2; i >= 0; i--) {
60095                     const image = trajectory[i];
60096                     if (image.sequenceId !== lastImage.sequenceId) {
60097                         break;
60098                     }
60099                     if (image.capturedAt !== lastImage.capturedAt) {
60100                         increasingTime = image.capturedAt < lastImage.capturedAt;
60101                         break;
60102                     }
60103                 }
60104                 return [frame.state.lastImage, increasingTime];
60105             }), withLatestFrom(this._direction$), switchMap(([[image, increasingTime], direction]) => {
60106                 return zip(([exports.NavigationDirection.Next, exports.NavigationDirection.Prev].indexOf(direction) > -1 ?
60107                     image.sequenceEdges$ :
60108                     image.spatialEdges$).pipe(first((status) => {
60109                     return status.cached;
60110                 }), timeout(15000)), of(direction)).pipe(map(([s, d]) => {
60111                     for (let edge of s.edges) {
60112                         if (edge.data.direction === d) {
60113                             return edge.target;
60114                         }
60115                     }
60116                     return null;
60117                 }), switchMap((key) => {
60118                     return key != null ?
60119                         this._graphService.cacheImage$(key) :
60120                         empty();
60121                 }));
60122             }))
60123                 .subscribe((image) => {
60124                 this._stateService.appendImagess([image]);
60125             }, (error) => {
60126                 console.error(error);
60127                 this.stop();
60128             });
60129             this._clearSubscription = this._stateService.currentImage$.pipe(bufferCount(1, 10))
60130                 .subscribe((images) => {
60131                 this._stateService.clearPriorImages();
60132             });
60133             this._setPlaying(true);
60134             const currentLastImages$ = this._stateService.currentState$.pipe(map((frame) => {
60135                 return frame.state;
60136             }), distinctUntilChanged(([kc1, kl1], [kc2, kl2]) => {
60137                 return kc1 === kc2 && kl1 === kl2;
60138             }, (state) => {
60139                 return [state.currentImage.id, state.lastImage.id];
60140             }), filter((state) => {
60141                 return state.currentImage.id === state.lastImage.id &&
60142                     state.currentIndex === state.trajectory.length - 1;
60143             }), map((state) => {
60144                 return state.currentImage;
60145             }));
60146             this._stopSubscription = combineLatest(currentLastImages$, this._direction$).pipe(switchMap(([image, direction]) => {
60147                 const edgeStatus$ = ([exports.NavigationDirection.Next, exports.NavigationDirection.Prev].indexOf(direction) > -1 ?
60148                     image.sequenceEdges$ :
60149                     image.spatialEdges$).pipe(first((status) => {
60150                     return status.cached;
60151                 }), timeout(15000), catchError((error) => {
60152                     console.error(error);
60153                     return of({ cached: false, edges: [] });
60154                 }));
60155                 return combineLatest(of(direction), edgeStatus$).pipe(map(([d, es]) => {
60156                     for (const edge of es.edges) {
60157                         if (edge.data.direction === d) {
60158                             return true;
60159                         }
60160                     }
60161                     return false;
60162                 }));
60163             }), mergeMap((hasEdge) => {
60164                 if (hasEdge || !this._bridging$) {
60165                     return of(hasEdge);
60166                 }
60167                 return this._bridging$.pipe(map((image) => {
60168                     return image != null;
60169                 }), catchError((error) => {
60170                     console.error(error);
60171                     return of(false);
60172                 }));
60173             }), first((hasEdge) => {
60174                 return !hasEdge;
60175             }))
60176                 .subscribe(undefined, undefined, () => { this.stop(); });
60177             if (this._stopSubscription.closed) {
60178                 this._stopSubscription = null;
60179             }
60180             this._earthSubscription = this._stateService.state$
60181                 .pipe(map((state) => {
60182                 return state === State.Earth;
60183             }), distinctUntilChanged(), first((earth) => {
60184                 return earth;
60185             }))
60186                 .subscribe(undefined, undefined, () => { this.stop(); });
60187             if (this._earthSubscription.closed) {
60188                 this._earthSubscription = null;
60189             }
60190         }
60191         dispose() {
60192             this.stop();
60193             this._subscriptions.unsubscribe();
60194         }
60195         setDirection(direction) {
60196             this._directionSubject$.next(direction);
60197         }
60198         setSpeed(speed) {
60199             speed = Math.max(0, Math.min(1, speed));
60200             if (speed === this._speed) {
60201                 return;
60202             }
60203             const stateSpeed = this._setSpeed(speed);
60204             if (this._playing) {
60205                 this._stateService.setSpeed(stateSpeed);
60206             }
60207             this._speedSubject$.next(this._speed);
60208         }
60209         stop() {
60210             if (!this._playing) {
60211                 return;
60212             }
60213             if (!!this._stopSubscription) {
60214                 if (!this._stopSubscription.closed) {
60215                     this._stopSubscription.unsubscribe();
60216                 }
60217                 this._stopSubscription = null;
60218             }
60219             if (!!this._earthSubscription) {
60220                 if (!this._earthSubscription.closed) {
60221                     this._earthSubscription.unsubscribe();
60222                 }
60223                 this._earthSubscription = null;
60224             }
60225             this._graphModeSubscription.unsubscribe();
60226             this._graphModeSubscription = null;
60227             this._cacheSubscription.unsubscribe();
60228             this._cacheSubscription = null;
60229             this._playingSubscription.unsubscribe();
60230             this._playingSubscription = null;
60231             this._clearSubscription.unsubscribe();
60232             this._clearSubscription = null;
60233             this._stateService.setSpeed(1);
60234             this._stateService.cutImages();
60235             this._graphService.setGraphMode(GraphMode.Spatial);
60236             this._setPlaying(false);
60237         }
60238         _mapSpeed(speed) {
60239             const x = 2 * speed - 1;
60240             return Math.pow(10, x) - 0.2 * x;
60241         }
60242         _mapImagesAhead(stateSpeed) {
60243             return Math.round(Math.max(10, Math.min(50, 8 + 6 * stateSpeed)));
60244         }
60245         _setPlaying(playing) {
60246             this._playing = playing;
60247             this._playingSubject$.next(playing);
60248         }
60249         _setSpeed(speed) {
60250             this._speed = speed;
60251             const stateSpeed = this._mapSpeed(this._speed);
60252             this._imagesAhead = this._mapImagesAhead(stateSpeed);
60253             return stateSpeed;
60254         }
60255     }
60256     PlayService.sequenceSpeed = 0.54;
60257
60258     exports.CameraVisualizationMode = void 0;
60259     (function (CameraVisualizationMode) {
60260         /**
60261          * Cameras are hidden.
60262          */
60263         CameraVisualizationMode[CameraVisualizationMode["Hidden"] = 0] = "Hidden";
60264         /**
60265          * Cameras are shown, all with the same color.
60266          */
60267         CameraVisualizationMode[CameraVisualizationMode["Homogeneous"] = 1] = "Homogeneous";
60268         /**
60269          * Cameras are shown with colors based on the
60270          * their clusters.
60271          */
60272         CameraVisualizationMode[CameraVisualizationMode["Cluster"] = 2] = "Cluster";
60273         /**
60274          * Cameras are shown with colors based on the
60275          * their connected components.
60276          */
60277         CameraVisualizationMode[CameraVisualizationMode["ConnectedComponent"] = 3] = "ConnectedComponent";
60278         /**
60279          * Cameras are shown, with colors based on the
60280          * their sequence.
60281          */
60282         CameraVisualizationMode[CameraVisualizationMode["Sequence"] = 4] = "Sequence";
60283     })(exports.CameraVisualizationMode || (exports.CameraVisualizationMode = {}));
60284
60285     exports.OriginalPositionMode = void 0;
60286     (function (OriginalPositionMode) {
60287         /**
60288          * Original positions are hidden.
60289          */
60290         OriginalPositionMode[OriginalPositionMode["Hidden"] = 0] = "Hidden";
60291         /**
60292          * Visualize original positions with altitude change.
60293          */
60294         OriginalPositionMode[OriginalPositionMode["Altitude"] = 1] = "Altitude";
60295         /**
60296          * Visualize original positions without altitude change,
60297          * i.e. as flat lines from the camera origin.
60298          */
60299         OriginalPositionMode[OriginalPositionMode["Flat"] = 2] = "Flat";
60300     })(exports.OriginalPositionMode || (exports.OriginalPositionMode = {}));
60301
60302     class ClusterPoints extends Points {
60303         constructor(parameters) {
60304             super();
60305             this._originalSize = parameters.originalSize;
60306             const { cluster, color, scale, translation } = parameters;
60307             this._makeAttributes(cluster);
60308             this.material.size = scale * this._originalSize;
60309             this.setColor(color);
60310             this.matrixAutoUpdate = false;
60311             this.position.fromArray(translation);
60312             this.updateMatrix();
60313             this.updateMatrixWorld(false);
60314         }
60315         dispose() {
60316             this.geometry.dispose();
60317             this.material.dispose();
60318         }
60319         setColor(color) {
60320             this.material.vertexColors = color == null;
60321             this.material.color = new Color(color);
60322             this.material.needsUpdate = true;
60323         }
60324         resize(scale) {
60325             this.material.size = scale * this._originalSize;
60326             this.material.needsUpdate = true;
60327         }
60328         _makeAttributes(cluster) {
60329             const positions = [];
60330             const colors = [];
60331             const points = cluster.points;
60332             for (const pointId in points) {
60333                 if (!points.hasOwnProperty(pointId)) {
60334                     continue;
60335                 }
60336                 const point = points[pointId];
60337                 positions.push(...point.coordinates);
60338                 const color = point.color;
60339                 colors.push(color[0]);
60340                 colors.push(color[1]);
60341                 colors.push(color[2]);
60342             }
60343             const geometry = this.geometry;
60344             geometry.setAttribute("position", new BufferAttribute(new Float32Array(positions), 3));
60345             geometry.setAttribute("color", new BufferAttribute(new Float32Array(colors), 3));
60346         }
60347     }
60348
60349     class CellLine extends Line {
60350         constructor(vertices) {
60351             super();
60352             this._makeAttributes(vertices);
60353             this.matrixAutoUpdate = false;
60354             this.updateMatrix();
60355             this.updateMatrixWorld(false);
60356         }
60357         dispose() {
60358             this.geometry.dispose();
60359             this.material.dispose();
60360         }
60361         _makeAttributes(vertices) {
60362             const closedPolygon = vertices.slice();
60363             closedPolygon.push(vertices[0]);
60364             let index = 0;
60365             const positions = new Float32Array(3 * (vertices.length + 1));
60366             for (const vertex of closedPolygon) {
60367                 positions[index++] = vertex[0];
60368                 positions[index++] = vertex[1];
60369                 positions[index++] = vertex[2];
60370             }
60371             this.geometry.setAttribute("position", new BufferAttribute(positions, 3));
60372         }
60373     }
60374
60375     // Level 0: 1 x 1 x 1 meter cubes
60376     const OCTREE_ROOT_LEVEL = 14; // 16384 meters
60377     const OCTREE_LEAF_LEVEL = 6; // 64 meters
60378     function isLeafLevel(level, leafLevel) {
60379         return level === leafLevel;
60380     }
60381     function levelToSize(level) {
60382         return Math.pow(2, level);
60383     }
60384     function levelToRootBoundingBox(level) {
60385         const size = levelToSize(level);
60386         const half = size / 2;
60387         const min = [-half, -half, -half];
60388         const max = [half, half, half];
60389         return { min, max };
60390     }
60391
60392     class SpatialOctreeNode {
60393         constructor(level, leafLevel, boundingBox, parent) {
60394             this.level = level;
60395             this.leafLevel = leafLevel;
60396             this.boundingBox = boundingBox;
60397             this.parent = parent;
60398             this.children = [];
60399             this.items = [];
60400             if (parent) {
60401                 parent.children.push(this);
60402             }
60403         }
60404         get isEmpty() {
60405             return !(this.children.length || this.items.length);
60406         }
60407         add(object) {
60408             const self = this;
60409             if (!self.boundingBox.containsPoint(object.position)) {
60410                 throw new Error(`Item not contained in node`);
60411             }
60412             if (isLeafLevel(self.level, self.leafLevel)) {
60413                 self.items.push(object);
60414                 return this;
60415             }
60416             for (const child of self.children) {
60417                 if (child.boundingBox.containsPoint(object.position)) {
60418                     return child.add(object);
60419                 }
60420             }
60421             for (const boundingBox of self._generateBoundingBoxes()) {
60422                 if (boundingBox.containsPoint(object.position)) {
60423                     const child = new SpatialOctreeNode(self.level - 1, self.leafLevel, boundingBox, self);
60424                     return child.add(object);
60425                 }
60426             }
60427             throw new Error(`Item not contained in children`);
60428         }
60429         intersect(ray, target, nodes) {
60430             if (!ray.intersectBox(this.boundingBox, target)) {
60431                 return;
60432             }
60433             if (isLeafLevel(this.level, this.leafLevel)) {
60434                 nodes.push(this);
60435                 return;
60436             }
60437             for (const child of this.children) {
60438                 child.intersect(ray, target, nodes);
60439             }
60440         }
60441         remove(object) {
60442             const index = this.items.indexOf(object);
60443             if (index < 0) {
60444                 throw new Error(`Item does not exist ${object.uuid}`);
60445             }
60446             this.items.splice(index, 1);
60447         }
60448         traverse() {
60449             const self = this;
60450             if (!self.isEmpty) {
60451                 return;
60452             }
60453             const parent = self.parent;
60454             if (!parent) {
60455                 return;
60456             }
60457             const index = parent.children.indexOf(self);
60458             if (index < 0) {
60459                 throw new Error(`Corrupt octree`);
60460             }
60461             parent.children.splice(index, 1);
60462             this.parent = null;
60463             parent.traverse();
60464         }
60465         _generateBoundingBoxes() {
60466             const self = this;
60467             const min = self.boundingBox.min;
60468             const max = self.boundingBox.max;
60469             const size = (max.x - min.x) / 2;
60470             const mins = [
60471                 [min.x, min.y + size, min.z + size],
60472                 [min.x + size, min.y + size, min.z + size],
60473                 [min.x, min.y, min.z + size],
60474                 [min.x + size, min.y, min.z + size],
60475                 [min.x, min.y + size, min.z],
60476                 [min.x + size, min.y + size, min.z],
60477                 [min.x, min.y, min.z],
60478                 [min.x + size, min.y, min.z],
60479             ];
60480             const boundingBoxes = [];
60481             for (const [minX, minY, minZ] of mins) {
60482                 boundingBoxes.push(new Box3(new Vector3(minX, minY, minZ), new Vector3(minX + size, minY + size, minZ + size)));
60483             }
60484             return boundingBoxes;
60485         }
60486     }
60487
60488     class SpatialOctree {
60489         constructor(rootLevel, leafLevel) {
60490             this.rootLevel = rootLevel;
60491             this.leafLevel = leafLevel;
60492             if (leafLevel > rootLevel) {
60493                 throw new Error();
60494             }
60495             this._index = new Map();
60496             this._root = this._makeRoot();
60497         }
60498         get root() {
60499             return this._root;
60500         }
60501         add(object) {
60502             if (!this.root.boundingBox.containsPoint(object.position)) {
60503                 console.warn(`Object outside bounding box ${object.uuid}`);
60504                 return;
60505             }
60506             const leaf = this._root.add(object);
60507             this._index.set(object.uuid, leaf);
60508         }
60509         has(object) {
60510             return this._index.has(object.uuid);
60511         }
60512         intersect(ray) {
60513             const leaves = [];
60514             const target = new Vector3();
60515             this._root.intersect(ray, target, leaves);
60516             return leaves
60517                 .map(leaf => leaf.items)
60518                 .reduce((acc, items) => {
60519                 acc.push(...items);
60520                 return acc;
60521             }, []);
60522         }
60523         reset() {
60524             this._root = this._makeRoot();
60525             this._index.clear();
60526         }
60527         remove(object) {
60528             if (!this.has(object)) {
60529                 throw new Error(`Frame does not exist ${object.uuid}`);
60530             }
60531             const leaf = this._index.get(object.uuid);
60532             leaf.remove(object);
60533             leaf.traverse();
60534             this._index.delete(object.uuid);
60535         }
60536         _makeRoot() {
60537             const level = this.rootLevel;
60538             const bbox = levelToRootBoundingBox(level);
60539             const box = new Box3(new Vector3().fromArray(bbox.min), new Vector3().fromArray(bbox.max));
60540             return new SpatialOctreeNode(level, this.leafLevel, box);
60541         }
60542     }
60543
60544     class SpatialIntersection {
60545         constructor(octree, raycaster) {
60546             this._objects = [];
60547             this._objectImageMap = new Map();
60548             this._octree = octree !== null && octree !== void 0 ? octree : new SpatialOctree(OCTREE_ROOT_LEVEL, OCTREE_LEAF_LEVEL);
60549             this._raycaster = raycaster !== null && raycaster !== void 0 ? raycaster : new Raycaster();
60550             this._interactiveLayer = 1;
60551             this._raycaster = !!raycaster ?
60552                 raycaster :
60553                 new Raycaster(undefined, undefined, 1, 10000);
60554             this._lineThreshold = 0.2;
60555             this._largeLineThreshold = 0.4;
60556             this._raycaster.params.Line.threshold = this._lineThreshold;
60557             this._raycaster.layers.set(this._interactiveLayer);
60558         }
60559         get interactiveLayer() { return this._interactiveLayer; }
60560         get octree() { return this._octree; }
60561         get raycaster() { return this._raycaster; }
60562         add(object, imageId) {
60563             const uuid = object.uuid;
60564             this._objectImageMap.set(uuid, imageId);
60565             this._objects.push(object);
60566             this._octree.add(object);
60567         }
60568         intersectObjects(viewport, camera) {
60569             this._raycaster.setFromCamera(new Vector2().fromArray(viewport), camera);
60570             const objects = this._octree.intersect(this.raycaster.ray);
60571             const intersects = this._raycaster.intersectObjects(objects);
60572             const onMap = this._objectImageMap;
60573             for (const intersect of intersects) {
60574                 const uuid = intersect.object.uuid;
60575                 if (!onMap.has(uuid)) {
60576                     continue;
60577                 }
60578                 return onMap.get(uuid);
60579             }
60580             return null;
60581         }
60582         remove(object) {
60583             const objects = this._objects;
60584             const index = objects.indexOf(object);
60585             if (index !== -1) {
60586                 const deleted = objects.splice(index, 1);
60587                 for (const d of deleted) {
60588                     this._objectImageMap.delete(d.uuid);
60589                 }
60590                 this._octree.remove(object);
60591             }
60592             else {
60593                 console.warn(`Object does not exist`);
60594             }
60595         }
60596         resetIntersectionThreshold(useLarge) {
60597             this._raycaster.params.Line.threshold = useLarge ?
60598                 this._largeLineThreshold :
60599                 this._lineThreshold;
60600         }
60601     }
60602
60603     class PositionLine extends Line {
60604         constructor(parameters) {
60605             super(parameters.geometry, parameters.material);
60606             const mode = parameters.mode;
60607             const originalOrigin = parameters.originalOrigin;
60608             const transform = parameters.transform;
60609             const origin = transform.unprojectBasic([0, 0], 0);
60610             this._relativeAltitude = originalOrigin[2] - origin[2];
60611             this._makeAttributes(origin, originalOrigin, mode);
60612             this.matrixAutoUpdate = false;
60613             this.position.fromArray(origin);
60614             this.updateMatrix();
60615             this.updateMatrixWorld(false);
60616         }
60617         dispose() {
60618             this.geometry.dispose();
60619             this.material.dispose();
60620         }
60621         setMode(mode) {
60622             const positionAttribute = this.geometry.attributes.position;
60623             const positions = positionAttribute.array;
60624             positions[5] = this._modeToAltitude(mode);
60625             positionAttribute.needsUpdate = true;
60626             this.geometry.computeBoundingSphere();
60627         }
60628         _makeAttributes(origin, originalOrigin, mode) {
60629             const positions = new Float32Array(6);
60630             positions[0] = 0;
60631             positions[1] = 0;
60632             positions[2] = 0;
60633             positions[3] = originalOrigin[0] - origin[0];
60634             positions[4] = originalOrigin[1] - origin[1];
60635             positions[5] = this._modeToAltitude(mode);
60636             const attribute = new BufferAttribute(positions, 3);
60637             this.geometry.setAttribute("position", attribute);
60638             attribute.needsUpdate = true;
60639             this.geometry.computeBoundingSphere();
60640         }
60641         _modeToAltitude(mode) {
60642             return mode === exports.OriginalPositionMode.Altitude ?
60643                 this._relativeAltitude : 0;
60644         }
60645     }
60646
60647     class CameraFrameBase extends LineSegments {
60648         constructor(parameters) {
60649             super(parameters.geometry, parameters.material);
60650             const color = parameters.color;
60651             const size = parameters.size;
60652             const scale = parameters.scale;
60653             const transform = parameters.transform;
60654             const origin = transform.unprojectBasic([0, 0], 0);
60655             const positions = this._makePositions(size, transform, origin);
60656             this._makeAttributes(positions, color);
60657             this.geometry.computeBoundingSphere();
60658             this.geometry.computeBoundingBox();
60659             this.matrixAutoUpdate = false;
60660             this.position.fromArray(origin);
60661             this.scale.set(scale, scale, scale);
60662             this.updateMatrix();
60663             this.updateMatrixWorld(false);
60664         }
60665         dispose() {
60666             this.geometry.dispose();
60667             this.material.dispose();
60668         }
60669         setColor(color) {
60670             this._updateColorAttribute(color);
60671             return this;
60672         }
60673         resize(scale) {
60674             this.scale.set(scale, scale, scale);
60675             this.updateMatrix();
60676             this.updateMatrixWorld(false);
60677             return this;
60678         }
60679         _makeAttributes(positions, color) {
60680             const geometry = this.geometry;
60681             const positionAttribute = new BufferAttribute(new Float32Array(positions), 3);
60682             geometry.setAttribute("position", positionAttribute);
60683             positionAttribute.needsUpdate = true;
60684             const colorAttribute = new BufferAttribute(new Float32Array(positions.length), 3);
60685             geometry.setAttribute("color", colorAttribute);
60686             this._updateColorAttribute(color);
60687         }
60688         _updateColorAttribute(color) {
60689             const [r, g, b] = new Color(color).toArray();
60690             const colorAttribute = this.geometry.attributes.color;
60691             const colors = colorAttribute.array;
60692             const length = colors.length;
60693             let index = 0;
60694             for (let i = 0; i < length; i++) {
60695                 colors[index++] = r;
60696                 colors[index++] = g;
60697                 colors[index++] = b;
60698             }
60699             colorAttribute.needsUpdate = true;
60700         }
60701     }
60702
60703     class SphericalCameraFrame extends CameraFrameBase {
60704         _makePositions(size, transform, origin) {
60705             const vs = 10;
60706             const positions = [];
60707             positions.push(...this._makeAxis(size, transform, origin));
60708             positions.push(...this._makeLat(0.5, vs, size, transform, origin));
60709             for (const lat of [0, 0.25, 0.5, 0.75]) {
60710                 positions
60711                     .push(...this._makeLng(lat, vs, size, transform, origin));
60712             }
60713             return positions;
60714         }
60715         _makeAxis(size, transform, origin) {
60716             const south = transform.unprojectBasic([0.5, 1], 0.8 * size);
60717             const north = transform.unprojectBasic([0.5, 0], 1.2 * size);
60718             return [
60719                 south[0] - origin[0],
60720                 south[1] - origin[1],
60721                 south[2] - origin[2],
60722                 north[0] - origin[0],
60723                 north[1] - origin[1],
60724                 north[2] - origin[2],
60725             ];
60726         }
60727         _makeLat(basicY, numVertices, size, transform, origin) {
60728             const dist = 0.8 * size;
60729             const [originX, originY, originZ] = origin;
60730             const positions = [];
60731             const first = transform.unprojectBasic([0, basicY], dist);
60732             first[0] -= originX;
60733             first[1] -= originY;
60734             first[2] -= originZ;
60735             positions.push(...first);
60736             for (let i = 1; i <= numVertices; i++) {
60737                 const position = transform.unprojectBasic([i / numVertices, basicY], dist);
60738                 position[0] -= originX;
60739                 position[1] -= originY;
60740                 position[2] -= originZ;
60741                 positions.push(...position, ...position);
60742             }
60743             positions.push(...first);
60744             return positions;
60745         }
60746         _makeLng(basicX, numVertices, size, transform, origin) {
60747             const dist = 0.8 * size;
60748             const [originX, originY, originZ] = origin;
60749             const positions = [];
60750             const first = transform.unprojectBasic([basicX, 0], dist);
60751             first[0] -= originX;
60752             first[1] -= originY;
60753             first[2] -= originZ;
60754             positions.push(...first);
60755             for (let i = 0; i <= numVertices; i++) {
60756                 const position = transform.unprojectBasic([basicX, i / numVertices], dist);
60757                 position[0] -= originX;
60758                 position[1] -= originY;
60759                 position[2] -= originZ;
60760                 positions.push(...position, ...position);
60761             }
60762             positions.push(...first);
60763             return positions;
60764         }
60765     }
60766
60767     class PerspectiveCameraFrame extends CameraFrameBase {
60768         _makePositions(size, transform, origin) {
60769             const samples = 8;
60770             const positions = [];
60771             positions.push(...this._makeDiags(size, transform, origin));
60772             positions.push(...this._makeFrame(size, samples, transform, origin));
60773             return positions;
60774         }
60775         _makeDiags(size, transform, origin) {
60776             const [originX, originY, originZ] = origin;
60777             const cameraCenter = [0, 0, 0];
60778             const positions = [];
60779             for (const vertex2d of [[0, 0], [1, 0], [1, 1], [0, 1]]) {
60780                 const corner = transform.unprojectBasic(vertex2d, size);
60781                 corner[0] -= originX;
60782                 corner[1] -= originY;
60783                 corner[2] -= originZ;
60784                 positions.push(...cameraCenter, ...corner);
60785             }
60786             return positions;
60787         }
60788         _makeFrame(size, samples, transform, origin) {
60789             const vertices2d = [];
60790             vertices2d.push(...this._subsample([0, 1], [0, 0], samples));
60791             vertices2d.push(...this._subsample([0, 0], [1, 0], samples));
60792             vertices2d.push(...this._subsample([1, 0], [1, 1], samples));
60793             const [originX, originY, originZ] = origin;
60794             const positions = [];
60795             for (const vertex2d of vertices2d) {
60796                 const position = transform.unprojectBasic(vertex2d, size);
60797                 position[0] -= originX;
60798                 position[1] -= originY;
60799                 position[2] -= originZ;
60800                 positions.push(...position);
60801             }
60802             return positions;
60803         }
60804         _interpolate(a, b, alpha) {
60805             return a + alpha * (b - a);
60806         }
60807         _subsample(p1, p2, subsamples) {
60808             if (subsamples < 1) {
60809                 return [p1, p2];
60810             }
60811             const samples = [];
60812             samples.push(p1);
60813             for (let i = 0; i <= subsamples; i++) {
60814                 const p = [];
60815                 for (let j = 0; j < 3; j++) {
60816                     p.push(this._interpolate(p1[j], p2[j], i / (subsamples + 1)));
60817                 }
60818                 samples.push(p);
60819                 samples.push(p);
60820             }
60821             samples.push(p2);
60822             return samples;
60823         }
60824     }
60825
60826     function resetEnu(reference, prevEnu, prevReference) {
60827         const [prevX, prevY, prevZ] = prevEnu;
60828         const [lng, lat, alt] = enuToGeodetic(prevX, prevY, prevZ, prevReference.lng, prevReference.lat, prevReference.alt);
60829         return geodeticToEnu(lng, lat, alt, reference.lng, reference.lat, reference.alt);
60830     }
60831
60832     class SpatialCell {
60833         constructor(id, _scene, _intersection) {
60834             this.id = id;
60835             this._scene = _scene;
60836             this._intersection = _intersection;
60837             this.cameras = new Object3D();
60838             this.keys = [];
60839             this._positionLines = {};
60840             this._positions = new Object3D();
60841             this._cameraFrames = {};
60842             this._clusters = new Map();
60843             this._connectedComponents = new Map();
60844             this._sequences = new Map();
60845             this._props = {};
60846             this.clusterVisibles = {};
60847             this._frameMaterial = new LineBasicMaterial({
60848                 fog: false,
60849                 vertexColors: true,
60850             });
60851             this._positionMaterial = new LineBasicMaterial({
60852                 fog: false,
60853                 color: 0xff0000,
60854             });
60855             this._scene.add(this.cameras, this._positions);
60856         }
60857         addImage(props) {
60858             const image = props.image;
60859             const id = image.id;
60860             if (this.hasImage(id)) {
60861                 throw new Error(`Image exists ${id}`);
60862             }
60863             const ccId = props.idMap.ccId;
60864             if (!(this._connectedComponents.has(ccId))) {
60865                 this._connectedComponents.set(ccId, []);
60866             }
60867             const cId = props.idMap.clusterId;
60868             if (!this._clusters.has(cId)) {
60869                 this._clusters.set(cId, []);
60870             }
60871             const sId = props.idMap.sequenceId;
60872             if (!this._sequences.has(sId)) {
60873                 this._sequences.set(sId, []);
60874             }
60875             this._props[id] = {
60876                 image: image,
60877                 ids: { ccId, clusterId: cId, sequenceId: sId },
60878             };
60879             this.keys.push(id);
60880         }
60881         applyCameraColor(imageId, color) {
60882             this._cameraFrames[imageId].setColor(color);
60883         }
60884         applyCameraSize(size) {
60885             for (const camera of this.cameras.children) {
60886                 camera.resize(size);
60887             }
60888         }
60889         applyFilter(filter) {
60890             var _a;
60891             const clusterVisibles = this.clusterVisibles;
60892             for (const clusterId in clusterVisibles) {
60893                 if (!clusterVisibles.hasOwnProperty(clusterId)) {
60894                     continue;
60895                 }
60896                 clusterVisibles[clusterId] = false;
60897             }
60898             const cameraFrames = this._cameraFrames;
60899             const positionLines = this._positionLines;
60900             const interactiveLayer = this._intersection.interactiveLayer;
60901             for (const props of Object.values(this._props)) {
60902                 const image = props.image;
60903                 const visible = filter(image);
60904                 const key = image.id;
60905                 positionLines[key].visible = visible;
60906                 const camera = cameraFrames[key];
60907                 this._setCameraVisibility(camera, visible, interactiveLayer);
60908                 clusterVisibles[_a = props.ids.clusterId] || (clusterVisibles[_a] = visible);
60909             }
60910         }
60911         applyPositionMode(mode) {
60912             this._positions.visible =
60913                 mode !== exports.OriginalPositionMode.Hidden;
60914             for (const position of this._positions.children) {
60915                 position.setMode(mode);
60916             }
60917         }
60918         dispose() {
60919             this._disposeCameras();
60920             this._disposePositions();
60921             this._scene = null;
60922             this._intersection = null;
60923         }
60924         getCamerasByMode(mode) {
60925             if (mode === exports.CameraVisualizationMode.Cluster) {
60926                 return this._clusters;
60927             }
60928             else if (mode === exports.CameraVisualizationMode.ConnectedComponent) {
60929                 return this._connectedComponents;
60930             }
60931             else if (mode === exports.CameraVisualizationMode.Sequence) {
60932                 return this._sequences;
60933             }
60934             const cvm = exports.CameraVisualizationMode;
60935             const defaultId = cvm[cvm.Homogeneous];
60936             const cameras = new Map();
60937             cameras.set(defaultId, this.cameras.children);
60938             return cameras;
60939         }
60940         getColorId(imageId, mode) {
60941             const props = this._props[imageId];
60942             const cvm = exports.CameraVisualizationMode;
60943             switch (mode) {
60944                 case cvm.Cluster:
60945                     return props.ids.clusterId;
60946                 case cvm.ConnectedComponent:
60947                     return props.ids.ccId;
60948                 case cvm.Sequence:
60949                     return props.ids.sequenceId;
60950                 default:
60951                     return cvm[cvm.Homogeneous];
60952             }
60953         }
60954         hasImage(key) {
60955             return this.keys.indexOf(key) !== -1;
60956         }
60957         resetReference(reference, prevReference) {
60958             const frames = this._cameraFrames;
60959             for (const frameId in frames) {
60960                 if (!frames.hasOwnProperty(frameId)) {
60961                     continue;
60962                 }
60963                 const frame = frames[frameId];
60964                 frame.position.fromArray(resetEnu(reference, frame.position.toArray(), prevReference));
60965             }
60966             const lines = this._positionLines;
60967             for (const lineId in lines) {
60968                 if (!lines.hasOwnProperty(lineId)) {
60969                     continue;
60970                 }
60971                 const line = lines[lineId];
60972                 line.position.fromArray(resetEnu(reference, line.position.toArray(), prevReference));
60973             }
60974         }
60975         visualize(props) {
60976             var _a, _b;
60977             const id = props.id;
60978             const visible = props.visible;
60979             const transform = props.transform;
60980             const cameraParameters = {
60981                 color: props.color,
60982                 material: this._frameMaterial,
60983                 scale: props.scale,
60984                 size: props.maxSize,
60985                 transform,
60986             };
60987             const camera = isSpherical(transform.cameraType) ?
60988                 new SphericalCameraFrame(cameraParameters) :
60989                 new PerspectiveCameraFrame(cameraParameters);
60990             const interactiveLayer = this._intersection.interactiveLayer;
60991             this._setCameraVisibility(camera, visible, interactiveLayer);
60992             this.cameras.add(camera);
60993             this._cameraFrames[id] = camera;
60994             const intersection = this._intersection;
60995             intersection.add(camera, id);
60996             const ids = this._props[id].ids;
60997             (_a = this.clusterVisibles)[_b = ids.clusterId] || (_a[_b] = visible);
60998             this._connectedComponents.get(ids.ccId).push(camera);
60999             this._clusters.get(ids.clusterId).push(camera);
61000             this._sequences.get(ids.sequenceId).push(camera);
61001             const positionParameters = {
61002                 material: this._positionMaterial,
61003                 mode: props.positionMode,
61004                 originalOrigin: props.originalPosition,
61005                 transform,
61006             };
61007             const position = new PositionLine(positionParameters);
61008             position.visible = visible;
61009             this._positions.add(position);
61010             this._positionLines[id] = position;
61011         }
61012         _disposeCameras() {
61013             const intersection = this._intersection;
61014             const cameras = this.cameras;
61015             for (const camera of cameras.children.slice()) {
61016                 camera.dispose();
61017                 intersection.remove(camera);
61018                 cameras.remove(camera);
61019             }
61020             this._scene.remove(this.cameras);
61021         }
61022         _disposePositions() {
61023             const positions = this._positions;
61024             for (const position of positions.children.slice()) {
61025                 position.dispose();
61026                 positions.remove(position);
61027             }
61028             this._scene.remove(this._positions);
61029         }
61030         _setCameraVisibility(camera, visible, layer) {
61031             camera.visible = visible;
61032             if (visible) {
61033                 camera.layers.enable(layer);
61034             }
61035             else {
61036                 camera.layers.disable(layer);
61037             }
61038         }
61039     }
61040
61041     class SpatialAssets {
61042         constructor() {
61043             this._colors = new Map();
61044             const cvm = exports.CameraVisualizationMode;
61045             this._colors.set(cvm[cvm.Homogeneous], "#FFFFFF");
61046         }
61047         getColor(id) {
61048             const colors = this._colors;
61049             if (!colors.has(id)) {
61050                 colors.set(id, this._randomColor());
61051             }
61052             return colors.get(id);
61053         }
61054         _randomColor() {
61055             return `hsl(${Math.floor(360 * Math.random())}, 100%, 50%)`;
61056         }
61057     }
61058
61059     function isModeVisible(mode) {
61060         return mode !== exports.CameraVisualizationMode.Hidden;
61061     }
61062     function isOverviewState(state) {
61063         return state === State.Custom || state === State.Earth;
61064     }
61065
61066     exports.PointVisualizationMode = void 0;
61067     (function (PointVisualizationMode) {
61068         /**
61069          * Points are hidden.
61070          */
61071         PointVisualizationMode[PointVisualizationMode["Hidden"] = 0] = "Hidden";
61072         /**
61073          * Visualize points with original colors.
61074          */
61075         PointVisualizationMode[PointVisualizationMode["Original"] = 1] = "Original";
61076         /**
61077          * Paint all points belonging to a specific
61078          * cluster with the same random color.
61079          */
61080         PointVisualizationMode[PointVisualizationMode["Cluster"] = 2] = "Cluster";
61081     })(exports.PointVisualizationMode || (exports.PointVisualizationMode = {}));
61082
61083     const NO_CLUSTER_ID = "NO_CLUSTER_ID";
61084     const NO_MERGE_ID = "NO_MERGE_ID";
61085     const NO_SEQUENCE_ID = "NO_SEQUENCE_ID";
61086     class SpatialScene {
61087         constructor(configuration, scene) {
61088             this._rayNearScale = 1.1;
61089             this._originalPointSize = 2;
61090             this._originalCameraSize = 2;
61091             this._imageCellMap = new Map();
61092             this._scene = !!scene ? scene : new Scene();
61093             this._scene.autoUpdate = false;
61094             this._intersection = new SpatialIntersection();
61095             this._assets = new SpatialAssets();
61096             this._needsRender = false;
61097             this._images = {};
61098             this._cells = {};
61099             this._cellClusters = {};
61100             this._clusters = {};
61101             this._cameraVisualizationMode =
61102                 !!configuration.cameraVisualizationMode ?
61103                     configuration.cameraVisualizationMode :
61104                     exports.CameraVisualizationMode.Homogeneous;
61105             this._cameraSize = configuration.cameraSize;
61106             this._pointSize = configuration.pointSize;
61107             this._pointVisualizationMode =
61108                 !!configuration.pointVisualizationMode ?
61109                     configuration.pointVisualizationMode :
61110                     exports.PointVisualizationMode.Original;
61111             this._positionMode = configuration.originalPositionMode;
61112             this._cellsVisible = configuration.cellsVisible;
61113             this._hoveredId = null;
61114             this._selectedId = null;
61115             this._colors = { hover: "#FF0000", select: "#FF8000" };
61116             this._filter = () => true;
61117         }
61118         get needsRender() { return this._needsRender; }
61119         get intersection() {
61120             return this._intersection;
61121         }
61122         addCluster(reconstruction, translation, cellId) {
61123             if (this.hasCluster(reconstruction.id, cellId)) {
61124                 return;
61125             }
61126             const clusterId = reconstruction.id;
61127             if (!(clusterId in this._clusters)) {
61128                 this._clusters[clusterId] = {
61129                     points: new Object3D(),
61130                     cellIds: [],
61131                 };
61132                 const visible = this._getClusterVisible(clusterId);
61133                 const cluster = this._clusters[clusterId];
61134                 const color = this._pointVisualizationMode === exports.PointVisualizationMode.Cluster ? this._assets.getColor(clusterId) : null;
61135                 const points = new ClusterPoints({
61136                     cluster: reconstruction,
61137                     color,
61138                     originalSize: this._originalPointSize,
61139                     scale: this._pointSize,
61140                     translation,
61141                 });
61142                 cluster.points.visible = visible;
61143                 cluster.points.add(points);
61144                 this._scene.add(cluster.points);
61145             }
61146             if (this._clusters[clusterId].cellIds.indexOf(cellId) === -1) {
61147                 this._clusters[clusterId].cellIds.push(cellId);
61148             }
61149             if (!(cellId in this._cellClusters)) {
61150                 this._cellClusters[cellId] = { keys: [] };
61151             }
61152             if (this._cellClusters[cellId].keys.indexOf(clusterId) === -1) {
61153                 this._cellClusters[cellId].keys.push(clusterId);
61154             }
61155             this._needsRender = true;
61156         }
61157         addImage(image, transform, originalPosition, cellId) {
61158             var _a, _b, _c;
61159             const imageId = image.id;
61160             const idMap = {
61161                 clusterId: (_a = image.clusterId) !== null && _a !== void 0 ? _a : NO_CLUSTER_ID,
61162                 sequenceId: (_b = image.sequenceId) !== null && _b !== void 0 ? _b : NO_SEQUENCE_ID,
61163                 ccId: (_c = image.mergeId) !== null && _c !== void 0 ? _c : NO_MERGE_ID,
61164             };
61165             if (!(cellId in this._images)) {
61166                 const created = new SpatialCell(cellId, this._scene, this._intersection);
61167                 created.cameras.visible =
61168                     isModeVisible(this._cameraVisualizationMode);
61169                 created.applyPositionMode(this._positionMode);
61170                 this._images[cellId] = created;
61171             }
61172             const cell = this._images[cellId];
61173             if (cell.hasImage(imageId)) {
61174                 return;
61175             }
61176             cell.addImage({ idMap, image: image });
61177             const colorId = cell.getColorId(imageId, this._cameraVisualizationMode);
61178             const color = this._assets.getColor(colorId);
61179             const visible = this._filter(image);
61180             cell.visualize({
61181                 id: imageId,
61182                 color,
61183                 positionMode: this._positionMode,
61184                 scale: this._cameraSize,
61185                 transform,
61186                 visible,
61187                 maxSize: this._originalCameraSize,
61188                 originalPosition
61189             });
61190             this._imageCellMap.set(imageId, cellId);
61191             if (imageId === this._selectedId) {
61192                 this._highlight(imageId, this._colors.select, this._cameraVisualizationMode);
61193             }
61194             if (idMap.clusterId in this._clusters) {
61195                 const clusterVisible = this._getClusterVisible(idMap.clusterId);
61196                 this._clusters[idMap.clusterId].points.visible = clusterVisible;
61197             }
61198             this._needsRender = true;
61199         }
61200         addCell(vertices, cellId) {
61201             if (this.hasCell(cellId)) {
61202                 return;
61203             }
61204             const cell = new CellLine(vertices);
61205             this._cells[cellId] = new Object3D();
61206             this._cells[cellId].visible = this._cellsVisible;
61207             this._cells[cellId].add(cell);
61208             this._scene.add(this._cells[cellId]);
61209             this._needsRender = true;
61210         }
61211         deactivate() {
61212             this._filter = () => true;
61213             this._selectedId = null;
61214             this._hoveredId = null;
61215             this.uncache();
61216         }
61217         hasCluster(clusterId, cellId) {
61218             return clusterId in this._clusters &&
61219                 this._clusters[clusterId].cellIds.indexOf(cellId) !== -1;
61220         }
61221         hasCell(cellId) {
61222             return cellId in this._cells;
61223         }
61224         hasImage(imageId, cellId) {
61225             return cellId in this._images &&
61226                 this._images[cellId].hasImage(imageId);
61227         }
61228         render(camera, renderer) {
61229             renderer.render(this._scene, camera);
61230             this._needsRender = false;
61231         }
61232         resetReference(reference, prevReference) {
61233             const clusters = this._clusters;
61234             for (const clusterId in clusters) {
61235                 if (!clusters.hasOwnProperty(clusterId)) {
61236                     continue;
61237                 }
61238                 const cluster = clusters[clusterId];
61239                 cluster.points.position.fromArray(resetEnu(reference, cluster.points.position.toArray(), prevReference));
61240             }
61241             const cells = this._cells;
61242             for (const cellId in cells) {
61243                 if (!cells.hasOwnProperty(cellId)) {
61244                     continue;
61245                 }
61246                 const cell = cells[cellId];
61247                 cell.position.fromArray(resetEnu(reference, cell.position.toArray(), prevReference));
61248             }
61249             const images = this._images;
61250             for (const cellId in images) {
61251                 if (!images.hasOwnProperty(cellId)) {
61252                     continue;
61253                 }
61254                 const spatialCell = images[cellId];
61255                 spatialCell.resetReference(reference, prevReference);
61256             }
61257         }
61258         setCameraSize(cameraSize) {
61259             if (Math.abs(cameraSize - this._cameraSize) < 1e-3) {
61260                 return;
61261             }
61262             const imageCells = this._images;
61263             for (const cellId of Object.keys(imageCells)) {
61264                 imageCells[cellId].applyCameraSize(cameraSize);
61265             }
61266             this._intersection.raycaster.near = this._getNear(cameraSize);
61267             this._cameraSize = cameraSize;
61268             this._needsRender = true;
61269         }
61270         setFilter(filter) {
61271             this._filter = filter;
61272             const clusterVisibles = {};
61273             for (const imageCell of Object.values(this._images)) {
61274                 imageCell.applyFilter(filter);
61275                 const imageCV = imageCell.clusterVisibles;
61276                 for (const clusterId in imageCV) {
61277                     if (!imageCV.hasOwnProperty(clusterId)) {
61278                         continue;
61279                     }
61280                     if (!(clusterId in clusterVisibles)) {
61281                         clusterVisibles[clusterId] = false;
61282                     }
61283                     clusterVisibles[clusterId] || (clusterVisibles[clusterId] = imageCV[clusterId]);
61284                 }
61285             }
61286             const pointsVisible = this._pointVisualizationMode !== exports.PointVisualizationMode.Hidden;
61287             for (const clusterId in clusterVisibles) {
61288                 if (!clusterVisibles.hasOwnProperty(clusterId)) {
61289                     continue;
61290                 }
61291                 clusterVisibles[clusterId] && (clusterVisibles[clusterId] = pointsVisible);
61292                 const visible = clusterVisibles[clusterId];
61293                 if (clusterId in this._clusters) {
61294                     this._clusters[clusterId].points.visible = visible;
61295                 }
61296             }
61297             this._needsRender = true;
61298         }
61299         setHoveredImage(imageId) {
61300             if (imageId != null && !this._imageCellMap.has(imageId)) {
61301                 throw new MapillaryError(`Image does not exist: ${imageId}`);
61302             }
61303             if (this._hoveredId === imageId) {
61304                 return;
61305             }
61306             this._needsRender = true;
61307             if (this._hoveredId != null) {
61308                 if (this._hoveredId === this._selectedId) {
61309                     this._highlight(this._hoveredId, this._colors.select, this._cameraVisualizationMode);
61310                 }
61311                 else {
61312                     this._resetCameraColor(this._hoveredId);
61313                 }
61314             }
61315             this._highlight(imageId, this._colors.hover, this._cameraVisualizationMode);
61316             this._hoveredId = imageId;
61317         }
61318         setNavigationState(isOverview) {
61319             this._intersection.resetIntersectionThreshold(isOverview);
61320         }
61321         setPointSize(pointSize) {
61322             if (Math.abs(pointSize - this._pointSize) < 1e-3) {
61323                 return;
61324             }
61325             const clusters = this._clusters;
61326             for (const key in clusters) {
61327                 if (!clusters.hasOwnProperty(key)) {
61328                     continue;
61329                 }
61330                 for (const points of clusters[key].points.children) {
61331                     points.resize(pointSize);
61332                 }
61333             }
61334             this._pointSize = pointSize;
61335             this._needsRender = true;
61336         }
61337         setPointVisualizationMode(mode) {
61338             if (mode === this._pointVisualizationMode) {
61339                 return;
61340             }
61341             this._pointVisualizationMode = mode;
61342             for (const clusterId in this._clusters) {
61343                 if (!this._clusters.hasOwnProperty(clusterId)) {
61344                     continue;
61345                 }
61346                 const cluster = this._clusters[clusterId];
61347                 cluster.points.visible = this._getClusterVisible(clusterId);
61348                 for (const points of cluster.points.children) {
61349                     const color = mode === exports.PointVisualizationMode.Cluster ?
61350                         this._assets.getColor(clusterId) : null;
61351                     points.setColor(color);
61352                 }
61353             }
61354             this._needsRender = true;
61355         }
61356         setPositionMode(mode) {
61357             if (mode === this._positionMode) {
61358                 return;
61359             }
61360             for (const cell of Object.values(this._images)) {
61361                 cell.applyPositionMode(mode);
61362             }
61363             this._positionMode = mode;
61364             this._needsRender = true;
61365         }
61366         setSelectedImage(id) {
61367             if (this._selectedId === id) {
61368                 return;
61369             }
61370             this._needsRender = true;
61371             if (this._selectedId != null) {
61372                 this._resetCameraColor(this._selectedId);
61373             }
61374             this._highlight(id, this._colors.select, this._cameraVisualizationMode);
61375             this._selectedId = id;
61376         }
61377         setCellVisibility(visible) {
61378             if (visible === this._cellsVisible) {
61379                 return;
61380             }
61381             for (const cellId in this._cells) {
61382                 if (!this._cells.hasOwnProperty(cellId)) {
61383                     continue;
61384                 }
61385                 this._cells[cellId].visible = visible;
61386             }
61387             this._cellsVisible = visible;
61388             this._needsRender = true;
61389         }
61390         setCameraVisualizationMode(mode) {
61391             if (mode === this._cameraVisualizationMode) {
61392                 return;
61393             }
61394             const visible = isModeVisible(mode);
61395             const assets = this._assets;
61396             for (const cell of Object.values(this._images)) {
61397                 cell.cameras.visible = visible;
61398                 const cameraMap = cell.getCamerasByMode(mode);
61399                 cameraMap.forEach((cameras, colorId) => {
61400                     const color = assets.getColor(colorId);
61401                     for (const camera of cameras) {
61402                         camera.setColor(color);
61403                     }
61404                 });
61405             }
61406             this._highlight(this._hoveredId, this._colors.hover, mode);
61407             this._highlight(this._selectedId, this._colors.select, mode);
61408             this._cameraVisualizationMode = mode;
61409             this._needsRender = true;
61410         }
61411         uncache(keepCellIds) {
61412             for (const cellId of Object.keys(this._cellClusters)) {
61413                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
61414                     continue;
61415                 }
61416                 this._disposeReconstruction(cellId);
61417             }
61418             for (const cellId of Object.keys(this._images)) {
61419                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
61420                     continue;
61421                 }
61422                 const nceMap = this._imageCellMap;
61423                 const keys = this._images[cellId].keys;
61424                 for (const key of keys) {
61425                     nceMap.delete(key);
61426                 }
61427                 this._images[cellId].dispose();
61428                 delete this._images[cellId];
61429             }
61430             for (const cellId of Object.keys(this._cells)) {
61431                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
61432                     continue;
61433                 }
61434                 this._disposeCell(cellId);
61435             }
61436             this._needsRender = true;
61437         }
61438         _getClusterVisible(clusterId) {
61439             if (this._pointVisualizationMode === exports.PointVisualizationMode.Hidden) {
61440                 return false;
61441             }
61442             let visible = false;
61443             for (const imageCell of Object.values(this._images)) {
61444                 const imageCV = imageCell.clusterVisibles;
61445                 if (!(clusterId in imageCV)) {
61446                     continue;
61447                 }
61448                 visible || (visible = imageCV[clusterId]);
61449             }
61450             return visible;
61451         }
61452         _disposePoints(cellId) {
61453             for (const clusterId of this._cellClusters[cellId].keys) {
61454                 if (!(clusterId in this._clusters)) {
61455                     continue;
61456                 }
61457                 const index = this._clusters[clusterId].cellIds.indexOf(cellId);
61458                 if (index === -1) {
61459                     continue;
61460                 }
61461                 this._clusters[clusterId].cellIds.splice(index, 1);
61462                 if (this._clusters[clusterId].cellIds.length > 0) {
61463                     continue;
61464                 }
61465                 for (const points of this._clusters[clusterId].points.children.slice()) {
61466                     points.dispose();
61467                 }
61468                 this._scene.remove(this._clusters[clusterId].points);
61469                 delete this._clusters[clusterId];
61470             }
61471         }
61472         _disposeReconstruction(cellId) {
61473             this._disposePoints(cellId);
61474             delete this._cellClusters[cellId];
61475         }
61476         _disposeCell(cellId) {
61477             const cell = this._cells[cellId];
61478             for (const line of cell.children.slice()) {
61479                 line.dispose();
61480                 cell.remove(line);
61481             }
61482             this._scene.remove(cell);
61483             delete this._cells[cellId];
61484         }
61485         _getNear(cameraSize) {
61486             const near = this._rayNearScale *
61487                 this._originalCameraSize *
61488                 cameraSize;
61489             return Math.max(1, near);
61490         }
61491         _resetCameraColor(imageId) {
61492             const nceMap = this._imageCellMap;
61493             if (imageId == null || !nceMap.has(imageId)) {
61494                 return;
61495             }
61496             const cellId = nceMap.get(imageId);
61497             const cell = this._images[cellId];
61498             const colorId = cell.getColorId(imageId, this._cameraVisualizationMode);
61499             const color = this._assets.getColor(colorId);
61500             cell.applyCameraColor(imageId, color);
61501         }
61502         _highlight(imageId, color, mode) {
61503             const nceMap = this._imageCellMap;
61504             if (imageId == null || !nceMap.has(imageId)) {
61505                 return;
61506             }
61507             const cellId = nceMap.get(imageId);
61508             color = mode === exports.CameraVisualizationMode.Homogeneous ?
61509                 color : "#FFFFFF";
61510             this._images[cellId].applyCameraColor(imageId, color);
61511         }
61512     }
61513
61514     class SpatialCache {
61515         constructor(graphService, provider) {
61516             this._graphService = graphService;
61517             this._data = provider;
61518             this._cells = {};
61519             this._cacheRequests = {};
61520             this._clusters = {};
61521             this._clusterCells = {};
61522             this._cellClusters = {};
61523             this._cachingCells$ = {};
61524             this._cachingClusters$ = {};
61525         }
61526         cacheClusters$(cellId) {
61527             if (!this.hasCell(cellId)) {
61528                 throw new Error("Cannot cache reconstructions of a non-existing cell.");
61529             }
61530             if (this.hasClusters(cellId)) {
61531                 throw new Error("Cannot cache reconstructions that already exists.");
61532             }
61533             if (this.isCachingClusters(cellId)) {
61534                 return this._cachingClusters$[cellId];
61535             }
61536             const duplicatedClusters = this.getCell(cellId)
61537                 .filter((n) => {
61538                 return !!n.clusterId && !!n.clusterUrl;
61539             })
61540                 .map((n) => {
61541                 return { key: n.clusterId, url: n.clusterUrl };
61542             });
61543             const clusters = Array
61544                 .from(new Map(duplicatedClusters.map((cd) => {
61545                 return [cd.key, cd];
61546             }))
61547                 .values());
61548             this._cellClusters[cellId] = clusters;
61549             this._cacheRequests[cellId] = [];
61550             let aborter;
61551             const abort = new Promise((_, reject) => {
61552                 aborter = reject;
61553             });
61554             this._cacheRequests[cellId].push(aborter);
61555             this._cachingClusters$[cellId] =
61556                 this._cacheClusters$(clusters, cellId, abort).pipe(finalize(() => {
61557                     if (cellId in this._cachingClusters$) {
61558                         delete this._cachingClusters$[cellId];
61559                     }
61560                     if (cellId in this._cacheRequests) {
61561                         delete this._cacheRequests[cellId];
61562                     }
61563                 }), publish(), refCount());
61564             return this._cachingClusters$[cellId];
61565         }
61566         cacheCell$(cellId) {
61567             if (this.hasCell(cellId)) {
61568                 throw new Error("Cannot cache cell that already exists.");
61569             }
61570             if (this.isCachingCell(cellId)) {
61571                 return this._cachingCells$[cellId];
61572             }
61573             this._cachingCells$[cellId] = this._graphService.cacheCell$(cellId).pipe(catchError((error) => {
61574                 console.error(error);
61575                 return empty();
61576             }), filter(() => {
61577                 return !(cellId in this._cells);
61578             }), tap((images) => {
61579                 this._cells[cellId] = [];
61580                 this._cells[cellId].push(...images);
61581                 delete this._cachingCells$[cellId];
61582             }), finalize(() => {
61583                 if (cellId in this._cachingCells$) {
61584                     delete this._cachingCells$[cellId];
61585                 }
61586             }), publish(), refCount());
61587             return this._cachingCells$[cellId];
61588         }
61589         isCachingClusters(cellId) {
61590             return cellId in this._cachingClusters$;
61591         }
61592         isCachingCell(cellId) {
61593             return cellId in this._cachingCells$;
61594         }
61595         hasClusters(cellId) {
61596             if (cellId in this._cachingClusters$ ||
61597                 !(cellId in this._cellClusters)) {
61598                 return false;
61599             }
61600             for (const cd of this._cellClusters[cellId]) {
61601                 if (!(cd.key in this._clusters)) {
61602                     return false;
61603                 }
61604             }
61605             return true;
61606         }
61607         hasCell(cellId) {
61608             return !(cellId in this._cachingCells$) && cellId in this._cells;
61609         }
61610         getClusters(cellId) {
61611             return cellId in this._cellClusters ?
61612                 this._cellClusters[cellId]
61613                     .map((cd) => {
61614                     return this._clusters[cd.key];
61615                 })
61616                     .filter((reconstruction) => {
61617                     return !!reconstruction;
61618                 }) :
61619                 [];
61620         }
61621         getCell(cellId) {
61622             return cellId in this._cells ? this._cells[cellId] : [];
61623         }
61624         uncache(keepCellIds) {
61625             for (let cellId of Object.keys(this._cacheRequests)) {
61626                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
61627                     continue;
61628                 }
61629                 for (const aborter of this._cacheRequests[cellId]) {
61630                     aborter();
61631                 }
61632                 delete this._cacheRequests[cellId];
61633             }
61634             for (let cellId of Object.keys(this._cellClusters)) {
61635                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
61636                     continue;
61637                 }
61638                 for (const cd of this._cellClusters[cellId]) {
61639                     if (!(cd.key in this._clusterCells)) {
61640                         continue;
61641                     }
61642                     const index = this._clusterCells[cd.key].indexOf(cellId);
61643                     if (index === -1) {
61644                         continue;
61645                     }
61646                     this._clusterCells[cd.key].splice(index, 1);
61647                     if (this._clusterCells[cd.key].length > 0) {
61648                         continue;
61649                     }
61650                     delete this._clusterCells[cd.key];
61651                     delete this._clusters[cd.key];
61652                 }
61653                 delete this._cellClusters[cellId];
61654             }
61655             for (let cellId of Object.keys(this._cells)) {
61656                 if (!!keepCellIds && keepCellIds.indexOf(cellId) !== -1) {
61657                     continue;
61658                 }
61659                 delete this._cells[cellId];
61660             }
61661         }
61662         updateCell$(cellId) {
61663             if (!this.hasCell(cellId)) {
61664                 throw new Error("Cannot update cell that does not exists.");
61665             }
61666             return this._graphService.cacheCell$(cellId).pipe(catchError((error) => {
61667                 console.error(error);
61668                 return empty();
61669             }), filter(() => {
61670                 return cellId in this._cells;
61671             }), tap((images) => {
61672                 this._cells[cellId] = [];
61673                 this._cells[cellId].push(...images);
61674             }), publish(), refCount());
61675         }
61676         updateClusters$(cellId) {
61677             if (!this.hasCell(cellId)) {
61678                 throw new Error("Cannot update reconstructions of a non-existing cell.");
61679             }
61680             if (!this.hasClusters(cellId)) {
61681                 throw new Error("Cannot update reconstructions for cell that is not cached.");
61682             }
61683             const duplicatedClusters = this.getCell(cellId)
61684                 .filter((n) => {
61685                 return !!n.clusterId && !!n.clusterUrl;
61686             })
61687                 .map((n) => {
61688                 return { key: n.clusterId, url: n.clusterUrl };
61689             });
61690             const clusters = Array
61691                 .from(new Map(duplicatedClusters.map((cd) => {
61692                 return [cd.key, cd];
61693             }))
61694                 .values())
61695                 .filter(cd => {
61696                 return !(cd.key in this._clusters);
61697             });
61698             this._cellClusters[cellId].push(...clusters);
61699             return this._cacheClusters$(clusters, cellId, null);
61700         }
61701         _cacheClusters$(clusters, cellId, cancellation) {
61702             return from(clusters).pipe(mergeMap((cd) => {
61703                 if (this._hasCluster(cd.key)) {
61704                     return of(this._getCluster(cd.key));
61705                 }
61706                 return this._getCluster$(cd.url, cd.key, cancellation)
61707                     .pipe(catchError((error) => {
61708                     if (error instanceof CancelMapillaryError) {
61709                         return empty();
61710                     }
61711                     console.error(error);
61712                     return empty();
61713                 }));
61714             }, 6), filter(() => {
61715                 return cellId in this._cellClusters;
61716             }), tap((reconstruction) => {
61717                 if (!this._hasCluster(reconstruction.id)) {
61718                     this._clusters[reconstruction.id] = reconstruction;
61719                 }
61720                 if (!(reconstruction.id in this._clusterCells)) {
61721                     this._clusterCells[reconstruction.id] = [];
61722                 }
61723                 if (this._clusterCells[reconstruction.id].indexOf(cellId) === -1) {
61724                     this._clusterCells[reconstruction.id].push(cellId);
61725                 }
61726             }));
61727         }
61728         _getCluster(id) {
61729             return this._clusters[id];
61730         }
61731         _getCluster$(url, clusterId, abort) {
61732             return Observable.create((subscriber) => {
61733                 this._data.getCluster(url, abort)
61734                     .then((reconstruction) => {
61735                     reconstruction.id = clusterId;
61736                     subscriber.next(reconstruction);
61737                     subscriber.complete();
61738                 }, (error) => {
61739                     subscriber.error(error);
61740                 });
61741             });
61742         }
61743         _hasCluster(id) {
61744             return id in this._clusters;
61745         }
61746     }
61747
61748     function connectedComponent(cellId, depth, geometry) {
61749         const cells = new Set();
61750         cells.add(cellId);
61751         connectedComponentRecursive(cells, [cellId], 0, depth, geometry);
61752         return Array.from(cells);
61753     }
61754     function connectedComponentRecursive(cells, current, currentDepth, maxDepth, geometry) {
61755         if (currentDepth >= maxDepth) {
61756             return;
61757         }
61758         const adjacent = [];
61759         for (const cellId of current) {
61760             const aCells = geometry.getAdjacent(cellId);
61761             adjacent.push(...aCells);
61762         }
61763         const newCells = [];
61764         for (const a of adjacent) {
61765             if (cells.has(a)) {
61766                 continue;
61767             }
61768             cells.add(a);
61769             newCells.push(a);
61770         }
61771         connectedComponentRecursive(cells, newCells, currentDepth + 1, maxDepth, geometry);
61772     }
61773
61774     class SpatialComponent extends Component {
61775         /** @ignore */
61776         constructor(name, container, navigator) {
61777             super(name, container, navigator);
61778             this._cache = new SpatialCache(navigator.graphService, navigator.api.data);
61779             this._scene = new SpatialScene(this._getDefaultConfiguration());
61780             this._viewportCoords = new ViewportCoords();
61781             this._spatial = new Spatial();
61782         }
61783         /**
61784          * Returns the image id of the camera frame closest to the current
61785          * render camera position at the specified point.
61786          *
61787          * @description Notice that the pixelPoint argument requires x, y
61788          * coordinates from pixel space.
61789          *
61790          * With this function, you can use the coordinates provided by mouse
61791          * events to get information out of the spatial component.
61792          *
61793          * If no camera frame exist at the pixel
61794          * point, `null` will be returned.
61795          *
61796          * @param {Array<number>} pixelPoint - Pixel coordinates on
61797          * the viewer element.
61798          * @returns {string} Image id of the camera frame closest to
61799          * the camera. If no camera frame is intersected at the
61800          * pixel point, `null` will be returned.
61801          *
61802          * @example
61803          * ```js
61804          * spatialComponent.getFrameIdAt([100, 125])
61805          *     .then((imageId) => { console.log(imageId); });
61806          * ```
61807          */
61808         getFrameIdAt(pixelPoint) {
61809             return new Promise((resolve, reject) => {
61810                 this._container.renderService.renderCamera$.pipe(first(), map((render) => {
61811                     const viewport = this._viewportCoords
61812                         .canvasToViewport(pixelPoint[0], pixelPoint[1], this._container.container);
61813                     const id = this._scene.intersection
61814                         .intersectObjects(viewport, render.perspective);
61815                     return id;
61816                 }))
61817                     .subscribe((id) => {
61818                     resolve(id);
61819                 }, (error) => {
61820                     reject(error);
61821                 });
61822             });
61823         }
61824         _activate() {
61825             this._navigator.cacheService.configure({ cellDepth: 3 });
61826             const subs = this._subscriptions;
61827             subs.push(this._navigator.stateService.reference$
61828                 .pipe(pairwise())
61829                 .subscribe(([prevReference, reference]) => {
61830                 this._scene.resetReference(reference, prevReference);
61831             }));
61832             subs.push(this._navigator.graphService.filter$
61833                 .subscribe(imageFilter => { this._scene.setFilter(imageFilter); }));
61834             const bearing$ = this._container.renderService.bearing$.pipe(map((bearing) => {
61835                 const interval = 6;
61836                 const discrete = interval * Math.floor(bearing / interval);
61837                 return discrete;
61838             }), distinctUntilChanged(), publishReplay(1), refCount());
61839             const cellId$ = this._navigator.stateService.currentImage$
61840                 .pipe(map((image) => {
61841                 return this._navigator.api.data.geometry
61842                     .lngLatToCellId(image.originalLngLat);
61843             }), distinctUntilChanged(), publishReplay(1), refCount());
61844             const cellGridDepth$ = this._configuration$
61845                 .pipe(map((c) => {
61846                 return this._spatial.clamp(c.cellGridDepth, 1, 3);
61847             }), distinctUntilChanged(), publishReplay(1), refCount());
61848             const sequencePlay$ = combineLatest(this._navigator.playService.playing$, this._navigator.playService.speed$).pipe(map(([playing, speed]) => {
61849                 return playing && speed > PlayService.sequenceSpeed;
61850             }), distinctUntilChanged(), publishReplay(1), refCount());
61851             const isOverview$ = this._navigator.stateService.state$.pipe(map((state) => {
61852                 return isOverviewState(state);
61853             }), distinctUntilChanged(), publishReplay(1), refCount());
61854             subs.push(isOverview$.subscribe((isOverview) => {
61855                 this._scene.setNavigationState(isOverview);
61856             }));
61857             const cell$ = combineLatest(isOverview$, sequencePlay$, bearing$, cellGridDepth$, this._navigator.stateService.currentImage$)
61858                 .pipe(distinctUntilChanged(([o1, s1, b1, d1, i1], [o2, s2, b2, d2, i2]) => {
61859                 if (o1 !== o2) {
61860                     return false;
61861                 }
61862                 const isd = i1.id === i2.id && s1 === s2 && d1 === d2;
61863                 if (o1) {
61864                     return isd;
61865                 }
61866                 return isd && b1 === b2;
61867             }), concatMap(([isOverview, sequencePlay, bearing, depth, image]) => {
61868                 if (isOverview) {
61869                     const geometry = this._navigator.api.data.geometry;
61870                     const cellId = geometry
61871                         .lngLatToCellId(image.originalLngLat);
61872                     const cells = sequencePlay ?
61873                         [cellId] :
61874                         connectedComponent(cellId, depth, geometry);
61875                     return of(cells);
61876                 }
61877                 const fov = sequencePlay ? 30 : 90;
61878                 return of(this._cellsInFov(image, bearing, fov));
61879             }), switchMap((cellIds) => {
61880                 return from(cellIds).pipe(mergeMap((cellId) => {
61881                     const t$ = this._cache.hasCell(cellId) ?
61882                         of(this._cache.getCell(cellId)) :
61883                         this._cache.cacheCell$(cellId);
61884                     return t$.pipe(map((images) => ({ id: cellId, images })));
61885                 }, 6));
61886             }));
61887             subs.push(cell$.pipe(withLatestFrom(this._navigator.stateService.reference$))
61888                 .subscribe(([cell, reference]) => {
61889                 if (this._scene.hasCell(cell.id)) {
61890                     return;
61891                 }
61892                 this._scene.addCell(this._cellToTopocentric(cell.id, reference), cell.id);
61893             }));
61894             subs.push(cell$.pipe(withLatestFrom(this._navigator.stateService.reference$))
61895                 .subscribe(([cell, reference]) => {
61896                 this._addSceneImages(cell, reference);
61897             }));
61898             subs.push(cell$.pipe(concatMap((cell) => {
61899                 const cellId = cell.id;
61900                 let reconstructions$;
61901                 if (this._cache.hasClusters(cellId)) {
61902                     reconstructions$ = from(this._cache.getClusters(cellId));
61903                 }
61904                 else if (this._cache.isCachingClusters(cellId)) {
61905                     reconstructions$ = this._cache.cacheClusters$(cellId).pipe(last(null, {}), switchMap(() => {
61906                         return from(this._cache.getClusters(cellId));
61907                     }));
61908                 }
61909                 else if (this._cache.hasCell(cellId)) {
61910                     reconstructions$ = this._cache.cacheClusters$(cellId);
61911                 }
61912                 else {
61913                     reconstructions$ = empty();
61914                 }
61915                 return combineLatest(of(cellId), reconstructions$);
61916             }), withLatestFrom(this._navigator.stateService.reference$))
61917                 .subscribe(([[cellId, reconstruction], reference]) => {
61918                 if (this._scene
61919                     .hasCluster(reconstruction.id, cellId)) {
61920                     return;
61921                 }
61922                 this._scene.addCluster(reconstruction, this._computeTranslation(reconstruction, reference), cellId);
61923             }));
61924             subs.push(this._configuration$.pipe(map((c) => {
61925                 var _a;
61926                 c.cameraSize = this._spatial.clamp(c.cameraSize, 0.01, 1);
61927                 c.pointSize = this._spatial.clamp(c.pointSize, 0.01, 1);
61928                 const pointVisualizationMode = c.pointsVisible ?
61929                     (_a = c.pointVisualizationMode) !== null && _a !== void 0 ? _a : exports.PointVisualizationMode.Original :
61930                     exports.PointVisualizationMode.Hidden;
61931                 return {
61932                     cameraSize: c.cameraSize,
61933                     cameraVisualizationMode: c.cameraVisualizationMode,
61934                     cellsVisible: c.cellsVisible,
61935                     originalPositionMode: c.originalPositionMode,
61936                     pointSize: c.pointSize,
61937                     pointVisualizationMode,
61938                 };
61939             }), distinctUntilChanged((c1, c2) => {
61940                 return c1.cameraSize === c2.cameraSize &&
61941                     c1.cameraVisualizationMode === c2.cameraVisualizationMode &&
61942                     c1.cellsVisible === c2.cellsVisible &&
61943                     c1.originalPositionMode === c2.originalPositionMode &&
61944                     c1.pointSize === c2.pointSize &&
61945                     c1.pointVisualizationMode === c2.pointVisualizationMode;
61946             }))
61947                 .subscribe((c) => {
61948                 this._scene.setCameraSize(c.cameraSize);
61949                 const cvm = c.cameraVisualizationMode;
61950                 this._scene.setCameraVisualizationMode(cvm);
61951                 this._scene.setCellVisibility(c.cellsVisible);
61952                 this._scene.setPointSize(c.pointSize);
61953                 const pvm = c.pointVisualizationMode;
61954                 this._scene.setPointVisualizationMode(pvm);
61955                 const opm = c.originalPositionMode;
61956                 this._scene.setPositionMode(opm);
61957             }));
61958             subs.push(combineLatest(cellId$, cellGridDepth$)
61959                 .subscribe(([cellId, depth]) => {
61960                 const keepCells = connectedComponent(cellId, depth, this._navigator.api.data.geometry);
61961                 this._scene.uncache(keepCells);
61962                 this._cache.uncache(keepCells);
61963             }));
61964             subs.push(this._navigator.playService.playing$.pipe(switchMap((playing) => {
61965                 return playing ?
61966                     empty() :
61967                     this._container.mouseService.dblClick$;
61968             }), withLatestFrom(this._container.renderService.renderCamera$), switchMap(([event, render]) => {
61969                 const element = this._container.container;
61970                 const [canvasX, canvasY] = this._viewportCoords
61971                     .canvasPosition(event, element);
61972                 const viewport = this._viewportCoords.canvasToViewport(canvasX, canvasY, element);
61973                 const id = this._scene.intersection
61974                     .intersectObjects(viewport, render.perspective);
61975                 return !!id ?
61976                     this._navigator.moveTo$(id).pipe(catchError(() => {
61977                         return empty();
61978                     })) :
61979                     empty();
61980             }))
61981                 .subscribe());
61982             const intersectChange$ = combineLatest(this._configuration$, this._navigator.stateService.state$).pipe(map(([c, state]) => {
61983                 c.cameraSize = this._spatial.clamp(c.cameraSize, 0.01, 1);
61984                 return {
61985                     size: c.cameraSize,
61986                     visible: isModeVisible(c.cameraVisualizationMode),
61987                     state,
61988                 };
61989             }), distinctUntilChanged((c1, c2) => {
61990                 return c1.size === c2.size &&
61991                     c1.visible === c2.visible &&
61992                     c1.state === c2.state;
61993             }));
61994             const mouseMove$ = this._container.mouseService.mouseMove$.pipe(publishReplay(1), refCount());
61995             subs.push(mouseMove$.subscribe());
61996             const mouseHover$ = merge(this._container.mouseService.mouseEnter$, this._container.mouseService.mouseLeave$, this._container.mouseService.windowBlur$);
61997             subs.push(combineLatest(this._navigator.playService.playing$, mouseHover$, isOverview$, this._navigator.graphService.filter$)
61998                 .pipe(switchMap(([playing, mouseHover]) => {
61999                 return !playing && mouseHover.type === "pointerenter" ?
62000                     combineLatest(concat(mouseMove$.pipe(take(1)), this._container.mouseService.mouseMove$), this._container.renderService.renderCamera$, intersectChange$) :
62001                     combineLatest(of(mouseHover), of(null), of(null));
62002             }))
62003                 .subscribe(([event, render]) => {
62004                 if (event.type !== "pointermove") {
62005                     this._scene.setHoveredImage(null);
62006                     return;
62007                 }
62008                 const element = this._container.container;
62009                 const [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
62010                 const viewport = this._viewportCoords.canvasToViewport(canvasX, canvasY, element);
62011                 const key = this._scene.intersection
62012                     .intersectObjects(viewport, render.perspective);
62013                 this._scene.setHoveredImage(key);
62014             }));
62015             subs.push(this._navigator.stateService.currentId$
62016                 .subscribe((id) => {
62017                 this._scene.setSelectedImage(id);
62018             }));
62019             subs.push(this._navigator.stateService.currentState$
62020                 .pipe(map((frame) => {
62021                 const scene = this._scene;
62022                 return {
62023                     name: this._name,
62024                     renderer: {
62025                         frameId: frame.id,
62026                         needsRender: scene.needsRender,
62027                         render: scene.render.bind(scene),
62028                         pass: RenderPass.Opaque,
62029                     },
62030                 };
62031             }))
62032                 .subscribe(this._container.glRenderer.render$));
62033             const updatedCell$ = this._navigator.graphService.dataAdded$
62034                 .pipe(filter((cellId) => {
62035                 return this._cache.hasCell(cellId);
62036             }), mergeMap((cellId) => {
62037                 return this._cache.updateCell$(cellId).pipe(map((images) => ({ id: cellId, images })), withLatestFrom(this._navigator.stateService.reference$));
62038             }), publish(), refCount());
62039             subs.push(updatedCell$
62040                 .subscribe(([cell, reference]) => {
62041                 this._addSceneImages(cell, reference);
62042             }));
62043             subs.push(updatedCell$
62044                 .pipe(concatMap(([cell]) => {
62045                 const cellId = cell.id;
62046                 const cache = this._cache;
62047                 let reconstructions$;
62048                 if (cache.hasClusters(cellId)) {
62049                     reconstructions$ =
62050                         cache.updateClusters$(cellId);
62051                 }
62052                 else if (cache.isCachingClusters(cellId)) {
62053                     reconstructions$ = this._cache.cacheClusters$(cellId).pipe(last(null, {}), switchMap(() => {
62054                         return from(cache.updateClusters$(cellId));
62055                     }));
62056                 }
62057                 else {
62058                     reconstructions$ = empty();
62059                 }
62060                 return combineLatest(of(cellId), reconstructions$);
62061             }), withLatestFrom(this._navigator.stateService.reference$))
62062                 .subscribe(([[cellId, reconstruction], reference]) => {
62063                 if (this._scene.hasCluster(reconstruction.id, cellId)) {
62064                     return;
62065                 }
62066                 this._scene.addCluster(reconstruction, this._computeTranslation(reconstruction, reference), cellId);
62067             }));
62068         }
62069         _deactivate() {
62070             this._subscriptions.unsubscribe();
62071             this._cache.uncache();
62072             this._scene.deactivate();
62073             this._navigator.cacheService.configure();
62074         }
62075         _getDefaultConfiguration() {
62076             return {
62077                 cameraSize: 0.1,
62078                 cameraVisualizationMode: exports.CameraVisualizationMode.Homogeneous,
62079                 cellGridDepth: 1,
62080                 originalPositionMode: exports.OriginalPositionMode.Hidden,
62081                 pointSize: 0.1,
62082                 pointsVisible: true,
62083                 pointVisualizationMode: exports.PointVisualizationMode.Original,
62084                 cellsVisible: false,
62085             };
62086         }
62087         _addSceneImages(cell, reference) {
62088             const cellId = cell.id;
62089             const images = cell.images;
62090             for (const image of images) {
62091                 if (this._scene.hasImage(image.id, cellId)) {
62092                     continue;
62093                 }
62094                 this._scene.addImage(image, this._createTransform(image, reference), this._computeOriginalPosition(image, reference), cellId);
62095             }
62096         }
62097         _cellsInFov(image, bearing, fov) {
62098             const spatial = this._spatial;
62099             const geometry = this._navigator.api.data.geometry;
62100             const cell = geometry.lngLatToCellId(image.originalLngLat);
62101             const cells = [cell];
62102             const threshold = fov / 2;
62103             const adjacent = geometry.getAdjacent(cell);
62104             for (const a of adjacent) {
62105                 const vertices = geometry.getVertices(a);
62106                 for (const vertex of vertices) {
62107                     const [x, y] = geodeticToEnu(vertex.lng, vertex.lat, 0, image.lngLat.lng, image.lngLat.lat, 0);
62108                     const azimuthal = Math.atan2(y, x);
62109                     const vertexBearing = spatial.radToDeg(spatial.azimuthalToBearing(azimuthal));
62110                     if (Math.abs(vertexBearing - bearing) < threshold) {
62111                         cells.push(a);
62112                     }
62113                 }
62114             }
62115             return cells;
62116         }
62117         _computeOriginalPosition(image, reference) {
62118             return geodeticToEnu(image.originalLngLat.lng, image.originalLngLat.lat, image.originalAltitude != null ? image.originalAltitude : image.computedAltitude, reference.lng, reference.lat, reference.alt);
62119         }
62120         _cellToTopocentric(cellId, reference) {
62121             const vertices = this._navigator.api.data.geometry
62122                 .getVertices(cellId)
62123                 .map((vertex) => {
62124                 return geodeticToEnu(vertex.lng, vertex.lat, -2, reference.lng, reference.lat, reference.alt);
62125             });
62126             return vertices;
62127         }
62128         _computeTranslation(reconstruction, reference) {
62129             return geodeticToEnu(reconstruction.reference.lng, reconstruction.reference.lat, reconstruction.reference.alt, reference.lng, reference.lat, reference.alt);
62130         }
62131         _createTransform(image, reference) {
62132             const translation = computeTranslation({ alt: image.computedAltitude, lat: image.lngLat.lat, lng: image.lngLat.lng }, image.rotation, reference);
62133             const transform = new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, undefined, undefined, image.cameraParameters, image.cameraType);
62134             return transform;
62135         }
62136     }
62137     SpatialComponent.componentName = "spatial";
62138
62139     /**
62140      * @class Geometry
62141      * @abstract
62142      * @classdesc Represents a geometry.
62143      */
62144     class Geometry {
62145         /**
62146          * Create a geometry.
62147          *
62148          * @constructor
62149          * @ignore
62150          */
62151         constructor() {
62152             this._notifyChanged$ = new Subject();
62153         }
62154         /**
62155          * Get changed observable.
62156          *
62157          * @description Emits the geometry itself every time the geometry
62158          * has changed.
62159          *
62160          * @returns {Observable<Geometry>} Observable emitting the geometry instance.
62161          * @ignore
62162          */
62163         get changed$() {
62164             return this._notifyChanged$;
62165         }
62166     }
62167
62168     class GeometryTagError extends MapillaryError {
62169         constructor(message) {
62170             super(message != null ? message : "The provided geometry value is incorrect");
62171             Object.setPrototypeOf(this, GeometryTagError.prototype);
62172             this.name = "GeometryTagError";
62173         }
62174     }
62175
62176     /**
62177      * @class PointsGeometry
62178      *
62179      * @classdesc Represents a point set in the 2D basic image coordinate system.
62180      *
62181      * @example
62182      * ```js
62183      * var points = [[0.5, 0.3], [0.7, 0.3], [0.6, 0.5]];
62184      * var pointsGeometry = new PointsGeometry(points);
62185      * ```
62186      */
62187     class PointsGeometry extends Geometry {
62188         /**
62189          * Create a points geometry.
62190          *
62191          * @constructor
62192          * @param {Array<Array<number>>} points - Array of 2D points on the basic coordinate
62193          * system. The number of points must be greater than or equal to two.
62194          *
62195          * @throws {GeometryTagError} Point coordinates must be valid basic coordinates.
62196          */
62197         constructor(points) {
62198             super();
62199             const pointsLength = points.length;
62200             if (pointsLength < 2) {
62201                 throw new GeometryTagError("A points geometry must have two or more positions.");
62202             }
62203             this._points = [];
62204             for (const point of points) {
62205                 if (point[0] < 0 || point[0] > 1 ||
62206                     point[1] < 0 || point[1] > 1) {
62207                     throw new GeometryTagError("Basic coordinates of points must be on the interval [0, 1].");
62208                 }
62209                 this._points.push(point.slice());
62210             }
62211         }
62212         /**
62213          * Get points property.
62214          * @returns {Array<Array<number>>} Array of 2d points.
62215          */
62216         get points() {
62217             return this._points;
62218         }
62219         /**
62220          * Add a point to the point set.
62221          *
62222          * @param {Array<number>} point - Point to add.
62223          * @ignore
62224          */
62225         addPoint2d(point) {
62226             const clamped = [
62227                 Math.max(0, Math.min(1, point[0])),
62228                 Math.max(0, Math.min(1, point[1])),
62229             ];
62230             this._points.push(clamped);
62231             this._notifyChanged$.next(this);
62232         }
62233         /**
62234          * Get the coordinates of a point from the point set representation of the geometry.
62235          *
62236          * @param {number} index - Point index.
62237          * @returns {Array<number>} Array representing the 2D basic coordinates of the point.
62238          * @ignore
62239          */
62240         getPoint2d(index) {
62241             return this._points[index].slice();
62242         }
62243         /**
62244          * Remove a point from the point set.
62245          *
62246          * @param {number} index - The index of the point to remove.
62247          * @ignore
62248          */
62249         removePoint2d(index) {
62250             if (index < 0 ||
62251                 index >= this._points.length ||
62252                 this._points.length < 3) {
62253                 throw new GeometryTagError("Index for removed point must be valid.");
62254             }
62255             this._points.splice(index, 1);
62256             this._notifyChanged$.next(this);
62257         }
62258         /** @ignore */
62259         setVertex2d(index, value, transform) {
62260             this.setPoint2d(index, value, transform);
62261         }
62262         /** @ignore */
62263         setPoint2d(index, value, transform) {
62264             const changed = [
62265                 Math.max(0, Math.min(1, value[0])),
62266                 Math.max(0, Math.min(1, value[1])),
62267             ];
62268             this._points[index] = changed;
62269             this._notifyChanged$.next(this);
62270         }
62271         /** @ignore */
62272         getPoints3d(transform) {
62273             return this._getPoints3d(this._points, transform);
62274         }
62275         /** @ignore */
62276         getPoint3d(index, transform) {
62277             return transform.unprojectBasic(this._points[index], 200);
62278         }
62279         /** @ignore */
62280         getPoints2d() {
62281             return this._points.slice();
62282         }
62283         /** @ignore */
62284         getCentroid2d(transform) {
62285             if (!transform) {
62286                 throw new GeometryTagError("Get centroid must be called with a transform for points geometries.");
62287             }
62288             const [minX, minY, maxX, maxY] = this.getRect2d(transform);
62289             const centroidX = minX < maxX ?
62290                 (minX + maxX) / 2 :
62291                 ((minX + maxX + 1) / 2) % 1;
62292             const centroidY = (minY + maxY) / 2;
62293             return [centroidX, centroidY];
62294         }
62295         /** @ignore */
62296         getCentroid3d(transform) {
62297             let centroid2d = this.getCentroid2d();
62298             return transform.unprojectBasic(centroid2d, 200);
62299         }
62300         /** @ignore */
62301         getRect2d(transform) {
62302             let minX = 1;
62303             let maxX = 0;
62304             let minY = 1;
62305             let maxY = 0;
62306             const points = this._points;
62307             for (const point of points) {
62308                 if (point[0] < minX) {
62309                     minX = point[0];
62310                 }
62311                 if (point[0] > maxX) {
62312                     maxX = point[0];
62313                 }
62314                 if (point[1] < minY) {
62315                     minY = point[1];
62316                 }
62317                 if (point[1] > maxY) {
62318                     maxY = point[1];
62319                 }
62320             }
62321             if (isSpherical(transform.cameraType)) {
62322                 const indices = [];
62323                 for (let i = 0; i < points.length; i++) {
62324                     indices[i] = i;
62325                 }
62326                 indices.sort((a, b) => {
62327                     return points[a][0] < points[b][0] ?
62328                         -1 :
62329                         points[a][0] > points[b][0] ?
62330                             1 :
62331                             a < b ? -1 : 1;
62332                 });
62333                 let maxDistanceX = points[indices[0]][0] + 1 - points[indices[indices.length - 1]][0];
62334                 let leftMostIndex = 0;
62335                 for (let i = 0; i < indices.length - 1; i++) {
62336                     const index1 = indices[i];
62337                     const index2 = indices[i + 1];
62338                     const distanceX = points[index2][0] - points[index1][0];
62339                     if (distanceX > maxDistanceX) {
62340                         maxDistanceX = distanceX;
62341                         leftMostIndex = i + 1;
62342                     }
62343                 }
62344                 if (leftMostIndex > 0) {
62345                     minX = points[indices[leftMostIndex]][0];
62346                     maxX = points[indices[leftMostIndex - 1]][0];
62347                 }
62348             }
62349             return [minX, minY, maxX, maxY];
62350         }
62351         /** @ignore */
62352         setCentroid2d(value, transform) {
62353             throw new Error("Not implemented");
62354         }
62355         _getPoints3d(points2d, transform) {
62356             return points2d
62357                 .map((point) => {
62358                 return transform.unprojectBasic(point, 200);
62359             });
62360         }
62361     }
62362
62363     class CreateTag {
62364         constructor(geometry, transform, viewportCoords) {
62365             this._geometry = geometry;
62366             this._transform = transform;
62367             this._viewportCoords = !!viewportCoords ? viewportCoords : new ViewportCoords();
62368             this._aborted$ = new Subject();
62369             this._created$ = new Subject();
62370             this._glObjectsChanged$ = new Subject();
62371             this._geometryChangedSubscription = this._geometry.changed$
62372                 .subscribe(() => {
62373                 this._onGeometryChanged();
62374                 this._glObjectsChanged$.next(this);
62375             });
62376         }
62377         get geometry() {
62378             return this._geometry;
62379         }
62380         get glObjects() {
62381             return this._glObjects;
62382         }
62383         get aborted$() {
62384             return this._aborted$;
62385         }
62386         get created$() {
62387             return this._created$;
62388         }
62389         get glObjectsChanged$() {
62390             return this._glObjectsChanged$;
62391         }
62392         get geometryChanged$() {
62393             return this._geometry.changed$.pipe(map(() => {
62394                 return this;
62395             }));
62396         }
62397         dispose() {
62398             this._geometryChangedSubscription.unsubscribe();
62399         }
62400         _canvasToTransform(canvas) {
62401             const canvasX = Math.round(canvas[0]);
62402             const canvasY = Math.round(canvas[1]);
62403             const transform = `translate(-50%,-50%) translate(${canvasX}px,${canvasY}px)`;
62404             return transform;
62405         }
62406         _colorToBackground(color) {
62407             return "#" + ("000000" + color.toString(16)).substr(-6);
62408         }
62409         _createOutine(polygon3d, color) {
62410             const positions = this._getLinePositions(polygon3d);
62411             const geometry = new BufferGeometry();
62412             geometry.setAttribute("position", new BufferAttribute(positions, 3));
62413             const material = new LineBasicMaterial({
62414                 color: color,
62415                 linewidth: 1,
62416             });
62417             return new Line(geometry, material);
62418         }
62419         _disposeLine(line) {
62420             if (line == null) {
62421                 return;
62422             }
62423             line.geometry.dispose();
62424             line.material.dispose();
62425         }
62426         _getLinePositions(polygon3d) {
62427             const length = polygon3d.length;
62428             const positions = new Float32Array(length * 3);
62429             for (let i = 0; i < length; ++i) {
62430                 const index = 3 * i;
62431                 const position = polygon3d[i];
62432                 positions[index] = position[0];
62433                 positions[index + 1] = position[1];
62434                 positions[index + 2] = position[2];
62435             }
62436             return positions;
62437         }
62438     }
62439
62440     var earcut$2 = {exports: {}};
62441
62442     earcut$2.exports = earcut;
62443     earcut$2.exports.default = earcut;
62444
62445     function earcut(data, holeIndices, dim) {
62446
62447         dim = dim || 2;
62448
62449         var hasHoles = holeIndices && holeIndices.length,
62450             outerLen = hasHoles ? holeIndices[0] * dim : data.length,
62451             outerNode = linkedList(data, 0, outerLen, dim, true),
62452             triangles = [];
62453
62454         if (!outerNode || outerNode.next === outerNode.prev) return triangles;
62455
62456         var minX, minY, maxX, maxY, x, y, invSize;
62457
62458         if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
62459
62460         // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
62461         if (data.length > 80 * dim) {
62462             minX = maxX = data[0];
62463             minY = maxY = data[1];
62464
62465             for (var i = dim; i < outerLen; i += dim) {
62466                 x = data[i];
62467                 y = data[i + 1];
62468                 if (x < minX) minX = x;
62469                 if (y < minY) minY = y;
62470                 if (x > maxX) maxX = x;
62471                 if (y > maxY) maxY = y;
62472             }
62473
62474             // minX, minY and invSize are later used to transform coords into integers for z-order calculation
62475             invSize = Math.max(maxX - minX, maxY - minY);
62476             invSize = invSize !== 0 ? 1 / invSize : 0;
62477         }
62478
62479         earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
62480
62481         return triangles;
62482     }
62483
62484     // create a circular doubly linked list from polygon points in the specified winding order
62485     function linkedList(data, start, end, dim, clockwise) {
62486         var i, last;
62487
62488         if (clockwise === (signedArea$1(data, start, end, dim) > 0)) {
62489             for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
62490         } else {
62491             for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
62492         }
62493
62494         if (last && equals$1(last, last.next)) {
62495             removeNode(last);
62496             last = last.next;
62497         }
62498
62499         return last;
62500     }
62501
62502     // eliminate colinear or duplicate points
62503     function filterPoints(start, end) {
62504         if (!start) return start;
62505         if (!end) end = start;
62506
62507         var p = start,
62508             again;
62509         do {
62510             again = false;
62511
62512             if (!p.steiner && (equals$1(p, p.next) || area(p.prev, p, p.next) === 0)) {
62513                 removeNode(p);
62514                 p = end = p.prev;
62515                 if (p === p.next) break;
62516                 again = true;
62517
62518             } else {
62519                 p = p.next;
62520             }
62521         } while (again || p !== end);
62522
62523         return end;
62524     }
62525
62526     // main ear slicing loop which triangulates a polygon (given as a linked list)
62527     function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
62528         if (!ear) return;
62529
62530         // interlink polygon nodes in z-order
62531         if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
62532
62533         var stop = ear,
62534             prev, next;
62535
62536         // iterate through ears, slicing them one by one
62537         while (ear.prev !== ear.next) {
62538             prev = ear.prev;
62539             next = ear.next;
62540
62541             if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
62542                 // cut off the triangle
62543                 triangles.push(prev.i / dim);
62544                 triangles.push(ear.i / dim);
62545                 triangles.push(next.i / dim);
62546
62547                 removeNode(ear);
62548
62549                 // skipping the next vertex leads to less sliver triangles
62550                 ear = next.next;
62551                 stop = next.next;
62552
62553                 continue;
62554             }
62555
62556             ear = next;
62557
62558             // if we looped through the whole remaining polygon and can't find any more ears
62559             if (ear === stop) {
62560                 // try filtering points and slicing again
62561                 if (!pass) {
62562                     earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
62563
62564                 // if this didn't work, try curing all small self-intersections locally
62565                 } else if (pass === 1) {
62566                     ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
62567                     earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
62568
62569                 // as a last resort, try splitting the remaining polygon into two
62570                 } else if (pass === 2) {
62571                     splitEarcut(ear, triangles, dim, minX, minY, invSize);
62572                 }
62573
62574                 break;
62575             }
62576         }
62577     }
62578
62579     // check whether a polygon node forms a valid ear with adjacent nodes
62580     function isEar(ear) {
62581         var a = ear.prev,
62582             b = ear,
62583             c = ear.next;
62584
62585         if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
62586
62587         // now make sure we don't have other points inside the potential ear
62588         var p = ear.next.next;
62589
62590         while (p !== ear.prev) {
62591             if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
62592                 area(p.prev, p, p.next) >= 0) return false;
62593             p = p.next;
62594         }
62595
62596         return true;
62597     }
62598
62599     function isEarHashed(ear, minX, minY, invSize) {
62600         var a = ear.prev,
62601             b = ear,
62602             c = ear.next;
62603
62604         if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
62605
62606         // triangle bbox; min & max are calculated like this for speed
62607         var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x),
62608             minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y),
62609             maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x),
62610             maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y);
62611
62612         // z-order range for the current triangle bbox;
62613         var minZ = zOrder(minTX, minTY, minX, minY, invSize),
62614             maxZ = zOrder(maxTX, maxTY, minX, minY, invSize);
62615
62616         var p = ear.prevZ,
62617             n = ear.nextZ;
62618
62619         // look for points inside the triangle in both directions
62620         while (p && p.z >= minZ && n && n.z <= maxZ) {
62621             if (p !== ear.prev && p !== ear.next &&
62622                 pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
62623                 area(p.prev, p, p.next) >= 0) return false;
62624             p = p.prevZ;
62625
62626             if (n !== ear.prev && n !== ear.next &&
62627                 pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) &&
62628                 area(n.prev, n, n.next) >= 0) return false;
62629             n = n.nextZ;
62630         }
62631
62632         // look for remaining points in decreasing z-order
62633         while (p && p.z >= minZ) {
62634             if (p !== ear.prev && p !== ear.next &&
62635                 pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
62636                 area(p.prev, p, p.next) >= 0) return false;
62637             p = p.prevZ;
62638         }
62639
62640         // look for remaining points in increasing z-order
62641         while (n && n.z <= maxZ) {
62642             if (n !== ear.prev && n !== ear.next &&
62643                 pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) &&
62644                 area(n.prev, n, n.next) >= 0) return false;
62645             n = n.nextZ;
62646         }
62647
62648         return true;
62649     }
62650
62651     // go through all polygon nodes and cure small local self-intersections
62652     function cureLocalIntersections(start, triangles, dim) {
62653         var p = start;
62654         do {
62655             var a = p.prev,
62656                 b = p.next.next;
62657
62658             if (!equals$1(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
62659
62660                 triangles.push(a.i / dim);
62661                 triangles.push(p.i / dim);
62662                 triangles.push(b.i / dim);
62663
62664                 // remove two nodes involved
62665                 removeNode(p);
62666                 removeNode(p.next);
62667
62668                 p = start = b;
62669             }
62670             p = p.next;
62671         } while (p !== start);
62672
62673         return filterPoints(p);
62674     }
62675
62676     // try splitting polygon into two and triangulate them independently
62677     function splitEarcut(start, triangles, dim, minX, minY, invSize) {
62678         // look for a valid diagonal that divides the polygon into two
62679         var a = start;
62680         do {
62681             var b = a.next.next;
62682             while (b !== a.prev) {
62683                 if (a.i !== b.i && isValidDiagonal(a, b)) {
62684                     // split the polygon in two by the diagonal
62685                     var c = splitPolygon(a, b);
62686
62687                     // filter colinear points around the cuts
62688                     a = filterPoints(a, a.next);
62689                     c = filterPoints(c, c.next);
62690
62691                     // run earcut on each half
62692                     earcutLinked(a, triangles, dim, minX, minY, invSize);
62693                     earcutLinked(c, triangles, dim, minX, minY, invSize);
62694                     return;
62695                 }
62696                 b = b.next;
62697             }
62698             a = a.next;
62699         } while (a !== start);
62700     }
62701
62702     // link every hole into the outer loop, producing a single-ring polygon without holes
62703     function eliminateHoles(data, holeIndices, outerNode, dim) {
62704         var queue = [],
62705             i, len, start, end, list;
62706
62707         for (i = 0, len = holeIndices.length; i < len; i++) {
62708             start = holeIndices[i] * dim;
62709             end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
62710             list = linkedList(data, start, end, dim, false);
62711             if (list === list.next) list.steiner = true;
62712             queue.push(getLeftmost(list));
62713         }
62714
62715         queue.sort(compareX);
62716
62717         // process holes from left to right
62718         for (i = 0; i < queue.length; i++) {
62719             outerNode = eliminateHole(queue[i], outerNode);
62720             outerNode = filterPoints(outerNode, outerNode.next);
62721         }
62722
62723         return outerNode;
62724     }
62725
62726     function compareX(a, b) {
62727         return a.x - b.x;
62728     }
62729
62730     // find a bridge between vertices that connects hole with an outer ring and and link it
62731     function eliminateHole(hole, outerNode) {
62732         var bridge = findHoleBridge(hole, outerNode);
62733         if (!bridge) {
62734             return outerNode;
62735         }
62736
62737         var bridgeReverse = splitPolygon(bridge, hole);
62738
62739         // filter collinear points around the cuts
62740         var filteredBridge = filterPoints(bridge, bridge.next);
62741         filterPoints(bridgeReverse, bridgeReverse.next);
62742
62743         // Check if input node was removed by the filtering
62744         return outerNode === bridge ? filteredBridge : outerNode;
62745     }
62746
62747     // David Eberly's algorithm for finding a bridge between hole and outer polygon
62748     function findHoleBridge(hole, outerNode) {
62749         var p = outerNode,
62750             hx = hole.x,
62751             hy = hole.y,
62752             qx = -Infinity,
62753             m;
62754
62755         // find a segment intersected by a ray from the hole's leftmost point to the left;
62756         // segment's endpoint with lesser x will be potential connection point
62757         do {
62758             if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
62759                 var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
62760                 if (x <= hx && x > qx) {
62761                     qx = x;
62762                     if (x === hx) {
62763                         if (hy === p.y) return p;
62764                         if (hy === p.next.y) return p.next;
62765                     }
62766                     m = p.x < p.next.x ? p : p.next;
62767                 }
62768             }
62769             p = p.next;
62770         } while (p !== outerNode);
62771
62772         if (!m) return null;
62773
62774         if (hx === qx) return m; // hole touches outer segment; pick leftmost endpoint
62775
62776         // look for points inside the triangle of hole point, segment intersection and endpoint;
62777         // if there are no points found, we have a valid connection;
62778         // otherwise choose the point of the minimum angle with the ray as connection point
62779
62780         var stop = m,
62781             mx = m.x,
62782             my = m.y,
62783             tanMin = Infinity,
62784             tan;
62785
62786         p = m;
62787
62788         do {
62789             if (hx >= p.x && p.x >= mx && hx !== p.x &&
62790                     pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
62791
62792                 tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
62793
62794                 if (locallyInside(p, hole) &&
62795                     (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
62796                     m = p;
62797                     tanMin = tan;
62798                 }
62799             }
62800
62801             p = p.next;
62802         } while (p !== stop);
62803
62804         return m;
62805     }
62806
62807     // whether sector in vertex m contains sector in vertex p in the same coordinates
62808     function sectorContainsSector(m, p) {
62809         return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
62810     }
62811
62812     // interlink polygon nodes in z-order
62813     function indexCurve(start, minX, minY, invSize) {
62814         var p = start;
62815         do {
62816             if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, invSize);
62817             p.prevZ = p.prev;
62818             p.nextZ = p.next;
62819             p = p.next;
62820         } while (p !== start);
62821
62822         p.prevZ.nextZ = null;
62823         p.prevZ = null;
62824
62825         sortLinked(p);
62826     }
62827
62828     // Simon Tatham's linked list merge sort algorithm
62829     // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
62830     function sortLinked(list) {
62831         var i, p, q, e, tail, numMerges, pSize, qSize,
62832             inSize = 1;
62833
62834         do {
62835             p = list;
62836             list = null;
62837             tail = null;
62838             numMerges = 0;
62839
62840             while (p) {
62841                 numMerges++;
62842                 q = p;
62843                 pSize = 0;
62844                 for (i = 0; i < inSize; i++) {
62845                     pSize++;
62846                     q = q.nextZ;
62847                     if (!q) break;
62848                 }
62849                 qSize = inSize;
62850
62851                 while (pSize > 0 || (qSize > 0 && q)) {
62852
62853                     if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
62854                         e = p;
62855                         p = p.nextZ;
62856                         pSize--;
62857                     } else {
62858                         e = q;
62859                         q = q.nextZ;
62860                         qSize--;
62861                     }
62862
62863                     if (tail) tail.nextZ = e;
62864                     else list = e;
62865
62866                     e.prevZ = tail;
62867                     tail = e;
62868                 }
62869
62870                 p = q;
62871             }
62872
62873             tail.nextZ = null;
62874             inSize *= 2;
62875
62876         } while (numMerges > 1);
62877
62878         return list;
62879     }
62880
62881     // z-order of a point given coords and inverse of the longer side of data bbox
62882     function zOrder(x, y, minX, minY, invSize) {
62883         // coords are transformed into non-negative 15-bit integer range
62884         x = 32767 * (x - minX) * invSize;
62885         y = 32767 * (y - minY) * invSize;
62886
62887         x = (x | (x << 8)) & 0x00FF00FF;
62888         x = (x | (x << 4)) & 0x0F0F0F0F;
62889         x = (x | (x << 2)) & 0x33333333;
62890         x = (x | (x << 1)) & 0x55555555;
62891
62892         y = (y | (y << 8)) & 0x00FF00FF;
62893         y = (y | (y << 4)) & 0x0F0F0F0F;
62894         y = (y | (y << 2)) & 0x33333333;
62895         y = (y | (y << 1)) & 0x55555555;
62896
62897         return x | (y << 1);
62898     }
62899
62900     // find the leftmost node of a polygon ring
62901     function getLeftmost(start) {
62902         var p = start,
62903             leftmost = start;
62904         do {
62905             if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;
62906             p = p.next;
62907         } while (p !== start);
62908
62909         return leftmost;
62910     }
62911
62912     // check if a point lies within a convex triangle
62913     function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
62914         return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
62915                (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
62916                (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
62917     }
62918
62919     // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
62920     function isValidDiagonal(a, b) {
62921         return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
62922                (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
62923                 (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
62924                 equals$1(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case
62925     }
62926
62927     // signed area of a triangle
62928     function area(p, q, r) {
62929         return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
62930     }
62931
62932     // check if two points are equal
62933     function equals$1(p1, p2) {
62934         return p1.x === p2.x && p1.y === p2.y;
62935     }
62936
62937     // check if two segments intersect
62938     function intersects(p1, q1, p2, q2) {
62939         var o1 = sign(area(p1, q1, p2));
62940         var o2 = sign(area(p1, q1, q2));
62941         var o3 = sign(area(p2, q2, p1));
62942         var o4 = sign(area(p2, q2, q1));
62943
62944         if (o1 !== o2 && o3 !== o4) return true; // general case
62945
62946         if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
62947         if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
62948         if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
62949         if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
62950
62951         return false;
62952     }
62953
62954     // for collinear points p, q, r, check if point q lies on segment pr
62955     function onSegment(p, q, r) {
62956         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);
62957     }
62958
62959     function sign(num) {
62960         return num > 0 ? 1 : num < 0 ? -1 : 0;
62961     }
62962
62963     // check if a polygon diagonal intersects any polygon segments
62964     function intersectsPolygon(a, b) {
62965         var p = a;
62966         do {
62967             if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
62968                     intersects(p, p.next, a, b)) return true;
62969             p = p.next;
62970         } while (p !== a);
62971
62972         return false;
62973     }
62974
62975     // check if a polygon diagonal is locally inside the polygon
62976     function locallyInside(a, b) {
62977         return area(a.prev, a, a.next) < 0 ?
62978             area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
62979             area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
62980     }
62981
62982     // check if the middle point of a polygon diagonal is inside the polygon
62983     function middleInside(a, b) {
62984         var p = a,
62985             inside = false,
62986             px = (a.x + b.x) / 2,
62987             py = (a.y + b.y) / 2;
62988         do {
62989             if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&
62990                     (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
62991                 inside = !inside;
62992             p = p.next;
62993         } while (p !== a);
62994
62995         return inside;
62996     }
62997
62998     // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
62999     // if one belongs to the outer ring and another to a hole, it merges it into a single ring
63000     function splitPolygon(a, b) {
63001         var a2 = new Node(a.i, a.x, a.y),
63002             b2 = new Node(b.i, b.x, b.y),
63003             an = a.next,
63004             bp = b.prev;
63005
63006         a.next = b;
63007         b.prev = a;
63008
63009         a2.next = an;
63010         an.prev = a2;
63011
63012         b2.next = a2;
63013         a2.prev = b2;
63014
63015         bp.next = b2;
63016         b2.prev = bp;
63017
63018         return b2;
63019     }
63020
63021     // create a node and optionally link it with previous one (in a circular doubly linked list)
63022     function insertNode(i, x, y, last) {
63023         var p = new Node(i, x, y);
63024
63025         if (!last) {
63026             p.prev = p;
63027             p.next = p;
63028
63029         } else {
63030             p.next = last.next;
63031             p.prev = last;
63032             last.next.prev = p;
63033             last.next = p;
63034         }
63035         return p;
63036     }
63037
63038     function removeNode(p) {
63039         p.next.prev = p.prev;
63040         p.prev.next = p.next;
63041
63042         if (p.prevZ) p.prevZ.nextZ = p.nextZ;
63043         if (p.nextZ) p.nextZ.prevZ = p.prevZ;
63044     }
63045
63046     function Node(i, x, y) {
63047         // vertex index in coordinates array
63048         this.i = i;
63049
63050         // vertex coordinates
63051         this.x = x;
63052         this.y = y;
63053
63054         // previous and next vertex nodes in a polygon ring
63055         this.prev = null;
63056         this.next = null;
63057
63058         // z-order curve value
63059         this.z = null;
63060
63061         // previous and next nodes in z-order
63062         this.prevZ = null;
63063         this.nextZ = null;
63064
63065         // indicates whether this is a steiner point
63066         this.steiner = false;
63067     }
63068
63069     // return a percentage difference between the polygon area and its triangulation area;
63070     // used to verify correctness of triangulation
63071     earcut.deviation = function (data, holeIndices, dim, triangles) {
63072         var hasHoles = holeIndices && holeIndices.length;
63073         var outerLen = hasHoles ? holeIndices[0] * dim : data.length;
63074
63075         var polygonArea = Math.abs(signedArea$1(data, 0, outerLen, dim));
63076         if (hasHoles) {
63077             for (var i = 0, len = holeIndices.length; i < len; i++) {
63078                 var start = holeIndices[i] * dim;
63079                 var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
63080                 polygonArea -= Math.abs(signedArea$1(data, start, end, dim));
63081             }
63082         }
63083
63084         var trianglesArea = 0;
63085         for (i = 0; i < triangles.length; i += 3) {
63086             var a = triangles[i] * dim;
63087             var b = triangles[i + 1] * dim;
63088             var c = triangles[i + 2] * dim;
63089             trianglesArea += Math.abs(
63090                 (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -
63091                 (data[a] - data[b]) * (data[c + 1] - data[a + 1]));
63092         }
63093
63094         return polygonArea === 0 && trianglesArea === 0 ? 0 :
63095             Math.abs((trianglesArea - polygonArea) / polygonArea);
63096     };
63097
63098     function signedArea$1(data, start, end, dim) {
63099         var sum = 0;
63100         for (var i = start, j = end - dim; i < end; i += dim) {
63101             sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
63102             j = i;
63103         }
63104         return sum;
63105     }
63106
63107     // turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts
63108     earcut.flatten = function (data) {
63109         var dim = data[0][0].length,
63110             result = {vertices: [], holes: [], dimensions: dim},
63111             holeIndex = 0;
63112
63113         for (var i = 0; i < data.length; i++) {
63114             for (var j = 0; j < data[i].length; j++) {
63115                 for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]);
63116             }
63117             if (i > 0) {
63118                 holeIndex += data[i - 1].length;
63119                 result.holes.push(holeIndex);
63120             }
63121         }
63122         return result;
63123     };
63124
63125     var earcut$1 = earcut$2.exports;
63126
63127     var polylabel$2 = {exports: {}};
63128
63129     class TinyQueue$1 {
63130         constructor(data = [], compare = defaultCompare$1) {
63131             this.data = data;
63132             this.length = this.data.length;
63133             this.compare = compare;
63134
63135             if (this.length > 0) {
63136                 for (let i = (this.length >> 1) - 1; i >= 0; i--) this._down(i);
63137             }
63138         }
63139
63140         push(item) {
63141             this.data.push(item);
63142             this.length++;
63143             this._up(this.length - 1);
63144         }
63145
63146         pop() {
63147             if (this.length === 0) return undefined;
63148
63149             const top = this.data[0];
63150             const bottom = this.data.pop();
63151             this.length--;
63152
63153             if (this.length > 0) {
63154                 this.data[0] = bottom;
63155                 this._down(0);
63156             }
63157
63158             return top;
63159         }
63160
63161         peek() {
63162             return this.data[0];
63163         }
63164
63165         _up(pos) {
63166             const {data, compare} = this;
63167             const item = data[pos];
63168
63169             while (pos > 0) {
63170                 const parent = (pos - 1) >> 1;
63171                 const current = data[parent];
63172                 if (compare(item, current) >= 0) break;
63173                 data[pos] = current;
63174                 pos = parent;
63175             }
63176
63177             data[pos] = item;
63178         }
63179
63180         _down(pos) {
63181             const {data, compare} = this;
63182             const halfLength = this.length >> 1;
63183             const item = data[pos];
63184
63185             while (pos < halfLength) {
63186                 let left = (pos << 1) + 1;
63187                 let best = data[left];
63188                 const right = left + 1;
63189
63190                 if (right < this.length && compare(data[right], best) < 0) {
63191                     left = right;
63192                     best = data[right];
63193                 }
63194                 if (compare(best, item) >= 0) break;
63195
63196                 data[pos] = best;
63197                 pos = left;
63198             }
63199
63200             data[pos] = item;
63201         }
63202     }
63203
63204     function defaultCompare$1(a, b) {
63205         return a < b ? -1 : a > b ? 1 : 0;
63206     }
63207
63208     var tinyqueue$1 = /*#__PURE__*/Object.freeze({
63209         __proto__: null,
63210         'default': TinyQueue$1
63211     });
63212
63213     var require$$0 = /*@__PURE__*/getAugmentedNamespace(tinyqueue$1);
63214
63215     var Queue$1 = require$$0;
63216
63217     if (Queue$1.default) Queue$1 = Queue$1.default; // temporary webpack fix
63218
63219     polylabel$2.exports = polylabel;
63220     polylabel$2.exports.default = polylabel;
63221
63222     function polylabel(polygon, precision, debug) {
63223         precision = precision || 1.0;
63224
63225         // find the bounding box of the outer ring
63226         var minX, minY, maxX, maxY;
63227         for (var i = 0; i < polygon[0].length; i++) {
63228             var p = polygon[0][i];
63229             if (!i || p[0] < minX) minX = p[0];
63230             if (!i || p[1] < minY) minY = p[1];
63231             if (!i || p[0] > maxX) maxX = p[0];
63232             if (!i || p[1] > maxY) maxY = p[1];
63233         }
63234
63235         var width = maxX - minX;
63236         var height = maxY - minY;
63237         var cellSize = Math.min(width, height);
63238         var h = cellSize / 2;
63239
63240         if (cellSize === 0) {
63241             var degeneratePoleOfInaccessibility = [minX, minY];
63242             degeneratePoleOfInaccessibility.distance = 0;
63243             return degeneratePoleOfInaccessibility;
63244         }
63245
63246         // a priority queue of cells in order of their "potential" (max distance to polygon)
63247         var cellQueue = new Queue$1(undefined, compareMax);
63248
63249         // cover polygon with initial cells
63250         for (var x = minX; x < maxX; x += cellSize) {
63251             for (var y = minY; y < maxY; y += cellSize) {
63252                 cellQueue.push(new Cell(x + h, y + h, h, polygon));
63253             }
63254         }
63255
63256         // take centroid as the first best guess
63257         var bestCell = getCentroidCell(polygon);
63258
63259         // special case for rectangular polygons
63260         var bboxCell = new Cell(minX + width / 2, minY + height / 2, 0, polygon);
63261         if (bboxCell.d > bestCell.d) bestCell = bboxCell;
63262
63263         var numProbes = cellQueue.length;
63264
63265         while (cellQueue.length) {
63266             // pick the most promising cell from the queue
63267             var cell = cellQueue.pop();
63268
63269             // update the best cell if we found a better one
63270             if (cell.d > bestCell.d) {
63271                 bestCell = cell;
63272                 if (debug) console.log('found best %d after %d probes', Math.round(1e4 * cell.d) / 1e4, numProbes);
63273             }
63274
63275             // do not drill down further if there's no chance of a better solution
63276             if (cell.max - bestCell.d <= precision) continue;
63277
63278             // split the cell into four cells
63279             h = cell.h / 2;
63280             cellQueue.push(new Cell(cell.x - h, cell.y - h, h, polygon));
63281             cellQueue.push(new Cell(cell.x + h, cell.y - h, h, polygon));
63282             cellQueue.push(new Cell(cell.x - h, cell.y + h, h, polygon));
63283             cellQueue.push(new Cell(cell.x + h, cell.y + h, h, polygon));
63284             numProbes += 4;
63285         }
63286
63287         if (debug) {
63288             console.log('num probes: ' + numProbes);
63289             console.log('best distance: ' + bestCell.d);
63290         }
63291
63292         var poleOfInaccessibility = [bestCell.x, bestCell.y];
63293         poleOfInaccessibility.distance = bestCell.d;
63294         return poleOfInaccessibility;
63295     }
63296
63297     function compareMax(a, b) {
63298         return b.max - a.max;
63299     }
63300
63301     function Cell(x, y, h, polygon) {
63302         this.x = x; // cell center x
63303         this.y = y; // cell center y
63304         this.h = h; // half the cell size
63305         this.d = pointToPolygonDist(x, y, polygon); // distance from cell center to polygon
63306         this.max = this.d + this.h * Math.SQRT2; // max distance to polygon within a cell
63307     }
63308
63309     // signed distance from point to polygon outline (negative if point is outside)
63310     function pointToPolygonDist(x, y, polygon) {
63311         var inside = false;
63312         var minDistSq = Infinity;
63313
63314         for (var k = 0; k < polygon.length; k++) {
63315             var ring = polygon[k];
63316
63317             for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
63318                 var a = ring[i];
63319                 var b = ring[j];
63320
63321                 if ((a[1] > y !== b[1] > y) &&
63322                     (x < (b[0] - a[0]) * (y - a[1]) / (b[1] - a[1]) + a[0])) inside = !inside;
63323
63324                 minDistSq = Math.min(minDistSq, getSegDistSq(x, y, a, b));
63325             }
63326         }
63327
63328         return minDistSq === 0 ? 0 : (inside ? 1 : -1) * Math.sqrt(minDistSq);
63329     }
63330
63331     // get polygon centroid
63332     function getCentroidCell(polygon) {
63333         var area = 0;
63334         var x = 0;
63335         var y = 0;
63336         var points = polygon[0];
63337
63338         for (var i = 0, len = points.length, j = len - 1; i < len; j = i++) {
63339             var a = points[i];
63340             var b = points[j];
63341             var f = a[0] * b[1] - b[0] * a[1];
63342             x += (a[0] + b[0]) * f;
63343             y += (a[1] + b[1]) * f;
63344             area += f * 3;
63345         }
63346         if (area === 0) return new Cell(points[0][0], points[0][1], 0, polygon);
63347         return new Cell(x / area, y / area, 0, polygon);
63348     }
63349
63350     // get squared distance from a point to a segment
63351     function getSegDistSq(px, py, a, b) {
63352
63353         var x = a[0];
63354         var y = a[1];
63355         var dx = b[0] - x;
63356         var dy = b[1] - y;
63357
63358         if (dx !== 0 || dy !== 0) {
63359
63360             var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
63361
63362             if (t > 1) {
63363                 x = b[0];
63364                 y = b[1];
63365
63366             } else if (t > 0) {
63367                 x += dx * t;
63368                 y += dy * t;
63369             }
63370         }
63371
63372         dx = px - x;
63373         dy = py - y;
63374
63375         return dx * dx + dy * dy;
63376     }
63377
63378     var polylabel$1 = polylabel$2.exports;
63379
63380     function DEFAULT_COMPARE (a, b) { return a > b ? 1 : a < b ? -1 : 0; }
63381
63382     class SplayTree {
63383
63384       constructor(compare = DEFAULT_COMPARE, noDuplicates = false) {
63385         this._compare = compare;
63386         this._root = null;
63387         this._size = 0;
63388         this._noDuplicates = !!noDuplicates;
63389       }
63390
63391
63392       rotateLeft(x) {
63393         var y = x.right;
63394         if (y) {
63395           x.right = y.left;
63396           if (y.left) y.left.parent = x;
63397           y.parent = x.parent;
63398         }
63399
63400         if (!x.parent)                this._root = y;
63401         else if (x === x.parent.left) x.parent.left = y;
63402         else                          x.parent.right = y;
63403         if (y) y.left = x;
63404         x.parent = y;
63405       }
63406
63407
63408       rotateRight(x) {
63409         var y = x.left;
63410         if (y) {
63411           x.left = y.right;
63412           if (y.right) y.right.parent = x;
63413           y.parent = x.parent;
63414         }
63415
63416         if (!x.parent)               this._root = y;
63417         else if(x === x.parent.left) x.parent.left = y;
63418         else                         x.parent.right = y;
63419         if (y) y.right = x;
63420         x.parent = y;
63421       }
63422
63423
63424       _splay(x) {
63425         while (x.parent) {
63426           var p = x.parent;
63427           if (!p.parent) {
63428             if (p.left === x) this.rotateRight(p);
63429             else              this.rotateLeft(p);
63430           } else if (p.left === x && p.parent.left === p) {
63431             this.rotateRight(p.parent);
63432             this.rotateRight(p);
63433           } else if (p.right === x && p.parent.right === p) {
63434             this.rotateLeft(p.parent);
63435             this.rotateLeft(p);
63436           } else if (p.left === x && p.parent.right === p) {
63437             this.rotateRight(p);
63438             this.rotateLeft(p);
63439           } else {
63440             this.rotateLeft(p);
63441             this.rotateRight(p);
63442           }
63443         }
63444       }
63445
63446
63447       splay(x) {
63448         var p, gp, ggp, l, r;
63449
63450         while (x.parent) {
63451           p = x.parent;
63452           gp = p.parent;
63453
63454           if (gp && gp.parent) {
63455             ggp = gp.parent;
63456             if (ggp.left === gp) ggp.left  = x;
63457             else                 ggp.right = x;
63458             x.parent = ggp;
63459           } else {
63460             x.parent = null;
63461             this._root = x;
63462           }
63463
63464           l = x.left; r = x.right;
63465
63466           if (x === p.left) { // left
63467             if (gp) {
63468               if (gp.left === p) {
63469                 /* zig-zig */
63470                 if (p.right) {
63471                   gp.left = p.right;
63472                   gp.left.parent = gp;
63473                 } else gp.left = null;
63474
63475                 p.right   = gp;
63476                 gp.parent = p;
63477               } else {
63478                 /* zig-zag */
63479                 if (l) {
63480                   gp.right = l;
63481                   l.parent = gp;
63482                 } else gp.right = null;
63483
63484                 x.left    = gp;
63485                 gp.parent = x;
63486               }
63487             }
63488             if (r) {
63489               p.left = r;
63490               r.parent = p;
63491             } else p.left = null;
63492
63493             x.right  = p;
63494             p.parent = x;
63495           } else { // right
63496             if (gp) {
63497               if (gp.right === p) {
63498                 /* zig-zig */
63499                 if (p.left) {
63500                   gp.right = p.left;
63501                   gp.right.parent = gp;
63502                 } else gp.right = null;
63503
63504                 p.left = gp;
63505                 gp.parent = p;
63506               } else {
63507                 /* zig-zag */
63508                 if (r) {
63509                   gp.left = r;
63510                   r.parent = gp;
63511                 } else gp.left = null;
63512
63513                 x.right   = gp;
63514                 gp.parent = x;
63515               }
63516             }
63517             if (l) {
63518               p.right = l;
63519               l.parent = p;
63520             } else p.right = null;
63521
63522             x.left   = p;
63523             p.parent = x;
63524           }
63525         }
63526       }
63527
63528
63529       replace(u, v) {
63530         if (!u.parent) this._root = v;
63531         else if (u === u.parent.left) u.parent.left = v;
63532         else u.parent.right = v;
63533         if (v) v.parent = u.parent;
63534       }
63535
63536
63537       minNode(u = this._root) {
63538         if (u) while (u.left) u = u.left;
63539         return u;
63540       }
63541
63542
63543       maxNode(u = this._root) {
63544         if (u) while (u.right) u = u.right;
63545         return u;
63546       }
63547
63548
63549       insert(key, data) {
63550         var z = this._root;
63551         var p = null;
63552         var comp = this._compare;
63553         var cmp;
63554
63555         if (this._noDuplicates) {
63556           while (z) {
63557             p = z;
63558             cmp = comp(z.key, key);
63559             if (cmp === 0) return;
63560             else if (comp(z.key, key) < 0) z = z.right;
63561             else z = z.left;
63562           }
63563         } else {
63564           while (z) {
63565             p = z;
63566             if (comp(z.key, key) < 0) z = z.right;
63567             else z = z.left;
63568           }
63569         }
63570
63571         z = { key, data, left: null, right: null, parent: p };
63572
63573         if (!p)                          this._root = z;
63574         else if (comp(p.key, z.key) < 0) p.right = z;
63575         else                             p.left  = z;
63576
63577         this.splay(z);
63578         this._size++;
63579         return z;
63580       }
63581
63582
63583       find (key) {
63584         var z    = this._root;
63585         var comp = this._compare;
63586         while (z) {
63587           var cmp = comp(z.key, key);
63588           if      (cmp < 0) z = z.right;
63589           else if (cmp > 0) z = z.left;
63590           else              return z;
63591         }
63592         return null;
63593       }
63594
63595       /**
63596        * Whether the tree contains a node with the given key
63597        * @param  {Key} key
63598        * @return {boolean} true/false
63599        */
63600       contains (key) {
63601         var node       = this._root;
63602         var comparator = this._compare;
63603         while (node)  {
63604           var cmp = comparator(key, node.key);
63605           if      (cmp === 0) return true;
63606           else if (cmp < 0)   node = node.left;
63607           else                node = node.right;
63608         }
63609
63610         return false;
63611       }
63612
63613
63614       remove (key) {
63615         var z = this.find(key);
63616
63617         if (!z) return false;
63618
63619         this.splay(z);
63620
63621         if (!z.left) this.replace(z, z.right);
63622         else if (!z.right) this.replace(z, z.left);
63623         else {
63624           var y = this.minNode(z.right);
63625           if (y.parent !== z) {
63626             this.replace(y, y.right);
63627             y.right = z.right;
63628             y.right.parent = y;
63629           }
63630           this.replace(z, y);
63631           y.left = z.left;
63632           y.left.parent = y;
63633         }
63634
63635         this._size--;
63636         return true;
63637       }
63638
63639
63640       removeNode(z) {
63641         if (!z) return false;
63642
63643         this.splay(z);
63644
63645         if (!z.left) this.replace(z, z.right);
63646         else if (!z.right) this.replace(z, z.left);
63647         else {
63648           var y = this.minNode(z.right);
63649           if (y.parent !== z) {
63650             this.replace(y, y.right);
63651             y.right = z.right;
63652             y.right.parent = y;
63653           }
63654           this.replace(z, y);
63655           y.left = z.left;
63656           y.left.parent = y;
63657         }
63658
63659         this._size--;
63660         return true;
63661       }
63662
63663
63664       erase (key) {
63665         var z = this.find(key);
63666         if (!z) return;
63667
63668         this.splay(z);
63669
63670         var s = z.left;
63671         var t = z.right;
63672
63673         var sMax = null;
63674         if (s) {
63675           s.parent = null;
63676           sMax = this.maxNode(s);
63677           this.splay(sMax);
63678           this._root = sMax;
63679         }
63680         if (t) {
63681           if (s) sMax.right = t;
63682           else   this._root = t;
63683           t.parent = sMax;
63684         }
63685
63686         this._size--;
63687       }
63688
63689       /**
63690        * Removes and returns the node with smallest key
63691        * @return {?Node}
63692        */
63693       pop () {
63694         var node = this._root, returnValue = null;
63695         if (node) {
63696           while (node.left) node = node.left;
63697           returnValue = { key: node.key, data: node.data };
63698           this.remove(node.key);
63699         }
63700         return returnValue;
63701       }
63702
63703
63704       /* eslint-disable class-methods-use-this */
63705
63706       /**
63707        * Successor node
63708        * @param  {Node} node
63709        * @return {?Node}
63710        */
63711       next (node) {
63712         var successor = node;
63713         if (successor) {
63714           if (successor.right) {
63715             successor = successor.right;
63716             while (successor && successor.left) successor = successor.left;
63717           } else {
63718             successor = node.parent;
63719             while (successor && successor.right === node) {
63720               node = successor; successor = successor.parent;
63721             }
63722           }
63723         }
63724         return successor;
63725       }
63726
63727
63728       /**
63729        * Predecessor node
63730        * @param  {Node} node
63731        * @return {?Node}
63732        */
63733       prev (node) {
63734         var predecessor = node;
63735         if (predecessor) {
63736           if (predecessor.left) {
63737             predecessor = predecessor.left;
63738             while (predecessor && predecessor.right) predecessor = predecessor.right;
63739           } else {
63740             predecessor = node.parent;
63741             while (predecessor && predecessor.left === node) {
63742               node = predecessor;
63743               predecessor = predecessor.parent;
63744             }
63745           }
63746         }
63747         return predecessor;
63748       }
63749       /* eslint-enable class-methods-use-this */
63750
63751
63752       /**
63753        * @param  {forEachCallback} callback
63754        * @return {SplayTree}
63755        */
63756       forEach(callback) {
63757         var current = this._root;
63758         var s = [], done = false, i = 0;
63759
63760         while (!done) {
63761           // Reach the left most Node of the current Node
63762           if (current) {
63763             // Place pointer to a tree node on the stack
63764             // before traversing the node's left subtree
63765             s.push(current);
63766             current = current.left;
63767           } else {
63768             // BackTrack from the empty subtree and visit the Node
63769             // at the top of the stack; however, if the stack is
63770             // empty you are done
63771             if (s.length > 0) {
63772               current = s.pop();
63773               callback(current, i++);
63774
63775               // We have visited the node and its left
63776               // subtree. Now, it's right subtree's turn
63777               current = current.right;
63778             } else done = true;
63779           }
63780         }
63781         return this;
63782       }
63783
63784
63785       /**
63786        * Walk key range from `low` to `high`. Stops if `fn` returns a value.
63787        * @param  {Key}      low
63788        * @param  {Key}      high
63789        * @param  {Function} fn
63790        * @param  {*?}       ctx
63791        * @return {SplayTree}
63792        */
63793       range(low, high, fn, ctx) {
63794         const Q = [];
63795         const compare = this._compare;
63796         let node = this._root, cmp;
63797
63798         while (Q.length !== 0 || node) {
63799           if (node) {
63800             Q.push(node);
63801             node = node.left;
63802           } else {
63803             node = Q.pop();
63804             cmp = compare(node.key, high);
63805             if (cmp > 0) {
63806               break;
63807             } else if (compare(node.key, low) >= 0) {
63808               if (fn.call(ctx, node)) return this; // stop if smth is returned
63809             }
63810             node = node.right;
63811           }
63812         }
63813         return this;
63814       }
63815
63816       /**
63817        * Returns all keys in order
63818        * @return {Array<Key>}
63819        */
63820       keys () {
63821         var current = this._root;
63822         var s = [], r = [], done = false;
63823
63824         while (!done) {
63825           if (current) {
63826             s.push(current);
63827             current = current.left;
63828           } else {
63829             if (s.length > 0) {
63830               current = s.pop();
63831               r.push(current.key);
63832               current = current.right;
63833             } else done = true;
63834           }
63835         }
63836         return r;
63837       }
63838
63839
63840       /**
63841        * Returns `data` fields of all nodes in order.
63842        * @return {Array<Value>}
63843        */
63844       values () {
63845         var current = this._root;
63846         var s = [], r = [], done = false;
63847
63848         while (!done) {
63849           if (current) {
63850             s.push(current);
63851             current = current.left;
63852           } else {
63853             if (s.length > 0) {
63854               current = s.pop();
63855               r.push(current.data);
63856               current = current.right;
63857             } else done = true;
63858           }
63859         }
63860         return r;
63861       }
63862
63863
63864       /**
63865        * Returns node at given index
63866        * @param  {number} index
63867        * @return {?Node}
63868        */
63869       at (index) {
63870         // removed after a consideration, more misleading than useful
63871         // index = index % this.size;
63872         // if (index < 0) index = this.size - index;
63873
63874         var current = this._root;
63875         var s = [], done = false, i = 0;
63876
63877         while (!done) {
63878           if (current) {
63879             s.push(current);
63880             current = current.left;
63881           } else {
63882             if (s.length > 0) {
63883               current = s.pop();
63884               if (i === index) return current;
63885               i++;
63886               current = current.right;
63887             } else done = true;
63888           }
63889         }
63890         return null;
63891       }
63892
63893       /**
63894        * Bulk-load items. Both array have to be same size
63895        * @param  {Array<Key>}    keys
63896        * @param  {Array<Value>}  [values]
63897        * @param  {Boolean}       [presort=false] Pre-sort keys and values, using
63898        *                                         tree's comparator. Sorting is done
63899        *                                         in-place
63900        * @return {AVLTree}
63901        */
63902       load(keys = [], values = [], presort = false) {
63903         if (this._size !== 0) throw new Error('bulk-load: tree is not empty');
63904         const size = keys.length;
63905         if (presort) sort(keys, values, 0, size - 1, this._compare);
63906         this._root = loadRecursive(null, keys, values, 0, size);
63907         this._size = size;
63908         return this;
63909       }
63910
63911
63912       min() {
63913         var node = this.minNode(this._root);
63914         if (node) return node.key;
63915         else      return null;
63916       }
63917
63918
63919       max() {
63920         var node = this.maxNode(this._root);
63921         if (node) return node.key;
63922         else      return null;
63923       }
63924
63925       isEmpty() { return this._root === null; }
63926       get size() { return this._size; }
63927
63928
63929       /**
63930        * Create a tree and load it with items
63931        * @param  {Array<Key>}          keys
63932        * @param  {Array<Value>?}        [values]
63933
63934        * @param  {Function?}            [comparator]
63935        * @param  {Boolean?}             [presort=false] Pre-sort keys and values, using
63936        *                                               tree's comparator. Sorting is done
63937        *                                               in-place
63938        * @param  {Boolean?}             [noDuplicates=false]   Allow duplicates
63939        * @return {SplayTree}
63940        */
63941       static createTree(keys, values, comparator, presort, noDuplicates) {
63942         return new SplayTree(comparator, noDuplicates).load(keys, values, presort);
63943       }
63944     }
63945
63946
63947     function loadRecursive (parent, keys, values, start, end) {
63948       const size = end - start;
63949       if (size > 0) {
63950         const middle = start + Math.floor(size / 2);
63951         const key    = keys[middle];
63952         const data   = values[middle];
63953         const node   = { key, data, parent };
63954         node.left    = loadRecursive(node, keys, values, start, middle);
63955         node.right   = loadRecursive(node, keys, values, middle + 1, end);
63956         return node;
63957       }
63958       return null;
63959     }
63960
63961
63962     function sort(keys, values, left, right, compare) {
63963       if (left >= right) return;
63964
63965       const pivot = keys[(left + right) >> 1];
63966       let i = left - 1;
63967       let j = right + 1;
63968
63969       while (true) {
63970         do i++; while (compare(keys[i], pivot) < 0);
63971         do j--; while (compare(keys[j], pivot) > 0);
63972         if (i >= j) break;
63973
63974         let tmp = keys[i];
63975         keys[i] = keys[j];
63976         keys[j] = tmp;
63977
63978         tmp = values[i];
63979         values[i] = values[j];
63980         values[j] = tmp;
63981       }
63982
63983       sort(keys, values,  left,     j, compare);
63984       sort(keys, values, j + 1, right, compare);
63985     }
63986
63987     const NORMAL               = 0;
63988     const NON_CONTRIBUTING     = 1;
63989     const SAME_TRANSITION      = 2;
63990     const DIFFERENT_TRANSITION = 3;
63991
63992     const INTERSECTION = 0;
63993     const UNION        = 1;
63994     const DIFFERENCE   = 2;
63995     const XOR          = 3;
63996
63997     /**
63998      * @param  {SweepEvent} event
63999      * @param  {SweepEvent} prev
64000      * @param  {Operation} operation
64001      */
64002     function computeFields (event, prev, operation) {
64003       // compute inOut and otherInOut fields
64004       if (prev === null) {
64005         event.inOut      = false;
64006         event.otherInOut = true;
64007
64008       // previous line segment in sweepline belongs to the same polygon
64009       } else {
64010         if (event.isSubject === prev.isSubject) {
64011           event.inOut      = !prev.inOut;
64012           event.otherInOut = prev.otherInOut;
64013
64014         // previous line segment in sweepline belongs to the clipping polygon
64015         } else {
64016           event.inOut      = !prev.otherInOut;
64017           event.otherInOut = prev.isVertical() ? !prev.inOut : prev.inOut;
64018         }
64019
64020         // compute prevInResult field
64021         if (prev) {
64022           event.prevInResult = (!inResult(prev, operation) || prev.isVertical())
64023             ? prev.prevInResult : prev;
64024         }
64025       }
64026
64027       // check if the line segment belongs to the Boolean operation
64028       let isInResult = inResult(event, operation);
64029       if (isInResult) {
64030         event.resultTransition = determineResultTransition(event, operation);
64031       } else {
64032         event.resultTransition = 0;
64033       }
64034     }
64035
64036
64037     /* eslint-disable indent */
64038     function inResult(event, operation) {
64039       switch (event.type) {
64040         case NORMAL:
64041           switch (operation) {
64042             case INTERSECTION:
64043               return !event.otherInOut;
64044             case UNION:
64045               return event.otherInOut;
64046             case DIFFERENCE:
64047               // return (event.isSubject && !event.otherInOut) ||
64048               //         (!event.isSubject && event.otherInOut);
64049               return (event.isSubject && event.otherInOut) ||
64050                       (!event.isSubject && !event.otherInOut);
64051             case XOR:
64052               return true;
64053           }
64054           break;
64055         case SAME_TRANSITION:
64056           return operation === INTERSECTION || operation === UNION;
64057         case DIFFERENT_TRANSITION:
64058           return operation === DIFFERENCE;
64059         case NON_CONTRIBUTING:
64060           return false;
64061       }
64062       return false;
64063     }
64064     /* eslint-enable indent */
64065
64066
64067     function determineResultTransition(event, operation) {
64068       let thisIn = !event.inOut;
64069       let thatIn = !event.otherInOut;
64070
64071       let isIn;
64072       switch (operation) {
64073         case INTERSECTION:
64074           isIn = thisIn && thatIn; break;
64075         case UNION:
64076           isIn = thisIn || thatIn; break;
64077         case XOR:
64078           isIn = thisIn ^ thatIn; break;
64079         case DIFFERENCE:
64080           if (event.isSubject) {
64081             isIn = thisIn && !thatIn;
64082           } else {
64083             isIn = thatIn && !thisIn;
64084           }
64085           break;
64086       }
64087       return isIn ? +1 : -1;
64088     }
64089
64090     class SweepEvent {
64091
64092
64093       /**
64094        * Sweepline event
64095        *
64096        * @class {SweepEvent}
64097        * @param {Array.<Number>}  point
64098        * @param {Boolean}         left
64099        * @param {SweepEvent=}     otherEvent
64100        * @param {Boolean}         isSubject
64101        * @param {Number}          edgeType
64102        */
64103       constructor (point, left, otherEvent, isSubject, edgeType) {
64104
64105         /**
64106          * Is left endpoint?
64107          * @type {Boolean}
64108          */
64109         this.left = left;
64110
64111         /**
64112          * @type {Array.<Number>}
64113          */
64114         this.point = point;
64115
64116         /**
64117          * Other edge reference
64118          * @type {SweepEvent}
64119          */
64120         this.otherEvent = otherEvent;
64121
64122         /**
64123          * Belongs to source or clipping polygon
64124          * @type {Boolean}
64125          */
64126         this.isSubject = isSubject;
64127
64128         /**
64129          * Edge contribution type
64130          * @type {Number}
64131          */
64132         this.type = edgeType || NORMAL;
64133
64134
64135         /**
64136          * In-out transition for the sweepline crossing polygon
64137          * @type {Boolean}
64138          */
64139         this.inOut = false;
64140
64141
64142         /**
64143          * @type {Boolean}
64144          */
64145         this.otherInOut = false;
64146
64147         /**
64148          * Previous event in result?
64149          * @type {SweepEvent}
64150          */
64151         this.prevInResult = null;
64152
64153         /**
64154          * Type of result transition (0 = not in result, +1 = out-in, -1, in-out)
64155          * @type {Number}
64156          */
64157         this.resultTransition = 0;
64158
64159         // connection step
64160
64161         /**
64162          * @type {Number}
64163          */
64164         this.otherPos = -1;
64165
64166         /**
64167          * @type {Number}
64168          */
64169         this.outputContourId = -1;
64170
64171         this.isExteriorRing = true;   // TODO: Looks unused, remove?
64172       }
64173
64174
64175       /**
64176        * @param  {Array.<Number>}  p
64177        * @return {Boolean}
64178        */
64179       isBelow (p) {
64180         const p0 = this.point, p1 = this.otherEvent.point;
64181         return this.left
64182           ? (p0[0] - p[0]) * (p1[1] - p[1]) - (p1[0] - p[0]) * (p0[1] - p[1]) > 0
64183           // signedArea(this.point, this.otherEvent.point, p) > 0 :
64184           : (p1[0] - p[0]) * (p0[1] - p[1]) - (p0[0] - p[0]) * (p1[1] - p[1]) > 0;
64185           //signedArea(this.otherEvent.point, this.point, p) > 0;
64186       }
64187
64188
64189       /**
64190        * @param  {Array.<Number>}  p
64191        * @return {Boolean}
64192        */
64193       isAbove (p) {
64194         return !this.isBelow(p);
64195       }
64196
64197
64198       /**
64199        * @return {Boolean}
64200        */
64201       isVertical () {
64202         return this.point[0] === this.otherEvent.point[0];
64203       }
64204
64205
64206       /**
64207        * Does event belong to result?
64208        * @return {Boolean}
64209        */
64210       get inResult() {
64211         return this.resultTransition !== 0;
64212       }
64213
64214
64215       clone () {
64216         const copy = new SweepEvent(
64217           this.point, this.left, this.otherEvent, this.isSubject, this.type);
64218
64219         copy.contourId        = this.contourId;
64220         copy.resultTransition = this.resultTransition;
64221         copy.prevInResult     = this.prevInResult;
64222         copy.isExteriorRing   = this.isExteriorRing;
64223         copy.inOut            = this.inOut;
64224         copy.otherInOut       = this.otherInOut;
64225
64226         return copy;
64227       }
64228     }
64229
64230     function equals(p1, p2) {
64231       if (p1[0] === p2[0]) {
64232         if (p1[1] === p2[1]) {
64233           return true;
64234         } else {
64235           return false;
64236         }
64237       }
64238       return false;
64239     }
64240
64241     // const EPSILON = 1e-9;
64242     // const abs = Math.abs;
64243     // TODO https://github.com/w8r/martinez/issues/6#issuecomment-262847164
64244     // Precision problem.
64245     //
64246     // module.exports = function equals(p1, p2) {
64247     //   return abs(p1[0] - p2[0]) <= EPSILON && abs(p1[1] - p2[1]) <= EPSILON;
64248     // };
64249
64250     const epsilon = 1.1102230246251565e-16;
64251     const splitter = 134217729;
64252     const resulterrbound = (3 + 8 * epsilon) * epsilon;
64253
64254     // fast_expansion_sum_zeroelim routine from oritinal code
64255     function sum(elen, e, flen, f, h) {
64256         let Q, Qnew, hh, bvirt;
64257         let enow = e[0];
64258         let fnow = f[0];
64259         let eindex = 0;
64260         let findex = 0;
64261         if ((fnow > enow) === (fnow > -enow)) {
64262             Q = enow;
64263             enow = e[++eindex];
64264         } else {
64265             Q = fnow;
64266             fnow = f[++findex];
64267         }
64268         let hindex = 0;
64269         if (eindex < elen && findex < flen) {
64270             if ((fnow > enow) === (fnow > -enow)) {
64271                 Qnew = enow + Q;
64272                 hh = Q - (Qnew - enow);
64273                 enow = e[++eindex];
64274             } else {
64275                 Qnew = fnow + Q;
64276                 hh = Q - (Qnew - fnow);
64277                 fnow = f[++findex];
64278             }
64279             Q = Qnew;
64280             if (hh !== 0) {
64281                 h[hindex++] = hh;
64282             }
64283             while (eindex < elen && findex < flen) {
64284                 if ((fnow > enow) === (fnow > -enow)) {
64285                     Qnew = Q + enow;
64286                     bvirt = Qnew - Q;
64287                     hh = Q - (Qnew - bvirt) + (enow - bvirt);
64288                     enow = e[++eindex];
64289                 } else {
64290                     Qnew = Q + fnow;
64291                     bvirt = Qnew - Q;
64292                     hh = Q - (Qnew - bvirt) + (fnow - bvirt);
64293                     fnow = f[++findex];
64294                 }
64295                 Q = Qnew;
64296                 if (hh !== 0) {
64297                     h[hindex++] = hh;
64298                 }
64299             }
64300         }
64301         while (eindex < elen) {
64302             Qnew = Q + enow;
64303             bvirt = Qnew - Q;
64304             hh = Q - (Qnew - bvirt) + (enow - bvirt);
64305             enow = e[++eindex];
64306             Q = Qnew;
64307             if (hh !== 0) {
64308                 h[hindex++] = hh;
64309             }
64310         }
64311         while (findex < flen) {
64312             Qnew = Q + fnow;
64313             bvirt = Qnew - Q;
64314             hh = Q - (Qnew - bvirt) + (fnow - bvirt);
64315             fnow = f[++findex];
64316             Q = Qnew;
64317             if (hh !== 0) {
64318                 h[hindex++] = hh;
64319             }
64320         }
64321         if (Q !== 0 || hindex === 0) {
64322             h[hindex++] = Q;
64323         }
64324         return hindex;
64325     }
64326
64327     function estimate(elen, e) {
64328         let Q = e[0];
64329         for (let i = 1; i < elen; i++) Q += e[i];
64330         return Q;
64331     }
64332
64333     function vec(n) {
64334         return new Float64Array(n);
64335     }
64336
64337     const ccwerrboundA = (3 + 16 * epsilon) * epsilon;
64338     const ccwerrboundB = (2 + 12 * epsilon) * epsilon;
64339     const ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;
64340
64341     const B = vec(4);
64342     const C1 = vec(8);
64343     const C2 = vec(12);
64344     const D = vec(16);
64345     const u = vec(4);
64346
64347     function orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {
64348         let acxtail, acytail, bcxtail, bcytail;
64349         let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;
64350
64351         const acx = ax - cx;
64352         const bcx = bx - cx;
64353         const acy = ay - cy;
64354         const bcy = by - cy;
64355
64356         s1 = acx * bcy;
64357         c = splitter * acx;
64358         ahi = c - (c - acx);
64359         alo = acx - ahi;
64360         c = splitter * bcy;
64361         bhi = c - (c - bcy);
64362         blo = bcy - bhi;
64363         s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
64364         t1 = acy * bcx;
64365         c = splitter * acy;
64366         ahi = c - (c - acy);
64367         alo = acy - ahi;
64368         c = splitter * bcx;
64369         bhi = c - (c - bcx);
64370         blo = bcx - bhi;
64371         t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
64372         _i = s0 - t0;
64373         bvirt = s0 - _i;
64374         B[0] = s0 - (_i + bvirt) + (bvirt - t0);
64375         _j = s1 + _i;
64376         bvirt = _j - s1;
64377         _0 = s1 - (_j - bvirt) + (_i - bvirt);
64378         _i = _0 - t1;
64379         bvirt = _0 - _i;
64380         B[1] = _0 - (_i + bvirt) + (bvirt - t1);
64381         u3 = _j + _i;
64382         bvirt = u3 - _j;
64383         B[2] = _j - (u3 - bvirt) + (_i - bvirt);
64384         B[3] = u3;
64385
64386         let det = estimate(4, B);
64387         let errbound = ccwerrboundB * detsum;
64388         if (det >= errbound || -det >= errbound) {
64389             return det;
64390         }
64391
64392         bvirt = ax - acx;
64393         acxtail = ax - (acx + bvirt) + (bvirt - cx);
64394         bvirt = bx - bcx;
64395         bcxtail = bx - (bcx + bvirt) + (bvirt - cx);
64396         bvirt = ay - acy;
64397         acytail = ay - (acy + bvirt) + (bvirt - cy);
64398         bvirt = by - bcy;
64399         bcytail = by - (bcy + bvirt) + (bvirt - cy);
64400
64401         if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {
64402             return det;
64403         }
64404
64405         errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);
64406         det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);
64407         if (det >= errbound || -det >= errbound) return det;
64408
64409         s1 = acxtail * bcy;
64410         c = splitter * acxtail;
64411         ahi = c - (c - acxtail);
64412         alo = acxtail - ahi;
64413         c = splitter * bcy;
64414         bhi = c - (c - bcy);
64415         blo = bcy - bhi;
64416         s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
64417         t1 = acytail * bcx;
64418         c = splitter * acytail;
64419         ahi = c - (c - acytail);
64420         alo = acytail - ahi;
64421         c = splitter * bcx;
64422         bhi = c - (c - bcx);
64423         blo = bcx - bhi;
64424         t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
64425         _i = s0 - t0;
64426         bvirt = s0 - _i;
64427         u[0] = s0 - (_i + bvirt) + (bvirt - t0);
64428         _j = s1 + _i;
64429         bvirt = _j - s1;
64430         _0 = s1 - (_j - bvirt) + (_i - bvirt);
64431         _i = _0 - t1;
64432         bvirt = _0 - _i;
64433         u[1] = _0 - (_i + bvirt) + (bvirt - t1);
64434         u3 = _j + _i;
64435         bvirt = u3 - _j;
64436         u[2] = _j - (u3 - bvirt) + (_i - bvirt);
64437         u[3] = u3;
64438         const C1len = sum(4, B, 4, u, C1);
64439
64440         s1 = acx * bcytail;
64441         c = splitter * acx;
64442         ahi = c - (c - acx);
64443         alo = acx - ahi;
64444         c = splitter * bcytail;
64445         bhi = c - (c - bcytail);
64446         blo = bcytail - bhi;
64447         s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
64448         t1 = acy * bcxtail;
64449         c = splitter * acy;
64450         ahi = c - (c - acy);
64451         alo = acy - ahi;
64452         c = splitter * bcxtail;
64453         bhi = c - (c - bcxtail);
64454         blo = bcxtail - bhi;
64455         t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
64456         _i = s0 - t0;
64457         bvirt = s0 - _i;
64458         u[0] = s0 - (_i + bvirt) + (bvirt - t0);
64459         _j = s1 + _i;
64460         bvirt = _j - s1;
64461         _0 = s1 - (_j - bvirt) + (_i - bvirt);
64462         _i = _0 - t1;
64463         bvirt = _0 - _i;
64464         u[1] = _0 - (_i + bvirt) + (bvirt - t1);
64465         u3 = _j + _i;
64466         bvirt = u3 - _j;
64467         u[2] = _j - (u3 - bvirt) + (_i - bvirt);
64468         u[3] = u3;
64469         const C2len = sum(C1len, C1, 4, u, C2);
64470
64471         s1 = acxtail * bcytail;
64472         c = splitter * acxtail;
64473         ahi = c - (c - acxtail);
64474         alo = acxtail - ahi;
64475         c = splitter * bcytail;
64476         bhi = c - (c - bcytail);
64477         blo = bcytail - bhi;
64478         s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
64479         t1 = acytail * bcxtail;
64480         c = splitter * acytail;
64481         ahi = c - (c - acytail);
64482         alo = acytail - ahi;
64483         c = splitter * bcxtail;
64484         bhi = c - (c - bcxtail);
64485         blo = bcxtail - bhi;
64486         t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
64487         _i = s0 - t0;
64488         bvirt = s0 - _i;
64489         u[0] = s0 - (_i + bvirt) + (bvirt - t0);
64490         _j = s1 + _i;
64491         bvirt = _j - s1;
64492         _0 = s1 - (_j - bvirt) + (_i - bvirt);
64493         _i = _0 - t1;
64494         bvirt = _0 - _i;
64495         u[1] = _0 - (_i + bvirt) + (bvirt - t1);
64496         u3 = _j + _i;
64497         bvirt = u3 - _j;
64498         u[2] = _j - (u3 - bvirt) + (_i - bvirt);
64499         u[3] = u3;
64500         const Dlen = sum(C2len, C2, 4, u, D);
64501
64502         return D[Dlen - 1];
64503     }
64504
64505     function orient2d(ax, ay, bx, by, cx, cy) {
64506         const detleft = (ay - cy) * (bx - cx);
64507         const detright = (ax - cx) * (by - cy);
64508         const det = detleft - detright;
64509
64510         if (detleft === 0 || detright === 0 || (detleft > 0) !== (detright > 0)) return det;
64511
64512         const detsum = Math.abs(detleft + detright);
64513         if (Math.abs(det) >= ccwerrboundA * detsum) return det;
64514
64515         return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);
64516     }
64517
64518     /**
64519      * Signed area of the triangle (p0, p1, p2)
64520      * @param  {Array.<Number>} p0
64521      * @param  {Array.<Number>} p1
64522      * @param  {Array.<Number>} p2
64523      * @return {Number}
64524      */
64525     function signedArea(p0, p1, p2) {
64526       const res = orient2d(p0[0], p0[1], p1[0], p1[1], p2[0], p2[1]);
64527       if (res > 0) return -1;
64528       if (res < 0) return 1;
64529       return 0;
64530     }
64531
64532     /**
64533      * @param  {SweepEvent} e1
64534      * @param  {SweepEvent} e2
64535      * @return {Number}
64536      */
64537     function compareEvents(e1, e2) {
64538       const p1 = e1.point;
64539       const p2 = e2.point;
64540
64541       // Different x-coordinate
64542       if (p1[0] > p2[0]) return 1;
64543       if (p1[0] < p2[0]) return -1;
64544
64545       // Different points, but same x-coordinate
64546       // Event with lower y-coordinate is processed first
64547       if (p1[1] !== p2[1]) return p1[1] > p2[1] ? 1 : -1;
64548
64549       return specialCases(e1, e2, p1);
64550     }
64551
64552
64553     /* eslint-disable no-unused-vars */
64554     function specialCases(e1, e2, p1, p2) {
64555       // Same coordinates, but one is a left endpoint and the other is
64556       // a right endpoint. The right endpoint is processed first
64557       if (e1.left !== e2.left)
64558         return e1.left ? 1 : -1;
64559
64560       // const p2 = e1.otherEvent.point, p3 = e2.otherEvent.point;
64561       // const sa = (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1])
64562       // Same coordinates, both events
64563       // are left endpoints or right endpoints.
64564       // not collinear
64565       if (signedArea(p1, e1.otherEvent.point, e2.otherEvent.point) !== 0) {
64566         // the event associate to the bottom segment is processed first
64567         return (!e1.isBelow(e2.otherEvent.point)) ? 1 : -1;
64568       }
64569
64570       return (!e1.isSubject && e2.isSubject) ? 1 : -1;
64571     }
64572     /* eslint-enable no-unused-vars */
64573
64574     /**
64575      * @param  {SweepEvent} se
64576      * @param  {Array.<Number>} p
64577      * @param  {Queue} queue
64578      * @return {Queue}
64579      */
64580     function divideSegment(se, p, queue)  {
64581       const r = new SweepEvent(p, false, se,            se.isSubject);
64582       const l = new SweepEvent(p, true,  se.otherEvent, se.isSubject);
64583
64584       /* eslint-disable no-console */
64585       if (equals(se.point, se.otherEvent.point)) {
64586         console.warn('what is that, a collapsed segment?', se);
64587       }
64588       /* eslint-enable no-console */
64589
64590       r.contourId = l.contourId = se.contourId;
64591
64592       // avoid a rounding error. The left event would be processed after the right event
64593       if (compareEvents(l, se.otherEvent) > 0) {
64594         se.otherEvent.left = true;
64595         l.left = false;
64596       }
64597
64598       // avoid a rounding error. The left event would be processed after the right event
64599       // if (compareEvents(se, r) > 0) {}
64600
64601       se.otherEvent.otherEvent = l;
64602       se.otherEvent = r;
64603
64604       queue.push(l);
64605       queue.push(r);
64606
64607       return queue;
64608     }
64609
64610     //const EPS = 1e-9;
64611
64612     /**
64613      * Finds the magnitude of the cross product of two vectors (if we pretend
64614      * they're in three dimensions)
64615      *
64616      * @param {Object} a First vector
64617      * @param {Object} b Second vector
64618      * @private
64619      * @returns {Number} The magnitude of the cross product
64620      */
64621     function crossProduct(a, b) {
64622       return (a[0] * b[1]) - (a[1] * b[0]);
64623     }
64624
64625     /**
64626      * Finds the dot product of two vectors.
64627      *
64628      * @param {Object} a First vector
64629      * @param {Object} b Second vector
64630      * @private
64631      * @returns {Number} The dot product
64632      */
64633     function dotProduct(a, b) {
64634       return (a[0] * b[0]) + (a[1] * b[1]);
64635     }
64636
64637     /**
64638      * Finds the intersection (if any) between two line segments a and b, given the
64639      * line segments' end points a1, a2 and b1, b2.
64640      *
64641      * This algorithm is based on Schneider and Eberly.
64642      * http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf
64643      * Page 244.
64644      *
64645      * @param {Array.<Number>} a1 point of first line
64646      * @param {Array.<Number>} a2 point of first line
64647      * @param {Array.<Number>} b1 point of second line
64648      * @param {Array.<Number>} b2 point of second line
64649      * @param {Boolean=}       noEndpointTouch whether to skip single touchpoints
64650      *                                         (meaning connected segments) as
64651      *                                         intersections
64652      * @returns {Array.<Array.<Number>>|Null} If the lines intersect, the point of
64653      * intersection. If they overlap, the two end points of the overlapping segment.
64654      * Otherwise, null.
64655      */
64656     function intersection$1 (a1, a2, b1, b2, noEndpointTouch) {
64657       // The algorithm expects our lines in the form P + sd, where P is a point,
64658       // s is on the interval [0, 1], and d is a vector.
64659       // We are passed two points. P can be the first point of each pair. The
64660       // vector, then, could be thought of as the distance (in x and y components)
64661       // from the first point to the second point.
64662       // So first, let's make our vectors:
64663       const va = [a2[0] - a1[0], a2[1] - a1[1]];
64664       const vb = [b2[0] - b1[0], b2[1] - b1[1]];
64665       // We also define a function to convert back to regular point form:
64666
64667       /* eslint-disable arrow-body-style */
64668
64669       function toPoint(p, s, d) {
64670         return [
64671           p[0] + s * d[0],
64672           p[1] + s * d[1]
64673         ];
64674       }
64675
64676       /* eslint-enable arrow-body-style */
64677
64678       // The rest is pretty much a straight port of the algorithm.
64679       const e = [b1[0] - a1[0], b1[1] - a1[1]];
64680       let kross    = crossProduct(va, vb);
64681       let sqrKross = kross * kross;
64682       const sqrLenA  = dotProduct(va, va);
64683       //const sqrLenB  = dotProduct(vb, vb);
64684
64685       // Check for line intersection. This works because of the properties of the
64686       // cross product -- specifically, two vectors are parallel if and only if the
64687       // cross product is the 0 vector. The full calculation involves relative error
64688       // to account for possible very small line segments. See Schneider & Eberly
64689       // for details.
64690       if (sqrKross > 0/* EPS * sqrLenB * sqLenA */) {
64691         // If they're not parallel, then (because these are line segments) they
64692         // still might not actually intersect. This code checks that the
64693         // intersection point of the lines is actually on both line segments.
64694         const s = crossProduct(e, vb) / kross;
64695         if (s < 0 || s > 1) {
64696           // not on line segment a
64697           return null;
64698         }
64699         const t = crossProduct(e, va) / kross;
64700         if (t < 0 || t > 1) {
64701           // not on line segment b
64702           return null;
64703         }
64704         if (s === 0 || s === 1) {
64705           // on an endpoint of line segment a
64706           return noEndpointTouch ? null : [toPoint(a1, s, va)];
64707         }
64708         if (t === 0 || t === 1) {
64709           // on an endpoint of line segment b
64710           return noEndpointTouch ? null : [toPoint(b1, t, vb)];
64711         }
64712         return [toPoint(a1, s, va)];
64713       }
64714
64715       // If we've reached this point, then the lines are either parallel or the
64716       // same, but the segments could overlap partially or fully, or not at all.
64717       // So we need to find the overlap, if any. To do that, we can use e, which is
64718       // the (vector) difference between the two initial points. If this is parallel
64719       // with the line itself, then the two lines are the same line, and there will
64720       // be overlap.
64721       //const sqrLenE = dotProduct(e, e);
64722       kross = crossProduct(e, va);
64723       sqrKross = kross * kross;
64724
64725       if (sqrKross > 0 /* EPS * sqLenB * sqLenE */) {
64726       // Lines are just parallel, not the same. No overlap.
64727         return null;
64728       }
64729
64730       const sa = dotProduct(va, e) / sqrLenA;
64731       const sb = sa + dotProduct(va, vb) / sqrLenA;
64732       const smin = Math.min(sa, sb);
64733       const smax = Math.max(sa, sb);
64734
64735       // this is, essentially, the FindIntersection acting on floats from
64736       // Schneider & Eberly, just inlined into this function.
64737       if (smin <= 1 && smax >= 0) {
64738
64739         // overlap on an end point
64740         if (smin === 1) {
64741           return noEndpointTouch ? null : [toPoint(a1, smin > 0 ? smin : 0, va)];
64742         }
64743
64744         if (smax === 0) {
64745           return noEndpointTouch ? null : [toPoint(a1, smax < 1 ? smax : 1, va)];
64746         }
64747
64748         if (noEndpointTouch && smin === 0 && smax === 1) return null;
64749
64750         // There's overlap on a segment -- two points of intersection. Return both.
64751         return [
64752           toPoint(a1, smin > 0 ? smin : 0, va),
64753           toPoint(a1, smax < 1 ? smax : 1, va)
64754         ];
64755       }
64756
64757       return null;
64758     }
64759
64760     /**
64761      * @param  {SweepEvent} se1
64762      * @param  {SweepEvent} se2
64763      * @param  {Queue}      queue
64764      * @return {Number}
64765      */
64766     function possibleIntersection (se1, se2, queue) {
64767       // that disallows self-intersecting polygons,
64768       // did cost us half a day, so I'll leave it
64769       // out of respect
64770       // if (se1.isSubject === se2.isSubject) return;
64771       const inter = intersection$1(
64772         se1.point, se1.otherEvent.point,
64773         se2.point, se2.otherEvent.point
64774       );
64775
64776       const nintersections = inter ? inter.length : 0;
64777       if (nintersections === 0) return 0; // no intersection
64778
64779       // the line segments intersect at an endpoint of both line segments
64780       if ((nintersections === 1) &&
64781           (equals(se1.point, se2.point) ||
64782            equals(se1.otherEvent.point, se2.otherEvent.point))) {
64783         return 0;
64784       }
64785
64786       if (nintersections === 2 && se1.isSubject === se2.isSubject) {
64787         // if(se1.contourId === se2.contourId){
64788         // console.warn('Edges of the same polygon overlap',
64789         //   se1.point, se1.otherEvent.point, se2.point, se2.otherEvent.point);
64790         // }
64791         //throw new Error('Edges of the same polygon overlap');
64792         return 0;
64793       }
64794
64795       // The line segments associated to se1 and se2 intersect
64796       if (nintersections === 1) {
64797
64798         // if the intersection point is not an endpoint of se1
64799         if (!equals(se1.point, inter[0]) && !equals(se1.otherEvent.point, inter[0])) {
64800           divideSegment(se1, inter[0], queue);
64801         }
64802
64803         // if the intersection point is not an endpoint of se2
64804         if (!equals(se2.point, inter[0]) && !equals(se2.otherEvent.point, inter[0])) {
64805           divideSegment(se2, inter[0], queue);
64806         }
64807         return 1;
64808       }
64809
64810       // The line segments associated to se1 and se2 overlap
64811       const events        = [];
64812       let leftCoincide  = false;
64813       let rightCoincide = false;
64814
64815       if (equals(se1.point, se2.point)) {
64816         leftCoincide = true; // linked
64817       } else if (compareEvents(se1, se2) === 1) {
64818         events.push(se2, se1);
64819       } else {
64820         events.push(se1, se2);
64821       }
64822
64823       if (equals(se1.otherEvent.point, se2.otherEvent.point)) {
64824         rightCoincide = true;
64825       } else if (compareEvents(se1.otherEvent, se2.otherEvent) === 1) {
64826         events.push(se2.otherEvent, se1.otherEvent);
64827       } else {
64828         events.push(se1.otherEvent, se2.otherEvent);
64829       }
64830
64831       if ((leftCoincide && rightCoincide) || leftCoincide) {
64832         // both line segments are equal or share the left endpoint
64833         se2.type = NON_CONTRIBUTING;
64834         se1.type = (se2.inOut === se1.inOut)
64835           ? SAME_TRANSITION : DIFFERENT_TRANSITION;
64836
64837         if (leftCoincide && !rightCoincide) {
64838           // honestly no idea, but changing events selection from [2, 1]
64839           // to [0, 1] fixes the overlapping self-intersecting polygons issue
64840           divideSegment(events[1].otherEvent, events[0].point, queue);
64841         }
64842         return 2;
64843       }
64844
64845       // the line segments share the right endpoint
64846       if (rightCoincide) {
64847         divideSegment(events[0], events[1].point, queue);
64848         return 3;
64849       }
64850
64851       // no line segment includes totally the other one
64852       if (events[0] !== events[3].otherEvent) {
64853         divideSegment(events[0], events[1].point, queue);
64854         divideSegment(events[1], events[2].point, queue);
64855         return 3;
64856       }
64857
64858       // one line segment includes the other one
64859       divideSegment(events[0], events[1].point, queue);
64860       divideSegment(events[3].otherEvent, events[2].point, queue);
64861
64862       return 3;
64863     }
64864
64865     /**
64866      * @param  {SweepEvent} le1
64867      * @param  {SweepEvent} le2
64868      * @return {Number}
64869      */
64870     function compareSegments(le1, le2) {
64871       if (le1 === le2) return 0;
64872
64873       // Segments are not collinear
64874       if (signedArea(le1.point, le1.otherEvent.point, le2.point) !== 0 ||
64875         signedArea(le1.point, le1.otherEvent.point, le2.otherEvent.point) !== 0) {
64876
64877         // If they share their left endpoint use the right endpoint to sort
64878         if (equals(le1.point, le2.point)) return le1.isBelow(le2.otherEvent.point) ? -1 : 1;
64879
64880         // Different left endpoint: use the left endpoint to sort
64881         if (le1.point[0] === le2.point[0]) return le1.point[1] < le2.point[1] ? -1 : 1;
64882
64883         // has the line segment associated to e1 been inserted
64884         // into S after the line segment associated to e2 ?
64885         if (compareEvents(le1, le2) === 1) return le2.isAbove(le1.point) ? -1 : 1;
64886
64887         // The line segment associated to e2 has been inserted
64888         // into S after the line segment associated to e1
64889         return le1.isBelow(le2.point) ? -1 : 1;
64890       }
64891
64892       if (le1.isSubject === le2.isSubject) { // same polygon
64893         let p1 = le1.point, p2 = le2.point;
64894         if (p1[0] === p2[0] && p1[1] === p2[1]/*equals(le1.point, le2.point)*/) {
64895           p1 = le1.otherEvent.point; p2 = le2.otherEvent.point;
64896           if (p1[0] === p2[0] && p1[1] === p2[1]) return 0;
64897           else return le1.contourId > le2.contourId ? 1 : -1;
64898         }
64899       } else { // Segments are collinear, but belong to separate polygons
64900         return le1.isSubject ? -1 : 1;
64901       }
64902
64903       return compareEvents(le1, le2) === 1 ? 1 : -1;
64904     }
64905
64906     function subdivide(eventQueue, subject, clipping, sbbox, cbbox, operation) {
64907       const sweepLine = new SplayTree(compareSegments);
64908       const sortedEvents = [];
64909
64910       const rightbound = Math.min(sbbox[2], cbbox[2]);
64911
64912       let prev, next, begin;
64913
64914       while (eventQueue.length !== 0) {
64915         let event = eventQueue.pop();
64916         sortedEvents.push(event);
64917
64918         // optimization by bboxes for intersection and difference goes here
64919         if ((operation === INTERSECTION && event.point[0] > rightbound) ||
64920             (operation === DIFFERENCE   && event.point[0] > sbbox[2])) {
64921           break;
64922         }
64923
64924         if (event.left) {
64925           next  = prev = sweepLine.insert(event);
64926           begin = sweepLine.minNode();
64927
64928           if (prev !== begin) prev = sweepLine.prev(prev);
64929           else                prev = null;
64930
64931           next = sweepLine.next(next);
64932
64933           const prevEvent = prev ? prev.key : null;
64934           let prevprevEvent;
64935           computeFields(event, prevEvent, operation);
64936           if (next) {
64937             if (possibleIntersection(event, next.key, eventQueue) === 2) {
64938               computeFields(event, prevEvent, operation);
64939               computeFields(event, next.key, operation);
64940             }
64941           }
64942
64943           if (prev) {
64944             if (possibleIntersection(prev.key, event, eventQueue) === 2) {
64945               let prevprev = prev;
64946               if (prevprev !== begin) prevprev = sweepLine.prev(prevprev);
64947               else                    prevprev = null;
64948
64949               prevprevEvent = prevprev ? prevprev.key : null;
64950               computeFields(prevEvent, prevprevEvent, operation);
64951               computeFields(event,     prevEvent,     operation);
64952             }
64953           }
64954         } else {
64955           event = event.otherEvent;
64956           next = prev = sweepLine.find(event);
64957
64958           if (prev && next) {
64959
64960             if (prev !== begin) prev = sweepLine.prev(prev);
64961             else                prev = null;
64962
64963             next = sweepLine.next(next);
64964             sweepLine.remove(event);
64965
64966             if (next && prev) {
64967               possibleIntersection(prev.key, next.key, eventQueue);
64968             }
64969           }
64970         }
64971       }
64972       return sortedEvents;
64973     }
64974
64975     class Contour {
64976
64977       /**
64978        * Contour
64979        *
64980        * @class {Contour}
64981        */
64982       constructor() {
64983         this.points = [];
64984         this.holeIds = [];
64985         this.holeOf = null;
64986         this.depth = null;
64987       }
64988
64989       isExterior() {
64990         return this.holeOf == null;
64991       }
64992
64993     }
64994
64995     /**
64996      * @param  {Array.<SweepEvent>} sortedEvents
64997      * @return {Array.<SweepEvent>}
64998      */
64999     function orderEvents(sortedEvents) {
65000       let event, i, len, tmp;
65001       const resultEvents = [];
65002       for (i = 0, len = sortedEvents.length; i < len; i++) {
65003         event = sortedEvents[i];
65004         if ((event.left && event.inResult) ||
65005           (!event.left && event.otherEvent.inResult)) {
65006           resultEvents.push(event);
65007         }
65008       }
65009       // Due to overlapping edges the resultEvents array can be not wholly sorted
65010       let sorted = false;
65011       while (!sorted) {
65012         sorted = true;
65013         for (i = 0, len = resultEvents.length; i < len; i++) {
65014           if ((i + 1) < len &&
65015             compareEvents(resultEvents[i], resultEvents[i + 1]) === 1) {
65016             tmp = resultEvents[i];
65017             resultEvents[i] = resultEvents[i + 1];
65018             resultEvents[i + 1] = tmp;
65019             sorted = false;
65020           }
65021         }
65022       }
65023
65024
65025       for (i = 0, len = resultEvents.length; i < len; i++) {
65026         event = resultEvents[i];
65027         event.otherPos = i;
65028       }
65029
65030       // imagine, the right event is found in the beginning of the queue,
65031       // when his left counterpart is not marked yet
65032       for (i = 0, len = resultEvents.length; i < len; i++) {
65033         event = resultEvents[i];
65034         if (!event.left) {
65035           tmp = event.otherPos;
65036           event.otherPos = event.otherEvent.otherPos;
65037           event.otherEvent.otherPos = tmp;
65038         }
65039       }
65040
65041       return resultEvents;
65042     }
65043
65044
65045     /**
65046      * @param  {Number} pos
65047      * @param  {Array.<SweepEvent>} resultEvents
65048      * @param  {Object>}    processed
65049      * @return {Number}
65050      */
65051     function nextPos(pos, resultEvents, processed, origPos) {
65052       let newPos = pos + 1,
65053           p = resultEvents[pos].point,
65054           p1;
65055       const length = resultEvents.length;
65056
65057       if (newPos < length)
65058         p1 = resultEvents[newPos].point;
65059
65060       while (newPos < length && p1[0] === p[0] && p1[1] === p[1]) {
65061         if (!processed[newPos]) {
65062           return newPos;
65063         } else   {
65064           newPos++;
65065         }
65066         p1 = resultEvents[newPos].point;
65067       }
65068
65069       newPos = pos - 1;
65070
65071       while (processed[newPos] && newPos > origPos) {
65072         newPos--;
65073       }
65074
65075       return newPos;
65076     }
65077
65078
65079     function initializeContourFromContext(event, contours, contourId) {
65080       const contour = new Contour();
65081       if (event.prevInResult != null) {
65082         const prevInResult = event.prevInResult;
65083         // Note that it is valid to query the "previous in result" for its output contour id,
65084         // because we must have already processed it (i.e., assigned an output contour id)
65085         // in an earlier iteration, otherwise it wouldn't be possible that it is "previous in
65086         // result".
65087         const lowerContourId = prevInResult.outputContourId;
65088         const lowerResultTransition = prevInResult.resultTransition;
65089         if (lowerResultTransition > 0) {
65090           // We are inside. Now we have to check if the thing below us is another hole or
65091           // an exterior contour.
65092           const lowerContour = contours[lowerContourId];
65093           if (lowerContour.holeOf != null) {
65094             // The lower contour is a hole => Connect the new contour as a hole to its parent,
65095             // and use same depth.
65096             const parentContourId = lowerContour.holeOf;
65097             contours[parentContourId].holeIds.push(contourId);
65098             contour.holeOf = parentContourId;
65099             contour.depth = contours[lowerContourId].depth;
65100           } else {
65101             // The lower contour is an exterior contour => Connect the new contour as a hole,
65102             // and increment depth.
65103             contours[lowerContourId].holeIds.push(contourId);
65104             contour.holeOf = lowerContourId;
65105             contour.depth = contours[lowerContourId].depth + 1;
65106           }
65107         } else {
65108           // We are outside => this contour is an exterior contour of same depth.
65109           contour.holeOf = null;
65110           contour.depth = contours[lowerContourId].depth;
65111         }
65112       } else {
65113         // There is no lower/previous contour => this contour is an exterior contour of depth 0.
65114         contour.holeOf = null;
65115         contour.depth = 0;
65116       }
65117       return contour;
65118     }
65119
65120     /**
65121      * @param  {Array.<SweepEvent>} sortedEvents
65122      * @return {Array.<*>} polygons
65123      */
65124     function connectEdges(sortedEvents) {
65125       let i, len;
65126       const resultEvents = orderEvents(sortedEvents);
65127
65128       // "false"-filled array
65129       const processed = {};
65130       const contours = [];
65131
65132       for (i = 0, len = resultEvents.length; i < len; i++) {
65133
65134         if (processed[i]) {
65135           continue;
65136         }
65137
65138         const contourId = contours.length;
65139         const contour = initializeContourFromContext(resultEvents[i], contours, contourId);
65140
65141         // Helper function that combines marking an event as processed with assigning its output contour ID
65142         const markAsProcessed = (pos) => {
65143           processed[pos] = true;
65144           resultEvents[pos].outputContourId = contourId;
65145         };
65146
65147         let pos = i;
65148         let origPos = i;
65149
65150         const initial = resultEvents[i].point;
65151         contour.points.push(initial);
65152
65153         /* eslint no-constant-condition: "off" */
65154         while (true) {
65155           markAsProcessed(pos);
65156
65157           pos = resultEvents[pos].otherPos;
65158
65159           markAsProcessed(pos);
65160           contour.points.push(resultEvents[pos].point);
65161
65162           pos = nextPos(pos, resultEvents, processed, origPos);
65163
65164           if (pos == origPos) {
65165             break;
65166           }
65167         }
65168
65169         contours.push(contour);
65170       }
65171
65172       return contours;
65173     }
65174
65175     var tinyqueue = {exports: {}};
65176
65177     tinyqueue.exports = TinyQueue;
65178     tinyqueue.exports.default = TinyQueue;
65179
65180     function TinyQueue(data, compare) {
65181         if (!(this instanceof TinyQueue)) return new TinyQueue(data, compare);
65182
65183         this.data = data || [];
65184         this.length = this.data.length;
65185         this.compare = compare || defaultCompare;
65186
65187         if (this.length > 0) {
65188             for (var i = (this.length >> 1) - 1; i >= 0; i--) this._down(i);
65189         }
65190     }
65191
65192     function defaultCompare(a, b) {
65193         return a < b ? -1 : a > b ? 1 : 0;
65194     }
65195
65196     TinyQueue.prototype = {
65197
65198         push: function (item) {
65199             this.data.push(item);
65200             this.length++;
65201             this._up(this.length - 1);
65202         },
65203
65204         pop: function () {
65205             if (this.length === 0) return undefined;
65206
65207             var top = this.data[0];
65208             this.length--;
65209
65210             if (this.length > 0) {
65211                 this.data[0] = this.data[this.length];
65212                 this._down(0);
65213             }
65214             this.data.pop();
65215
65216             return top;
65217         },
65218
65219         peek: function () {
65220             return this.data[0];
65221         },
65222
65223         _up: function (pos) {
65224             var data = this.data;
65225             var compare = this.compare;
65226             var item = data[pos];
65227
65228             while (pos > 0) {
65229                 var parent = (pos - 1) >> 1;
65230                 var current = data[parent];
65231                 if (compare(item, current) >= 0) break;
65232                 data[pos] = current;
65233                 pos = parent;
65234             }
65235
65236             data[pos] = item;
65237         },
65238
65239         _down: function (pos) {
65240             var data = this.data;
65241             var compare = this.compare;
65242             var halfLength = this.length >> 1;
65243             var item = data[pos];
65244
65245             while (pos < halfLength) {
65246                 var left = (pos << 1) + 1;
65247                 var right = left + 1;
65248                 var best = data[left];
65249
65250                 if (right < this.length && compare(data[right], best) < 0) {
65251                     left = right;
65252                     best = data[right];
65253                 }
65254                 if (compare(best, item) >= 0) break;
65255
65256                 data[pos] = best;
65257                 pos = left;
65258             }
65259
65260             data[pos] = item;
65261         }
65262     };
65263
65264     var Queue = tinyqueue.exports;
65265
65266     const max = Math.max;
65267     const min = Math.min;
65268
65269     let contourId = 0;
65270
65271
65272     function processPolygon(contourOrHole, isSubject, depth, Q, bbox, isExteriorRing) {
65273       let i, len, s1, s2, e1, e2;
65274       for (i = 0, len = contourOrHole.length - 1; i < len; i++) {
65275         s1 = contourOrHole[i];
65276         s2 = contourOrHole[i + 1];
65277         e1 = new SweepEvent(s1, false, undefined, isSubject);
65278         e2 = new SweepEvent(s2, false, e1,        isSubject);
65279         e1.otherEvent = e2;
65280
65281         if (s1[0] === s2[0] && s1[1] === s2[1]) {
65282           continue; // skip collapsed edges, or it breaks
65283         }
65284
65285         e1.contourId = e2.contourId = depth;
65286         if (!isExteriorRing) {
65287           e1.isExteriorRing = false;
65288           e2.isExteriorRing = false;
65289         }
65290         if (compareEvents(e1, e2) > 0) {
65291           e2.left = true;
65292         } else {
65293           e1.left = true;
65294         }
65295
65296         const x = s1[0], y = s1[1];
65297         bbox[0] = min(bbox[0], x);
65298         bbox[1] = min(bbox[1], y);
65299         bbox[2] = max(bbox[2], x);
65300         bbox[3] = max(bbox[3], y);
65301
65302         // Pushing it so the queue is sorted from left to right,
65303         // with object on the left having the highest priority.
65304         Q.push(e1);
65305         Q.push(e2);
65306       }
65307     }
65308
65309
65310     function fillQueue(subject, clipping, sbbox, cbbox, operation) {
65311       const eventQueue = new Queue(null, compareEvents);
65312       let polygonSet, isExteriorRing, i, ii, j, jj; //, k, kk;
65313
65314       for (i = 0, ii = subject.length; i < ii; i++) {
65315         polygonSet = subject[i];
65316         for (j = 0, jj = polygonSet.length; j < jj; j++) {
65317           isExteriorRing = j === 0;
65318           if (isExteriorRing) contourId++;
65319           processPolygon(polygonSet[j], true, contourId, eventQueue, sbbox, isExteriorRing);
65320         }
65321       }
65322
65323       for (i = 0, ii = clipping.length; i < ii; i++) {
65324         polygonSet = clipping[i];
65325         for (j = 0, jj = polygonSet.length; j < jj; j++) {
65326           isExteriorRing = j === 0;
65327           if (operation === DIFFERENCE) isExteriorRing = false;
65328           if (isExteriorRing) contourId++;
65329           processPolygon(polygonSet[j], false, contourId, eventQueue, cbbox, isExteriorRing);
65330         }
65331       }
65332
65333       return eventQueue;
65334     }
65335
65336     const EMPTY = [];
65337
65338
65339     function trivialOperation(subject, clipping, operation) {
65340       let result = null;
65341       if (subject.length * clipping.length === 0) {
65342         if        (operation === INTERSECTION) {
65343           result = EMPTY;
65344         } else if (operation === DIFFERENCE) {
65345           result = subject;
65346         } else if (operation === UNION ||
65347                    operation === XOR) {
65348           result = (subject.length === 0) ? clipping : subject;
65349         }
65350       }
65351       return result;
65352     }
65353
65354
65355     function compareBBoxes(subject, clipping, sbbox, cbbox, operation) {
65356       let result = null;
65357       if (sbbox[0] > cbbox[2] ||
65358           cbbox[0] > sbbox[2] ||
65359           sbbox[1] > cbbox[3] ||
65360           cbbox[1] > sbbox[3]) {
65361         if        (operation === INTERSECTION) {
65362           result = EMPTY;
65363         } else if (operation === DIFFERENCE) {
65364           result = subject;
65365         } else if (operation === UNION ||
65366                    operation === XOR) {
65367           result = subject.concat(clipping);
65368         }
65369       }
65370       return result;
65371     }
65372
65373
65374     function boolean(subject, clipping, operation) {
65375       if (typeof subject[0][0][0] === 'number') {
65376         subject = [subject];
65377       }
65378       if (typeof clipping[0][0][0] === 'number') {
65379         clipping = [clipping];
65380       }
65381       let trivial = trivialOperation(subject, clipping, operation);
65382       if (trivial) {
65383         return trivial === EMPTY ? null : trivial;
65384       }
65385       const sbbox = [Infinity, Infinity, -Infinity, -Infinity];
65386       const cbbox = [Infinity, Infinity, -Infinity, -Infinity];
65387
65388       // console.time('fill queue');
65389       const eventQueue = fillQueue(subject, clipping, sbbox, cbbox, operation);
65390       //console.timeEnd('fill queue');
65391
65392       trivial = compareBBoxes(subject, clipping, sbbox, cbbox, operation);
65393       if (trivial) {
65394         return trivial === EMPTY ? null : trivial;
65395       }
65396       // console.time('subdivide edges');
65397       const sortedEvents = subdivide(eventQueue, subject, clipping, sbbox, cbbox, operation);
65398       //console.timeEnd('subdivide edges');
65399
65400       // console.time('connect vertices');
65401       const contours = connectEdges(sortedEvents);
65402       //console.timeEnd('connect vertices');
65403
65404       // Convert contours to polygons
65405       const polygons = [];
65406       for (let i = 0; i < contours.length; i++) {
65407         let contour = contours[i];
65408         if (contour.isExterior()) {
65409           // The exterior ring goes first
65410           let rings = [contour.points];
65411           // Followed by holes if any
65412           for (let j = 0; j < contour.holeIds.length; j++) {
65413             let holeId = contour.holeIds[j];
65414             rings.push(contours[holeId].points);
65415           }
65416           polygons.push(rings);
65417         }
65418       }
65419
65420       return polygons;
65421     }
65422
65423     function intersection (subject, clipping) {
65424       return boolean(subject, clipping, INTERSECTION);
65425     }
65426
65427     /**
65428      * @class VertexGeometry
65429      * @abstract
65430      * @classdesc Represents a vertex geometry.
65431      */
65432     class VertexGeometry extends Geometry {
65433         /**
65434          * Create a vertex geometry.
65435          *
65436          * @constructor
65437          * @ignore
65438          */
65439         constructor() {
65440             super();
65441             this._subsampleThreshold = 0.005;
65442         }
65443         /**
65444          * Finds the polygon pole of inaccessibility, the most distant internal
65445          * point from the polygon outline.
65446          *
65447          * @param {Array<Array<number>>} points2d - 2d points of outline to triangulate.
65448          * @returns {Array<number>} Point of inaccessibility.
65449          * @ignore
65450          */
65451         _getPoleOfInaccessibility2d(points2d) {
65452             let pole2d = polylabel$1([points2d], 3e-2);
65453             return pole2d;
65454         }
65455         _project(points2d, transform) {
65456             const camera = this._createCamera(transform.upVector().toArray(), transform.unprojectSfM([0, 0], 0), transform.unprojectSfM([0, 0], 10));
65457             return this._deunproject(points2d, transform, camera);
65458         }
65459         _subsample(points2d, threshold = this._subsampleThreshold) {
65460             const subsampled = [];
65461             const length = points2d.length;
65462             for (let index = 0; index < length; index++) {
65463                 const p1 = points2d[index];
65464                 const p2 = points2d[(index + 1) % length];
65465                 subsampled.push(p1);
65466                 const dist = Math.sqrt(Math.pow((p2[0] - p1[0]), 2) + Math.pow((p2[1] - p1[1]), 2));
65467                 const subsamples = Math.floor(dist / threshold);
65468                 const coeff = 1 / (subsamples + 1);
65469                 for (let i = 1; i <= subsamples; i++) {
65470                     const alpha = i * coeff;
65471                     const subsample = [
65472                         (1 - alpha) * p1[0] + alpha * p2[0],
65473                         (1 - alpha) * p1[1] + alpha * p2[1],
65474                     ];
65475                     subsampled.push(subsample);
65476                 }
65477             }
65478             return subsampled;
65479         }
65480         /**
65481          * Triangulates a 2d polygon and returns the triangle
65482          * representation as a flattened array of 3d points.
65483          *
65484          * @param {Array<Array<number>>} points2d - 2d points of outline to triangulate.
65485          * @param {Array<Array<number>>} points3d - 3d points of outline corresponding to the 2d points.
65486          * @param {Array<Array<Array<number>>>} [holes2d] - 2d points of holes to triangulate.
65487          * @param {Array<Array<Array<number>>>} [holes3d] - 3d points of holes corresponding to the 2d points.
65488          * @returns {Array<number>} Flattened array of 3d points ordered based on the triangles.
65489          * @ignore
65490          */
65491         _triangulate(points2d, points3d, holes2d, holes3d) {
65492             let data = [points2d.slice(0, -1)];
65493             for (let hole2d of holes2d != null ? holes2d : []) {
65494                 data.push(hole2d.slice(0, -1));
65495             }
65496             let points = points3d.slice(0, -1);
65497             for (let hole3d of holes3d != null ? holes3d : []) {
65498                 points = points.concat(hole3d.slice(0, -1));
65499             }
65500             let flattened = earcut$1.flatten(data);
65501             let indices = earcut$1(flattened.vertices, flattened.holes, flattened.dimensions);
65502             let triangles = [];
65503             for (let i = 0; i < indices.length; ++i) {
65504                 let point = points[indices[i]];
65505                 triangles.push(point[0]);
65506                 triangles.push(point[1]);
65507                 triangles.push(point[2]);
65508             }
65509             return triangles;
65510         }
65511         _triangulateSpherical(points2d, holes2d, transform) {
65512             const triangles = [];
65513             const epsilon = 1e-9;
65514             const subareasX = 3;
65515             const subareasY = 3;
65516             for (let x = 0; x < subareasX; x++) {
65517                 for (let y = 0; y < subareasY; y++) {
65518                     const epsilonX0 = x === 0 ? -epsilon : epsilon;
65519                     const epsilonY0 = y === 0 ? -epsilon : epsilon;
65520                     const x0 = x / subareasX + epsilonX0;
65521                     const y0 = y / subareasY + epsilonY0;
65522                     const x1 = (x + 1) / subareasX + epsilon;
65523                     const y1 = (y + 1) / subareasY + epsilon;
65524                     const bbox2d = [
65525                         [x0, y0],
65526                         [x0, y1],
65527                         [x1, y1],
65528                         [x1, y0],
65529                         [x0, y0],
65530                     ];
65531                     const lookat2d = [
65532                         (2 * x + 1) / (2 * subareasX),
65533                         (2 * y + 1) / (2 * subareasY),
65534                     ];
65535                     triangles.push(...this._triangulateSubarea(points2d, holes2d, bbox2d, lookat2d, transform));
65536                 }
65537             }
65538             return triangles;
65539         }
65540         _unproject(points2d, transform, distance = 200) {
65541             return points2d
65542                 .map((point) => {
65543                 return transform.unprojectBasic(point, distance);
65544             });
65545         }
65546         _createCamera(upVector, position, lookAt) {
65547             const camera = new Camera$1();
65548             camera.up.copy(new Vector3().fromArray(upVector));
65549             camera.position.copy(new Vector3().fromArray(position));
65550             camera.lookAt(new Vector3().fromArray(lookAt));
65551             camera.updateMatrix();
65552             camera.updateMatrixWorld(true);
65553             return camera;
65554         }
65555         _deunproject(points2d, transform, camera) {
65556             return points2d
65557                 .map((point2d) => {
65558                 const pointWorld = transform.unprojectBasic(point2d, 10000);
65559                 const pointCamera = new Vector3(pointWorld[0], pointWorld[1], pointWorld[2])
65560                     .applyMatrix4(camera.matrixWorldInverse);
65561                 return [pointCamera.x / pointCamera.z, pointCamera.y / pointCamera.z];
65562             });
65563         }
65564         _triangulateSubarea(points2d, holes2d, bbox2d, lookat2d, transform) {
65565             const intersections = intersection([points2d, ...holes2d], [bbox2d]);
65566             if (!intersections) {
65567                 return [];
65568             }
65569             const triangles = [];
65570             const threshold = this._subsampleThreshold;
65571             const camera = this._createCamera(transform.upVector().toArray(), transform.unprojectSfM([0, 0], 0), transform.unprojectBasic(lookat2d, 10));
65572             for (const intersection of intersections) {
65573                 const subsampledPolygon2d = this._subsample(intersection[0], threshold);
65574                 const polygon2d = this._deunproject(subsampledPolygon2d, transform, camera);
65575                 const polygon3d = this._unproject(subsampledPolygon2d, transform);
65576                 const polygonHoles2d = [];
65577                 const polygonHoles3d = [];
65578                 for (let i = 1; i < intersection.length; i++) {
65579                     let subsampledHole2d = this._subsample(intersection[i], threshold);
65580                     const hole2d = this._deunproject(subsampledHole2d, transform, camera);
65581                     const hole3d = this._unproject(subsampledHole2d, transform);
65582                     polygonHoles2d.push(hole2d);
65583                     polygonHoles3d.push(hole3d);
65584                 }
65585                 triangles.push(...this._triangulate(polygon2d, polygon3d, polygonHoles2d, polygonHoles3d));
65586             }
65587             return triangles;
65588         }
65589     }
65590
65591     /**
65592      * @class RectGeometry
65593      *
65594      * @classdesc Represents a rectangle geometry in the 2D basic image coordinate system.
65595      *
65596      * @example
65597      * ```js
65598      * var basicRect = [0.5, 0.3, 0.7, 0.4];
65599      * var rectGeometry = new RectGeometry(basicRect);
65600      * ```
65601      */
65602     class RectGeometry extends VertexGeometry {
65603         /**
65604          * Create a rectangle geometry.
65605          *
65606          * @constructor
65607          * @param {Array<number>} rect - An array representing the top-left and bottom-right
65608          * corners of the rectangle in basic coordinates. Ordered according to [x0, y0, x1, y1].
65609          *
65610          * @throws {GeometryTagError} Rectangle coordinates must be valid basic coordinates.
65611          */
65612         constructor(rect) {
65613             super();
65614             if (rect.length !== 4) {
65615                 throw new GeometryTagError("Rectangle needs to have four values.");
65616             }
65617             if (rect[1] > rect[3]) {
65618                 throw new GeometryTagError("Basic Y coordinates values can not be inverted.");
65619             }
65620             for (let coord of rect) {
65621                 if (coord < 0 || coord > 1) {
65622                     throw new GeometryTagError("Basic coordinates must be on the interval [0, 1].");
65623                 }
65624             }
65625             this._anchorIndex = undefined;
65626             this._rect = rect.slice(0, 4);
65627             this._inverted = this._rect[0] > this._rect[2];
65628         }
65629         /**
65630          * Get anchor index property.
65631          *
65632          * @returns {number} Index representing the current anchor property if
65633          * achoring indexing has been initialized. If anchor indexing has not been
65634          * initialized or has been terminated undefined will be returned.
65635          * @ignore
65636          */
65637         get anchorIndex() {
65638             return this._anchorIndex;
65639         }
65640         /**
65641          * Get inverted property.
65642          *
65643          * @returns {boolean} Boolean determining whether the rect geometry is
65644          * inverted. For spherical the rect geometrye may be inverted.
65645          * @ignore
65646          */
65647         get inverted() {
65648             return this._inverted;
65649         }
65650         /**
65651          * Get rect property.
65652          *
65653          * @returns {Array<number>} Array representing the top-left and bottom-right
65654          * corners of the rectangle in basic coordinates.
65655          */
65656         get rect() {
65657             return this._rect;
65658         }
65659         /**
65660          * Initialize anchor indexing to enable setting opposite vertex.
65661          *
65662          * @param {number} [index] - The index of the vertex to use as anchor.
65663          *
65664          * @throws {GeometryTagError} If anchor indexing has already been initialized.
65665          * @throws {GeometryTagError} If index is not valid (0 to 3).
65666          * @ignore
65667          */
65668         initializeAnchorIndexing(index) {
65669             if (this._anchorIndex !== undefined) {
65670                 throw new GeometryTagError("Anchor indexing is already initialized.");
65671             }
65672             if (index < 0 || index > 3) {
65673                 throw new GeometryTagError(`Invalid anchor index: ${index}.`);
65674             }
65675             this._anchorIndex = index === undefined ? 0 : index;
65676         }
65677         /**
65678          * Terminate anchor indexing to disable setting pposite vertex.
65679          * @ignore
65680          */
65681         terminateAnchorIndexing() {
65682             this._anchorIndex = undefined;
65683         }
65684         /**
65685          * Set the value of the vertex opposite to the anchor in the polygon
65686          * representation of the rectangle.
65687          *
65688          * @description Setting the opposite vertex may change the anchor index.
65689          *
65690          * @param {Array<number>} opposite - The new value of the vertex opposite to the anchor.
65691          * @param {Transform} transform - The transform of the image related to the rectangle.
65692          *
65693          * @throws {GeometryTagError} When anchor indexing has not been initialized.
65694          * @ignore
65695          */
65696         setOppositeVertex2d(opposite, transform) {
65697             if (this._anchorIndex === undefined) {
65698                 throw new GeometryTagError("Anchor indexing needs to be initialized.");
65699             }
65700             const changed = [
65701                 Math.max(0, Math.min(1, opposite[0])),
65702                 Math.max(0, Math.min(1, opposite[1])),
65703             ];
65704             const original = this._rect.slice();
65705             const anchor = this._anchorIndex === 0 ? [original[0], original[3]] :
65706                 this._anchorIndex === 1 ? [original[0], original[1]] :
65707                     this._anchorIndex === 2 ? [original[2], original[1]] :
65708                         [original[2], original[3]];
65709             if (isSpherical(transform.cameraType)) {
65710                 const deltaX = this._anchorIndex < 2 ?
65711                     changed[0] - original[2] :
65712                     changed[0] - original[0];
65713                 if (!this._inverted && this._anchorIndex < 2 && changed[0] < 0.25 && original[2] > 0.75 && deltaX < -0.5) {
65714                     // right side passes boundary rightward
65715                     this._inverted = true;
65716                     this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
65717                 }
65718                 else if (!this._inverted && this._anchorIndex >= 2 && changed[0] < 0.25 && original[2] > 0.75 && deltaX < -0.5) {
65719                     // left side passes right side and boundary rightward
65720                     this._inverted = true;
65721                     this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
65722                 }
65723                 else if (this._inverted && this._anchorIndex >= 2 && changed[0] < 0.25 && original[0] > 0.75 && deltaX < -0.5) {
65724                     this._inverted = false;
65725                     if (anchor[0] > changed[0]) {
65726                         // left side passes boundary rightward
65727                         this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
65728                     }
65729                     else {
65730                         // left side passes right side and boundary rightward
65731                         this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
65732                     }
65733                 }
65734                 else if (!this._inverted && this._anchorIndex >= 2 && changed[0] > 0.75 && original[0] < 0.25 && deltaX > 0.5) {
65735                     // left side passes boundary leftward
65736                     this._inverted = true;
65737                     this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
65738                 }
65739                 else if (!this._inverted && this._anchorIndex < 2 && changed[0] > 0.75 && original[0] < 0.25 && deltaX > 0.5) {
65740                     // right side passes left side and boundary leftward
65741                     this._inverted = true;
65742                     this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
65743                 }
65744                 else if (this._inverted && this._anchorIndex < 2 && changed[0] > 0.75 && original[2] < 0.25 && deltaX > 0.5) {
65745                     this._inverted = false;
65746                     if (anchor[0] > changed[0]) {
65747                         // right side passes boundary leftward
65748                         this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
65749                     }
65750                     else {
65751                         // right side passes left side and boundary leftward
65752                         this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
65753                     }
65754                 }
65755                 else if (this._inverted && this._anchorIndex < 2 && changed[0] > original[0]) {
65756                     // inverted and right side passes left side completing a loop
65757                     this._inverted = false;
65758                     this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
65759                 }
65760                 else if (this._inverted && this._anchorIndex >= 2 && changed[0] < original[2]) {
65761                     // inverted and left side passes right side completing a loop
65762                     this._inverted = false;
65763                     this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
65764                 }
65765                 else if (this._inverted) {
65766                     // if still inverted only top and bottom can switch
65767                     if (this._anchorIndex < 2) {
65768                         this._anchorIndex = anchor[1] > changed[1] ? 0 : 1;
65769                     }
65770                     else {
65771                         this._anchorIndex = anchor[1] > changed[1] ? 3 : 2;
65772                     }
65773                 }
65774                 else {
65775                     // if still not inverted treat as non spherical
65776                     if (anchor[0] <= changed[0] && anchor[1] > changed[1]) {
65777                         this._anchorIndex = 0;
65778                     }
65779                     else if (anchor[0] <= changed[0] && anchor[1] <= changed[1]) {
65780                         this._anchorIndex = 1;
65781                     }
65782                     else if (anchor[0] > changed[0] && anchor[1] <= changed[1]) {
65783                         this._anchorIndex = 2;
65784                     }
65785                     else {
65786                         this._anchorIndex = 3;
65787                     }
65788                 }
65789                 const rect = [];
65790                 if (this._anchorIndex === 0) {
65791                     rect[0] = anchor[0];
65792                     rect[1] = changed[1];
65793                     rect[2] = changed[0];
65794                     rect[3] = anchor[1];
65795                 }
65796                 else if (this._anchorIndex === 1) {
65797                     rect[0] = anchor[0];
65798                     rect[1] = anchor[1];
65799                     rect[2] = changed[0];
65800                     rect[3] = changed[1];
65801                 }
65802                 else if (this._anchorIndex === 2) {
65803                     rect[0] = changed[0];
65804                     rect[1] = anchor[1];
65805                     rect[2] = anchor[0];
65806                     rect[3] = changed[1];
65807                 }
65808                 else {
65809                     rect[0] = changed[0];
65810                     rect[1] = changed[1];
65811                     rect[2] = anchor[0];
65812                     rect[3] = anchor[1];
65813                 }
65814                 if (!this._inverted && rect[0] > rect[2] ||
65815                     this._inverted && rect[0] < rect[2]) {
65816                     rect[0] = original[0];
65817                     rect[2] = original[2];
65818                 }
65819                 if (rect[1] > rect[3]) {
65820                     rect[1] = original[1];
65821                     rect[3] = original[3];
65822                 }
65823                 this._rect[0] = rect[0];
65824                 this._rect[1] = rect[1];
65825                 this._rect[2] = rect[2];
65826                 this._rect[3] = rect[3];
65827             }
65828             else {
65829                 if (anchor[0] <= changed[0] && anchor[1] > changed[1]) {
65830                     this._anchorIndex = 0;
65831                 }
65832                 else if (anchor[0] <= changed[0] && anchor[1] <= changed[1]) {
65833                     this._anchorIndex = 1;
65834                 }
65835                 else if (anchor[0] > changed[0] && anchor[1] <= changed[1]) {
65836                     this._anchorIndex = 2;
65837                 }
65838                 else {
65839                     this._anchorIndex = 3;
65840                 }
65841                 const rect = [];
65842                 if (this._anchorIndex === 0) {
65843                     rect[0] = anchor[0];
65844                     rect[1] = changed[1];
65845                     rect[2] = changed[0];
65846                     rect[3] = anchor[1];
65847                 }
65848                 else if (this._anchorIndex === 1) {
65849                     rect[0] = anchor[0];
65850                     rect[1] = anchor[1];
65851                     rect[2] = changed[0];
65852                     rect[3] = changed[1];
65853                 }
65854                 else if (this._anchorIndex === 2) {
65855                     rect[0] = changed[0];
65856                     rect[1] = anchor[1];
65857                     rect[2] = anchor[0];
65858                     rect[3] = changed[1];
65859                 }
65860                 else {
65861                     rect[0] = changed[0];
65862                     rect[1] = changed[1];
65863                     rect[2] = anchor[0];
65864                     rect[3] = anchor[1];
65865                 }
65866                 if (rect[0] > rect[2]) {
65867                     rect[0] = original[0];
65868                     rect[2] = original[2];
65869                 }
65870                 if (rect[1] > rect[3]) {
65871                     rect[1] = original[1];
65872                     rect[3] = original[3];
65873                 }
65874                 this._rect[0] = rect[0];
65875                 this._rect[1] = rect[1];
65876                 this._rect[2] = rect[2];
65877                 this._rect[3] = rect[3];
65878             }
65879             this._notifyChanged$.next(this);
65880         }
65881         /**
65882          * Set the value of a vertex in the polygon representation of the rectangle.
65883          *
65884          * @description The polygon is defined to have the first vertex at the
65885          * bottom-left corner with the rest of the vertices following in clockwise order.
65886          *
65887          * @param {number} index - The index of the vertex to be set.
65888          * @param {Array<number>} value - The new value of the vertex.
65889          * @param {Transform} transform - The transform of the image related to the rectangle.
65890          * @ignore
65891          */
65892         setVertex2d(index, value, transform) {
65893             let original = this._rect.slice();
65894             let changed = [
65895                 Math.max(0, Math.min(1, value[0])),
65896                 Math.max(0, Math.min(1, value[1])),
65897             ];
65898             let rect = [];
65899             if (index === 0) {
65900                 rect[0] = changed[0];
65901                 rect[1] = original[1];
65902                 rect[2] = original[2];
65903                 rect[3] = changed[1];
65904             }
65905             else if (index === 1) {
65906                 rect[0] = changed[0];
65907                 rect[1] = changed[1];
65908                 rect[2] = original[2];
65909                 rect[3] = original[3];
65910             }
65911             else if (index === 2) {
65912                 rect[0] = original[0];
65913                 rect[1] = changed[1];
65914                 rect[2] = changed[0];
65915                 rect[3] = original[3];
65916             }
65917             else if (index === 3) {
65918                 rect[0] = original[0];
65919                 rect[1] = original[1];
65920                 rect[2] = changed[0];
65921                 rect[3] = changed[1];
65922             }
65923             if (isSpherical(transform.cameraType)) {
65924                 let passingBoundaryLeftward = index < 2 && changed[0] > 0.75 && original[0] < 0.25 ||
65925                     index >= 2 && this._inverted && changed[0] > 0.75 && original[2] < 0.25;
65926                 let passingBoundaryRightward = index < 2 && this._inverted && changed[0] < 0.25 && original[0] > 0.75 ||
65927                     index >= 2 && changed[0] < 0.25 && original[2] > 0.75;
65928                 if (passingBoundaryLeftward || passingBoundaryRightward) {
65929                     this._inverted = !this._inverted;
65930                 }
65931                 else {
65932                     if (rect[0] - original[0] < -0.25) {
65933                         rect[0] = original[0];
65934                     }
65935                     if (rect[2] - original[2] > 0.25) {
65936                         rect[2] = original[2];
65937                     }
65938                 }
65939                 if (!this._inverted && rect[0] > rect[2] ||
65940                     this._inverted && rect[0] < rect[2]) {
65941                     rect[0] = original[0];
65942                     rect[2] = original[2];
65943                 }
65944             }
65945             else {
65946                 if (rect[0] > rect[2]) {
65947                     rect[0] = original[0];
65948                     rect[2] = original[2];
65949                 }
65950             }
65951             if (rect[1] > rect[3]) {
65952                 rect[1] = original[1];
65953                 rect[3] = original[3];
65954             }
65955             this._rect[0] = rect[0];
65956             this._rect[1] = rect[1];
65957             this._rect[2] = rect[2];
65958             this._rect[3] = rect[3];
65959             this._notifyChanged$.next(this);
65960         }
65961         /** @ignore */
65962         setCentroid2d(value, transform) {
65963             let original = this._rect.slice();
65964             let x0 = original[0];
65965             let x1 = this._inverted ? original[2] + 1 : original[2];
65966             let y0 = original[1];
65967             let y1 = original[3];
65968             let centerX = x0 + (x1 - x0) / 2;
65969             let centerY = y0 + (y1 - y0) / 2;
65970             let translationX = 0;
65971             if (isSpherical(transform.cameraType)) {
65972                 translationX = this._inverted ? value[0] + 1 - centerX : value[0] - centerX;
65973             }
65974             else {
65975                 let minTranslationX = -x0;
65976                 let maxTranslationX = 1 - x1;
65977                 translationX = Math.max(minTranslationX, Math.min(maxTranslationX, value[0] - centerX));
65978             }
65979             let minTranslationY = -y0;
65980             let maxTranslationY = 1 - y1;
65981             let translationY = Math.max(minTranslationY, Math.min(maxTranslationY, value[1] - centerY));
65982             this._rect[0] = original[0] + translationX;
65983             this._rect[1] = original[1] + translationY;
65984             this._rect[2] = original[2] + translationX;
65985             this._rect[3] = original[3] + translationY;
65986             if (this._rect[0] < 0) {
65987                 this._rect[0] += 1;
65988                 this._inverted = !this._inverted;
65989             }
65990             else if (this._rect[0] > 1) {
65991                 this._rect[0] -= 1;
65992                 this._inverted = !this._inverted;
65993             }
65994             if (this._rect[2] < 0) {
65995                 this._rect[2] += 1;
65996                 this._inverted = !this._inverted;
65997             }
65998             else if (this._rect[2] > 1) {
65999                 this._rect[2] -= 1;
66000                 this._inverted = !this._inverted;
66001             }
66002             this._notifyChanged$.next(this);
66003         }
66004         /**
66005          * Get the 3D coordinates for the vertices of the rectangle with
66006          * interpolated points along the lines.
66007          *
66008          * @param {Transform} transform - The transform of the image related to
66009          * the rectangle.
66010          * @returns {Array<Array<number>>} Polygon array of 3D world coordinates
66011          * representing the rectangle.
66012          * @ignore
66013          */
66014         getPoints3d(transform) {
66015             return this._getPoints2d()
66016                 .map((point) => {
66017                 return transform.unprojectBasic(point, 200);
66018             });
66019         }
66020         /**
66021          * Get the coordinates of a vertex from the polygon representation of the geometry.
66022          *
66023          * @description The first vertex represents the bottom-left corner with the rest of
66024          * the vertices following in clockwise order. The method shifts the right side
66025          * coordinates of the rectangle by one unit to ensure that the vertices are ordered
66026          * clockwise.
66027          *
66028          * @param {number} index - Vertex index.
66029          * @returns {Array<number>} Array representing the 2D basic coordinates of the vertex.
66030          * @ignore
66031          */
66032         getVertex2d(index) {
66033             return this._rectToVertices2d(this._rect)[index];
66034         }
66035         /**
66036          * Get the coordinates of a vertex from the polygon representation of the geometry.
66037          *
66038          * @description The first vertex represents the bottom-left corner with the rest of
66039          * the vertices following in clockwise order. The coordinates will not be shifted
66040          * so they may not appear in clockwise order when layed out on the plane.
66041          *
66042          * @param {number} index - Vertex index.
66043          * @returns {Array<number>} Array representing the 2D basic coordinates of the vertex.
66044          * @ignore
66045          */
66046         getNonAdjustedVertex2d(index) {
66047             return this._rectToNonAdjustedVertices2d(this._rect)[index];
66048         }
66049         /**
66050          * Get a vertex from the polygon representation of the 3D coordinates for the
66051          * vertices of the geometry.
66052          *
66053          * @description The first vertex represents the bottom-left corner with the rest of
66054          * the vertices following in clockwise order.
66055          *
66056          * @param {number} index - Vertex index.
66057          * @param {Transform} transform - The transform of the image related to the geometry.
66058          * @returns {Array<Array<number>>} Polygon array of 3D world coordinates representing
66059          * the vertices of the geometry.
66060          * @ignore
66061          */
66062         getVertex3d(index, transform) {
66063             return transform.unprojectBasic(this._rectToVertices2d(this._rect)[index], 200);
66064         }
66065         /**
66066          * Get a polygon representation of the 2D basic coordinates for the vertices of the rectangle.
66067          *
66068          * @description The first vertex represents the bottom-left corner with the rest of
66069          * the vertices following in clockwise order.
66070          *
66071          * @returns {Array<Array<number>>} Polygon array of 2D basic coordinates representing
66072          * the rectangle vertices.
66073          * @ignore
66074          */
66075         getVertices2d() {
66076             return this._rectToVertices2d(this._rect);
66077         }
66078         /**
66079          * Get a polygon representation of the 3D coordinates for the vertices of the rectangle.
66080          *
66081          * @description The first vertex represents the bottom-left corner with the rest of
66082          * the vertices following in clockwise order.
66083          *
66084          * @param {Transform} transform - The transform of the image related to the rectangle.
66085          * @returns {Array<Array<number>>} Polygon array of 3D world coordinates representing
66086          * the rectangle vertices.
66087          * @ignore
66088          */
66089         getVertices3d(transform) {
66090             return this._rectToVertices2d(this._rect)
66091                 .map((vertex) => {
66092                 return transform.unprojectBasic(vertex, 200);
66093             });
66094         }
66095         /** @ignore */
66096         getCentroid2d() {
66097             const rect = this._rect;
66098             const x0 = rect[0];
66099             const x1 = this._inverted ? rect[2] + 1 : rect[2];
66100             const y0 = rect[1];
66101             const y1 = rect[3];
66102             const centroidX = (x0 + x1) / 2;
66103             const centroidY = (y0 + y1) / 2;
66104             return [centroidX, centroidY];
66105         }
66106         /** @ignore */
66107         getCentroid3d(transform) {
66108             const centroid2d = this.getCentroid2d();
66109             return transform.unprojectBasic(centroid2d, 200);
66110         }
66111         /**
66112          * @ignore
66113          */
66114         getPoleOfInaccessibility2d() {
66115             return this._getPoleOfInaccessibility2d(this._rectToVertices2d(this._rect));
66116         }
66117         /** @ignore */
66118         getPoleOfInaccessibility3d(transform) {
66119             let pole2d = this._getPoleOfInaccessibility2d(this._rectToVertices2d(this._rect));
66120             return transform.unprojectBasic(pole2d, 200);
66121         }
66122         /** @ignore */
66123         getTriangles3d(transform) {
66124             return isSpherical(transform.cameraType) ?
66125                 [] :
66126                 this._triangulate(this._project(this._getPoints2d(), transform), this.getPoints3d(transform));
66127         }
66128         /**
66129          * Check if a particular bottom-right value is valid according to the current
66130          * rectangle coordinates.
66131          *
66132          * @param {Array<number>} bottomRight - The bottom-right coordinates to validate
66133          * @returns {boolean} Value indicating whether the provided bottom-right coordinates
66134          * are valid.
66135          * @ignore
66136          */
66137         validate(bottomRight) {
66138             let rect = this._rect;
66139             if (!this._inverted && bottomRight[0] < rect[0] ||
66140                 bottomRight[0] - rect[2] > 0.25 ||
66141                 bottomRight[1] < rect[1]) {
66142                 return false;
66143             }
66144             return true;
66145         }
66146         /**
66147          * Get the 2D coordinates for the vertices of the rectangle with
66148          * interpolated points along the lines.
66149          *
66150          * @returns {Array<Array<number>>} Polygon array of 2D basic coordinates
66151          * representing the rectangle.
66152          */
66153         _getPoints2d() {
66154             let vertices2d = this._rectToVertices2d(this._rect);
66155             let sides = vertices2d.length - 1;
66156             let sections = 10;
66157             let points2d = [];
66158             for (let i = 0; i < sides; ++i) {
66159                 let startX = vertices2d[i][0];
66160                 let startY = vertices2d[i][1];
66161                 let endX = vertices2d[i + 1][0];
66162                 let endY = vertices2d[i + 1][1];
66163                 let intervalX = (endX - startX) / (sections - 1);
66164                 let intervalY = (endY - startY) / (sections - 1);
66165                 for (let j = 0; j < sections; ++j) {
66166                     let point = [
66167                         startX + j * intervalX,
66168                         startY + j * intervalY,
66169                     ];
66170                     points2d.push(point);
66171                 }
66172             }
66173             return points2d;
66174         }
66175         /**
66176          * Convert the top-left, bottom-right representation of a rectangle to a polygon
66177          * representation of the vertices starting at the bottom-left corner going
66178          * clockwise.
66179          *
66180          * @description The method shifts the right side coordinates of the rectangle
66181          * by one unit to ensure that the vertices are ordered clockwise.
66182          *
66183          * @param {Array<number>} rect - Top-left, bottom-right representation of a
66184          * rectangle.
66185          * @returns {Array<Array<number>>} Polygon representation of the vertices of the
66186          * rectangle.
66187          */
66188         _rectToVertices2d(rect) {
66189             return [
66190                 [rect[0], rect[3]],
66191                 [rect[0], rect[1]],
66192                 [this._inverted ? rect[2] + 1 : rect[2], rect[1]],
66193                 [this._inverted ? rect[2] + 1 : rect[2], rect[3]],
66194                 [rect[0], rect[3]],
66195             ];
66196         }
66197         /**
66198          * Convert the top-left, bottom-right representation of a rectangle to a polygon
66199          * representation of the vertices starting at the bottom-left corner going
66200          * clockwise.
66201          *
66202          * @description The first vertex represents the bottom-left corner with the rest of
66203          * the vertices following in clockwise order. The coordinates will not be shifted
66204          * to ensure that the vertices are ordered clockwise when layed out on the plane.
66205          *
66206          * @param {Array<number>} rect - Top-left, bottom-right representation of a
66207          * rectangle.
66208          * @returns {Array<Array<number>>} Polygon representation of the vertices of the
66209          * rectangle.
66210          */
66211         _rectToNonAdjustedVertices2d(rect) {
66212             return [
66213                 [rect[0], rect[3]],
66214                 [rect[0], rect[1]],
66215                 [rect[2], rect[1]],
66216                 [rect[2], rect[3]],
66217                 [rect[0], rect[3]],
66218             ];
66219         }
66220     }
66221
66222     class ExtremePointCreateTag extends CreateTag {
66223         constructor(geometry, options, transform, viewportCoords) {
66224             super(geometry, transform, viewportCoords);
66225             this._options = {
66226                 color: options.color == null ? 0xFFFFFF : options.color,
66227                 indicateCompleter: options.indicateCompleter == null ? true : options.indicateCompleter,
66228             };
66229             this._rectGeometry = new RectGeometry(this._geometry.getRect2d(transform));
66230             this._createGlObjects();
66231         }
66232         create() {
66233             if (this._geometry.points.length < 3) {
66234                 return;
66235             }
66236             this._geometry.removePoint2d(this._geometry.points.length - 1);
66237             this._created$.next(this);
66238         }
66239         dispose() {
66240             super.dispose();
66241             this._disposeObjects();
66242         }
66243         getDOMObjects(camera, size) {
66244             const container = {
66245                 offsetHeight: size.height, offsetWidth: size.width,
66246             };
66247             const vNodes = [];
66248             const points2d = this._geometry.getPoints2d();
66249             const length = points2d.length;
66250             for (let index = 0; index < length - 1; index++) {
66251                 const nonModifiedIndex = index;
66252                 const [pointX, pointY] = points2d[index];
66253                 const pointCanvas = this._viewportCoords.basicToCanvasSafe(pointX, pointY, container, this._transform, camera);
66254                 if (!pointCanvas) {
66255                     continue;
66256                 }
66257                 const abort = (e) => {
66258                     e.stopPropagation();
66259                     this._aborted$.next(this);
66260                 };
66261                 const remove = (e) => {
66262                     e.stopPropagation();
66263                     this._geometry.removePoint2d(nonModifiedIndex);
66264                 };
66265                 const transform = this._canvasToTransform(pointCanvas);
66266                 const completerProperties = {
66267                     onclick: index === 0 && length < 3 ? abort : remove,
66268                     style: { transform: transform },
66269                 };
66270                 vNodes.push(virtualDom.h("div.mapillary-tag-interactor", completerProperties, []));
66271                 const background = this._colorToBackground(this._options.color);
66272                 const pointProperties = {
66273                     style: {
66274                         background: background,
66275                         transform: transform,
66276                     },
66277                 };
66278                 vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
66279             }
66280             if (length > 2 && this._options.indicateCompleter === true) {
66281                 const [centroidX, centroidY] = this._geometry.getCentroid2d(this._transform);
66282                 const centroidCanvas = this._viewportCoords.basicToCanvasSafe(centroidX, centroidY, container, this._transform, camera);
66283                 if (!!centroidCanvas) {
66284                     const complete = (e) => {
66285                         e.stopPropagation();
66286                         this._geometry.removePoint2d(this._geometry.points.length - 1);
66287                         this._created$.next(this);
66288                     };
66289                     const transform = this._canvasToTransform(centroidCanvas);
66290                     const completerProperties = {
66291                         onclick: complete,
66292                         style: { transform: transform },
66293                     };
66294                     vNodes.push(virtualDom.h("div.mapillary-tag-completer.mapillary-tag-larger", completerProperties, []));
66295                     const pointProperties = {
66296                         style: {
66297                             background: this._colorToBackground(this._options.color),
66298                             transform: transform,
66299                         },
66300                     };
66301                     vNodes.push(virtualDom.h("div.mapillary-tag-vertex.mapillary-tag-larger", pointProperties, []));
66302                     const dotProperties = {
66303                         style: {
66304                             transform: transform,
66305                         },
66306                     };
66307                     vNodes.push(virtualDom.h("div.mapillary-tag-dot", dotProperties, []));
66308                 }
66309             }
66310             return vNodes;
66311         }
66312         _onGeometryChanged() {
66313             this._disposeObjects();
66314             this._rectGeometry = new RectGeometry(this._geometry.getRect2d(this._transform));
66315             this._createGlObjects();
66316         }
66317         _createGlObjects() {
66318             this._glObjects = [];
66319             const polygon3d = this._rectGeometry.getPoints3d(this._transform);
66320             this._outline = this._createOutine(polygon3d, this._options.color);
66321             this._glObjects.push(this._outline);
66322         }
66323         _disposeObjects() {
66324             this._disposeLine(this._outline);
66325             this._outline = null;
66326             this._glObjects = null;
66327         }
66328     }
66329
66330     /**
66331      * @class PolygonGeometry
66332      *
66333      * @classdesc Represents a polygon geometry in the 2D basic image coordinate system.
66334      * All polygons and holes provided to the constructor needs to be closed.
66335      *
66336      * @example
66337      * ```js
66338      * var basicPolygon = [[0.5, 0.3], [0.7, 0.3], [0.6, 0.5], [0.5, 0.3]];
66339      * var polygonGeometry = new PolygonGeometry(basicPolygon);
66340      * ```
66341      */
66342     class PolygonGeometry extends VertexGeometry {
66343         /**
66344          * Create a polygon geometry.
66345          *
66346          * @constructor
66347          * @param {Array<Array<number>>} polygon - Array of polygon vertices. Must be closed.
66348          * @param {Array<Array<Array<number>>>} [holes] - Array of arrays of hole vertices.
66349          * Each array of holes vertices must be closed.
66350          *
66351          * @throws {GeometryTagError} Polygon coordinates must be valid basic coordinates.
66352          */
66353         constructor(polygon, holes) {
66354             super();
66355             let polygonLength = polygon.length;
66356             if (polygonLength < 3) {
66357                 throw new GeometryTagError("A polygon must have three or more positions.");
66358             }
66359             if (polygon[0][0] !== polygon[polygonLength - 1][0] ||
66360                 polygon[0][1] !== polygon[polygonLength - 1][1]) {
66361                 throw new GeometryTagError("First and last positions must be equivalent.");
66362             }
66363             this._polygon = [];
66364             for (let vertex of polygon) {
66365                 if (vertex[0] < 0 || vertex[0] > 1 ||
66366                     vertex[1] < 0 || vertex[1] > 1) {
66367                     throw new GeometryTagError("Basic coordinates of polygon must be on the interval [0, 1].");
66368                 }
66369                 this._polygon.push(vertex.slice());
66370             }
66371             this._holes = [];
66372             if (holes == null) {
66373                 return;
66374             }
66375             for (let i = 0; i < holes.length; i++) {
66376                 let hole = holes[i];
66377                 let holeLength = hole.length;
66378                 if (holeLength < 3) {
66379                     throw new GeometryTagError("A polygon hole must have three or more positions.");
66380                 }
66381                 if (hole[0][0] !== hole[holeLength - 1][0] ||
66382                     hole[0][1] !== hole[holeLength - 1][1]) {
66383                     throw new GeometryTagError("First and last positions of hole must be equivalent.");
66384                 }
66385                 this._holes.push([]);
66386                 for (let vertex of hole) {
66387                     if (vertex[0] < 0 || vertex[0] > 1 ||
66388                         vertex[1] < 0 || vertex[1] > 1) {
66389                         throw new GeometryTagError("Basic coordinates of hole must be on the interval [0, 1].");
66390                     }
66391                     this._holes[i].push(vertex.slice());
66392                 }
66393             }
66394         }
66395         /**
66396          * Get polygon property.
66397          * @returns {Array<Array<number>>} Closed 2d polygon.
66398          */
66399         get polygon() {
66400             return this._polygon;
66401         }
66402         /**
66403          * Get holes property.
66404          * @returns {Array<Array<Array<number>>>} Holes of 2d polygon.
66405          */
66406         get holes() {
66407             return this._holes;
66408         }
66409         /**
66410          * Add a vertex to the polygon by appending it after the last vertex.
66411          *
66412          * @param {Array<number>} vertex - Vertex to add.
66413          * @ignore
66414          */
66415         addVertex2d(vertex) {
66416             let clamped = [
66417                 Math.max(0, Math.min(1, vertex[0])),
66418                 Math.max(0, Math.min(1, vertex[1])),
66419             ];
66420             this._polygon.splice(this._polygon.length - 1, 0, clamped);
66421             this._notifyChanged$.next(this);
66422         }
66423         /**
66424          * Get the coordinates of a vertex from the polygon representation of the geometry.
66425          *
66426          * @param {number} index - Vertex index.
66427          * @returns {Array<number>} Array representing the 2D basic coordinates of the vertex.
66428          * @ignore
66429          */
66430         getVertex2d(index) {
66431             return this._polygon[index].slice();
66432         }
66433         /**
66434          * Remove a vertex from the polygon.
66435          *
66436          * @param {number} index - The index of the vertex to remove.
66437          * @ignore
66438          */
66439         removeVertex2d(index) {
66440             if (index < 0 ||
66441                 index >= this._polygon.length ||
66442                 this._polygon.length < 4) {
66443                 throw new GeometryTagError("Index for removed vertex must be valid.");
66444             }
66445             if (index > 0 && index < this._polygon.length - 1) {
66446                 this._polygon.splice(index, 1);
66447             }
66448             else {
66449                 this._polygon.splice(0, 1);
66450                 this._polygon.pop();
66451                 let closing = this._polygon[0].slice();
66452                 this._polygon.push(closing);
66453             }
66454             this._notifyChanged$.next(this);
66455         }
66456         /** @ignore */
66457         setVertex2d(index, value, transform) {
66458             let changed = [
66459                 Math.max(0, Math.min(1, value[0])),
66460                 Math.max(0, Math.min(1, value[1])),
66461             ];
66462             if (index === 0 || index === this._polygon.length - 1) {
66463                 this._polygon[0] = changed.slice();
66464                 this._polygon[this._polygon.length - 1] = changed.slice();
66465             }
66466             else {
66467                 this._polygon[index] = changed.slice();
66468             }
66469             this._notifyChanged$.next(this);
66470         }
66471         /** @ignore */
66472         setCentroid2d(value, transform) {
66473             let xs = this._polygon.map((point) => { return point[0]; });
66474             let ys = this._polygon.map((point) => { return point[1]; });
66475             let minX = Math.min.apply(Math, xs);
66476             let maxX = Math.max.apply(Math, xs);
66477             let minY = Math.min.apply(Math, ys);
66478             let maxY = Math.max.apply(Math, ys);
66479             let centroid = this.getCentroid2d();
66480             let minTranslationX = -minX;
66481             let maxTranslationX = 1 - maxX;
66482             let minTranslationY = -minY;
66483             let maxTranslationY = 1 - maxY;
66484             let translationX = Math.max(minTranslationX, Math.min(maxTranslationX, value[0] - centroid[0]));
66485             let translationY = Math.max(minTranslationY, Math.min(maxTranslationY, value[1] - centroid[1]));
66486             for (let point of this._polygon) {
66487                 point[0] += translationX;
66488                 point[1] += translationY;
66489             }
66490             this._notifyChanged$.next(this);
66491         }
66492         /** @ignore */
66493         getPoints3d(transform) {
66494             return this._getPoints3d(this._subsample(this._polygon), transform);
66495         }
66496         /** @ignore */
66497         getVertex3d(index, transform) {
66498             return transform.unprojectBasic(this._polygon[index], 200);
66499         }
66500         /** @ignore */
66501         getVertices2d() {
66502             return this._polygon.slice();
66503         }
66504         /** @ignore */
66505         getVertices3d(transform) {
66506             return this._getPoints3d(this._polygon, transform);
66507         }
66508         /**
66509          * Get a polygon representation of the 3D coordinates for the vertices of each hole
66510          * of the geometry. Line segments between vertices will possibly be subsampled
66511          * resulting in a larger number of points than the total number of vertices.
66512          *
66513          * @param {Transform} transform - The transform of the image related to the geometry.
66514          * @returns {Array<Array<Array<number>>>} Array of hole polygons in 3D world coordinates
66515          * representing the vertices of each hole of the geometry.
66516          * @ignore
66517          */
66518         getHolePoints3d(transform) {
66519             return this._holes
66520                 .map((hole2d) => {
66521                 return this._getPoints3d(this._subsample(hole2d), transform);
66522             });
66523         }
66524         /**
66525          * Get a polygon representation of the 3D coordinates for the vertices of each hole
66526          * of the geometry.
66527          *
66528          * @param {Transform} transform - The transform of the image related to the geometry.
66529          * @returns {Array<Array<Array<number>>>} Array of hole polygons in 3D world coordinates
66530          * representing the vertices of each hole of the geometry.
66531          * @ignore
66532          */
66533         getHoleVertices3d(transform) {
66534             return this._holes
66535                 .map((hole2d) => {
66536                 return this._getPoints3d(hole2d, transform);
66537             });
66538         }
66539         /** @ignore */
66540         getCentroid2d() {
66541             let polygon = this._polygon;
66542             let area = 0;
66543             let centroidX = 0;
66544             let centroidY = 0;
66545             for (let i = 0; i < polygon.length - 1; i++) {
66546                 let xi = polygon[i][0];
66547                 let yi = polygon[i][1];
66548                 let xi1 = polygon[i + 1][0];
66549                 let yi1 = polygon[i + 1][1];
66550                 let a = xi * yi1 - xi1 * yi;
66551                 area += a;
66552                 centroidX += (xi + xi1) * a;
66553                 centroidY += (yi + yi1) * a;
66554             }
66555             area /= 2;
66556             centroidX /= 6 * area;
66557             centroidY /= 6 * area;
66558             return [centroidX, centroidY];
66559         }
66560         /** @ignore */
66561         getCentroid3d(transform) {
66562             let centroid2d = this.getCentroid2d();
66563             return transform.unprojectBasic(centroid2d, 200);
66564         }
66565         /** @ignore */
66566         get3dDomainTriangles3d(transform) {
66567             return this._triangulate(this._project(this._polygon, transform), this.getVertices3d(transform), this._holes
66568                 .map((hole2d) => {
66569                 return this._project(hole2d, transform);
66570             }), this.getHoleVertices3d(transform));
66571         }
66572         /** @ignore */
66573         getTriangles3d(transform) {
66574             if (isSpherical(transform.cameraType)) {
66575                 return this._triangulateSpherical(this._polygon.slice(), this.holes.slice(), transform);
66576             }
66577             const points2d = this._project(this._subsample(this._polygon), transform);
66578             const points3d = this.getPoints3d(transform);
66579             const holes2d = this._holes
66580                 .map((hole) => {
66581                 return this._project(this._subsample(hole), transform);
66582             });
66583             const holes3d = this.getHolePoints3d(transform);
66584             return this._triangulate(points2d, points3d, holes2d, holes3d);
66585         }
66586         /** @ignore */
66587         getPoleOfInaccessibility2d() {
66588             return this._getPoleOfInaccessibility2d(this._polygon.slice());
66589         }
66590         /** @ignore */
66591         getPoleOfInaccessibility3d(transform) {
66592             let pole2d = this._getPoleOfInaccessibility2d(this._polygon.slice());
66593             return transform.unprojectBasic(pole2d, 200);
66594         }
66595         _getPoints3d(points2d, transform) {
66596             return points2d
66597                 .map((point) => {
66598                 return transform.unprojectBasic(point, 200);
66599             });
66600         }
66601     }
66602
66603     class OutlineCreateTag extends CreateTag {
66604         constructor(geometry, options, transform, viewportCoords) {
66605             super(geometry, transform, viewportCoords);
66606             this._options = { color: options.color == null ? 0xFFFFFF : options.color };
66607             this._createGlObjects();
66608         }
66609         create() {
66610             if (this._geometry instanceof RectGeometry) {
66611                 this._created$.next(this);
66612             }
66613             else if (this._geometry instanceof PolygonGeometry) {
66614                 const polygonGeometry = this._geometry;
66615                 polygonGeometry.removeVertex2d(polygonGeometry.polygon.length - 2);
66616                 this._created$.next(this);
66617             }
66618         }
66619         dispose() {
66620             super.dispose();
66621             this._disposeLine(this._outline);
66622             this._disposeObjects();
66623         }
66624         getDOMObjects(camera, size) {
66625             const vNodes = [];
66626             const container = {
66627                 offsetHeight: size.height, offsetWidth: size.width,
66628             };
66629             const abort = (e) => {
66630                 e.stopPropagation();
66631                 this._aborted$.next(this);
66632             };
66633             if (this._geometry instanceof RectGeometry) {
66634                 const anchorIndex = this._geometry.anchorIndex;
66635                 const vertexIndex = anchorIndex === undefined ? 1 : anchorIndex;
66636                 const [basicX, basicY] = this._geometry.getVertex2d(vertexIndex);
66637                 const canvasPoint = this._viewportCoords.basicToCanvasSafe(basicX, basicY, container, this._transform, camera);
66638                 if (canvasPoint != null) {
66639                     const background = this._colorToBackground(this._options.color);
66640                     const transform = this._canvasToTransform(canvasPoint);
66641                     const pointProperties = {
66642                         style: { background: background, transform: transform },
66643                     };
66644                     const completerProperties = {
66645                         onclick: abort,
66646                         style: { transform: transform },
66647                     };
66648                     vNodes.push(virtualDom.h("div.mapillary-tag-interactor", completerProperties, []));
66649                     vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
66650                 }
66651             }
66652             else if (this._geometry instanceof PolygonGeometry) {
66653                 const polygonGeometry = this._geometry;
66654                 const [firstVertexBasicX, firstVertexBasicY] = polygonGeometry.getVertex2d(0);
66655                 const firstVertexCanvas = this._viewportCoords.basicToCanvasSafe(firstVertexBasicX, firstVertexBasicY, container, this._transform, camera);
66656                 if (firstVertexCanvas != null) {
66657                     const firstOnclick = polygonGeometry.polygon.length > 4 ?
66658                         (e) => {
66659                             e.stopPropagation();
66660                             polygonGeometry.removeVertex2d(polygonGeometry.polygon.length - 2);
66661                             this._created$.next(this);
66662                         } :
66663                         abort;
66664                     const transform = this._canvasToTransform(firstVertexCanvas);
66665                     const completerProperties = {
66666                         onclick: firstOnclick,
66667                         style: { transform: transform },
66668                     };
66669                     const firstClass = polygonGeometry.polygon.length > 4 ?
66670                         "mapillary-tag-completer" :
66671                         "mapillary-tag-interactor";
66672                     vNodes.push(virtualDom.h("div." + firstClass, completerProperties, []));
66673                 }
66674                 if (polygonGeometry.polygon.length > 3) {
66675                     const [lastVertexBasicX, lastVertexBasicY] = polygonGeometry.getVertex2d(polygonGeometry.polygon.length - 3);
66676                     const lastVertexCanvas = this._viewportCoords.basicToCanvasSafe(lastVertexBasicX, lastVertexBasicY, container, this._transform, camera);
66677                     if (lastVertexCanvas != null) {
66678                         const remove = (e) => {
66679                             e.stopPropagation();
66680                             polygonGeometry.removeVertex2d(polygonGeometry.polygon.length - 3);
66681                         };
66682                         const transform = this._canvasToTransform(lastVertexCanvas);
66683                         const completerProperties = {
66684                             onclick: remove,
66685                             style: { transform: transform },
66686                         };
66687                         vNodes.push(virtualDom.h("div.mapillary-tag-interactor", completerProperties, []));
66688                     }
66689                 }
66690                 const verticesBasic = polygonGeometry.polygon.slice();
66691                 verticesBasic.splice(-2, 2);
66692                 for (const vertexBasic of verticesBasic) {
66693                     const vertexCanvas = this._viewportCoords.basicToCanvasSafe(vertexBasic[0], vertexBasic[1], container, this._transform, camera);
66694                     if (vertexCanvas != null) {
66695                         const background = this._colorToBackground(this._options.color);
66696                         const transform = this._canvasToTransform(vertexCanvas);
66697                         const pointProperties = {
66698                             style: {
66699                                 background: background,
66700                                 transform: transform,
66701                             },
66702                         };
66703                         vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
66704                     }
66705                 }
66706             }
66707             return vNodes;
66708         }
66709         addPoint(point) {
66710             if (this._geometry instanceof RectGeometry) {
66711                 const rectGeometry = this._geometry;
66712                 if (!rectGeometry.validate(point)) {
66713                     return;
66714                 }
66715                 this._created$.next(this);
66716             }
66717             else if (this._geometry instanceof PolygonGeometry) {
66718                 const polygonGeometry = this._geometry;
66719                 polygonGeometry.addVertex2d(point);
66720             }
66721         }
66722         _onGeometryChanged() {
66723             this._disposeLine(this._outline);
66724             this._disposeObjects();
66725             this._createGlObjects();
66726         }
66727         _disposeObjects() {
66728             this._outline = null;
66729             this._glObjects = [];
66730         }
66731         _createGlObjects() {
66732             const polygon3d = this._geometry instanceof RectGeometry ?
66733                 this._geometry.getPoints3d(this._transform) :
66734                 this._geometry.getVertices3d(this._transform);
66735             this._outline = this._createOutine(polygon3d, this._options.color);
66736             this._glObjects = [this._outline];
66737         }
66738     }
66739
66740     class TagCreator {
66741         constructor(component, navigator) {
66742             this._component = component;
66743             this._navigator = navigator;
66744             this._tagOperation$ = new Subject();
66745             this._createPoints$ = new Subject();
66746             this._createPolygon$ = new Subject();
66747             this._createRect$ = new Subject();
66748             this._delete$ = new Subject();
66749             this._tag$ = this._tagOperation$.pipe(scan((tag, operation) => {
66750                 return operation(tag);
66751             }, null), share());
66752             this._replayedTag$ = this._tag$.pipe(publishReplay(1), refCount());
66753             this._replayedTag$.subscribe();
66754             this._createPoints$.pipe(withLatestFrom(this._component.configuration$, this._navigator.stateService.currentTransform$), map(([coord, conf, transform]) => {
66755                 return () => {
66756                     const geometry = new PointsGeometry([
66757                         [coord[0], coord[1]],
66758                         [coord[0], coord[1]],
66759                     ]);
66760                     return new ExtremePointCreateTag(geometry, {
66761                         color: conf.createColor,
66762                         indicateCompleter: conf.indicatePointsCompleter,
66763                     }, transform);
66764                 };
66765             }))
66766                 .subscribe(this._tagOperation$);
66767             this._createRect$.pipe(withLatestFrom(this._component.configuration$, this._navigator.stateService.currentTransform$), map(([coord, conf, transform]) => {
66768                 return () => {
66769                     const geometry = new RectGeometry([
66770                         coord[0],
66771                         coord[1],
66772                         coord[0],
66773                         coord[1],
66774                     ]);
66775                     return new OutlineCreateTag(geometry, { color: conf.createColor }, transform);
66776                 };
66777             }))
66778                 .subscribe(this._tagOperation$);
66779             this._createPolygon$.pipe(withLatestFrom(this._component.configuration$, this._navigator.stateService.currentTransform$), map(([coord, conf, transform]) => {
66780                 return () => {
66781                     const geometry = new PolygonGeometry([
66782                         [coord[0], coord[1]],
66783                         [coord[0], coord[1]],
66784                         [coord[0], coord[1]],
66785                     ]);
66786                     return new OutlineCreateTag(geometry, { color: conf.createColor }, transform);
66787                 };
66788             }))
66789                 .subscribe(this._tagOperation$);
66790             this._delete$.pipe(map(() => {
66791                 return () => {
66792                     return null;
66793                 };
66794             }))
66795                 .subscribe(this._tagOperation$);
66796         }
66797         get createRect$() {
66798             return this._createRect$;
66799         }
66800         get createPolygon$() {
66801             return this._createPolygon$;
66802         }
66803         get createPoints$() {
66804             return this._createPoints$;
66805         }
66806         get delete$() {
66807             return this._delete$;
66808         }
66809         get tag$() {
66810             return this._tag$;
66811         }
66812         get replayedTag$() {
66813             return this._replayedTag$;
66814         }
66815     }
66816
66817     class TagDOMRenderer {
66818         render(tags, createTag, atlas, camera, size) {
66819             let vNodes = [];
66820             for (const tag of tags) {
66821                 vNodes = vNodes.concat(tag.getDOMObjects(atlas, camera, size));
66822             }
66823             if (createTag != null) {
66824                 vNodes = vNodes.concat(createTag.getDOMObjects(camera, size));
66825             }
66826             return virtualDom.h("div.mapillary-tag-container", {}, vNodes);
66827         }
66828         clear() {
66829             return virtualDom.h("div", {}, []);
66830         }
66831     }
66832
66833     class TagScene {
66834         constructor(scene, raycaster) {
66835             this._createTag = null;
66836             this._needsRender = false;
66837             this._raycaster = !!raycaster ? raycaster : new Raycaster();
66838             this._scene = !!scene ? scene : new Scene();
66839             this._objectTags = {};
66840             this._retrievableObjects = [];
66841             this._tags = {};
66842         }
66843         get needsRender() {
66844             return this._needsRender;
66845         }
66846         add(tags) {
66847             for (let tag of tags) {
66848                 if (tag.tag.id in this._tags) {
66849                     this._remove(tag.tag.id);
66850                 }
66851                 this._add(tag);
66852             }
66853             this._needsRender = true;
66854         }
66855         addCreateTag(tag) {
66856             for (const object of tag.glObjects) {
66857                 this._scene.add(object);
66858             }
66859             this._createTag = { tag: tag, objects: tag.glObjects };
66860             this._needsRender = true;
66861         }
66862         clear() {
66863             for (const id of Object.keys(this._tags)) {
66864                 this._remove(id);
66865             }
66866             this._needsRender = false;
66867         }
66868         get(id) {
66869             return this.has(id) ? this._tags[id].tag : undefined;
66870         }
66871         has(id) {
66872             return id in this._tags;
66873         }
66874         hasCreateTag() {
66875             return this._createTag != null;
66876         }
66877         intersectObjects([viewportX, viewportY], camera) {
66878             this._raycaster.setFromCamera(new Vector2(viewportX, viewportY), camera);
66879             const intersects = this._raycaster.intersectObjects(this._retrievableObjects);
66880             const intersectedIds = [];
66881             for (const intersect of intersects) {
66882                 if (intersect.object.uuid in this._objectTags) {
66883                     intersectedIds.push(this._objectTags[intersect.object.uuid]);
66884                 }
66885             }
66886             return intersectedIds;
66887         }
66888         remove(ids) {
66889             for (const id of ids) {
66890                 this._remove(id);
66891             }
66892             this._needsRender = true;
66893         }
66894         removeAll() {
66895             for (const id of Object.keys(this._tags)) {
66896                 this._remove(id);
66897             }
66898             this._needsRender = true;
66899         }
66900         removeCreateTag() {
66901             if (this._createTag == null) {
66902                 return;
66903             }
66904             for (const object of this._createTag.objects) {
66905                 this._scene.remove(object);
66906             }
66907             this._createTag.tag.dispose();
66908             this._createTag = null;
66909             this._needsRender = true;
66910         }
66911         render(perspectiveCamera, renderer) {
66912             renderer.render(this._scene, perspectiveCamera);
66913             this._needsRender = false;
66914         }
66915         update() {
66916             this._needsRender = true;
66917         }
66918         updateCreateTagObjects(tag) {
66919             if (this._createTag.tag !== tag) {
66920                 throw new Error("Create tags do not have the same reference.");
66921             }
66922             for (let object of this._createTag.objects) {
66923                 this._scene.remove(object);
66924             }
66925             for (const object of tag.glObjects) {
66926                 this._scene.add(object);
66927             }
66928             this._createTag.objects = tag.glObjects;
66929             this._needsRender = true;
66930         }
66931         updateObjects(tag) {
66932             const id = tag.tag.id;
66933             if (this._tags[id].tag !== tag) {
66934                 throw new Error("Tags do not have the same reference.");
66935             }
66936             const tagObjects = this._tags[id];
66937             this._removeObjects(tagObjects);
66938             delete this._tags[id];
66939             this._add(tag);
66940             this._needsRender = true;
66941         }
66942         _add(tag) {
66943             const id = tag.tag.id;
66944             const tagObjects = { tag: tag, objects: [], retrievableObjects: [] };
66945             this._tags[id] = tagObjects;
66946             for (const object of tag.getGLObjects()) {
66947                 tagObjects.objects.push(object);
66948                 this._scene.add(object);
66949             }
66950             for (const retrievableObject of tag.getRetrievableObjects()) {
66951                 tagObjects.retrievableObjects.push(retrievableObject);
66952                 this._retrievableObjects.push(retrievableObject);
66953                 this._objectTags[retrievableObject.uuid] = tag.tag.id;
66954             }
66955         }
66956         _remove(id) {
66957             const tagObjects = this._tags[id];
66958             this._removeObjects(tagObjects);
66959             tagObjects.tag.dispose();
66960             delete this._tags[id];
66961         }
66962         _removeObjects(tagObjects) {
66963             for (const object of tagObjects.objects) {
66964                 this._scene.remove(object);
66965             }
66966             for (const retrievableObject of tagObjects.retrievableObjects) {
66967                 const index = this._retrievableObjects.indexOf(retrievableObject);
66968                 if (index !== -1) {
66969                     this._retrievableObjects.splice(index, 1);
66970                 }
66971             }
66972         }
66973     }
66974
66975     /**
66976      * Enumeration for tag modes
66977      * @enum {number}
66978      * @readonly
66979      * @description Modes for the interaction in the tag component.
66980      */
66981     exports.TagMode = void 0;
66982     (function (TagMode) {
66983         /**
66984          * Disables creating tags.
66985          */
66986         TagMode[TagMode["Default"] = 0] = "Default";
66987         /**
66988          * Create a point geometry through a click.
66989          */
66990         TagMode[TagMode["CreatePoint"] = 1] = "CreatePoint";
66991         /**
66992          * Create a points geometry through clicks.
66993          */
66994         TagMode[TagMode["CreatePoints"] = 2] = "CreatePoints";
66995         /**
66996          * Create a polygon geometry through clicks.
66997          */
66998         TagMode[TagMode["CreatePolygon"] = 3] = "CreatePolygon";
66999         /**
67000          * Create a rect geometry through clicks.
67001          */
67002         TagMode[TagMode["CreateRect"] = 4] = "CreateRect";
67003         /**
67004          * Create a rect geometry through drag.
67005          *
67006          * @description Claims the mouse which results in mouse handlers like
67007          * drag pan and scroll zoom becoming inactive.
67008          */
67009         TagMode[TagMode["CreateRectDrag"] = 5] = "CreateRectDrag";
67010     })(exports.TagMode || (exports.TagMode = {}));
67011
67012     var TagOperation;
67013     (function (TagOperation) {
67014         TagOperation[TagOperation["None"] = 0] = "None";
67015         TagOperation[TagOperation["Centroid"] = 1] = "Centroid";
67016         TagOperation[TagOperation["Vertex"] = 2] = "Vertex";
67017     })(TagOperation || (TagOperation = {}));
67018
67019     class RenderTag {
67020         constructor(tag, transform, viewportCoords) {
67021             this._tag = tag;
67022             this._transform = transform;
67023             this._viewportCoords = !!viewportCoords ? viewportCoords : new ViewportCoords();
67024             this._glObjectsChanged$ = new Subject();
67025             this._interact$ = new Subject();
67026         }
67027         get glObjectsChanged$() {
67028             return this._glObjectsChanged$;
67029         }
67030         get interact$() {
67031             return this._interact$;
67032         }
67033         get tag() {
67034             return this._tag;
67035         }
67036     }
67037
67038     class OutlineRenderTagBase extends RenderTag {
67039         constructor(tag, transform) {
67040             super(tag, transform);
67041             this._geometryChangedSubscription = this._tag.geometry.changed$
67042                 .subscribe(() => {
67043                 this._onGeometryChanged();
67044             });
67045             this._changedSubscription = this._tag.changed$
67046                 .subscribe(() => {
67047                 const glObjectsChanged = this._onTagChanged();
67048                 if (glObjectsChanged) {
67049                     this._glObjectsChanged$.next(this);
67050                 }
67051             });
67052         }
67053         dispose() {
67054             this._changedSubscription.unsubscribe();
67055             this._geometryChangedSubscription.unsubscribe();
67056         }
67057         _colorToCss(color) {
67058             return "#" + ("000000" + color.toString(16)).substr(-6);
67059         }
67060         _createFill() {
67061             let triangles = this._getTriangles();
67062             let positions = new Float32Array(triangles);
67063             let geometry = new BufferGeometry();
67064             geometry.setAttribute("position", new BufferAttribute(positions, 3));
67065             geometry.computeBoundingSphere();
67066             let material = new MeshBasicMaterial({ side: DoubleSide, transparent: true });
67067             this._updateFillMaterial(material);
67068             return new Mesh(geometry, material);
67069         }
67070         _createLine(points3d) {
67071             let positions = this._getLinePositions(points3d);
67072             let geometry = new BufferGeometry();
67073             geometry.setAttribute("position", new BufferAttribute(positions, 3));
67074             geometry.computeBoundingSphere();
67075             let material = new LineBasicMaterial();
67076             this._updateLineBasicMaterial(material);
67077             const line = new Line(geometry, material);
67078             line.renderOrder = 1;
67079             return line;
67080         }
67081         _createOutline() {
67082             return this._createLine(this._getPoints3d());
67083         }
67084         _disposeFill() {
67085             if (this._fill == null) {
67086                 return;
67087             }
67088             this._fill.geometry.dispose();
67089             this._fill.material.dispose();
67090             this._fill = null;
67091         }
67092         _disposeOutline() {
67093             if (this._outline == null) {
67094                 return;
67095             }
67096             this._outline.geometry.dispose();
67097             this._outline.material.dispose();
67098             this._outline = null;
67099         }
67100         _getLinePositions(points3d) {
67101             let length = points3d.length;
67102             let positions = new Float32Array(length * 3);
67103             for (let i = 0; i < length; ++i) {
67104                 let index = 3 * i;
67105                 let position = points3d[i];
67106                 positions[index + 0] = position[0];
67107                 positions[index + 1] = position[1];
67108                 positions[index + 2] = position[2];
67109             }
67110             return positions;
67111         }
67112         _interact(operation, cursor, vertexIndex) {
67113             return (e) => {
67114                 let offsetX = e.offsetX - e.target.offsetWidth / 2;
67115                 let offsetY = e.offsetY - e.target.offsetHeight / 2;
67116                 this._interact$.next({
67117                     cursor: cursor,
67118                     offsetX: offsetX,
67119                     offsetY: offsetY,
67120                     operation: operation,
67121                     tag: this._tag,
67122                     vertexIndex: vertexIndex,
67123                 });
67124             };
67125         }
67126         _updateFillGeometry() {
67127             let triangles = this._getTriangles();
67128             let positions = new Float32Array(triangles);
67129             let geometry = this._fill.geometry;
67130             let attribute = geometry.getAttribute("position");
67131             if (attribute.array.length === positions.length) {
67132                 attribute.set(positions);
67133                 attribute.needsUpdate = true;
67134             }
67135             else {
67136                 geometry.deleteAttribute("position");
67137                 geometry.setAttribute("position", new BufferAttribute(positions, 3));
67138             }
67139             geometry.computeBoundingSphere();
67140         }
67141         _updateLine(line, points3d) {
67142             let positions = this._getLinePositions(points3d);
67143             let geometry = line.geometry;
67144             let attribute = geometry.getAttribute("position");
67145             attribute.set(positions);
67146             attribute.needsUpdate = true;
67147             geometry.computeBoundingSphere();
67148         }
67149         _updateOulineGeometry() {
67150             this._updateLine(this._outline, this._getPoints3d());
67151         }
67152     }
67153
67154     /**
67155      * @class OutlineRenderTag
67156      * @classdesc Tag visualizing the properties of an OutlineTag.
67157      */
67158     class ExtremePointRenderTag extends OutlineRenderTagBase {
67159         constructor(tag, transform) {
67160             super(tag, transform);
67161             this._rectGeometry = new RectGeometry(this._tag.geometry.getRect2d(transform));
67162             this._fill = !isSpherical(transform.cameraType) ?
67163                 this._createFill() : null;
67164             this._outline = this._tag.lineWidth >= 1 ?
67165                 this._createOutline() :
67166                 null;
67167         }
67168         dispose() {
67169             super.dispose();
67170             this._disposeFill();
67171             this._disposeOutline();
67172         }
67173         getDOMObjects(atlas, camera, size) {
67174             const vNodes = [];
67175             const container = {
67176                 offsetHeight: size.height, offsetWidth: size.width,
67177             };
67178             if (!this._tag.editable) {
67179                 return vNodes;
67180             }
67181             const lineColor = this._colorToCss(this._tag.lineColor);
67182             const points2d = this._tag.geometry.getPoints2d();
67183             for (let i = 0; i < points2d.length; i++) {
67184                 const [vertexBasicX, vertexBasicY] = points2d[i];
67185                 const vertexCanvas = this._viewportCoords.basicToCanvasSafe(vertexBasicX, vertexBasicY, container, this._transform, camera);
67186                 if (vertexCanvas == null) {
67187                     continue;
67188                 }
67189                 const cursor = "crosshair";
67190                 const interact = this._interact(TagOperation.Vertex, cursor, i);
67191                 const vertexCanvasX = Math.round(vertexCanvas[0]);
67192                 const vertexCanvasY = Math.round(vertexCanvas[1]);
67193                 const transform = `translate(-50%, -50%) translate(${vertexCanvasX}px,${vertexCanvasY}px)`;
67194                 const properties = {
67195                     onpointerdown: interact,
67196                     style: { background: lineColor, transform: transform, cursor: cursor },
67197                 };
67198                 vNodes.push(virtualDom.h("div.mapillary-tag-resizer", properties, []));
67199                 if (!this._tag.indicateVertices) {
67200                     continue;
67201                 }
67202                 const pointProperties = {
67203                     style: { background: lineColor, transform: transform },
67204                 };
67205                 vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
67206             }
67207             return vNodes;
67208         }
67209         getGLObjects() {
67210             const glObjects = [];
67211             if (this._fill != null) {
67212                 glObjects.push(this._fill);
67213             }
67214             if (this._outline != null) {
67215                 glObjects.push(this._outline);
67216             }
67217             return glObjects;
67218         }
67219         getRetrievableObjects() {
67220             return this._fill != null ? [this._fill] : [];
67221         }
67222         _onGeometryChanged() {
67223             this._rectGeometry = new RectGeometry(this._tag.geometry.getRect2d(this._transform));
67224             if (this._fill != null) {
67225                 this._updateFillGeometry();
67226             }
67227             if (this._outline != null) {
67228                 this._updateOulineGeometry();
67229             }
67230         }
67231         _onTagChanged() {
67232             let glObjectsChanged = false;
67233             if (this._fill != null) {
67234                 this._updateFillMaterial(this._fill.material);
67235             }
67236             if (this._outline == null) {
67237                 if (this._tag.lineWidth >= 1) {
67238                     this._outline = this._createOutline();
67239                     glObjectsChanged = true;
67240                 }
67241             }
67242             else {
67243                 this._updateOutlineMaterial();
67244             }
67245             return glObjectsChanged;
67246         }
67247         _getPoints3d() {
67248             return this._rectGeometry.getPoints3d(this._transform);
67249         }
67250         _getTriangles() {
67251             return this._rectGeometry.getTriangles3d(this._transform);
67252         }
67253         _updateFillMaterial(material) {
67254             material.color = new Color(this._tag.fillColor);
67255             material.opacity = this._tag.fillOpacity;
67256             material.needsUpdate = true;
67257         }
67258         _updateLineBasicMaterial(material) {
67259             material.color = new Color(this._tag.lineColor);
67260             material.linewidth = Math.max(this._tag.lineWidth, 1);
67261             material.visible = this._tag.lineWidth >= 1 && this._tag.lineOpacity > 0;
67262             material.opacity = this._tag.lineOpacity;
67263             material.transparent = this._tag.lineOpacity < 1;
67264             material.needsUpdate = true;
67265         }
67266         _updateOutlineMaterial() {
67267             let material = this._outline.material;
67268             this._updateLineBasicMaterial(material);
67269         }
67270     }
67271
67272     /**
67273      * @class Tag
67274      * @abstract
67275      * @classdesc Abstract class representing the basic functionality of for a tag.
67276      */
67277     class Tag extends EventEmitter {
67278         /**
67279          * Create a tag.
67280          *
67281          * @constructor
67282          * @param {string} id
67283          * @param {Geometry} geometry
67284          */
67285         constructor(id, geometry) {
67286             super();
67287             this._id = id;
67288             this._geometry = geometry;
67289             this._notifyChanged$ = new Subject();
67290             this._notifyChanged$
67291                 .subscribe((t) => {
67292                 const type = "tag";
67293                 const event = {
67294                     target: this,
67295                     type,
67296                 };
67297                 this.fire(type, event);
67298             });
67299             this._geometry.changed$
67300                 .subscribe((g) => {
67301                 const type = "geometry";
67302                 const event = {
67303                     target: this,
67304                     type,
67305                 };
67306                 this.fire(type, event);
67307             });
67308         }
67309         /**
67310          * Get id property.
67311          * @returns {string}
67312          */
67313         get id() {
67314             return this._id;
67315         }
67316         /**
67317          * Get geometry property.
67318          * @returns {Geometry} The geometry of the tag.
67319          */
67320         get geometry() {
67321             return this._geometry;
67322         }
67323         /**
67324          * Get changed observable.
67325          * @returns {Observable<Tag>}
67326          * @ignore
67327          */
67328         get changed$() {
67329             return this._notifyChanged$;
67330         }
67331         /**
67332          * Get geometry changed observable.
67333          * @returns {Observable<Tag>}
67334          * @ignore
67335          */
67336         get geometryChanged$() {
67337             return this._geometry.changed$.pipe(map(() => {
67338                 return this;
67339             }), share());
67340         }
67341         fire(type, event) {
67342             super.fire(type, event);
67343         }
67344         off(type, handler) {
67345             super.off(type, handler);
67346         }
67347         on(type, handler) {
67348             super.on(type, handler);
67349         }
67350     }
67351
67352     /**
67353      * @class ExtremePointTag
67354      *
67355      * @classdesc Tag holding properties for visualizing a extreme points
67356      * and their outline.
67357      *
67358      * @example
67359      * ```js
67360      * var geometry = new PointsGeometry([[0.3, 0.3], [0.5, 0.4]]);
67361      * var tag = new ExtremePointTag(
67362      *     "id-1",
67363      *     geometry
67364      *     { editable: true, lineColor: 0xff0000 });
67365      *
67366      * tagComponent.add([tag]);
67367      * ```
67368      */
67369     class ExtremePointTag extends Tag {
67370         /**
67371          * Create an extreme point tag.
67372          *
67373          * @override
67374          * @constructor
67375          * @param {string} id - Unique identifier of the tag.
67376          * @param {PointsGeometry} geometry - Geometry defining points of tag.
67377          * @param {ExtremePointTagOptions} options - Options defining the visual appearance and
67378          * behavior of the extreme point tag.
67379          */
67380         constructor(id, geometry, options) {
67381             super(id, geometry);
67382             options = !!options ? options : {};
67383             this._editable = options.editable == null ? false : options.editable;
67384             this._fillColor = options.fillColor == null ? 0xFFFFFF : options.fillColor;
67385             this._fillOpacity = options.fillOpacity == null ? 0.0 : options.fillOpacity;
67386             this._indicateVertices = options.indicateVertices == null ? true : options.indicateVertices;
67387             this._lineColor = options.lineColor == null ? 0xFFFFFF : options.lineColor;
67388             this._lineOpacity = options.lineOpacity == null ? 1 : options.lineOpacity;
67389             this._lineWidth = options.lineWidth == null ? 1 : options.lineWidth;
67390         }
67391         /**
67392          * Get editable property.
67393          * @returns {boolean} Value indicating if tag is editable.
67394          */
67395         get editable() {
67396             return this._editable;
67397         }
67398         /**
67399          * Set editable property.
67400          * @param {boolean}
67401          *
67402          * @fires changed
67403          */
67404         set editable(value) {
67405             this._editable = value;
67406             this._notifyChanged$.next(this);
67407         }
67408         /**
67409          * Get fill color property.
67410          * @returns {number}
67411          */
67412         get fillColor() {
67413             return this._fillColor;
67414         }
67415         /**
67416          * Set fill color property.
67417          * @param {number}
67418          *
67419          * @fires changed
67420          */
67421         set fillColor(value) {
67422             this._fillColor = value;
67423             this._notifyChanged$.next(this);
67424         }
67425         /**
67426          * Get fill opacity property.
67427          * @returns {number}
67428          */
67429         get fillOpacity() {
67430             return this._fillOpacity;
67431         }
67432         /**
67433          * Set fill opacity property.
67434          * @param {number}
67435          *
67436          * @fires changed
67437          */
67438         set fillOpacity(value) {
67439             this._fillOpacity = value;
67440             this._notifyChanged$.next(this);
67441         }
67442         /** @inheritdoc */
67443         get geometry() {
67444             return this._geometry;
67445         }
67446         /**
67447          * Get indicate vertices property.
67448          * @returns {boolean} Value indicating if vertices should be indicated
67449          * when tag is editable.
67450          */
67451         get indicateVertices() {
67452             return this._indicateVertices;
67453         }
67454         /**
67455          * Set indicate vertices property.
67456          * @param {boolean}
67457          *
67458          * @fires changed
67459          */
67460         set indicateVertices(value) {
67461             this._indicateVertices = value;
67462             this._notifyChanged$.next(this);
67463         }
67464         /**
67465          * Get line color property.
67466          * @returns {number}
67467          */
67468         get lineColor() {
67469             return this._lineColor;
67470         }
67471         /**
67472          * Set line color property.
67473          * @param {number}
67474          *
67475          * @fires changed
67476          */
67477         set lineColor(value) {
67478             this._lineColor = value;
67479             this._notifyChanged$.next(this);
67480         }
67481         /**
67482          * Get line opacity property.
67483          * @returns {number}
67484          */
67485         get lineOpacity() {
67486             return this._lineOpacity;
67487         }
67488         /**
67489          * Set line opacity property.
67490          * @param {number}
67491          *
67492          * @fires changed
67493          */
67494         set lineOpacity(value) {
67495             this._lineOpacity = value;
67496             this._notifyChanged$.next(this);
67497         }
67498         /**
67499          * Get line width property.
67500          * @returns {number}
67501          */
67502         get lineWidth() {
67503             return this._lineWidth;
67504         }
67505         /**
67506          * Set line width property.
67507          * @param {number}
67508          *
67509          * @fires changed
67510          */
67511         set lineWidth(value) {
67512             this._lineWidth = value;
67513             this._notifyChanged$.next(this);
67514         }
67515         /**
67516          * Set options for tag.
67517          *
67518          * @description Sets all the option properties provided and keeps
67519          * the rest of the values as is.
67520          *
67521          * @param {ExtremePointTagOptions} options - Extreme point tag options
67522          *
67523          * @fires changed
67524          */
67525         setOptions(options) {
67526             this._editable = options.editable == null ? this._editable : options.editable;
67527             this._indicateVertices = options.indicateVertices == null ? this._indicateVertices : options.indicateVertices;
67528             this._lineColor = options.lineColor == null ? this._lineColor : options.lineColor;
67529             this._lineWidth = options.lineWidth == null ? this._lineWidth : options.lineWidth;
67530             this._fillColor = options.fillColor == null ? this._fillColor : options.fillColor;
67531             this._fillOpacity = options.fillOpacity == null ? this._fillOpacity : options.fillOpacity;
67532             this._notifyChanged$.next(this);
67533         }
67534     }
67535
67536     /**
67537      * Enumeration for tag domains.
67538      * @enum {number}
67539      * @readonly
67540      * @description Defines where lines between two vertices are treated
67541      * as straight.
67542      *
67543      * Only applicable for polygons. For rectangles lines between
67544      * vertices are always treated as straight in the distorted 2D
67545      * projection and bended in the undistorted 3D space.
67546      */
67547     exports.TagDomain = void 0;
67548     (function (TagDomain) {
67549         /**
67550          * Treats lines between two vertices as straight in the
67551          * distorted 2D projection, i.e. on the image. If the image
67552          * is distorted this will result in bended lines when rendered
67553          * in the undistorted 3D space.
67554          */
67555         TagDomain[TagDomain["TwoDimensional"] = 0] = "TwoDimensional";
67556         /**
67557          * Treats lines as straight in the undistorted 3D space. If the
67558          * image is distorted this will result in bended lines when rendered
67559          * on the distorted 2D projection of the image.
67560          */
67561         TagDomain[TagDomain["ThreeDimensional"] = 1] = "ThreeDimensional";
67562     })(exports.TagDomain || (exports.TagDomain = {}));
67563
67564     /**
67565      * @class OutlineRenderTag
67566      * @classdesc Tag visualizing the properties of an OutlineTag.
67567      */
67568     class OutlineRenderTag extends OutlineRenderTagBase {
67569         constructor(tag, transform) {
67570             super(tag, transform);
67571             this._fill = !isSpherical(transform.cameraType) ?
67572                 this._createFill() :
67573                 tag.domain === exports.TagDomain.TwoDimensional &&
67574                     tag.geometry instanceof PolygonGeometry ?
67575                     this._createFill() :
67576                     null;
67577             this._holes = this._tag.lineWidth >= 1 ?
67578                 this._createHoles() :
67579                 [];
67580             this._outline = this._tag.lineWidth >= 1 ?
67581                 this._createOutline() :
67582                 null;
67583         }
67584         dispose() {
67585             super.dispose();
67586             this._disposeFill();
67587             this._disposeHoles();
67588             this._disposeOutline();
67589         }
67590         getDOMObjects(atlas, camera, size) {
67591             const vNodes = [];
67592             const isRect = this._tag.geometry instanceof RectGeometry;
67593             const isPerspective = !isSpherical(this._transform.cameraType);
67594             const container = {
67595                 offsetHeight: size.height, offsetWidth: size.width,
67596             };
67597             if (this._tag.icon != null && (isRect || isPerspective)) {
67598                 const [iconBasicX, iconBasicY] = this._tag.geometry instanceof RectGeometry ?
67599                     this._tag.geometry.getVertex2d(this._tag.iconIndex) :
67600                     this._tag.geometry.getPoleOfInaccessibility2d();
67601                 const iconCanvas = this._viewportCoords.basicToCanvasSafe(iconBasicX, iconBasicY, container, this._transform, camera);
67602                 if (iconCanvas != null) {
67603                     const interact = () => {
67604                         this._interact$.next({ offsetX: 0, offsetY: 0, operation: TagOperation.None, tag: this._tag });
67605                     };
67606                     if (atlas.loaded) {
67607                         const sprite = atlas.getDOMSprite(this._tag.icon, this._tag.iconFloat);
67608                         const iconCanvasX = Math.round(iconCanvas[0]);
67609                         const iconCanvasY = Math.round(iconCanvas[1]);
67610                         const transform = `translate(${iconCanvasX}px,${iconCanvasY}px)`;
67611                         const click = (e) => {
67612                             e.stopPropagation();
67613                             this._tag.click$.next(this._tag);
67614                         };
67615                         const properties = {
67616                             onclick: click,
67617                             onpointerdown: interact,
67618                             style: { transform: transform },
67619                         };
67620                         vNodes.push(virtualDom.h("div.mapillary-tag-symbol", properties, [sprite]));
67621                     }
67622                 }
67623             }
67624             else if (this._tag.text != null && (isRect || isPerspective)) {
67625                 const [textBasicX, textBasicY] = this._tag.geometry instanceof RectGeometry ?
67626                     this._tag.geometry.getVertex2d(3) :
67627                     this._tag.geometry.getPoleOfInaccessibility2d();
67628                 const textCanvas = this._viewportCoords.basicToCanvasSafe(textBasicX, textBasicY, container, this._transform, camera);
67629                 if (textCanvas != null) {
67630                     const textCanvasX = Math.round(textCanvas[0]);
67631                     const textCanvasY = Math.round(textCanvas[1]);
67632                     const transform = this._tag.geometry instanceof RectGeometry ?
67633                         `translate(${textCanvasX}px,${textCanvasY}px)` :
67634                         `translate(-50%, -50%) translate(${textCanvasX}px,${textCanvasY}px)`;
67635                     const interact = () => {
67636                         this._interact$.next({ offsetX: 0, offsetY: 0, operation: TagOperation.None, tag: this._tag });
67637                     };
67638                     const properties = {
67639                         onpointerdown: interact,
67640                         style: {
67641                             color: this._colorToCss(this._tag.textColor),
67642                             transform: transform,
67643                         },
67644                         textContent: this._tag.text,
67645                     };
67646                     vNodes.push(virtualDom.h("span.mapillary-tag-symbol", properties, []));
67647                 }
67648             }
67649             if (!this._tag.editable) {
67650                 return vNodes;
67651             }
67652             const lineColor = this._colorToCss(this._tag.lineColor);
67653             if (this._tag.geometry instanceof RectGeometry) {
67654                 const [centroidBasicX, centroidBasicY] = this._tag.geometry.getCentroid2d();
67655                 const centroidCanvas = this._viewportCoords.basicToCanvasSafe(centroidBasicX, centroidBasicY, container, this._transform, camera);
67656                 if (centroidCanvas != null) {
67657                     const interact = this._interact(TagOperation.Centroid, "move");
67658                     const centroidCanvasX = Math.round(centroidCanvas[0]);
67659                     const centroidCanvasY = Math.round(centroidCanvas[1]);
67660                     const transform = `translate(-50%, -50%) translate(${centroidCanvasX}px,${centroidCanvasY}px)`;
67661                     const properties = {
67662                         onpointerdown: interact,
67663                         style: { background: lineColor, transform: transform },
67664                     };
67665                     vNodes.push(virtualDom.h("div.mapillary-tag-mover", properties, []));
67666                 }
67667             }
67668             const vertices2d = this._tag.geometry.getVertices2d();
67669             for (let i = 0; i < vertices2d.length - 1; i++) {
67670                 if (isRect &&
67671                     ((this._tag.icon != null && i === this._tag.iconIndex) ||
67672                         (this._tag.icon == null && this._tag.text != null && i === 3))) {
67673                     continue;
67674                 }
67675                 const [vertexBasicX, vertexBasicY] = vertices2d[i];
67676                 const vertexCanvas = this._viewportCoords.basicToCanvasSafe(vertexBasicX, vertexBasicY, container, this._transform, camera);
67677                 if (vertexCanvas == null) {
67678                     continue;
67679                 }
67680                 const cursor = isRect ?
67681                     i % 2 === 0 ? "nesw-resize" : "nwse-resize" :
67682                     "crosshair";
67683                 const interact = this._interact(TagOperation.Vertex, cursor, i);
67684                 const vertexCanvasX = Math.round(vertexCanvas[0]);
67685                 const vertexCanvasY = Math.round(vertexCanvas[1]);
67686                 const transform = `translate(-50%, -50%) translate(${vertexCanvasX}px,${vertexCanvasY}px)`;
67687                 const properties = {
67688                     onpointerdown: interact,
67689                     style: { background: lineColor, transform: transform, cursor: cursor },
67690                 };
67691                 vNodes.push(virtualDom.h("div.mapillary-tag-resizer", properties, []));
67692                 if (!this._tag.indicateVertices) {
67693                     continue;
67694                 }
67695                 const pointProperties = {
67696                     style: { background: lineColor, transform: transform },
67697                 };
67698                 vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
67699             }
67700             return vNodes;
67701         }
67702         getGLObjects() {
67703             const glObjects = [];
67704             if (this._fill != null) {
67705                 glObjects.push(this._fill);
67706             }
67707             for (const hole of this._holes) {
67708                 glObjects.push(hole);
67709             }
67710             if (this._outline != null) {
67711                 glObjects.push(this._outline);
67712             }
67713             return glObjects;
67714         }
67715         getRetrievableObjects() {
67716             return this._fill != null ? [this._fill] : [];
67717         }
67718         _onGeometryChanged() {
67719             if (this._fill != null) {
67720                 this._updateFillGeometry();
67721             }
67722             if (this._holes.length > 0) {
67723                 this._updateHoleGeometries();
67724             }
67725             if (this._outline != null) {
67726                 this._updateOulineGeometry();
67727             }
67728         }
67729         _onTagChanged() {
67730             let glObjectsChanged = false;
67731             if (this._fill != null) {
67732                 this._updateFillMaterial(this._fill.material);
67733             }
67734             if (this._outline == null) {
67735                 if (this._tag.lineWidth >= 1) {
67736                     this._holes = this._createHoles();
67737                     this._outline = this._createOutline();
67738                     glObjectsChanged = true;
67739                 }
67740             }
67741             else {
67742                 this._updateHoleMaterials();
67743                 this._updateOutlineMaterial();
67744             }
67745             return glObjectsChanged;
67746         }
67747         _getPoints3d() {
67748             return this._in3dDomain() ?
67749                 this._tag.geometry.getVertices3d(this._transform) :
67750                 this._tag.geometry.getPoints3d(this._transform);
67751         }
67752         _getTriangles() {
67753             return this._in3dDomain() ?
67754                 this._tag.geometry.get3dDomainTriangles3d(this._transform) :
67755                 this._tag.geometry.getTriangles3d(this._transform);
67756         }
67757         _updateFillMaterial(material) {
67758             material.color = new Color(this._tag.fillColor);
67759             material.opacity = this._tag.fillOpacity;
67760             material.needsUpdate = true;
67761         }
67762         _updateLineBasicMaterial(material) {
67763             material.color = new Color(this._tag.lineColor);
67764             material.linewidth = Math.max(this._tag.lineWidth, 1);
67765             material.visible = this._tag.lineWidth >= 1 && this._tag.lineOpacity > 0;
67766             material.opacity = this._tag.lineOpacity;
67767             material.transparent = this._tag.lineOpacity < 1;
67768             material.needsUpdate = true;
67769         }
67770         _createHoles() {
67771             let holes = [];
67772             if (this._tag.geometry instanceof PolygonGeometry) {
67773                 let holes3d = this._getHoles3d();
67774                 for (let holePoints3d of holes3d) {
67775                     let hole = this._createLine(holePoints3d);
67776                     holes.push(hole);
67777                 }
67778             }
67779             return holes;
67780         }
67781         _disposeHoles() {
67782             for (let hole of this._holes) {
67783                 hole.geometry.dispose();
67784                 hole.material.dispose();
67785             }
67786             this._holes = [];
67787         }
67788         _getHoles3d() {
67789             const polygonGeometry = this._tag.geometry;
67790             return this._in3dDomain() ?
67791                 polygonGeometry.getHoleVertices3d(this._transform) :
67792                 polygonGeometry.getHolePoints3d(this._transform);
67793         }
67794         _in3dDomain() {
67795             return this._tag.geometry instanceof PolygonGeometry && this._tag.domain === exports.TagDomain.ThreeDimensional;
67796         }
67797         _updateHoleGeometries() {
67798             let holes3d = this._getHoles3d();
67799             if (holes3d.length !== this._holes.length) {
67800                 throw new Error("Changing the number of holes is not supported.");
67801             }
67802             for (let i = 0; i < this._holes.length; i++) {
67803                 let holePoints3d = holes3d[i];
67804                 let hole = this._holes[i];
67805                 this._updateLine(hole, holePoints3d);
67806             }
67807         }
67808         _updateHoleMaterials() {
67809             for (const hole of this._holes) {
67810                 this._updateLineBasicMaterial(hole.material);
67811             }
67812         }
67813         _updateOutlineMaterial() {
67814             this._updateLineBasicMaterial(this._outline.material);
67815         }
67816     }
67817
67818     /**
67819      * Enumeration for alignments
67820      * @enum {number}
67821      * @readonly
67822      */
67823     exports.Alignment = void 0;
67824     (function (Alignment) {
67825         /**
67826          * Align to bottom
67827          */
67828         Alignment[Alignment["Bottom"] = 0] = "Bottom";
67829         /**
67830          * Align to bottom left
67831          */
67832         Alignment[Alignment["BottomLeft"] = 1] = "BottomLeft";
67833         /**
67834          * Align to bottom right
67835          */
67836         Alignment[Alignment["BottomRight"] = 2] = "BottomRight";
67837         /**
67838          * Align to center
67839          */
67840         Alignment[Alignment["Center"] = 3] = "Center";
67841         /**
67842          * Align to left
67843          */
67844         Alignment[Alignment["Left"] = 4] = "Left";
67845         /**
67846          * Align to right
67847          */
67848         Alignment[Alignment["Right"] = 5] = "Right";
67849         /**
67850          * Align to top
67851          */
67852         Alignment[Alignment["Top"] = 6] = "Top";
67853         /**
67854          * Align to top left
67855          */
67856         Alignment[Alignment["TopLeft"] = 7] = "TopLeft";
67857         /**
67858          * Align to top right
67859          */
67860         Alignment[Alignment["TopRight"] = 8] = "TopRight";
67861     })(exports.Alignment || (exports.Alignment = {}));
67862
67863     /**
67864      * @class OutlineTag
67865      *
67866      * @classdesc Tag holding properties for visualizing a geometry outline.
67867      *
67868      * @example
67869      * ```js
67870      * var geometry = new RectGeometry([0.3, 0.3, 0.5, 0.4]);
67871      * var tag = new OutlineTag(
67872      *     "id-1",
67873      *     geometry
67874      *     { editable: true, lineColor: 0xff0000 });
67875      *
67876      * tagComponent.add([tag]);
67877      * ```
67878      */
67879     class OutlineTag extends Tag {
67880         /**
67881          * Create an outline tag.
67882          *
67883          * @override
67884          * @constructor
67885          * @param {string} id - Unique identifier of the tag.
67886          * @param {VertexGeometry} geometry - Geometry defining vertices of tag.
67887          * @param {OutlineTagOptions} options - Options defining the visual appearance and
67888          * behavior of the outline tag.
67889          */
67890         constructor(id, geometry, options) {
67891             super(id, geometry);
67892             options = !!options ? options : {};
67893             const domain = options.domain != null && geometry instanceof PolygonGeometry ?
67894                 options.domain : exports.TagDomain.TwoDimensional;
67895             const twoDimensionalPolygon = this._twoDimensionalPolygon(domain, geometry);
67896             this._domain = domain;
67897             this._editable = options.editable == null || twoDimensionalPolygon ? false : options.editable;
67898             this._fillColor = options.fillColor == null ? 0xFFFFFF : options.fillColor;
67899             this._fillOpacity = options.fillOpacity == null ? 0.0 : options.fillOpacity;
67900             this._icon = options.icon === undefined ? null : options.icon;
67901             this._iconFloat = options.iconFloat == null ? exports.Alignment.Center : options.iconFloat;
67902             this._iconIndex = options.iconIndex == null ? 3 : options.iconIndex;
67903             this._indicateVertices = options.indicateVertices == null ? true : options.indicateVertices;
67904             this._lineColor = options.lineColor == null ? 0xFFFFFF : options.lineColor;
67905             this._lineOpacity = options.lineOpacity == null ? 1 : options.lineOpacity;
67906             this._lineWidth = options.lineWidth == null ? 1 : options.lineWidth;
67907             this._text = options.text === undefined ? null : options.text;
67908             this._textColor = options.textColor == null ? 0xFFFFFF : options.textColor;
67909             this._click$ = new Subject();
67910             this._click$
67911                 .subscribe(() => {
67912                 const type = "click";
67913                 const event = {
67914                     target: this,
67915                     type,
67916                 };
67917                 this.fire(type, event);
67918             });
67919         }
67920         /**
67921          * Click observable.
67922          *
67923          * @description An observable emitting the tag when the icon of the
67924          * tag has been clicked.
67925          *
67926          * @returns {Observable<Tag>}
67927          */
67928         get click$() {
67929             return this._click$;
67930         }
67931         /**
67932          * Get domain property.
67933          *
67934          * @description Readonly property that can only be set in constructor.
67935          *
67936          * @returns Value indicating the domain of the tag.
67937          */
67938         get domain() {
67939             return this._domain;
67940         }
67941         /**
67942          * Get editable property.
67943          * @returns {boolean} Value indicating if tag is editable.
67944          */
67945         get editable() {
67946             return this._editable;
67947         }
67948         /**
67949          * Set editable property.
67950          * @param {boolean}
67951          *
67952          * @fires changed
67953          */
67954         set editable(value) {
67955             if (this._twoDimensionalPolygon(this._domain, this._geometry)) {
67956                 return;
67957             }
67958             this._editable = value;
67959             this._notifyChanged$.next(this);
67960         }
67961         /**
67962          * Get fill color property.
67963          * @returns {number}
67964          */
67965         get fillColor() {
67966             return this._fillColor;
67967         }
67968         /**
67969          * Set fill color property.
67970          * @param {number}
67971          *
67972          * @fires changed
67973          */
67974         set fillColor(value) {
67975             this._fillColor = value;
67976             this._notifyChanged$.next(this);
67977         }
67978         /**
67979          * Get fill opacity property.
67980          * @returns {number}
67981          */
67982         get fillOpacity() {
67983             return this._fillOpacity;
67984         }
67985         /**
67986          * Set fill opacity property.
67987          * @param {number}
67988          *
67989          * @fires changed
67990          */
67991         set fillOpacity(value) {
67992             this._fillOpacity = value;
67993             this._notifyChanged$.next(this);
67994         }
67995         /** @inheritdoc */
67996         get geometry() {
67997             return this._geometry;
67998         }
67999         /**
68000          * Get icon property.
68001          * @returns {string}
68002          */
68003         get icon() {
68004             return this._icon;
68005         }
68006         /**
68007          * Set icon property.
68008          * @param {string}
68009          *
68010          * @fires changed
68011          */
68012         set icon(value) {
68013             this._icon = value;
68014             this._notifyChanged$.next(this);
68015         }
68016         /**
68017          * Get icon float property.
68018          * @returns {Alignment}
68019          */
68020         get iconFloat() {
68021             return this._iconFloat;
68022         }
68023         /**
68024          * Set icon float property.
68025          * @param {Alignment}
68026          *
68027          * @fires changed
68028          */
68029         set iconFloat(value) {
68030             this._iconFloat = value;
68031             this._notifyChanged$.next(this);
68032         }
68033         /**
68034          * Get icon index property.
68035          * @returns {number}
68036          */
68037         get iconIndex() {
68038             return this._iconIndex;
68039         }
68040         /**
68041          * Set icon index property.
68042          * @param {number}
68043          *
68044          * @fires changed
68045          */
68046         set iconIndex(value) {
68047             this._iconIndex = value;
68048             this._notifyChanged$.next(this);
68049         }
68050         /**
68051          * Get indicate vertices property.
68052          * @returns {boolean} Value indicating if vertices should be indicated
68053          * when tag is editable.
68054          */
68055         get indicateVertices() {
68056             return this._indicateVertices;
68057         }
68058         /**
68059          * Set indicate vertices property.
68060          * @param {boolean}
68061          *
68062          * @fires changed
68063          */
68064         set indicateVertices(value) {
68065             this._indicateVertices = value;
68066             this._notifyChanged$.next(this);
68067         }
68068         /**
68069          * Get line color property.
68070          * @returns {number}
68071          */
68072         get lineColor() {
68073             return this._lineColor;
68074         }
68075         /**
68076          * Set line color property.
68077          * @param {number}
68078          *
68079          * @fires changed
68080          */
68081         set lineColor(value) {
68082             this._lineColor = value;
68083             this._notifyChanged$.next(this);
68084         }
68085         /**
68086          * Get line opacity property.
68087          * @returns {number}
68088          */
68089         get lineOpacity() {
68090             return this._lineOpacity;
68091         }
68092         /**
68093          * Set line opacity property.
68094          * @param {number}
68095          *
68096          * @fires changed
68097          */
68098         set lineOpacity(value) {
68099             this._lineOpacity = value;
68100             this._notifyChanged$.next(this);
68101         }
68102         /**
68103          * Get line width property.
68104          * @returns {number}
68105          */
68106         get lineWidth() {
68107             return this._lineWidth;
68108         }
68109         /**
68110          * Set line width property.
68111          * @param {number}
68112          *
68113          * @fires changed
68114          */
68115         set lineWidth(value) {
68116             this._lineWidth = value;
68117             this._notifyChanged$.next(this);
68118         }
68119         /**
68120          * Get text property.
68121          * @returns {string}
68122          */
68123         get text() {
68124             return this._text;
68125         }
68126         /**
68127          * Set text property.
68128          * @param {string}
68129          *
68130          * @fires changed
68131          */
68132         set text(value) {
68133             this._text = value;
68134             this._notifyChanged$.next(this);
68135         }
68136         /**
68137          * Get text color property.
68138          * @returns {number}
68139          */
68140         get textColor() {
68141             return this._textColor;
68142         }
68143         /**
68144          * Set text color property.
68145          * @param {number}
68146          *
68147          * @fires changed
68148          */
68149         set textColor(value) {
68150             this._textColor = value;
68151             this._notifyChanged$.next(this);
68152         }
68153         fire(type, event) {
68154             super.fire(type, event);
68155         }
68156         off(type, handler) {
68157             super.off(type, handler);
68158         }
68159         on(type, handler) {
68160             super.on(type, handler);
68161         }
68162         /**
68163          * Set options for tag.
68164          *
68165          * @description Sets all the option properties provided and keeps
68166          * the rest of the values as is.
68167          *
68168          * @param {OutlineTagOptions} options - Outline tag options
68169          *
68170          * @fires changed
68171          */
68172         setOptions(options) {
68173             const twoDimensionalPolygon = this._twoDimensionalPolygon(this._domain, this._geometry);
68174             this._editable = twoDimensionalPolygon || options.editable == null ? this._editable : options.editable;
68175             this._icon = options.icon === undefined ? this._icon : options.icon;
68176             this._iconFloat = options.iconFloat == null ? this._iconFloat : options.iconFloat;
68177             this._iconIndex = options.iconIndex == null ? this._iconIndex : options.iconIndex;
68178             this._indicateVertices = options.indicateVertices == null ? this._indicateVertices : options.indicateVertices;
68179             this._lineColor = options.lineColor == null ? this._lineColor : options.lineColor;
68180             this._lineWidth = options.lineWidth == null ? this._lineWidth : options.lineWidth;
68181             this._fillColor = options.fillColor == null ? this._fillColor : options.fillColor;
68182             this._fillOpacity = options.fillOpacity == null ? this._fillOpacity : options.fillOpacity;
68183             this._text = options.text === undefined ? this._text : options.text;
68184             this._textColor = options.textColor == null ? this._textColor : options.textColor;
68185             this._notifyChanged$.next(this);
68186         }
68187         _twoDimensionalPolygon(domain, geometry) {
68188             return domain !== exports.TagDomain.ThreeDimensional && geometry instanceof PolygonGeometry;
68189         }
68190     }
68191
68192     /**
68193      * @class SpotRenderTag
68194      * @classdesc Tag visualizing the properties of a SpotTag.
68195      */
68196     class SpotRenderTag extends RenderTag {
68197         dispose() { }
68198         getDOMObjects(atlas, camera, size) {
68199             const tag = this._tag;
68200             const container = {
68201                 offsetHeight: size.height, offsetWidth: size.width,
68202             };
68203             const vNodes = [];
68204             const [centroidBasicX, centroidBasicY] = tag.geometry.getCentroid2d();
68205             const centroidCanvas = this._viewportCoords.basicToCanvasSafe(centroidBasicX, centroidBasicY, container, this._transform, camera);
68206             if (centroidCanvas != null) {
68207                 const interactNone = (e) => {
68208                     this._interact$.next({ offsetX: 0, offsetY: 0, operation: TagOperation.None, tag: tag });
68209                 };
68210                 const canvasX = Math.round(centroidCanvas[0]);
68211                 const canvasY = Math.round(centroidCanvas[1]);
68212                 if (tag.icon != null) {
68213                     if (atlas.loaded) {
68214                         const sprite = atlas.getDOMSprite(tag.icon, exports.Alignment.Bottom);
68215                         const iconTransform = `translate(${canvasX}px,${canvasY + 8}px)`;
68216                         const properties = {
68217                             onpointerdown: interactNone,
68218                             style: {
68219                                 pointerEvents: "all",
68220                                 transform: iconTransform,
68221                             },
68222                         };
68223                         vNodes.push(virtualDom.h("div", properties, [sprite]));
68224                     }
68225                 }
68226                 else if (tag.text != null) {
68227                     const textTransform = `translate(-50%,0%) translate(${canvasX}px,${canvasY + 8}px)`;
68228                     const properties = {
68229                         onpointerdown: interactNone,
68230                         style: {
68231                             color: this._colorToCss(tag.textColor),
68232                             transform: textTransform,
68233                         },
68234                         textContent: tag.text,
68235                     };
68236                     vNodes.push(virtualDom.h("span.mapillary-tag-symbol", properties, []));
68237                 }
68238                 const interact = this._interact(TagOperation.Centroid, tag, "move");
68239                 const background = this._colorToCss(tag.color);
68240                 const transform = `translate(-50%,-50%) translate(${canvasX}px,${canvasY}px)`;
68241                 if (tag.editable) {
68242                     let interactorProperties = {
68243                         onpointerdown: interact,
68244                         style: {
68245                             background: background,
68246                             transform: transform,
68247                         },
68248                     };
68249                     vNodes.push(virtualDom.h("div.mapillary-tag-spot-interactor", interactorProperties, []));
68250                 }
68251                 const pointProperties = {
68252                     style: {
68253                         background: background,
68254                         transform: transform,
68255                     },
68256                 };
68257                 vNodes.push(virtualDom.h("div.mapillary-tag-vertex", pointProperties, []));
68258             }
68259             return vNodes;
68260         }
68261         getGLObjects() { return []; }
68262         getRetrievableObjects() { return []; }
68263         _colorToCss(color) {
68264             return "#" + ("000000" + color.toString(16)).substr(-6);
68265         }
68266         _interact(operation, tag, cursor, vertexIndex) {
68267             return (e) => {
68268                 const offsetX = e.offsetX - e.target.offsetWidth / 2;
68269                 const offsetY = e.offsetY - e.target.offsetHeight / 2;
68270                 this._interact$.next({
68271                     cursor: cursor,
68272                     offsetX: offsetX,
68273                     offsetY: offsetY,
68274                     operation: operation,
68275                     tag: tag,
68276                     vertexIndex: vertexIndex,
68277                 });
68278             };
68279         }
68280     }
68281
68282     /**
68283      * @class SpotTag
68284      *
68285      * @classdesc Tag holding properties for visualizing the centroid of a geometry.
68286      *
68287      * @example
68288      * ```js
68289      * var geometry = new PointGeometry([0.3, 0.3]);
68290      * var tag = new SpotTag(
68291      *     "id-1",
68292      *     geometry
68293      *     { editable: true, color: 0xff0000 });
68294      *
68295      * tagComponent.add([tag]);
68296      * ```
68297      */
68298     class SpotTag extends Tag {
68299         /**
68300          * Create a spot tag.
68301          *
68302          * @override
68303          * @constructor
68304          * @param {string} id
68305          * @param {Geometry} geometry
68306          * @param {IOutlineTagOptions} options - Options defining the visual appearance and
68307          * behavior of the spot tag.
68308          */
68309         constructor(id, geometry, options) {
68310             super(id, geometry);
68311             options = !!options ? options : {};
68312             this._color = options.color == null ? 0xFFFFFF : options.color;
68313             this._editable = options.editable == null ? false : options.editable;
68314             this._icon = options.icon === undefined ? null : options.icon;
68315             this._text = options.text === undefined ? null : options.text;
68316             this._textColor = options.textColor == null ? 0xFFFFFF : options.textColor;
68317         }
68318         /**
68319          * Get color property.
68320          * @returns {number} The color of the spot as a hexagonal number;
68321          */
68322         get color() {
68323             return this._color;
68324         }
68325         /**
68326          * Set color property.
68327          * @param {number}
68328          *
68329          * @fires changed
68330          */
68331         set color(value) {
68332             this._color = value;
68333             this._notifyChanged$.next(this);
68334         }
68335         /**
68336          * Get editable property.
68337          * @returns {boolean} Value indicating if tag is editable.
68338          */
68339         get editable() {
68340             return this._editable;
68341         }
68342         /**
68343          * Set editable property.
68344          * @param {boolean}
68345          *
68346          * @fires changed
68347          */
68348         set editable(value) {
68349             this._editable = value;
68350             this._notifyChanged$.next(this);
68351         }
68352         /**
68353          * Get icon property.
68354          * @returns {string}
68355          */
68356         get icon() {
68357             return this._icon;
68358         }
68359         /**
68360          * Set icon property.
68361          * @param {string}
68362          *
68363          * @fires changed
68364          */
68365         set icon(value) {
68366             this._icon = value;
68367             this._notifyChanged$.next(this);
68368         }
68369         /**
68370          * Get text property.
68371          * @returns {string}
68372          */
68373         get text() {
68374             return this._text;
68375         }
68376         /**
68377          * Set text property.
68378          * @param {string}
68379          *
68380          * @fires changed
68381          */
68382         set text(value) {
68383             this._text = value;
68384             this._notifyChanged$.next(this);
68385         }
68386         /**
68387          * Get text color property.
68388          * @returns {number}
68389          */
68390         get textColor() {
68391             return this._textColor;
68392         }
68393         /**
68394          * Set text color property.
68395          * @param {number}
68396          *
68397          * @fires changed
68398          */
68399         set textColor(value) {
68400             this._textColor = value;
68401             this._notifyChanged$.next(this);
68402         }
68403         /**
68404          * Set options for tag.
68405          *
68406          * @description Sets all the option properties provided and keps
68407          * the rest of the values as is.
68408          *
68409          * @param {SpotTagOptions} options - Spot tag options
68410          *
68411          * @fires changed
68412          */
68413         setOptions(options) {
68414             this._color = options.color == null ? this._color : options.color;
68415             this._editable = options.editable == null ? this._editable : options.editable;
68416             this._icon = options.icon === undefined ? this._icon : options.icon;
68417             this._text = options.text === undefined ? this._text : options.text;
68418             this._textColor = options.textColor == null ? this._textColor : options.textColor;
68419             this._notifyChanged$.next(this);
68420         }
68421     }
68422
68423     class TagSet {
68424         constructor() {
68425             this._active = false;
68426             this._hash = {};
68427             this._hashDeactivated = {};
68428             this._notifyChanged$ = new Subject();
68429         }
68430         get active() {
68431             return this._active;
68432         }
68433         get changed$() {
68434             return this._notifyChanged$;
68435         }
68436         activate(transform) {
68437             if (this._active) {
68438                 return;
68439             }
68440             for (const id in this._hashDeactivated) {
68441                 if (!this._hashDeactivated.hasOwnProperty(id)) {
68442                     continue;
68443                 }
68444                 const tag = this._hashDeactivated[id];
68445                 this._add(tag, transform);
68446             }
68447             this._hashDeactivated = {};
68448             this._active = true;
68449             this._notifyChanged$.next(this);
68450         }
68451         deactivate() {
68452             if (!this._active) {
68453                 return;
68454             }
68455             for (const id in this._hash) {
68456                 if (!this._hash.hasOwnProperty(id)) {
68457                     continue;
68458                 }
68459                 this._hashDeactivated[id] = this._hash[id].tag;
68460             }
68461             this._hash = {};
68462             this._active = false;
68463         }
68464         add(tags, transform) {
68465             this._assertActivationState(true);
68466             for (const tag of tags) {
68467                 this._add(tag, transform);
68468             }
68469             this._notifyChanged$.next(this);
68470         }
68471         addDeactivated(tags) {
68472             this._assertActivationState(false);
68473             for (const tag of tags) {
68474                 if (!(tag instanceof OutlineTag ||
68475                     tag instanceof SpotTag ||
68476                     tag instanceof ExtremePointTag)) {
68477                     throw new Error("Tag type not supported");
68478                 }
68479                 this._hashDeactivated[tag.id] = tag;
68480             }
68481         }
68482         get(id) {
68483             return this.has(id) ? this._hash[id] : undefined;
68484         }
68485         getAll() {
68486             const hash = this._hash;
68487             return Object.keys(hash)
68488                 .map((id) => {
68489                 return hash[id];
68490             });
68491         }
68492         getAllDeactivated() {
68493             const hashDeactivated = this._hashDeactivated;
68494             return Object.keys(hashDeactivated)
68495                 .map((id) => {
68496                 return hashDeactivated[id];
68497             });
68498         }
68499         getDeactivated(id) {
68500             return this.hasDeactivated(id) ? this._hashDeactivated[id] : undefined;
68501         }
68502         has(id) {
68503             return id in this._hash;
68504         }
68505         hasDeactivated(id) {
68506             return id in this._hashDeactivated;
68507         }
68508         remove(ids) {
68509             this._assertActivationState(true);
68510             const hash = this._hash;
68511             for (const id of ids) {
68512                 if (!(id in hash)) {
68513                     continue;
68514                 }
68515                 delete hash[id];
68516             }
68517             this._notifyChanged$.next(this);
68518         }
68519         removeAll() {
68520             this._assertActivationState(true);
68521             this._hash = {};
68522             this._notifyChanged$.next(this);
68523         }
68524         removeAllDeactivated() {
68525             this._assertActivationState(false);
68526             this._hashDeactivated = {};
68527         }
68528         removeDeactivated(ids) {
68529             this._assertActivationState(false);
68530             const hashDeactivated = this._hashDeactivated;
68531             for (const id of ids) {
68532                 if (!(id in hashDeactivated)) {
68533                     continue;
68534                 }
68535                 delete hashDeactivated[id];
68536             }
68537         }
68538         _add(tag, transform) {
68539             if (tag instanceof OutlineTag) {
68540                 this._hash[tag.id] = new OutlineRenderTag(tag, transform);
68541             }
68542             else if (tag instanceof SpotTag) {
68543                 this._hash[tag.id] = new SpotRenderTag(tag, transform);
68544             }
68545             else if (tag instanceof ExtremePointTag) {
68546                 this._hash[tag.id] = new ExtremePointRenderTag(tag, transform);
68547             }
68548             else {
68549                 throw new Error("Tag type not supported");
68550             }
68551         }
68552         _assertActivationState(should) {
68553             if (should !== this._active) {
68554                 throw new Error("Tag set not in correct state for operation.");
68555             }
68556         }
68557     }
68558
68559     /**
68560      * @class PointGeometry
68561      *
68562      * @classdesc Represents a point geometry in the 2D basic image coordinate system.
68563      *
68564      * @example
68565      * ```js
68566      * var basicPoint = [0.5, 0.7];
68567      * var pointGeometry = new PointGeometry(basicPoint);
68568      * ```
68569      */
68570     class PointGeometry extends Geometry {
68571         /**
68572          * Create a point geometry.
68573          *
68574          * @constructor
68575          * @param {Array<number>} point - An array representing the basic coordinates of
68576          * the point.
68577          *
68578          * @throws {GeometryTagError} Point coordinates must be valid basic coordinates.
68579          */
68580         constructor(point) {
68581             super();
68582             let x = point[0];
68583             let y = point[1];
68584             if (x < 0 || x > 1 || y < 0 || y > 1) {
68585                 throw new GeometryTagError("Basic coordinates must be on the interval [0, 1].");
68586             }
68587             this._point = point.slice();
68588         }
68589         /**
68590          * Get point property.
68591          * @returns {Array<number>} Array representing the basic coordinates of the point.
68592          */
68593         get point() {
68594             return this._point;
68595         }
68596         /**
68597          * Get the 2D basic coordinates for the centroid of the point, i.e. the 2D
68598          * basic coordinates of the point itself.
68599          *
68600          * @returns {Array<number>} 2D basic coordinates representing the centroid.
68601          * @ignore
68602          */
68603         getCentroid2d() {
68604             return this._point.slice();
68605         }
68606         /**
68607          * Get the 3D world coordinates for the centroid of the point, i.e. the 3D
68608          * world coordinates of the point itself.
68609          *
68610          * @param {Transform} transform - The transform of the image related to the point.
68611          * @returns {Array<number>} 3D world coordinates representing the centroid.
68612          * @ignore
68613          */
68614         getCentroid3d(transform) {
68615             return transform.unprojectBasic(this._point, 200);
68616         }
68617         /**
68618          * Set the centroid of the point, i.e. the point coordinates.
68619          *
68620          * @param {Array<number>} value - The new value of the centroid.
68621          * @param {Transform} transform - The transform of the image related to the point.
68622          * @ignore
68623          */
68624         setCentroid2d(value, transform) {
68625             let changed = [
68626                 Math.max(0, Math.min(1, value[0])),
68627                 Math.max(0, Math.min(1, value[1])),
68628             ];
68629             this._point[0] = changed[0];
68630             this._point[1] = changed[1];
68631             this._notifyChanged$.next(this);
68632         }
68633     }
68634
68635     class TagHandlerBase extends HandlerBase {
68636         constructor(component, container, navigator, viewportCoords) {
68637             super(component, container, navigator);
68638             this._name = `${this._component.name}-${this._getNameExtension()}`;
68639             this._viewportCoords = viewportCoords;
68640         }
68641         _getConfiguration(enable) {
68642             return {};
68643         }
68644         _mouseEventToBasic(event, element, camera, transform, offsetX, offsetY) {
68645             offsetX = offsetX != null ? offsetX : 0;
68646             offsetY = offsetY != null ? offsetY : 0;
68647             const [canvasX, canvasY] = this._viewportCoords.canvasPosition(event, element);
68648             const basic = this._viewportCoords.canvasToBasic(canvasX - offsetX, canvasY - offsetY, element, transform, camera.perspective);
68649             return basic;
68650         }
68651     }
68652
68653     class CreateHandlerBase extends TagHandlerBase {
68654         constructor(component, container, navigator, viewportCoords, tagCreator) {
68655             super(component, container, navigator, viewportCoords);
68656             this._tagCreator = tagCreator;
68657             this._geometryCreated$ = new Subject();
68658         }
68659         get geometryCreated$() {
68660             return this._geometryCreated$;
68661         }
68662         _enable() {
68663             this._enableCreate();
68664             this._container.container.classList.add("component-tag-create");
68665         }
68666         _disable() {
68667             this._container.container.classList.remove("component-tag-create");
68668             this._disableCreate();
68669         }
68670         _validateBasic(basic) {
68671             const x = basic[0];
68672             const y = basic[1];
68673             return 0 <= x && x <= 1 && 0 <= y && y <= 1;
68674         }
68675         _mouseEventToBasic$(mouseEvent$) {
68676             return mouseEvent$.pipe(withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$), map(([event, camera, transform]) => {
68677                 return this._mouseEventToBasic(event, this._container.container, camera, transform);
68678             }));
68679         }
68680     }
68681
68682     class CreatePointHandler extends CreateHandlerBase {
68683         _enableCreate() {
68684             this._container.mouseService.deferPixels(this._name, 4);
68685             this._geometryCreatedSubscription = this._mouseEventToBasic$(this._container.mouseService.proximateClick$).pipe(filter(this._validateBasic), map((basic) => {
68686                 return new PointGeometry(basic);
68687             }))
68688                 .subscribe(this._geometryCreated$);
68689         }
68690         _disableCreate() {
68691             this._container.mouseService.undeferPixels(this._name);
68692             this._geometryCreatedSubscription.unsubscribe();
68693         }
68694         _getNameExtension() {
68695             return "create-point";
68696         }
68697     }
68698
68699     class CreateVertexHandler extends CreateHandlerBase {
68700         _enableCreate() {
68701             this._container.mouseService.deferPixels(this._name, 4);
68702             const transformChanged$ = this._navigator.stateService.currentTransform$.pipe(map(() => { }), publishReplay(1), refCount());
68703             this._deleteSubscription = transformChanged$.pipe(skip(1))
68704                 .subscribe(this._tagCreator.delete$);
68705             const basicClick$ = this._mouseEventToBasic$(this._container.mouseService.proximateClick$).pipe(share());
68706             this._createSubscription = transformChanged$.pipe(switchMap(() => {
68707                 return basicClick$.pipe(filter(this._validateBasic), take(1));
68708             }))
68709                 .subscribe(this._create$);
68710             this._setVertexSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
68711                 return !!tag ?
68712                     combineLatest(of(tag), merge(this._container.mouseService.mouseMove$, this._container.mouseService.domMouseMove$), this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$) :
68713                     empty();
68714             }))
68715                 .subscribe(([tag, event, camera, transform]) => {
68716                 const basicPoint = this._mouseEventToBasic(event, this._container.container, camera, transform);
68717                 this._setVertex2d(tag, basicPoint, transform);
68718             });
68719             this._addPointSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
68720                 return !!tag ?
68721                     combineLatest(of(tag), basicClick$) :
68722                     empty();
68723             }))
68724                 .subscribe(([tag, basicPoint]) => {
68725                 this._addPoint(tag, basicPoint);
68726             });
68727             this._geometryCreateSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
68728                 return !!tag ?
68729                     tag.created$.pipe(map((t) => {
68730                         return t.geometry;
68731                     })) :
68732                     empty();
68733             }))
68734                 .subscribe(this._geometryCreated$);
68735         }
68736         _disableCreate() {
68737             this._container.mouseService.undeferPixels(this._name);
68738             this._tagCreator.delete$.next(null);
68739             this._addPointSubscription.unsubscribe();
68740             this._createSubscription.unsubscribe();
68741             this._deleteSubscription.unsubscribe();
68742             this._geometryCreateSubscription.unsubscribe();
68743             this._setVertexSubscription.unsubscribe();
68744         }
68745     }
68746
68747     class CreatePointsHandler extends CreateVertexHandler {
68748         get _create$() {
68749             return this._tagCreator.createPoints$;
68750         }
68751         _addPoint(tag, basicPoint) {
68752             tag.geometry.addPoint2d(basicPoint);
68753         }
68754         _getNameExtension() {
68755             return "create-points";
68756         }
68757         _setVertex2d(tag, basicPoint, transform) {
68758             tag.geometry.setPoint2d((tag.geometry).points.length - 1, basicPoint, transform);
68759         }
68760     }
68761
68762     class CreatePolygonHandler extends CreateVertexHandler {
68763         get _create$() {
68764             return this._tagCreator.createPolygon$;
68765         }
68766         _addPoint(tag, basicPoint) {
68767             tag.addPoint(basicPoint);
68768         }
68769         _getNameExtension() {
68770             return "create-polygon";
68771         }
68772         _setVertex2d(tag, basicPoint, transform) {
68773             tag.geometry.setVertex2d(tag.geometry.polygon.length - 2, basicPoint, transform);
68774         }
68775     }
68776
68777     class CreateRectHandler extends CreateVertexHandler {
68778         get _create$() {
68779             return this._tagCreator.createRect$;
68780         }
68781         _addPoint(tag, basicPoint) {
68782             const rectGeometry = tag.geometry;
68783             if (!rectGeometry.validate(basicPoint)) {
68784                 basicPoint = rectGeometry.getNonAdjustedVertex2d(3);
68785             }
68786             tag.addPoint(basicPoint);
68787         }
68788         _enable() {
68789             super._enable();
68790             this._initializeAnchorIndexingSubscription = this._tagCreator.tag$.pipe(filter((tag) => {
68791                 return !!tag;
68792             }))
68793                 .subscribe((tag) => {
68794                 tag.geometry.initializeAnchorIndexing();
68795             });
68796         }
68797         _disable() {
68798             super._disable();
68799             this._initializeAnchorIndexingSubscription.unsubscribe();
68800         }
68801         _getNameExtension() {
68802             return "create-rect";
68803         }
68804         _setVertex2d(tag, basicPoint, transform) {
68805             tag.geometry.setOppositeVertex2d(basicPoint, transform);
68806         }
68807     }
68808
68809     class CreateRectDragHandler extends CreateHandlerBase {
68810         _enableCreate() {
68811             this._container.mouseService.claimMouse(this._name, 2);
68812             this._deleteSubscription = this._navigator.stateService.currentTransform$.pipe(map((transform) => { return null; }), skip(1))
68813                 .subscribe(this._tagCreator.delete$);
68814             this._createSubscription = this._mouseEventToBasic$(this._container.mouseService.filtered$(this._name, this._container.mouseService.mouseDragStart$)).pipe(filter(this._validateBasic))
68815                 .subscribe(this._tagCreator.createRect$);
68816             this._initializeAnchorIndexingSubscription = this._tagCreator.tag$.pipe(filter((tag) => {
68817                 return !!tag;
68818             }))
68819                 .subscribe((tag) => {
68820                 tag.geometry.initializeAnchorIndexing();
68821             });
68822             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]) => {
68823                 return this._mouseEventToBasic(event, this._container.container, camera, transform);
68824             }));
68825             this._setVertexSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
68826                 return !!tag ?
68827                     combineLatest(of(tag), basicMouse$, this._navigator.stateService.currentTransform$) :
68828                     empty();
68829             }))
68830                 .subscribe(([tag, basicPoint, transform]) => {
68831                 tag.geometry.setOppositeVertex2d(basicPoint, transform);
68832             });
68833             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) => {
68834                 return basicPoint;
68835             }), share());
68836             this._addPointSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
68837                 return !!tag ?
68838                     combineLatest(of(tag), basicMouseDragEnd$) :
68839                     empty();
68840             }))
68841                 .subscribe(([tag, basicPoint]) => {
68842                 const rectGeometry = tag.geometry;
68843                 if (!rectGeometry.validate(basicPoint)) {
68844                     basicPoint = rectGeometry.getNonAdjustedVertex2d(3);
68845                 }
68846                 tag.addPoint(basicPoint);
68847             });
68848             this._geometryCreatedSubscription = this._tagCreator.tag$.pipe(switchMap((tag) => {
68849                 return !!tag ?
68850                     tag.created$.pipe(map((t) => {
68851                         return t.geometry;
68852                     })) :
68853                     empty();
68854             }))
68855                 .subscribe(this._geometryCreated$);
68856         }
68857         _disableCreate() {
68858             this._container.mouseService.unclaimMouse(this._name);
68859             this._tagCreator.delete$.next(null);
68860             this._addPointSubscription.unsubscribe();
68861             this._createSubscription.unsubscribe();
68862             this._deleteSubscription.unsubscribe();
68863             this._geometryCreatedSubscription.unsubscribe();
68864             this._initializeAnchorIndexingSubscription.unsubscribe();
68865             this._setVertexSubscription.unsubscribe();
68866         }
68867         _getNameExtension() {
68868             return "create-rect-drag";
68869         }
68870     }
68871
68872     class EditVertexHandler extends TagHandlerBase {
68873         constructor(component, container, navigator, viewportCoords, tagSet) {
68874             super(component, container, navigator, viewportCoords);
68875             this._tagSet = tagSet;
68876         }
68877         _enable() {
68878             const interaction$ = this._tagSet.changed$.pipe(map((tagSet) => {
68879                 return tagSet.getAll();
68880             }), switchMap((tags) => {
68881                 return from(tags).pipe(mergeMap((tag) => {
68882                     return tag.interact$;
68883                 }));
68884             }), switchMap((interaction) => {
68885                 return concat(of(interaction), this._container.mouseService.documentMouseUp$.pipe(map(() => {
68886                     return { offsetX: 0, offsetY: 0, operation: TagOperation.None, tag: null };
68887                 }), first()));
68888             }), share());
68889             merge(this._container.mouseService.mouseMove$, this._container.mouseService.domMouseMove$).pipe(share());
68890             this._claimMouseSubscription = interaction$.pipe(switchMap((interaction) => {
68891                 return !!interaction.tag ? this._container.mouseService.domMouseDragStart$ : empty();
68892             }))
68893                 .subscribe(() => {
68894                 this._container.mouseService.claimMouse(this._name, 3);
68895             });
68896             this._cursorSubscription = interaction$.pipe(map((interaction) => {
68897                 return interaction.cursor;
68898             }), distinctUntilChanged())
68899                 .subscribe((cursor) => {
68900                 const interactionCursors = ["crosshair", "move", "nesw-resize", "nwse-resize"];
68901                 for (const interactionCursor of interactionCursors) {
68902                     this._container.container.classList.remove(`component-tag-edit-${interactionCursor}`);
68903                 }
68904                 if (!!cursor) {
68905                     this._container.container.classList.add(`component-tag-edit-${cursor}`);
68906                 }
68907             });
68908             this._unclaimMouseSubscription = this._container.mouseService
68909                 .filtered$(this._name, this._container.mouseService.domMouseDragEnd$)
68910                 .subscribe((e) => {
68911                 this._container.mouseService.unclaimMouse(this._name);
68912             });
68913             this._preventDefaultSubscription = interaction$.pipe(switchMap((interaction) => {
68914                 return !!interaction.tag ?
68915                     this._container.mouseService.documentMouseMove$ :
68916                     empty();
68917             }))
68918                 .subscribe((event) => {
68919                 event.preventDefault(); // prevent selection of content outside the viewer
68920             });
68921             this._updateGeometrySubscription = interaction$.pipe(switchMap((interaction) => {
68922                 if (interaction.operation === TagOperation.None || !interaction.tag) {
68923                     return empty();
68924                 }
68925                 const mouseDrag$ = this._container.mouseService
68926                     .filtered$(this._name, this._container.mouseService.domMouseDrag$).pipe(filter((event) => {
68927                     return this._viewportCoords.insideElement(event, this._container.container);
68928                 }));
68929                 return combineLatest(mouseDrag$, this._container.renderService.renderCamera$).pipe(withLatestFrom(of(interaction), this._navigator.stateService.currentTransform$, ([event, render], i, transform) => {
68930                     return [event, render, i, transform];
68931                 }));
68932             }))
68933                 .subscribe(([mouseEvent, renderCamera, interaction, transform]) => {
68934                 const basic = this._mouseEventToBasic(mouseEvent, this._container.container, renderCamera, transform, interaction.offsetX, interaction.offsetY);
68935                 const geometry = interaction.tag.geometry;
68936                 if (interaction.operation === TagOperation.Centroid) {
68937                     geometry.setCentroid2d(basic, transform);
68938                 }
68939                 else if (interaction.operation === TagOperation.Vertex) {
68940                     geometry.setVertex2d(interaction.vertexIndex, basic, transform);
68941                 }
68942             });
68943         }
68944         _disable() {
68945             this._claimMouseSubscription.unsubscribe();
68946             this._cursorSubscription.unsubscribe();
68947             this._preventDefaultSubscription.unsubscribe();
68948             this._unclaimMouseSubscription.unsubscribe();
68949             this._updateGeometrySubscription.unsubscribe();
68950         }
68951         _getNameExtension() {
68952             return "edit-vertex";
68953         }
68954     }
68955
68956     /**
68957      * @class TagComponent
68958      *
68959      * @classdesc Component for showing and editing tags with different
68960      * geometries composed from 2D basic image coordinates (see the
68961      * {@link Viewer} class documentation for more information about coordinate
68962      * systems).
68963      *
68964      * The `add` method is used for adding new tags or replacing
68965      * tags already in the set. Tags are removed by id.
68966      *
68967      * If a tag already in the set has the same
68968      * id as one of the tags added, the old tag will be removed and
68969      * the added tag will take its place.
68970      *
68971      * The tag component mode can be set to either be non interactive or
68972      * to be in creating mode of a certain geometry type.
68973      *
68974      * The tag properties can be updated at any time and the change will
68975      * be visibile immediately.
68976      *
68977      * Tags are only relevant to a single image because they are based on
68978      * 2D basic image coordinates. Tags related to a certain image should
68979      * be removed when the viewer is moved to another image.
68980      *
68981      * To retrive and use the tag component
68982      *
68983      * @example
68984      * ```js
68985      * var viewer = new Viewer({ component: { tag: true } }, ...);
68986      *
68987      * var tagComponent = viewer.getComponent("tag");
68988      * ```
68989      */
68990     class TagComponent extends Component {
68991         /** @ignore */
68992         constructor(name, container, navigator) {
68993             super(name, container, navigator);
68994             this._tagDomRenderer = new TagDOMRenderer();
68995             this._tagScene = new TagScene();
68996             this._tagSet = new TagSet();
68997             this._tagCreator = new TagCreator(this, navigator);
68998             this._viewportCoords = new ViewportCoords();
68999             this._createHandlers = {
69000                 "CreatePoint": new CreatePointHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
69001                 "CreatePoints": new CreatePointsHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
69002                 "CreatePolygon": new CreatePolygonHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
69003                 "CreateRect": new CreateRectHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
69004                 "CreateRectDrag": new CreateRectDragHandler(this, container, navigator, this._viewportCoords, this._tagCreator),
69005                 "Default": undefined,
69006             };
69007             this._editVertexHandler =
69008                 new EditVertexHandler(this, container, navigator, this._viewportCoords, this._tagSet);
69009             this._renderTags$ = this._tagSet.changed$.pipe(map((tagSet) => {
69010                 const tags = tagSet.getAll();
69011                 // ensure that tags are always rendered in the same order
69012                 // to avoid hover tracking problems on first resize.
69013                 tags.sort((t1, t2) => {
69014                     const id1 = t1.tag.id;
69015                     const id2 = t2.tag.id;
69016                     if (id1 < id2) {
69017                         return -1;
69018                     }
69019                     if (id1 > id2) {
69020                         return 1;
69021                     }
69022                     return 0;
69023                 });
69024                 return tags;
69025             }), share());
69026             this._tagChanged$ = this._renderTags$.pipe(switchMap((tags) => {
69027                 return from(tags).pipe(mergeMap((tag) => {
69028                     return merge(tag.tag.changed$, tag.tag.geometryChanged$);
69029                 }));
69030             }), share());
69031             this._renderTagGLChanged$ = this._renderTags$.pipe(switchMap((tags) => {
69032                 return from(tags).pipe(mergeMap((tag) => {
69033                     return tag.glObjectsChanged$;
69034                 }));
69035             }), share());
69036             this._createGeometryChanged$ = this._tagCreator.tag$.pipe(switchMap((tag) => {
69037                 return tag != null ?
69038                     tag.geometryChanged$ :
69039                     empty();
69040             }), share());
69041             this._createGLObjectsChanged$ = this._tagCreator.tag$.pipe(switchMap((tag) => {
69042                 return tag != null ?
69043                     tag.glObjectsChanged$ :
69044                     empty();
69045             }), share());
69046             this._creatingConfiguration$ = this._configuration$.pipe(distinctUntilChanged((c1, c2) => {
69047                 return c1.mode === c2.mode;
69048             }, (configuration) => {
69049                 return {
69050                     createColor: configuration.createColor,
69051                     mode: configuration.mode,
69052                 };
69053             }), publishReplay(1), refCount());
69054             this._creatingConfiguration$
69055                 .subscribe((configuration) => {
69056                 const type = "tagmode";
69057                 const event = {
69058                     mode: configuration.mode,
69059                     target: this,
69060                     type,
69061                 };
69062                 this.fire(type, event);
69063             });
69064         }
69065         /**
69066          * Add tags to the tag set or replace tags in the tag set.
69067          *
69068          * @description If a tag already in the set has the same
69069          * id as one of the tags added, the old tag will be removed
69070          * the added tag will take its place.
69071          *
69072          * @param {Array<Tag>} tags - Tags to add.
69073          *
69074          * @example
69075          * ```js
69076          * tagComponent.add([tag1, tag2]);
69077          * ```
69078          */
69079         add(tags) {
69080             if (this._activated) {
69081                 this._navigator.stateService.currentTransform$.pipe(first())
69082                     .subscribe((transform) => {
69083                     this._tagSet.add(tags, transform);
69084                     const renderTags = tags
69085                         .map((tag) => {
69086                         return this._tagSet.get(tag.id);
69087                     });
69088                     this._tagScene.add(renderTags);
69089                 });
69090             }
69091             else {
69092                 this._tagSet.addDeactivated(tags);
69093             }
69094         }
69095         /**
69096          * Calculate the smallest rectangle containing all the points
69097          * in the points geometry.
69098          *
69099          * @description The result may be different depending on if the
69100          * current image is an spherical or not. If the
69101          * current image is an spherical the rectangle may
69102          * wrap the horizontal border of the image.
69103          *
69104          * @returns {Promise<Array<number>>} Promise to the rectangle
69105          * on the format specified for the {@link RectGeometry} in basic
69106          * coordinates.
69107          */
69108         calculateRect(geometry) {
69109             return new Promise((resolve, reject) => {
69110                 this._navigator.stateService.currentTransform$.pipe(first(), map((transform) => {
69111                     return geometry.getRect2d(transform);
69112                 }))
69113                     .subscribe((rect) => {
69114                     resolve(rect);
69115                 }, (error) => {
69116                     reject(error);
69117                 });
69118             });
69119         }
69120         /**
69121          * Force the creation of a geometry programatically using its
69122          * current vertices.
69123          *
69124          * @description The method only has an effect when the tag
69125          * mode is either of the following modes:
69126          *
69127          * {@link TagMode.CreatePoints}
69128          * {@link TagMode.CreatePolygon}
69129          * {@link TagMode.CreateRect}
69130          * {@link TagMode.CreateRectDrag}
69131          *
69132          * In the case of points or polygon creation, only the created
69133          * vertices are used, i.e. the mouse position is disregarded.
69134          *
69135          * In the case of rectangle creation the position of the mouse
69136          * at the time of the method call is used as one of the vertices
69137          * defining the rectangle.
69138          *
69139          * @fires geometrycreate
69140          *
69141          * @example
69142          * ```js
69143          * tagComponent.on("geometrycreate", function(geometry) {
69144          *     console.log(geometry);
69145          * });
69146          *
69147          * tagComponent.create();
69148          * ```
69149          */
69150         create() {
69151             this._tagCreator.replayedTag$.pipe(first(), filter((tag) => {
69152                 return !!tag;
69153             }))
69154                 .subscribe((tag) => {
69155                 tag.create();
69156             });
69157         }
69158         /**
69159          * Change the current tag mode.
69160          *
69161          * @description Change the tag mode to one of the create modes for creating new geometries.
69162          *
69163          * @param {TagMode} mode - New tag mode.
69164          *
69165          * @fires tagmode
69166          *
69167          * @example
69168          * ```js
69169          * tagComponent.changeMode(TagMode.CreateRect);
69170          * ```
69171          */
69172         changeMode(mode) {
69173             this.configure({ mode: mode });
69174         }
69175         fire(type, event) {
69176             super.fire(type, event);
69177         }
69178         /**
69179          * Returns the tag in the tag set with the specified id, or
69180          * undefined if the id matches no tag.
69181          *
69182          * @param {string} tagId - Id of the tag.
69183          *
69184          * @example
69185          * ```js
69186          * var tag = tagComponent.get("tagId");
69187          * ```
69188          */
69189         get(tagId) {
69190             if (this._activated) {
69191                 const renderTag = this._tagSet.get(tagId);
69192                 return renderTag !== undefined ? renderTag.tag : undefined;
69193             }
69194             else {
69195                 return this._tagSet.getDeactivated(tagId);
69196             }
69197         }
69198         /**
69199          * Returns an array of all tags.
69200          *
69201          * @example
69202          * ```js
69203          * var tags = tagComponent.getAll();
69204          * ```
69205          */
69206         getAll() {
69207             if (this.activated) {
69208                 return this._tagSet
69209                     .getAll()
69210                     .map((renderTag) => {
69211                     return renderTag.tag;
69212                 });
69213             }
69214             else {
69215                 return this._tagSet.getAllDeactivated();
69216             }
69217         }
69218         /**
69219          * Returns an array of tag ids for tags that contain the specified point.
69220          *
69221          * @description The pixel point must lie inside the polygon or rectangle
69222          * of an added tag for the tag id to be returned. Tag ids for
69223          * tags that do not have a fill will also be returned if the point is inside
69224          * the geometry of the tag. Tags with point geometries can not be retrieved.
69225          *
69226          * No tag ids will be returned for polygons rendered in cropped spherical or
69227          * rectangles rendered in spherical.
69228          *
69229          * Notice that the pixelPoint argument requires x, y coordinates from pixel space.
69230          *
69231          * With this function, you can use the coordinates provided by mouse
69232          * events to get information out of the tag component.
69233          *
69234          * If no tag at exist the pixel point, an empty array will be returned.
69235          *
69236          * @param {Array<number>} pixelPoint - Pixel coordinates on the viewer element.
69237          * @returns {Promise<Array<string>>} Promise to the ids of the tags that
69238          * contain the specified pixel point.
69239          *
69240          * @example
69241          * ```js
69242          * tagComponent.getTagIdsAt([100, 100])
69243          *     .then((tagIds) => { console.log(tagIds); });
69244          * ```
69245          */
69246         getTagIdsAt(pixelPoint) {
69247             return new Promise((resolve, reject) => {
69248                 this._container.renderService.renderCamera$.pipe(first(), map((render) => {
69249                     const viewport = this._viewportCoords
69250                         .canvasToViewport(pixelPoint[0], pixelPoint[1], this._container.container);
69251                     const ids = this._tagScene.intersectObjects(viewport, render.perspective);
69252                     return ids;
69253                 }))
69254                     .subscribe((ids) => {
69255                     resolve(ids);
69256                 }, (error) => {
69257                     reject(error);
69258                 });
69259             });
69260         }
69261         /**
69262          * Check if a tag exist in the tag set.
69263          *
69264          * @param {string} tagId - Id of the tag.
69265          *
69266          * @example
69267          * ```js
69268          * var tagExists = tagComponent.has("tagId");
69269          * ```
69270          */
69271         has(tagId) {
69272             return this._activated ? this._tagSet.has(tagId) : this._tagSet.hasDeactivated(tagId);
69273         }
69274         off(type, handler) {
69275             super.off(type, handler);
69276         }
69277         on(type, handler) {
69278             super.on(type, handler);
69279         }
69280         /**
69281          * Remove tags with the specified ids from the tag set.
69282          *
69283          * @param {Array<string>} tagIds - Ids for tags to remove.
69284          *
69285          * @example
69286          * ```js
69287          * tagComponent.remove(["id-1", "id-2"]);
69288          * ```
69289          */
69290         remove(tagIds) {
69291             if (this._activated) {
69292                 this._tagSet.remove(tagIds);
69293                 this._tagScene.remove(tagIds);
69294             }
69295             else {
69296                 this._tagSet.removeDeactivated(tagIds);
69297             }
69298         }
69299         /**
69300          * Remove all tags from the tag set.
69301          *
69302          * @example
69303          * ```js
69304          * tagComponent.removeAll();
69305          * ```
69306          */
69307         removeAll() {
69308             if (this._activated) {
69309                 this._tagSet.removeAll();
69310                 this._tagScene.removeAll();
69311             }
69312             else {
69313                 this._tagSet.removeAllDeactivated();
69314             }
69315         }
69316         _activate() {
69317             this._editVertexHandler.enable();
69318             const handlerGeometryCreated$ = from(Object.keys(this._createHandlers)).pipe(map((key) => {
69319                 return this._createHandlers[key];
69320             }), filter((handler) => {
69321                 return !!handler;
69322             }), mergeMap((handler) => {
69323                 return handler.geometryCreated$;
69324             }), share());
69325             const subs = this._subscriptions;
69326             subs.push(handlerGeometryCreated$
69327                 .subscribe((geometry) => {
69328                 const type = "geometrycreate";
69329                 const event = {
69330                     geometry,
69331                     target: this,
69332                     type,
69333                 };
69334                 this.fire(type, event);
69335             }));
69336             subs.push(this._tagCreator.tag$.pipe(skipWhile((tag) => {
69337                 return tag == null;
69338             }), distinctUntilChanged())
69339                 .subscribe((tag) => {
69340                 const type = tag != null ?
69341                     "tagcreatestart" :
69342                     "tagcreateend";
69343                 const event = {
69344                     target: this,
69345                     type,
69346                 };
69347                 this.fire(type, event);
69348             }));
69349             subs.push(handlerGeometryCreated$
69350                 .subscribe(() => {
69351                 this.changeMode(exports.TagMode.Default);
69352             }));
69353             subs.push(this._creatingConfiguration$
69354                 .subscribe((configuration) => {
69355                 this._disableCreateHandlers();
69356                 const mode = exports.TagMode[configuration.mode];
69357                 const handler = this._createHandlers[mode];
69358                 if (!!handler) {
69359                     handler.enable();
69360                 }
69361             }));
69362             subs.push(this._renderTags$
69363                 .subscribe(() => {
69364                 const type = "tags";
69365                 const event = {
69366                     target: this,
69367                     type,
69368                 };
69369                 this.fire(type, event);
69370             }));
69371             subs.push(this._tagCreator.tag$.pipe(switchMap((tag) => {
69372                 return tag != null ?
69373                     tag.aborted$.pipe(map(() => { return null; })) :
69374                     empty();
69375             }))
69376                 .subscribe(() => { this.changeMode(exports.TagMode.Default); }));
69377             subs.push(this._tagCreator.tag$
69378                 .subscribe((tag) => {
69379                 if (this._tagScene.hasCreateTag()) {
69380                     this._tagScene.removeCreateTag();
69381                 }
69382                 if (tag != null) {
69383                     this._tagScene.addCreateTag(tag);
69384                 }
69385             }));
69386             subs.push(this._createGLObjectsChanged$
69387                 .subscribe((tag) => {
69388                 this._tagScene.updateCreateTagObjects(tag);
69389             }));
69390             subs.push(this._renderTagGLChanged$
69391                 .subscribe((tag) => {
69392                 this._tagScene.updateObjects(tag);
69393             }));
69394             subs.push(this._tagChanged$
69395                 .subscribe(() => {
69396                 this._tagScene.update();
69397             }));
69398             subs.push(combineLatest(this._renderTags$.pipe(startWith([]), tap(() => {
69399                 this._container.domRenderer.render$.next({
69400                     name: this._name,
69401                     vNode: this._tagDomRenderer.clear(),
69402                 });
69403             })), 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]) => {
69404                 return {
69405                     name: this._name,
69406                     vNode: this._tagDomRenderer.render(renderTags, ct, atlas, rc.perspective, size),
69407                 };
69408             }))
69409                 .subscribe(this._container.domRenderer.render$));
69410             subs.push(this._navigator.stateService.currentState$.pipe(map((frame) => {
69411                 const tagScene = this._tagScene;
69412                 return {
69413                     name: this._name,
69414                     renderer: {
69415                         frameId: frame.id,
69416                         needsRender: tagScene.needsRender,
69417                         render: tagScene.render.bind(tagScene),
69418                         pass: RenderPass.Opaque,
69419                     },
69420                 };
69421             }))
69422                 .subscribe(this._container.glRenderer.render$));
69423             this._navigator.stateService.currentTransform$.pipe(first())
69424                 .subscribe((transform) => {
69425                 this._tagSet.activate(transform);
69426                 this._tagScene.add(this._tagSet.getAll());
69427             });
69428         }
69429         _deactivate() {
69430             this._editVertexHandler.disable();
69431             this._disableCreateHandlers();
69432             this._tagScene.clear();
69433             this._tagSet.deactivate();
69434             this._tagCreator.delete$.next(null);
69435             this._subscriptions.unsubscribe();
69436             this._container.container.classList.remove("component-tag-create");
69437         }
69438         _getDefaultConfiguration() {
69439             return {
69440                 createColor: 0xFFFFFF,
69441                 indicatePointsCompleter: true,
69442                 mode: exports.TagMode.Default,
69443             };
69444         }
69445         _disableCreateHandlers() {
69446             const createHandlers = this._createHandlers;
69447             for (const key in createHandlers) {
69448                 if (!createHandlers.hasOwnProperty(key)) {
69449                     continue;
69450                 }
69451                 const handler = createHandlers[key];
69452                 if (!!handler) {
69453                     handler.disable();
69454                 }
69455             }
69456         }
69457     }
69458     /** @inheritdoc */
69459     TagComponent.componentName = "tag";
69460
69461     /**
69462      * @class ZoomComponent
69463      *
69464      * @classdesc Component rendering UI elements used for zooming.
69465      *
69466      * @example
69467      * ```js
69468      * var viewer = new Viewer({ ... });
69469      *
69470      * var zoomComponent = viewer.getComponent("zoom");
69471      * zoomComponent.configure({ size: ComponentSize.Small });
69472      * ```
69473      */
69474     class ZoomComponent extends Component {
69475         constructor(name, container, navigator) {
69476             super(name, container, navigator);
69477             this._viewportCoords = new ViewportCoords();
69478             this._zoomDelta$ = new Subject();
69479         }
69480         _activate() {
69481             const subs = this._subscriptions;
69482             subs.push(combineLatest(this._navigator.stateService.currentState$, this._navigator.stateService.state$, this._configuration$, this._container.renderService.size$).pipe(map(([frame, state, configuration, size]) => {
69483                 const zoom = frame.state.zoom;
69484                 const zoomInIcon = virtualDom.h("div.mapillary-zoom-in-icon", []);
69485                 const zoomInButton = zoom >= 3 || state === State.Waiting ?
69486                     virtualDom.h("div.mapillary-zoom-in-button-inactive", [zoomInIcon]) :
69487                     virtualDom.h("div.mapillary-zoom-in-button", { onclick: () => { this._zoomDelta$.next(1); } }, [zoomInIcon]);
69488                 const zoomOutIcon = virtualDom.h("div.mapillary-zoom-out-icon", []);
69489                 const zoomOutButton = zoom <= 0 || state === State.Waiting ?
69490                     virtualDom.h("div.mapillary-zoom-out-button-inactive", [zoomOutIcon]) :
69491                     virtualDom.h("div.mapillary-zoom-out-button", { onclick: () => { this._zoomDelta$.next(-1); } }, [zoomOutIcon]);
69492                 const compact = configuration.size === exports.ComponentSize.Small ||
69493                     configuration.size === exports.ComponentSize.Automatic && size.width < 640 ?
69494                     ".mapillary-zoom-compact" : "";
69495                 return {
69496                     name: this._name,
69497                     vNode: virtualDom.h("div.mapillary-zoom-container" + compact, { oncontextmenu: (event) => { event.preventDefault(); } }, [zoomInButton, zoomOutButton]),
69498                 };
69499             }))
69500                 .subscribe(this._container.domRenderer.render$));
69501             subs.push(this._zoomDelta$.pipe(withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$))
69502                 .subscribe(([zoomDelta, render, transform]) => {
69503                 const unprojected = this._viewportCoords.unprojectFromViewport(0, 0, render.perspective);
69504                 const reference = transform.projectBasic(unprojected.toArray());
69505                 this._navigator.stateService.zoomIn(zoomDelta, reference);
69506             }));
69507         }
69508         _deactivate() {
69509             this._subscriptions.unsubscribe();
69510         }
69511         _getDefaultConfiguration() {
69512             return { size: exports.ComponentSize.Automatic };
69513         }
69514     }
69515     ZoomComponent.componentName = "zoom";
69516
69517     class ImageFallbackComponent extends Component {
69518         constructor(name, container, navigator, dom) {
69519             super(name, container, navigator);
69520             this._canvasId = `${container.id}-${this._name}`;
69521             this._dom = !!dom ? dom : new DOM();
69522         }
69523         _activate() {
69524             const canvasSize$ = this._container.domRenderer.element$.pipe(map(() => {
69525                 return this._dom.document.getElementById(this._canvasId);
69526             }), filter((canvas) => {
69527                 return !!canvas;
69528             }), map((canvas) => {
69529                 const adaptableDomRenderer = canvas.parentElement;
69530                 const width = adaptableDomRenderer.offsetWidth;
69531                 const height = adaptableDomRenderer.offsetHeight;
69532                 return [canvas, { height: height, width: width }];
69533             }), distinctUntilChanged((s1, s2) => {
69534                 return s1.height === s2.height && s1.width === s2.width;
69535             }, ([, size]) => {
69536                 return size;
69537             }));
69538             this._subscriptions.push(combineLatest(canvasSize$, this._navigator.stateService.currentImage$)
69539                 .subscribe(([[canvas, size], image]) => {
69540                 canvas.width = size.width;
69541                 canvas.height = size.height;
69542                 canvas
69543                     .getContext("2d")
69544                     .drawImage(image.image, 0, 0, size.width, size.height);
69545             }));
69546             this._container.domRenderer.renderAdaptive$.next({ name: this._name, vNode: virtualDom.h(`canvas#${this._canvasId}`, []) });
69547         }
69548         _deactivate() {
69549             this._subscriptions.unsubscribe();
69550         }
69551         _getDefaultConfiguration() {
69552             return {};
69553         }
69554     }
69555     ImageFallbackComponent.componentName = "imagefallback";
69556
69557     /**
69558      * @class NavigationFallbackComponent
69559      *
69560      * @classdesc Fallback navigation component for environments without WebGL support.
69561      *
69562      * Replaces the functionality in the Direction and Sequence components.
69563      */
69564     class NavigationFallbackComponent extends Component {
69565         /** @ignore */
69566         constructor(name, container, navigator) {
69567             super(name, container, navigator);
69568             this._seqNames = {};
69569             this._seqNames[exports.NavigationDirection[exports.NavigationDirection.Prev]] = "-prev";
69570             this._seqNames[exports.NavigationDirection[exports.NavigationDirection.Next]] = "-next";
69571             this._spaTopNames = {};
69572             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.TurnLeft]] = "-turn-left";
69573             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.StepLeft]] = "-left";
69574             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.StepForward]] = "-forward";
69575             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.StepRight]] = "-right";
69576             this._spaTopNames[exports.NavigationDirection[exports.NavigationDirection.TurnRight]] = "-turn-right";
69577             this._spaBottomNames = {};
69578             this._spaBottomNames[exports.NavigationDirection[exports.NavigationDirection.TurnU]] = "-turn-around";
69579             this._spaBottomNames[exports.NavigationDirection[exports.NavigationDirection.StepBackward]] = "-backward";
69580         }
69581         _activate() {
69582             this._subscriptions.push(combineLatest(this._navigator.stateService.currentImage$, this._configuration$).pipe(switchMap(([image, configuration]) => {
69583                 const sequenceEdges$ = configuration.sequence ?
69584                     image.sequenceEdges$.pipe(map((status) => {
69585                         return status.edges
69586                             .map((edge) => {
69587                             return edge.data.direction;
69588                         });
69589                     })) :
69590                     of([]);
69591                 const spatialEdges$ = !isSpherical(image.cameraType) &&
69592                     configuration.spatial ?
69593                     image.spatialEdges$.pipe(map((status) => {
69594                         return status.edges
69595                             .map((edge) => {
69596                             return edge.data.direction;
69597                         });
69598                     })) :
69599                     of([]);
69600                 return combineLatest(sequenceEdges$, spatialEdges$).pipe(map(([seq, spa]) => {
69601                     return seq.concat(spa);
69602                 }));
69603             }), map((edgeDirections) => {
69604                 const seqs = this._createArrowRow(this._seqNames, edgeDirections);
69605                 const spaTops = this._createArrowRow(this._spaTopNames, edgeDirections);
69606                 const spaBottoms = this._createArrowRow(this._spaBottomNames, edgeDirections);
69607                 const seqContainer = virtualDom.h(`div.mapillary-navigation-sequence`, seqs);
69608                 const spaTopContainer = virtualDom.h(`div.NavigationSpatialTop`, spaTops);
69609                 const spaBottomContainer = virtualDom.h(`div.mapillary-navigation-spatial-bottom`, spaBottoms);
69610                 const spaContainer = virtualDom.h(`div.mapillary-navigation-spatial`, [spaTopContainer, spaBottomContainer]);
69611                 return { name: this._name, vNode: virtualDom.h(`div.NavigationContainer`, [seqContainer, spaContainer]) };
69612             }))
69613                 .subscribe(this._container.domRenderer.render$));
69614         }
69615         _deactivate() {
69616             this._subscriptions.unsubscribe();
69617         }
69618         _getDefaultConfiguration() {
69619             return { sequence: true, spatial: true };
69620         }
69621         _createArrowRow(arrowNames, edgeDirections) {
69622             const arrows = [];
69623             for (const arrowName in arrowNames) {
69624                 if (!(arrowNames.hasOwnProperty(arrowName))) {
69625                     continue;
69626                 }
69627                 const direction = exports.NavigationDirection[arrowName];
69628                 if (edgeDirections.indexOf(direction) !== -1) {
69629                     arrows.push(this._createVNode(direction, arrowNames[arrowName], "visible"));
69630                 }
69631                 else {
69632                     arrows.push(this._createVNode(direction, arrowNames[arrowName], "hidden"));
69633                 }
69634             }
69635             return arrows;
69636         }
69637         _createVNode(direction, name, visibility) {
69638             return virtualDom.h(`span.mapillary-navigation-button.mapillary-navigation${name}`, {
69639                 onclick: () => {
69640                     this._navigator.moveDir$(direction)
69641                         .subscribe(undefined, (error) => {
69642                         if (!(error instanceof CancelMapillaryError)) {
69643                             console.error(error);
69644                         }
69645                     });
69646                 },
69647                 style: {
69648                     visibility: visibility,
69649                 },
69650             }, []);
69651         }
69652     }
69653     NavigationFallbackComponent.componentName = "navigationfallback";
69654
69655     /*! pako 2.0.4 https://github.com/nodeca/pako @license (MIT AND Zlib) */
69656     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
69657     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
69658     //
69659     // This software is provided 'as-is', without any express or implied
69660     // warranty. In no event will the authors be held liable for any damages
69661     // arising from the use of this software.
69662     //
69663     // Permission is granted to anyone to use this software for any purpose,
69664     // including commercial applications, and to alter it and redistribute it
69665     // freely, subject to the following restrictions:
69666     //
69667     // 1. The origin of this software must not be misrepresented; you must not
69668     //   claim that you wrote the original software. If you use this software
69669     //   in a product, an acknowledgment in the product documentation would be
69670     //   appreciated but is not required.
69671     // 2. Altered source versions must be plainly marked as such, and must not be
69672     //   misrepresented as being the original software.
69673     // 3. This notice may not be removed or altered from any source distribution.
69674
69675     /* eslint-disable space-unary-ops */
69676
69677     /* Public constants ==========================================================*/
69678     /* ===========================================================================*/
69679
69680
69681     //const Z_FILTERED          = 1;
69682     //const Z_HUFFMAN_ONLY      = 2;
69683     //const Z_RLE               = 3;
69684     const Z_FIXED$1               = 4;
69685     //const Z_DEFAULT_STRATEGY  = 0;
69686
69687     /* Possible values of the data_type field (though see inflate()) */
69688     const Z_BINARY              = 0;
69689     const Z_TEXT                = 1;
69690     //const Z_ASCII             = 1; // = Z_TEXT
69691     const Z_UNKNOWN$1             = 2;
69692
69693     /*============================================================================*/
69694
69695
69696     function zero$1(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } }
69697
69698     // From zutil.h
69699
69700     const STORED_BLOCK = 0;
69701     const STATIC_TREES = 1;
69702     const DYN_TREES    = 2;
69703     /* The three kinds of block type */
69704
69705     const MIN_MATCH$1    = 3;
69706     const MAX_MATCH$1    = 258;
69707     /* The minimum and maximum match lengths */
69708
69709     // From deflate.h
69710     /* ===========================================================================
69711      * Internal compression state.
69712      */
69713
69714     const LENGTH_CODES$1  = 29;
69715     /* number of length codes, not counting the special END_BLOCK code */
69716
69717     const LITERALS$1      = 256;
69718     /* number of literal bytes 0..255 */
69719
69720     const L_CODES$1       = LITERALS$1 + 1 + LENGTH_CODES$1;
69721     /* number of Literal or Length codes, including the END_BLOCK code */
69722
69723     const D_CODES$1       = 30;
69724     /* number of distance codes */
69725
69726     const BL_CODES$1      = 19;
69727     /* number of codes used to transfer the bit lengths */
69728
69729     const HEAP_SIZE$1     = 2 * L_CODES$1 + 1;
69730     /* maximum heap size */
69731
69732     const MAX_BITS$1      = 15;
69733     /* All codes must not exceed MAX_BITS bits */
69734
69735     const Buf_size      = 16;
69736     /* size of bit buffer in bi_buf */
69737
69738
69739     /* ===========================================================================
69740      * Constants
69741      */
69742
69743     const MAX_BL_BITS = 7;
69744     /* Bit length codes must not exceed MAX_BL_BITS bits */
69745
69746     const END_BLOCK   = 256;
69747     /* end of block literal code */
69748
69749     const REP_3_6     = 16;
69750     /* repeat previous bit length 3-6 times (2 bits of repeat count) */
69751
69752     const REPZ_3_10   = 17;
69753     /* repeat a zero length 3-10 times  (3 bits of repeat count) */
69754
69755     const REPZ_11_138 = 18;
69756     /* repeat a zero length 11-138 times  (7 bits of repeat count) */
69757
69758     /* eslint-disable comma-spacing,array-bracket-spacing */
69759     const extra_lbits =   /* extra bits for each length code */
69760       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]);
69761
69762     const extra_dbits =   /* extra bits for each distance code */
69763       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]);
69764
69765     const extra_blbits =  /* extra bits for each bit length code */
69766       new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]);
69767
69768     const bl_order =
69769       new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);
69770     /* eslint-enable comma-spacing,array-bracket-spacing */
69771
69772     /* The lengths of the bit length codes are sent in order of decreasing
69773      * probability, to avoid transmitting the lengths for unused bit length codes.
69774      */
69775
69776     /* ===========================================================================
69777      * Local data. These are initialized only once.
69778      */
69779
69780     // We pre-fill arrays with 0 to avoid uninitialized gaps
69781
69782     const DIST_CODE_LEN = 512; /* see definition of array dist_code below */
69783
69784     // !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1
69785     const static_ltree  = new Array((L_CODES$1 + 2) * 2);
69786     zero$1(static_ltree);
69787     /* The static literal tree. Since the bit lengths are imposed, there is no
69788      * need for the L_CODES extra codes used during heap construction. However
69789      * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
69790      * below).
69791      */
69792
69793     const static_dtree  = new Array(D_CODES$1 * 2);
69794     zero$1(static_dtree);
69795     /* The static distance tree. (Actually a trivial tree since all codes use
69796      * 5 bits.)
69797      */
69798
69799     const _dist_code    = new Array(DIST_CODE_LEN);
69800     zero$1(_dist_code);
69801     /* Distance codes. The first 256 values correspond to the distances
69802      * 3 .. 258, the last 256 values correspond to the top 8 bits of
69803      * the 15 bit distances.
69804      */
69805
69806     const _length_code  = new Array(MAX_MATCH$1 - MIN_MATCH$1 + 1);
69807     zero$1(_length_code);
69808     /* length code for each normalized match length (0 == MIN_MATCH) */
69809
69810     const base_length   = new Array(LENGTH_CODES$1);
69811     zero$1(base_length);
69812     /* First normalized length for each code (0 = MIN_MATCH) */
69813
69814     const base_dist     = new Array(D_CODES$1);
69815     zero$1(base_dist);
69816     /* First normalized distance for each code (0 = distance of 1) */
69817
69818
69819     function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {
69820
69821       this.static_tree  = static_tree;  /* static tree or NULL */
69822       this.extra_bits   = extra_bits;   /* extra bits for each code or NULL */
69823       this.extra_base   = extra_base;   /* base index for extra_bits */
69824       this.elems        = elems;        /* max number of elements in the tree */
69825       this.max_length   = max_length;   /* max bit length for the codes */
69826
69827       // show if `static_tree` has data or dummy - needed for monomorphic objects
69828       this.has_stree    = static_tree && static_tree.length;
69829     }
69830
69831
69832     let static_l_desc;
69833     let static_d_desc;
69834     let static_bl_desc;
69835
69836
69837     function TreeDesc(dyn_tree, stat_desc) {
69838       this.dyn_tree = dyn_tree;     /* the dynamic tree */
69839       this.max_code = 0;            /* largest code with non zero frequency */
69840       this.stat_desc = stat_desc;   /* the corresponding static tree */
69841     }
69842
69843
69844
69845     const d_code = (dist) => {
69846
69847       return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
69848     };
69849
69850
69851     /* ===========================================================================
69852      * Output a short LSB first on the stream.
69853      * IN assertion: there is enough room in pendingBuf.
69854      */
69855     const put_short = (s, w) => {
69856     //    put_byte(s, (uch)((w) & 0xff));
69857     //    put_byte(s, (uch)((ush)(w) >> 8));
69858       s.pending_buf[s.pending++] = (w) & 0xff;
69859       s.pending_buf[s.pending++] = (w >>> 8) & 0xff;
69860     };
69861
69862
69863     /* ===========================================================================
69864      * Send a value on a given number of bits.
69865      * IN assertion: length <= 16 and value fits in length bits.
69866      */
69867     const send_bits = (s, value, length) => {
69868
69869       if (s.bi_valid > (Buf_size - length)) {
69870         s.bi_buf |= (value << s.bi_valid) & 0xffff;
69871         put_short(s, s.bi_buf);
69872         s.bi_buf = value >> (Buf_size - s.bi_valid);
69873         s.bi_valid += length - Buf_size;
69874       } else {
69875         s.bi_buf |= (value << s.bi_valid) & 0xffff;
69876         s.bi_valid += length;
69877       }
69878     };
69879
69880
69881     const send_code = (s, c, tree) => {
69882
69883       send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/);
69884     };
69885
69886
69887     /* ===========================================================================
69888      * Reverse the first len bits of a code, using straightforward code (a faster
69889      * method would use a table)
69890      * IN assertion: 1 <= len <= 15
69891      */
69892     const bi_reverse = (code, len) => {
69893
69894       let res = 0;
69895       do {
69896         res |= code & 1;
69897         code >>>= 1;
69898         res <<= 1;
69899       } while (--len > 0);
69900       return res >>> 1;
69901     };
69902
69903
69904     /* ===========================================================================
69905      * Flush the bit buffer, keeping at most 7 bits in it.
69906      */
69907     const bi_flush = (s) => {
69908
69909       if (s.bi_valid === 16) {
69910         put_short(s, s.bi_buf);
69911         s.bi_buf = 0;
69912         s.bi_valid = 0;
69913
69914       } else if (s.bi_valid >= 8) {
69915         s.pending_buf[s.pending++] = s.bi_buf & 0xff;
69916         s.bi_buf >>= 8;
69917         s.bi_valid -= 8;
69918       }
69919     };
69920
69921
69922     /* ===========================================================================
69923      * Compute the optimal bit lengths for a tree and update the total bit length
69924      * for the current block.
69925      * IN assertion: the fields freq and dad are set, heap[heap_max] and
69926      *    above are the tree nodes sorted by increasing frequency.
69927      * OUT assertions: the field len is set to the optimal bit length, the
69928      *     array bl_count contains the frequencies for each bit length.
69929      *     The length opt_len is updated; static_len is also updated if stree is
69930      *     not null.
69931      */
69932     const gen_bitlen = (s, desc) =>
69933     //    deflate_state *s;
69934     //    tree_desc *desc;    /* the tree descriptor */
69935     {
69936       const tree            = desc.dyn_tree;
69937       const max_code        = desc.max_code;
69938       const stree           = desc.stat_desc.static_tree;
69939       const has_stree       = desc.stat_desc.has_stree;
69940       const extra           = desc.stat_desc.extra_bits;
69941       const base            = desc.stat_desc.extra_base;
69942       const max_length      = desc.stat_desc.max_length;
69943       let h;              /* heap index */
69944       let n, m;           /* iterate over the tree elements */
69945       let bits;           /* bit length */
69946       let xbits;          /* extra bits */
69947       let f;              /* frequency */
69948       let overflow = 0;   /* number of elements with bit length too large */
69949
69950       for (bits = 0; bits <= MAX_BITS$1; bits++) {
69951         s.bl_count[bits] = 0;
69952       }
69953
69954       /* In a first pass, compute the optimal bit lengths (which may
69955        * overflow in the case of the bit length tree).
69956        */
69957       tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */
69958
69959       for (h = s.heap_max + 1; h < HEAP_SIZE$1; h++) {
69960         n = s.heap[h];
69961         bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;
69962         if (bits > max_length) {
69963           bits = max_length;
69964           overflow++;
69965         }
69966         tree[n * 2 + 1]/*.Len*/ = bits;
69967         /* We overwrite tree[n].Dad which is no longer needed */
69968
69969         if (n > max_code) { continue; } /* not a leaf node */
69970
69971         s.bl_count[bits]++;
69972         xbits = 0;
69973         if (n >= base) {
69974           xbits = extra[n - base];
69975         }
69976         f = tree[n * 2]/*.Freq*/;
69977         s.opt_len += f * (bits + xbits);
69978         if (has_stree) {
69979           s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);
69980         }
69981       }
69982       if (overflow === 0) { return; }
69983
69984       // Trace((stderr,"\nbit length overflow\n"));
69985       /* This happens for example on obj2 and pic of the Calgary corpus */
69986
69987       /* Find the first bit length which could increase: */
69988       do {
69989         bits = max_length - 1;
69990         while (s.bl_count[bits] === 0) { bits--; }
69991         s.bl_count[bits]--;      /* move one leaf down the tree */
69992         s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */
69993         s.bl_count[max_length]--;
69994         /* The brother of the overflow item also moves one step up,
69995          * but this does not affect bl_count[max_length]
69996          */
69997         overflow -= 2;
69998       } while (overflow > 0);
69999
70000       /* Now recompute all bit lengths, scanning in increasing frequency.
70001        * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
70002        * lengths instead of fixing only the wrong ones. This idea is taken
70003        * from 'ar' written by Haruhiko Okumura.)
70004        */
70005       for (bits = max_length; bits !== 0; bits--) {
70006         n = s.bl_count[bits];
70007         while (n !== 0) {
70008           m = s.heap[--h];
70009           if (m > max_code) { continue; }
70010           if (tree[m * 2 + 1]/*.Len*/ !== bits) {
70011             // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
70012             s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;
70013             tree[m * 2 + 1]/*.Len*/ = bits;
70014           }
70015           n--;
70016         }
70017       }
70018     };
70019
70020
70021     /* ===========================================================================
70022      * Generate the codes for a given tree and bit counts (which need not be
70023      * optimal).
70024      * IN assertion: the array bl_count contains the bit length statistics for
70025      * the given tree and the field len is set for all tree elements.
70026      * OUT assertion: the field code is set for all tree elements of non
70027      *     zero code length.
70028      */
70029     const gen_codes = (tree, max_code, bl_count) =>
70030     //    ct_data *tree;             /* the tree to decorate */
70031     //    int max_code;              /* largest code with non zero frequency */
70032     //    ushf *bl_count;            /* number of codes at each bit length */
70033     {
70034       const next_code = new Array(MAX_BITS$1 + 1); /* next code value for each bit length */
70035       let code = 0;              /* running code value */
70036       let bits;                  /* bit index */
70037       let n;                     /* code index */
70038
70039       /* The distribution counts are first used to generate the code values
70040        * without bit reversal.
70041        */
70042       for (bits = 1; bits <= MAX_BITS$1; bits++) {
70043         next_code[bits] = code = (code + bl_count[bits - 1]) << 1;
70044       }
70045       /* Check that the bit counts in bl_count are consistent. The last code
70046        * must be all ones.
70047        */
70048       //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
70049       //        "inconsistent bit counts");
70050       //Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
70051
70052       for (n = 0;  n <= max_code; n++) {
70053         let len = tree[n * 2 + 1]/*.Len*/;
70054         if (len === 0) { continue; }
70055         /* Now reverse the bits */
70056         tree[n * 2]/*.Code*/ = bi_reverse(next_code[len]++, len);
70057
70058         //Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
70059         //     n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
70060       }
70061     };
70062
70063
70064     /* ===========================================================================
70065      * Initialize the various 'constant' tables.
70066      */
70067     const tr_static_init = () => {
70068
70069       let n;        /* iterates over tree elements */
70070       let bits;     /* bit counter */
70071       let length;   /* length value */
70072       let code;     /* code value */
70073       let dist;     /* distance index */
70074       const bl_count = new Array(MAX_BITS$1 + 1);
70075       /* number of codes at each bit length for an optimal tree */
70076
70077       // do check in _tr_init()
70078       //if (static_init_done) return;
70079
70080       /* For some embedded targets, global variables are not initialized: */
70081     /*#ifdef NO_INIT_GLOBAL_POINTERS
70082       static_l_desc.static_tree = static_ltree;
70083       static_l_desc.extra_bits = extra_lbits;
70084       static_d_desc.static_tree = static_dtree;
70085       static_d_desc.extra_bits = extra_dbits;
70086       static_bl_desc.extra_bits = extra_blbits;
70087     #endif*/
70088
70089       /* Initialize the mapping length (0..255) -> length code (0..28) */
70090       length = 0;
70091       for (code = 0; code < LENGTH_CODES$1 - 1; code++) {
70092         base_length[code] = length;
70093         for (n = 0; n < (1 << extra_lbits[code]); n++) {
70094           _length_code[length++] = code;
70095         }
70096       }
70097       //Assert (length == 256, "tr_static_init: length != 256");
70098       /* Note that the length 255 (match length 258) can be represented
70099        * in two different ways: code 284 + 5 bits or code 285, so we
70100        * overwrite length_code[255] to use the best encoding:
70101        */
70102       _length_code[length - 1] = code;
70103
70104       /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
70105       dist = 0;
70106       for (code = 0; code < 16; code++) {
70107         base_dist[code] = dist;
70108         for (n = 0; n < (1 << extra_dbits[code]); n++) {
70109           _dist_code[dist++] = code;
70110         }
70111       }
70112       //Assert (dist == 256, "tr_static_init: dist != 256");
70113       dist >>= 7; /* from now on, all distances are divided by 128 */
70114       for (; code < D_CODES$1; code++) {
70115         base_dist[code] = dist << 7;
70116         for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
70117           _dist_code[256 + dist++] = code;
70118         }
70119       }
70120       //Assert (dist == 256, "tr_static_init: 256+dist != 512");
70121
70122       /* Construct the codes of the static literal tree */
70123       for (bits = 0; bits <= MAX_BITS$1; bits++) {
70124         bl_count[bits] = 0;
70125       }
70126
70127       n = 0;
70128       while (n <= 143) {
70129         static_ltree[n * 2 + 1]/*.Len*/ = 8;
70130         n++;
70131         bl_count[8]++;
70132       }
70133       while (n <= 255) {
70134         static_ltree[n * 2 + 1]/*.Len*/ = 9;
70135         n++;
70136         bl_count[9]++;
70137       }
70138       while (n <= 279) {
70139         static_ltree[n * 2 + 1]/*.Len*/ = 7;
70140         n++;
70141         bl_count[7]++;
70142       }
70143       while (n <= 287) {
70144         static_ltree[n * 2 + 1]/*.Len*/ = 8;
70145         n++;
70146         bl_count[8]++;
70147       }
70148       /* Codes 286 and 287 do not exist, but we must include them in the
70149        * tree construction to get a canonical Huffman tree (longest code
70150        * all ones)
70151        */
70152       gen_codes(static_ltree, L_CODES$1 + 1, bl_count);
70153
70154       /* The static distance tree is trivial: */
70155       for (n = 0; n < D_CODES$1; n++) {
70156         static_dtree[n * 2 + 1]/*.Len*/ = 5;
70157         static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5);
70158       }
70159
70160       // Now data ready and we can init static trees
70161       static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS$1 + 1, L_CODES$1, MAX_BITS$1);
70162       static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0,          D_CODES$1, MAX_BITS$1);
70163       static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0,         BL_CODES$1, MAX_BL_BITS);
70164
70165       //static_init_done = true;
70166     };
70167
70168
70169     /* ===========================================================================
70170      * Initialize a new block.
70171      */
70172     const init_block = (s) => {
70173
70174       let n; /* iterates over tree elements */
70175
70176       /* Initialize the trees. */
70177       for (n = 0; n < L_CODES$1;  n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; }
70178       for (n = 0; n < D_CODES$1;  n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; }
70179       for (n = 0; n < BL_CODES$1; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; }
70180
70181       s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1;
70182       s.opt_len = s.static_len = 0;
70183       s.last_lit = s.matches = 0;
70184     };
70185
70186
70187     /* ===========================================================================
70188      * Flush the bit buffer and align the output on a byte boundary
70189      */
70190     const bi_windup = (s) =>
70191     {
70192       if (s.bi_valid > 8) {
70193         put_short(s, s.bi_buf);
70194       } else if (s.bi_valid > 0) {
70195         //put_byte(s, (Byte)s->bi_buf);
70196         s.pending_buf[s.pending++] = s.bi_buf;
70197       }
70198       s.bi_buf = 0;
70199       s.bi_valid = 0;
70200     };
70201
70202     /* ===========================================================================
70203      * Copy a stored block, storing first the length and its
70204      * one's complement if requested.
70205      */
70206     const copy_block = (s, buf, len, header) =>
70207     //DeflateState *s;
70208     //charf    *buf;    /* the input data */
70209     //unsigned len;     /* its length */
70210     //int      header;  /* true if block header must be written */
70211     {
70212       bi_windup(s);        /* align on byte boundary */
70213
70214       if (header) {
70215         put_short(s, len);
70216         put_short(s, ~len);
70217       }
70218     //  while (len--) {
70219     //    put_byte(s, *buf++);
70220     //  }
70221       s.pending_buf.set(s.window.subarray(buf, buf + len), s.pending);
70222       s.pending += len;
70223     };
70224
70225     /* ===========================================================================
70226      * Compares to subtrees, using the tree depth as tie breaker when
70227      * the subtrees have equal frequency. This minimizes the worst case length.
70228      */
70229     const smaller = (tree, n, m, depth) => {
70230
70231       const _n2 = n * 2;
70232       const _m2 = m * 2;
70233       return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||
70234              (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));
70235     };
70236
70237     /* ===========================================================================
70238      * Restore the heap property by moving down the tree starting at node k,
70239      * exchanging a node with the smallest of its two sons if necessary, stopping
70240      * when the heap property is re-established (each father smaller than its
70241      * two sons).
70242      */
70243     const pqdownheap = (s, tree, k) =>
70244     //    deflate_state *s;
70245     //    ct_data *tree;  /* the tree to restore */
70246     //    int k;               /* node to move down */
70247     {
70248       const v = s.heap[k];
70249       let j = k << 1;  /* left son of k */
70250       while (j <= s.heap_len) {
70251         /* Set j to the smallest of the two sons: */
70252         if (j < s.heap_len &&
70253           smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {
70254           j++;
70255         }
70256         /* Exit if v is smaller than both sons */
70257         if (smaller(tree, v, s.heap[j], s.depth)) { break; }
70258
70259         /* Exchange v with the smallest son */
70260         s.heap[k] = s.heap[j];
70261         k = j;
70262
70263         /* And continue down the tree, setting j to the left son of k */
70264         j <<= 1;
70265       }
70266       s.heap[k] = v;
70267     };
70268
70269
70270     // inlined manually
70271     // const SMALLEST = 1;
70272
70273     /* ===========================================================================
70274      * Send the block data compressed using the given Huffman trees
70275      */
70276     const compress_block = (s, ltree, dtree) =>
70277     //    deflate_state *s;
70278     //    const ct_data *ltree; /* literal tree */
70279     //    const ct_data *dtree; /* distance tree */
70280     {
70281       let dist;           /* distance of matched string */
70282       let lc;             /* match length or unmatched char (if dist == 0) */
70283       let lx = 0;         /* running index in l_buf */
70284       let code;           /* the code to send */
70285       let extra;          /* number of extra bits to send */
70286
70287       if (s.last_lit !== 0) {
70288         do {
70289           dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]);
70290           lc = s.pending_buf[s.l_buf + lx];
70291           lx++;
70292
70293           if (dist === 0) {
70294             send_code(s, lc, ltree); /* send a literal byte */
70295             //Tracecv(isgraph(lc), (stderr," '%c' ", lc));
70296           } else {
70297             /* Here, lc is the match length - MIN_MATCH */
70298             code = _length_code[lc];
70299             send_code(s, code + LITERALS$1 + 1, ltree); /* send the length code */
70300             extra = extra_lbits[code];
70301             if (extra !== 0) {
70302               lc -= base_length[code];
70303               send_bits(s, lc, extra);       /* send the extra length bits */
70304             }
70305             dist--; /* dist is now the match distance - 1 */
70306             code = d_code(dist);
70307             //Assert (code < D_CODES, "bad d_code");
70308
70309             send_code(s, code, dtree);       /* send the distance code */
70310             extra = extra_dbits[code];
70311             if (extra !== 0) {
70312               dist -= base_dist[code];
70313               send_bits(s, dist, extra);   /* send the extra distance bits */
70314             }
70315           } /* literal or match pair ? */
70316
70317           /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
70318           //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
70319           //       "pendingBuf overflow");
70320
70321         } while (lx < s.last_lit);
70322       }
70323
70324       send_code(s, END_BLOCK, ltree);
70325     };
70326
70327
70328     /* ===========================================================================
70329      * Construct one Huffman tree and assigns the code bit strings and lengths.
70330      * Update the total bit length for the current block.
70331      * IN assertion: the field freq is set for all tree elements.
70332      * OUT assertions: the fields len and code are set to the optimal bit length
70333      *     and corresponding code. The length opt_len is updated; static_len is
70334      *     also updated if stree is not null. The field max_code is set.
70335      */
70336     const build_tree = (s, desc) =>
70337     //    deflate_state *s;
70338     //    tree_desc *desc; /* the tree descriptor */
70339     {
70340       const tree     = desc.dyn_tree;
70341       const stree    = desc.stat_desc.static_tree;
70342       const has_stree = desc.stat_desc.has_stree;
70343       const elems    = desc.stat_desc.elems;
70344       let n, m;          /* iterate over heap elements */
70345       let max_code = -1; /* largest code with non zero frequency */
70346       let node;          /* new node being created */
70347
70348       /* Construct the initial heap, with least frequent element in
70349        * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
70350        * heap[0] is not used.
70351        */
70352       s.heap_len = 0;
70353       s.heap_max = HEAP_SIZE$1;
70354
70355       for (n = 0; n < elems; n++) {
70356         if (tree[n * 2]/*.Freq*/ !== 0) {
70357           s.heap[++s.heap_len] = max_code = n;
70358           s.depth[n] = 0;
70359
70360         } else {
70361           tree[n * 2 + 1]/*.Len*/ = 0;
70362         }
70363       }
70364
70365       /* The pkzip format requires that at least one distance code exists,
70366        * and that at least one bit should be sent even if there is only one
70367        * possible code. So to avoid special checks later on we force at least
70368        * two codes of non zero frequency.
70369        */
70370       while (s.heap_len < 2) {
70371         node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
70372         tree[node * 2]/*.Freq*/ = 1;
70373         s.depth[node] = 0;
70374         s.opt_len--;
70375
70376         if (has_stree) {
70377           s.static_len -= stree[node * 2 + 1]/*.Len*/;
70378         }
70379         /* node is 0 or 1 so it does not have extra bits */
70380       }
70381       desc.max_code = max_code;
70382
70383       /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
70384        * establish sub-heaps of increasing lengths:
70385        */
70386       for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }
70387
70388       /* Construct the Huffman tree by repeatedly combining the least two
70389        * frequent nodes.
70390        */
70391       node = elems;              /* next internal node of the tree */
70392       do {
70393         //pqremove(s, tree, n);  /* n = node of least frequency */
70394         /*** pqremove ***/
70395         n = s.heap[1/*SMALLEST*/];
70396         s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];
70397         pqdownheap(s, tree, 1/*SMALLEST*/);
70398         /***/
70399
70400         m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */
70401
70402         s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */
70403         s.heap[--s.heap_max] = m;
70404
70405         /* Create a new node father of n and m */
70406         tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;
70407         s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;
70408         tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;
70409
70410         /* and insert the new node in the heap */
70411         s.heap[1/*SMALLEST*/] = node++;
70412         pqdownheap(s, tree, 1/*SMALLEST*/);
70413
70414       } while (s.heap_len >= 2);
70415
70416       s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];
70417
70418       /* At this point, the fields freq and dad are set. We can now
70419        * generate the bit lengths.
70420        */
70421       gen_bitlen(s, desc);
70422
70423       /* The field len is now set, we can generate the bit codes */
70424       gen_codes(tree, max_code, s.bl_count);
70425     };
70426
70427
70428     /* ===========================================================================
70429      * Scan a literal or distance tree to determine the frequencies of the codes
70430      * in the bit length tree.
70431      */
70432     const scan_tree = (s, tree, max_code) =>
70433     //    deflate_state *s;
70434     //    ct_data *tree;   /* the tree to be scanned */
70435     //    int max_code;    /* and its largest code of non zero frequency */
70436     {
70437       let n;                     /* iterates over all tree elements */
70438       let prevlen = -1;          /* last emitted length */
70439       let curlen;                /* length of current code */
70440
70441       let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
70442
70443       let count = 0;             /* repeat count of the current code */
70444       let max_count = 7;         /* max repeat count */
70445       let min_count = 4;         /* min repeat count */
70446
70447       if (nextlen === 0) {
70448         max_count = 138;
70449         min_count = 3;
70450       }
70451       tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */
70452
70453       for (n = 0; n <= max_code; n++) {
70454         curlen = nextlen;
70455         nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
70456
70457         if (++count < max_count && curlen === nextlen) {
70458           continue;
70459
70460         } else if (count < min_count) {
70461           s.bl_tree[curlen * 2]/*.Freq*/ += count;
70462
70463         } else if (curlen !== 0) {
70464
70465           if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }
70466           s.bl_tree[REP_3_6 * 2]/*.Freq*/++;
70467
70468         } else if (count <= 10) {
70469           s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++;
70470
70471         } else {
70472           s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++;
70473         }
70474
70475         count = 0;
70476         prevlen = curlen;
70477
70478         if (nextlen === 0) {
70479           max_count = 138;
70480           min_count = 3;
70481
70482         } else if (curlen === nextlen) {
70483           max_count = 6;
70484           min_count = 3;
70485
70486         } else {
70487           max_count = 7;
70488           min_count = 4;
70489         }
70490       }
70491     };
70492
70493
70494     /* ===========================================================================
70495      * Send a literal or distance tree in compressed form, using the codes in
70496      * bl_tree.
70497      */
70498     const send_tree = (s, tree, max_code) =>
70499     //    deflate_state *s;
70500     //    ct_data *tree; /* the tree to be scanned */
70501     //    int max_code;       /* and its largest code of non zero frequency */
70502     {
70503       let n;                     /* iterates over all tree elements */
70504       let prevlen = -1;          /* last emitted length */
70505       let curlen;                /* length of current code */
70506
70507       let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
70508
70509       let count = 0;             /* repeat count of the current code */
70510       let max_count = 7;         /* max repeat count */
70511       let min_count = 4;         /* min repeat count */
70512
70513       /* tree[max_code+1].Len = -1; */  /* guard already set */
70514       if (nextlen === 0) {
70515         max_count = 138;
70516         min_count = 3;
70517       }
70518
70519       for (n = 0; n <= max_code; n++) {
70520         curlen = nextlen;
70521         nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
70522
70523         if (++count < max_count && curlen === nextlen) {
70524           continue;
70525
70526         } else if (count < min_count) {
70527           do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);
70528
70529         } else if (curlen !== 0) {
70530           if (curlen !== prevlen) {
70531             send_code(s, curlen, s.bl_tree);
70532             count--;
70533           }
70534           //Assert(count >= 3 && count <= 6, " 3_6?");
70535           send_code(s, REP_3_6, s.bl_tree);
70536           send_bits(s, count - 3, 2);
70537
70538         } else if (count <= 10) {
70539           send_code(s, REPZ_3_10, s.bl_tree);
70540           send_bits(s, count - 3, 3);
70541
70542         } else {
70543           send_code(s, REPZ_11_138, s.bl_tree);
70544           send_bits(s, count - 11, 7);
70545         }
70546
70547         count = 0;
70548         prevlen = curlen;
70549         if (nextlen === 0) {
70550           max_count = 138;
70551           min_count = 3;
70552
70553         } else if (curlen === nextlen) {
70554           max_count = 6;
70555           min_count = 3;
70556
70557         } else {
70558           max_count = 7;
70559           min_count = 4;
70560         }
70561       }
70562     };
70563
70564
70565     /* ===========================================================================
70566      * Construct the Huffman tree for the bit lengths and return the index in
70567      * bl_order of the last bit length code to send.
70568      */
70569     const build_bl_tree = (s) => {
70570
70571       let max_blindex;  /* index of last bit length code of non zero freq */
70572
70573       /* Determine the bit length frequencies for literal and distance trees */
70574       scan_tree(s, s.dyn_ltree, s.l_desc.max_code);
70575       scan_tree(s, s.dyn_dtree, s.d_desc.max_code);
70576
70577       /* Build the bit length tree: */
70578       build_tree(s, s.bl_desc);
70579       /* opt_len now includes the length of the tree representations, except
70580        * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
70581        */
70582
70583       /* Determine the number of bit length codes to send. The pkzip format
70584        * requires that at least 4 bit length codes be sent. (appnote.txt says
70585        * 3 but the actual value used is 4.)
70586        */
70587       for (max_blindex = BL_CODES$1 - 1; max_blindex >= 3; max_blindex--) {
70588         if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {
70589           break;
70590         }
70591       }
70592       /* Update opt_len to include the bit length tree and counts */
70593       s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
70594       //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
70595       //        s->opt_len, s->static_len));
70596
70597       return max_blindex;
70598     };
70599
70600
70601     /* ===========================================================================
70602      * Send the header for a block using dynamic Huffman trees: the counts, the
70603      * lengths of the bit length codes, the literal tree and the distance tree.
70604      * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
70605      */
70606     const send_all_trees = (s, lcodes, dcodes, blcodes) =>
70607     //    deflate_state *s;
70608     //    int lcodes, dcodes, blcodes; /* number of codes for each tree */
70609     {
70610       let rank;                    /* index in bl_order */
70611
70612       //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
70613       //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
70614       //        "too many codes");
70615       //Tracev((stderr, "\nbl counts: "));
70616       send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
70617       send_bits(s, dcodes - 1,   5);
70618       send_bits(s, blcodes - 4,  4); /* not -3 as stated in appnote.txt */
70619       for (rank = 0; rank < blcodes; rank++) {
70620         //Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
70621         send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3);
70622       }
70623       //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
70624
70625       send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */
70626       //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
70627
70628       send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */
70629       //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
70630     };
70631
70632
70633     /* ===========================================================================
70634      * Check if the data type is TEXT or BINARY, using the following algorithm:
70635      * - TEXT if the two conditions below are satisfied:
70636      *    a) There are no non-portable control characters belonging to the
70637      *       "black list" (0..6, 14..25, 28..31).
70638      *    b) There is at least one printable character belonging to the
70639      *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
70640      * - BINARY otherwise.
70641      * - The following partially-portable control characters form a
70642      *   "gray list" that is ignored in this detection algorithm:
70643      *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
70644      * IN assertion: the fields Freq of dyn_ltree are set.
70645      */
70646     const detect_data_type = (s) => {
70647       /* black_mask is the bit mask of black-listed bytes
70648        * set bits 0..6, 14..25, and 28..31
70649        * 0xf3ffc07f = binary 11110011111111111100000001111111
70650        */
70651       let black_mask = 0xf3ffc07f;
70652       let n;
70653
70654       /* Check for non-textual ("black-listed") bytes. */
70655       for (n = 0; n <= 31; n++, black_mask >>>= 1) {
70656         if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {
70657           return Z_BINARY;
70658         }
70659       }
70660
70661       /* Check for textual ("white-listed") bytes. */
70662       if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||
70663           s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {
70664         return Z_TEXT;
70665       }
70666       for (n = 32; n < LITERALS$1; n++) {
70667         if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {
70668           return Z_TEXT;
70669         }
70670       }
70671
70672       /* There are no "black-listed" or "white-listed" bytes:
70673        * this stream either is empty or has tolerated ("gray-listed") bytes only.
70674        */
70675       return Z_BINARY;
70676     };
70677
70678
70679     let static_init_done = false;
70680
70681     /* ===========================================================================
70682      * Initialize the tree data structures for a new zlib stream.
70683      */
70684     const _tr_init$1 = (s) =>
70685     {
70686
70687       if (!static_init_done) {
70688         tr_static_init();
70689         static_init_done = true;
70690       }
70691
70692       s.l_desc  = new TreeDesc(s.dyn_ltree, static_l_desc);
70693       s.d_desc  = new TreeDesc(s.dyn_dtree, static_d_desc);
70694       s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);
70695
70696       s.bi_buf = 0;
70697       s.bi_valid = 0;
70698
70699       /* Initialize the first block of the first file: */
70700       init_block(s);
70701     };
70702
70703
70704     /* ===========================================================================
70705      * Send a stored block
70706      */
70707     const _tr_stored_block$1 = (s, buf, stored_len, last) =>
70708     //DeflateState *s;
70709     //charf *buf;       /* input block */
70710     //ulg stored_len;   /* length of input block */
70711     //int last;         /* one if this is the last block for a file */
70712     {
70713       send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3);    /* send block type */
70714       copy_block(s, buf, stored_len, true); /* with header */
70715     };
70716
70717
70718     /* ===========================================================================
70719      * Send one empty static block to give enough lookahead for inflate.
70720      * This takes 10 bits, of which 7 may remain in the bit buffer.
70721      */
70722     const _tr_align$1 = (s) => {
70723       send_bits(s, STATIC_TREES << 1, 3);
70724       send_code(s, END_BLOCK, static_ltree);
70725       bi_flush(s);
70726     };
70727
70728
70729     /* ===========================================================================
70730      * Determine the best encoding for the current block: dynamic trees, static
70731      * trees or store, and output the encoded block to the zip file.
70732      */
70733     const _tr_flush_block$1 = (s, buf, stored_len, last) =>
70734     //DeflateState *s;
70735     //charf *buf;       /* input block, or NULL if too old */
70736     //ulg stored_len;   /* length of input block */
70737     //int last;         /* one if this is the last block for a file */
70738     {
70739       let opt_lenb, static_lenb;  /* opt_len and static_len in bytes */
70740       let max_blindex = 0;        /* index of last bit length code of non zero freq */
70741
70742       /* Build the Huffman trees unless a stored block is forced */
70743       if (s.level > 0) {
70744
70745         /* Check if the file is binary or text */
70746         if (s.strm.data_type === Z_UNKNOWN$1) {
70747           s.strm.data_type = detect_data_type(s);
70748         }
70749
70750         /* Construct the literal and distance trees */
70751         build_tree(s, s.l_desc);
70752         // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
70753         //        s->static_len));
70754
70755         build_tree(s, s.d_desc);
70756         // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
70757         //        s->static_len));
70758         /* At this point, opt_len and static_len are the total bit lengths of
70759          * the compressed block data, excluding the tree representations.
70760          */
70761
70762         /* Build the bit length tree for the above two trees, and get the index
70763          * in bl_order of the last bit length code to send.
70764          */
70765         max_blindex = build_bl_tree(s);
70766
70767         /* Determine the best encoding. Compute the block lengths in bytes. */
70768         opt_lenb = (s.opt_len + 3 + 7) >>> 3;
70769         static_lenb = (s.static_len + 3 + 7) >>> 3;
70770
70771         // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
70772         //        opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
70773         //        s->last_lit));
70774
70775         if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }
70776
70777       } else {
70778         // Assert(buf != (char*)0, "lost buf");
70779         opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
70780       }
70781
70782       if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) {
70783         /* 4: two words for the lengths */
70784
70785         /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
70786          * Otherwise we can't have processed more than WSIZE input bytes since
70787          * the last block flush, because compression would have been
70788          * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
70789          * transform a block into a stored block.
70790          */
70791         _tr_stored_block$1(s, buf, stored_len, last);
70792
70793       } else if (s.strategy === Z_FIXED$1 || static_lenb === opt_lenb) {
70794
70795         send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3);
70796         compress_block(s, static_ltree, static_dtree);
70797
70798       } else {
70799         send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3);
70800         send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1);
70801         compress_block(s, s.dyn_ltree, s.dyn_dtree);
70802       }
70803       // Assert (s->compressed_len == s->bits_sent, "bad compressed size");
70804       /* The above check is made mod 2^32, for files larger than 512 MB
70805        * and uLong implemented on 32 bits.
70806        */
70807       init_block(s);
70808
70809       if (last) {
70810         bi_windup(s);
70811       }
70812       // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
70813       //       s->compressed_len-7*last));
70814     };
70815
70816     /* ===========================================================================
70817      * Save the match info and tally the frequency counts. Return true if
70818      * the current block must be flushed.
70819      */
70820     const _tr_tally$1 = (s, dist, lc) =>
70821     //    deflate_state *s;
70822     //    unsigned dist;  /* distance of matched string */
70823     //    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
70824     {
70825       //let out_length, in_length, dcode;
70826
70827       s.pending_buf[s.d_buf + s.last_lit * 2]     = (dist >>> 8) & 0xff;
70828       s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff;
70829
70830       s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff;
70831       s.last_lit++;
70832
70833       if (dist === 0) {
70834         /* lc is the unmatched char */
70835         s.dyn_ltree[lc * 2]/*.Freq*/++;
70836       } else {
70837         s.matches++;
70838         /* Here, lc is the match length - MIN_MATCH */
70839         dist--;             /* dist = match distance - 1 */
70840         //Assert((ush)dist < (ush)MAX_DIST(s) &&
70841         //       (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
70842         //       (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
70843
70844         s.dyn_ltree[(_length_code[lc] + LITERALS$1 + 1) * 2]/*.Freq*/++;
70845         s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;
70846       }
70847
70848     // (!) This block is disabled in zlib defaults,
70849     // don't enable it for binary compatibility
70850
70851     //#ifdef TRUNCATE_BLOCK
70852     //  /* Try to guess if it is profitable to stop the current block here */
70853     //  if ((s.last_lit & 0x1fff) === 0 && s.level > 2) {
70854     //    /* Compute an upper bound for the compressed length */
70855     //    out_length = s.last_lit*8;
70856     //    in_length = s.strstart - s.block_start;
70857     //
70858     //    for (dcode = 0; dcode < D_CODES; dcode++) {
70859     //      out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]);
70860     //    }
70861     //    out_length >>>= 3;
70862     //    //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
70863     //    //       s->last_lit, in_length, out_length,
70864     //    //       100L - out_length*100L/in_length));
70865     //    if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) {
70866     //      return true;
70867     //    }
70868     //  }
70869     //#endif
70870
70871       return (s.last_lit === s.lit_bufsize - 1);
70872       /* We avoid equality with lit_bufsize because of wraparound at 64K
70873        * on 16 bit machines and because stored blocks are restricted to
70874        * 64K-1 bytes.
70875        */
70876     };
70877
70878     var _tr_init_1  = _tr_init$1;
70879     var _tr_stored_block_1 = _tr_stored_block$1;
70880     var _tr_flush_block_1  = _tr_flush_block$1;
70881     var _tr_tally_1 = _tr_tally$1;
70882     var _tr_align_1 = _tr_align$1;
70883
70884     var trees = {
70885         _tr_init: _tr_init_1,
70886         _tr_stored_block: _tr_stored_block_1,
70887         _tr_flush_block: _tr_flush_block_1,
70888         _tr_tally: _tr_tally_1,
70889         _tr_align: _tr_align_1
70890     };
70891
70892     // Note: adler32 takes 12% for level 0 and 2% for level 6.
70893     // It isn't worth it to make additional optimizations as in original.
70894     // Small size is preferable.
70895
70896     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
70897     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
70898     //
70899     // This software is provided 'as-is', without any express or implied
70900     // warranty. In no event will the authors be held liable for any damages
70901     // arising from the use of this software.
70902     //
70903     // Permission is granted to anyone to use this software for any purpose,
70904     // including commercial applications, and to alter it and redistribute it
70905     // freely, subject to the following restrictions:
70906     //
70907     // 1. The origin of this software must not be misrepresented; you must not
70908     //   claim that you wrote the original software. If you use this software
70909     //   in a product, an acknowledgment in the product documentation would be
70910     //   appreciated but is not required.
70911     // 2. Altered source versions must be plainly marked as such, and must not be
70912     //   misrepresented as being the original software.
70913     // 3. This notice may not be removed or altered from any source distribution.
70914
70915     const adler32 = (adler, buf, len, pos) => {
70916       let s1 = (adler & 0xffff) |0,
70917           s2 = ((adler >>> 16) & 0xffff) |0,
70918           n = 0;
70919
70920       while (len !== 0) {
70921         // Set limit ~ twice less than 5552, to keep
70922         // s2 in 31-bits, because we force signed ints.
70923         // in other case %= will fail.
70924         n = len > 2000 ? 2000 : len;
70925         len -= n;
70926
70927         do {
70928           s1 = (s1 + buf[pos++]) |0;
70929           s2 = (s2 + s1) |0;
70930         } while (--n);
70931
70932         s1 %= 65521;
70933         s2 %= 65521;
70934       }
70935
70936       return (s1 | (s2 << 16)) |0;
70937     };
70938
70939
70940     var adler32_1 = adler32;
70941
70942     // Note: we can't get significant speed boost here.
70943     // So write code to minimize size - no pregenerated tables
70944     // and array tools dependencies.
70945
70946     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
70947     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
70948     //
70949     // This software is provided 'as-is', without any express or implied
70950     // warranty. In no event will the authors be held liable for any damages
70951     // arising from the use of this software.
70952     //
70953     // Permission is granted to anyone to use this software for any purpose,
70954     // including commercial applications, and to alter it and redistribute it
70955     // freely, subject to the following restrictions:
70956     //
70957     // 1. The origin of this software must not be misrepresented; you must not
70958     //   claim that you wrote the original software. If you use this software
70959     //   in a product, an acknowledgment in the product documentation would be
70960     //   appreciated but is not required.
70961     // 2. Altered source versions must be plainly marked as such, and must not be
70962     //   misrepresented as being the original software.
70963     // 3. This notice may not be removed or altered from any source distribution.
70964
70965     // Use ordinary array, since untyped makes no boost here
70966     const makeTable = () => {
70967       let c, table = [];
70968
70969       for (var n = 0; n < 256; n++) {
70970         c = n;
70971         for (var k = 0; k < 8; k++) {
70972           c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
70973         }
70974         table[n] = c;
70975       }
70976
70977       return table;
70978     };
70979
70980     // Create table on load. Just 255 signed longs. Not a problem.
70981     const crcTable = new Uint32Array(makeTable());
70982
70983
70984     const crc32 = (crc, buf, len, pos) => {
70985       const t = crcTable;
70986       const end = pos + len;
70987
70988       crc ^= -1;
70989
70990       for (let i = pos; i < end; i++) {
70991         crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
70992       }
70993
70994       return (crc ^ (-1)); // >>> 0;
70995     };
70996
70997
70998     var crc32_1 = crc32;
70999
71000     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
71001     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
71002     //
71003     // This software is provided 'as-is', without any express or implied
71004     // warranty. In no event will the authors be held liable for any damages
71005     // arising from the use of this software.
71006     //
71007     // Permission is granted to anyone to use this software for any purpose,
71008     // including commercial applications, and to alter it and redistribute it
71009     // freely, subject to the following restrictions:
71010     //
71011     // 1. The origin of this software must not be misrepresented; you must not
71012     //   claim that you wrote the original software. If you use this software
71013     //   in a product, an acknowledgment in the product documentation would be
71014     //   appreciated but is not required.
71015     // 2. Altered source versions must be plainly marked as such, and must not be
71016     //   misrepresented as being the original software.
71017     // 3. This notice may not be removed or altered from any source distribution.
71018
71019     var messages = {
71020       2:      'need dictionary',     /* Z_NEED_DICT       2  */
71021       1:      'stream end',          /* Z_STREAM_END      1  */
71022       0:      '',                    /* Z_OK              0  */
71023       '-1':   'file error',          /* Z_ERRNO         (-1) */
71024       '-2':   'stream error',        /* Z_STREAM_ERROR  (-2) */
71025       '-3':   'data error',          /* Z_DATA_ERROR    (-3) */
71026       '-4':   'insufficient memory', /* Z_MEM_ERROR     (-4) */
71027       '-5':   'buffer error',        /* Z_BUF_ERROR     (-5) */
71028       '-6':   'incompatible version' /* Z_VERSION_ERROR (-6) */
71029     };
71030
71031     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
71032     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
71033     //
71034     // This software is provided 'as-is', without any express or implied
71035     // warranty. In no event will the authors be held liable for any damages
71036     // arising from the use of this software.
71037     //
71038     // Permission is granted to anyone to use this software for any purpose,
71039     // including commercial applications, and to alter it and redistribute it
71040     // freely, subject to the following restrictions:
71041     //
71042     // 1. The origin of this software must not be misrepresented; you must not
71043     //   claim that you wrote the original software. If you use this software
71044     //   in a product, an acknowledgment in the product documentation would be
71045     //   appreciated but is not required.
71046     // 2. Altered source versions must be plainly marked as such, and must not be
71047     //   misrepresented as being the original software.
71048     // 3. This notice may not be removed or altered from any source distribution.
71049
71050     var constants$2 = {
71051
71052       /* Allowed flush values; see deflate() and inflate() below for details */
71053       Z_NO_FLUSH:         0,
71054       Z_PARTIAL_FLUSH:    1,
71055       Z_SYNC_FLUSH:       2,
71056       Z_FULL_FLUSH:       3,
71057       Z_FINISH:           4,
71058       Z_BLOCK:            5,
71059       Z_TREES:            6,
71060
71061       /* Return codes for the compression/decompression functions. Negative values
71062       * are errors, positive values are used for special but normal events.
71063       */
71064       Z_OK:               0,
71065       Z_STREAM_END:       1,
71066       Z_NEED_DICT:        2,
71067       Z_ERRNO:           -1,
71068       Z_STREAM_ERROR:    -2,
71069       Z_DATA_ERROR:      -3,
71070       Z_MEM_ERROR:       -4,
71071       Z_BUF_ERROR:       -5,
71072       //Z_VERSION_ERROR: -6,
71073
71074       /* compression levels */
71075       Z_NO_COMPRESSION:         0,
71076       Z_BEST_SPEED:             1,
71077       Z_BEST_COMPRESSION:       9,
71078       Z_DEFAULT_COMPRESSION:   -1,
71079
71080
71081       Z_FILTERED:               1,
71082       Z_HUFFMAN_ONLY:           2,
71083       Z_RLE:                    3,
71084       Z_FIXED:                  4,
71085       Z_DEFAULT_STRATEGY:       0,
71086
71087       /* Possible values of the data_type field (though see inflate()) */
71088       Z_BINARY:                 0,
71089       Z_TEXT:                   1,
71090       //Z_ASCII:                1, // = Z_TEXT (deprecated)
71091       Z_UNKNOWN:                2,
71092
71093       /* The deflate compression method */
71094       Z_DEFLATED:               8
71095       //Z_NULL:                 null // Use -1 or null inline, depending on var type
71096     };
71097
71098     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
71099     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
71100     //
71101     // This software is provided 'as-is', without any express or implied
71102     // warranty. In no event will the authors be held liable for any damages
71103     // arising from the use of this software.
71104     //
71105     // Permission is granted to anyone to use this software for any purpose,
71106     // including commercial applications, and to alter it and redistribute it
71107     // freely, subject to the following restrictions:
71108     //
71109     // 1. The origin of this software must not be misrepresented; you must not
71110     //   claim that you wrote the original software. If you use this software
71111     //   in a product, an acknowledgment in the product documentation would be
71112     //   appreciated but is not required.
71113     // 2. Altered source versions must be plainly marked as such, and must not be
71114     //   misrepresented as being the original software.
71115     // 3. This notice may not be removed or altered from any source distribution.
71116
71117     const { _tr_init, _tr_stored_block, _tr_flush_block, _tr_tally, _tr_align } = trees;
71118
71119
71120
71121
71122     /* Public constants ==========================================================*/
71123     /* ===========================================================================*/
71124
71125     const {
71126       Z_NO_FLUSH: Z_NO_FLUSH$2, Z_PARTIAL_FLUSH, Z_FULL_FLUSH: Z_FULL_FLUSH$1, Z_FINISH: Z_FINISH$3, Z_BLOCK: Z_BLOCK$1,
71127       Z_OK: Z_OK$3, Z_STREAM_END: Z_STREAM_END$3, Z_STREAM_ERROR: Z_STREAM_ERROR$2, Z_DATA_ERROR: Z_DATA_ERROR$2, Z_BUF_ERROR: Z_BUF_ERROR$1,
71128       Z_DEFAULT_COMPRESSION: Z_DEFAULT_COMPRESSION$1,
71129       Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED, Z_DEFAULT_STRATEGY: Z_DEFAULT_STRATEGY$1,
71130       Z_UNKNOWN,
71131       Z_DEFLATED: Z_DEFLATED$2
71132     } = constants$2;
71133
71134     /*============================================================================*/
71135
71136
71137     const MAX_MEM_LEVEL = 9;
71138     /* Maximum value for memLevel in deflateInit2 */
71139     const MAX_WBITS$1 = 15;
71140     /* 32K LZ77 window */
71141     const DEF_MEM_LEVEL = 8;
71142
71143
71144     const LENGTH_CODES  = 29;
71145     /* number of length codes, not counting the special END_BLOCK code */
71146     const LITERALS      = 256;
71147     /* number of literal bytes 0..255 */
71148     const L_CODES       = LITERALS + 1 + LENGTH_CODES;
71149     /* number of Literal or Length codes, including the END_BLOCK code */
71150     const D_CODES       = 30;
71151     /* number of distance codes */
71152     const BL_CODES      = 19;
71153     /* number of codes used to transfer the bit lengths */
71154     const HEAP_SIZE     = 2 * L_CODES + 1;
71155     /* maximum heap size */
71156     const MAX_BITS  = 15;
71157     /* All codes must not exceed MAX_BITS bits */
71158
71159     const MIN_MATCH = 3;
71160     const MAX_MATCH = 258;
71161     const MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
71162
71163     const PRESET_DICT = 0x20;
71164
71165     const INIT_STATE = 42;
71166     const EXTRA_STATE = 69;
71167     const NAME_STATE = 73;
71168     const COMMENT_STATE = 91;
71169     const HCRC_STATE = 103;
71170     const BUSY_STATE = 113;
71171     const FINISH_STATE = 666;
71172
71173     const BS_NEED_MORE      = 1; /* block not completed, need more input or more output */
71174     const BS_BLOCK_DONE     = 2; /* block flush performed */
71175     const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
71176     const BS_FINISH_DONE    = 4; /* finish done, accept no more input or output */
71177
71178     const OS_CODE = 0x03; // Unix :) . Don't detect, use this default.
71179
71180     const err = (strm, errorCode) => {
71181       strm.msg = messages[errorCode];
71182       return errorCode;
71183     };
71184
71185     const rank = (f) => {
71186       return ((f) << 1) - ((f) > 4 ? 9 : 0);
71187     };
71188
71189     const zero = (buf) => {
71190       let len = buf.length; while (--len >= 0) { buf[len] = 0; }
71191     };
71192
71193
71194     /* eslint-disable new-cap */
71195     let HASH_ZLIB = (s, prev, data) => ((prev << s.hash_shift) ^ data) & s.hash_mask;
71196     // This hash causes less collisions, https://github.com/nodeca/pako/issues/135
71197     // But breaks binary compatibility
71198     //let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask;
71199     let HASH = HASH_ZLIB;
71200
71201     /* =========================================================================
71202      * Flush as much pending output as possible. All deflate() output goes
71203      * through this function so some applications may wish to modify it
71204      * to avoid allocating a large strm->output buffer and copying into it.
71205      * (See also read_buf()).
71206      */
71207     const flush_pending = (strm) => {
71208       const s = strm.state;
71209
71210       //_tr_flush_bits(s);
71211       let len = s.pending;
71212       if (len > strm.avail_out) {
71213         len = strm.avail_out;
71214       }
71215       if (len === 0) { return; }
71216
71217       strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out);
71218       strm.next_out += len;
71219       s.pending_out += len;
71220       strm.total_out += len;
71221       strm.avail_out -= len;
71222       s.pending -= len;
71223       if (s.pending === 0) {
71224         s.pending_out = 0;
71225       }
71226     };
71227
71228
71229     const flush_block_only = (s, last) => {
71230       _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);
71231       s.block_start = s.strstart;
71232       flush_pending(s.strm);
71233     };
71234
71235
71236     const put_byte = (s, b) => {
71237       s.pending_buf[s.pending++] = b;
71238     };
71239
71240
71241     /* =========================================================================
71242      * Put a short in the pending buffer. The 16-bit value is put in MSB order.
71243      * IN assertion: the stream state is correct and there is enough room in
71244      * pending_buf.
71245      */
71246     const putShortMSB = (s, b) => {
71247
71248       //  put_byte(s, (Byte)(b >> 8));
71249     //  put_byte(s, (Byte)(b & 0xff));
71250       s.pending_buf[s.pending++] = (b >>> 8) & 0xff;
71251       s.pending_buf[s.pending++] = b & 0xff;
71252     };
71253
71254
71255     /* ===========================================================================
71256      * Read a new buffer from the current input stream, update the adler32
71257      * and total number of bytes read.  All deflate() input goes through
71258      * this function so some applications may wish to modify it to avoid
71259      * allocating a large strm->input buffer and copying from it.
71260      * (See also flush_pending()).
71261      */
71262     const read_buf = (strm, buf, start, size) => {
71263
71264       let len = strm.avail_in;
71265
71266       if (len > size) { len = size; }
71267       if (len === 0) { return 0; }
71268
71269       strm.avail_in -= len;
71270
71271       // zmemcpy(buf, strm->next_in, len);
71272       buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start);
71273       if (strm.state.wrap === 1) {
71274         strm.adler = adler32_1(strm.adler, buf, len, start);
71275       }
71276
71277       else if (strm.state.wrap === 2) {
71278         strm.adler = crc32_1(strm.adler, buf, len, start);
71279       }
71280
71281       strm.next_in += len;
71282       strm.total_in += len;
71283
71284       return len;
71285     };
71286
71287
71288     /* ===========================================================================
71289      * Set match_start to the longest match starting at the given string and
71290      * return its length. Matches shorter or equal to prev_length are discarded,
71291      * in which case the result is equal to prev_length and match_start is
71292      * garbage.
71293      * IN assertions: cur_match is the head of the hash chain for the current
71294      *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
71295      * OUT assertion: the match length is not greater than s->lookahead.
71296      */
71297     const longest_match = (s, cur_match) => {
71298
71299       let chain_length = s.max_chain_length;      /* max hash chain length */
71300       let scan = s.strstart; /* current string */
71301       let match;                       /* matched string */
71302       let len;                           /* length of current match */
71303       let best_len = s.prev_length;              /* best match length so far */
71304       let nice_match = s.nice_match;             /* stop if match long enough */
71305       const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?
71306           s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;
71307
71308       const _win = s.window; // shortcut
71309
71310       const wmask = s.w_mask;
71311       const prev  = s.prev;
71312
71313       /* Stop when cur_match becomes <= limit. To simplify the code,
71314        * we prevent matches with the string of window index 0.
71315        */
71316
71317       const strend = s.strstart + MAX_MATCH;
71318       let scan_end1  = _win[scan + best_len - 1];
71319       let scan_end   = _win[scan + best_len];
71320
71321       /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
71322        * It is easy to get rid of this optimization if necessary.
71323        */
71324       // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
71325
71326       /* Do not waste too much time if we already have a good match: */
71327       if (s.prev_length >= s.good_match) {
71328         chain_length >>= 2;
71329       }
71330       /* Do not look for matches beyond the end of the input. This is necessary
71331        * to make deflate deterministic.
71332        */
71333       if (nice_match > s.lookahead) { nice_match = s.lookahead; }
71334
71335       // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
71336
71337       do {
71338         // Assert(cur_match < s->strstart, "no future");
71339         match = cur_match;
71340
71341         /* Skip to next match if the match length cannot increase
71342          * or if the match length is less than 2.  Note that the checks below
71343          * for insufficient lookahead only occur occasionally for performance
71344          * reasons.  Therefore uninitialized memory will be accessed, and
71345          * conditional jumps will be made that depend on those values.
71346          * However the length of the match is limited to the lookahead, so
71347          * the output of deflate is not affected by the uninitialized values.
71348          */
71349
71350         if (_win[match + best_len]     !== scan_end  ||
71351             _win[match + best_len - 1] !== scan_end1 ||
71352             _win[match]                !== _win[scan] ||
71353             _win[++match]              !== _win[scan + 1]) {
71354           continue;
71355         }
71356
71357         /* The check at best_len-1 can be removed because it will be made
71358          * again later. (This heuristic is not always a win.)
71359          * It is not necessary to compare scan[2] and match[2] since they
71360          * are always equal when the other bytes match, given that
71361          * the hash keys are equal and that HASH_BITS >= 8.
71362          */
71363         scan += 2;
71364         match++;
71365         // Assert(*scan == *match, "match[2]?");
71366
71367         /* We check for insufficient lookahead only every 8th comparison;
71368          * the 256th check will be made at strstart+258.
71369          */
71370         do {
71371           /*jshint noempty:false*/
71372         } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
71373                  _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
71374                  _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
71375                  _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
71376                  scan < strend);
71377
71378         // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
71379
71380         len = MAX_MATCH - (strend - scan);
71381         scan = strend - MAX_MATCH;
71382
71383         if (len > best_len) {
71384           s.match_start = cur_match;
71385           best_len = len;
71386           if (len >= nice_match) {
71387             break;
71388           }
71389           scan_end1  = _win[scan + best_len - 1];
71390           scan_end   = _win[scan + best_len];
71391         }
71392       } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);
71393
71394       if (best_len <= s.lookahead) {
71395         return best_len;
71396       }
71397       return s.lookahead;
71398     };
71399
71400
71401     /* ===========================================================================
71402      * Fill the window when the lookahead becomes insufficient.
71403      * Updates strstart and lookahead.
71404      *
71405      * IN assertion: lookahead < MIN_LOOKAHEAD
71406      * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
71407      *    At least one byte has been read, or avail_in == 0; reads are
71408      *    performed for at least two bytes (required for the zip translate_eol
71409      *    option -- not supported here).
71410      */
71411     const fill_window = (s) => {
71412
71413       const _w_size = s.w_size;
71414       let p, n, m, more, str;
71415
71416       //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
71417
71418       do {
71419         more = s.window_size - s.lookahead - s.strstart;
71420
71421         // JS ints have 32 bit, block below not needed
71422         /* Deal with !@#$% 64K limit: */
71423         //if (sizeof(int) <= 2) {
71424         //    if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
71425         //        more = wsize;
71426         //
71427         //  } else if (more == (unsigned)(-1)) {
71428         //        /* Very unlikely, but possible on 16 bit machine if
71429         //         * strstart == 0 && lookahead == 1 (input done a byte at time)
71430         //         */
71431         //        more--;
71432         //    }
71433         //}
71434
71435
71436         /* If the window is almost full and there is insufficient lookahead,
71437          * move the upper half to the lower one to make room in the upper half.
71438          */
71439         if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {
71440
71441           s.window.set(s.window.subarray(_w_size, _w_size + _w_size), 0);
71442           s.match_start -= _w_size;
71443           s.strstart -= _w_size;
71444           /* we now have strstart >= MAX_DIST */
71445           s.block_start -= _w_size;
71446
71447           /* Slide the hash table (could be avoided with 32 bit values
71448            at the expense of memory usage). We slide even when level == 0
71449            to keep the hash table consistent if we switch back to level > 0
71450            later. (Using level 0 permanently is not an optimal usage of
71451            zlib, so we don't care about this pathological case.)
71452            */
71453
71454           n = s.hash_size;
71455           p = n;
71456
71457           do {
71458             m = s.head[--p];
71459             s.head[p] = (m >= _w_size ? m - _w_size : 0);
71460           } while (--n);
71461
71462           n = _w_size;
71463           p = n;
71464
71465           do {
71466             m = s.prev[--p];
71467             s.prev[p] = (m >= _w_size ? m - _w_size : 0);
71468             /* If n is not on any hash chain, prev[n] is garbage but
71469              * its value will never be used.
71470              */
71471           } while (--n);
71472
71473           more += _w_size;
71474         }
71475         if (s.strm.avail_in === 0) {
71476           break;
71477         }
71478
71479         /* If there was no sliding:
71480          *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
71481          *    more == window_size - lookahead - strstart
71482          * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
71483          * => more >= window_size - 2*WSIZE + 2
71484          * In the BIG_MEM or MMAP case (not yet supported),
71485          *   window_size == input_size + MIN_LOOKAHEAD  &&
71486          *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
71487          * Otherwise, window_size == 2*WSIZE so more >= 2.
71488          * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
71489          */
71490         //Assert(more >= 2, "more < 2");
71491         n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);
71492         s.lookahead += n;
71493
71494         /* Initialize the hash value now that we have some input: */
71495         if (s.lookahead + s.insert >= MIN_MATCH) {
71496           str = s.strstart - s.insert;
71497           s.ins_h = s.window[str];
71498
71499           /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */
71500           s.ins_h = HASH(s, s.ins_h, s.window[str + 1]);
71501     //#if MIN_MATCH != 3
71502     //        Call update_hash() MIN_MATCH-3 more times
71503     //#endif
71504           while (s.insert) {
71505             /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
71506             s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]);
71507
71508             s.prev[str & s.w_mask] = s.head[s.ins_h];
71509             s.head[s.ins_h] = str;
71510             str++;
71511             s.insert--;
71512             if (s.lookahead + s.insert < MIN_MATCH) {
71513               break;
71514             }
71515           }
71516         }
71517         /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
71518          * but this is not important since only literal bytes will be emitted.
71519          */
71520
71521       } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);
71522
71523       /* If the WIN_INIT bytes after the end of the current data have never been
71524        * written, then zero those bytes in order to avoid memory check reports of
71525        * the use of uninitialized (or uninitialised as Julian writes) bytes by
71526        * the longest match routines.  Update the high water mark for the next
71527        * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
71528        * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
71529        */
71530     //  if (s.high_water < s.window_size) {
71531     //    const curr = s.strstart + s.lookahead;
71532     //    let init = 0;
71533     //
71534     //    if (s.high_water < curr) {
71535     //      /* Previous high water mark below current data -- zero WIN_INIT
71536     //       * bytes or up to end of window, whichever is less.
71537     //       */
71538     //      init = s.window_size - curr;
71539     //      if (init > WIN_INIT)
71540     //        init = WIN_INIT;
71541     //      zmemzero(s->window + curr, (unsigned)init);
71542     //      s->high_water = curr + init;
71543     //    }
71544     //    else if (s->high_water < (ulg)curr + WIN_INIT) {
71545     //      /* High water mark at or above current data, but below current data
71546     //       * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
71547     //       * to end of window, whichever is less.
71548     //       */
71549     //      init = (ulg)curr + WIN_INIT - s->high_water;
71550     //      if (init > s->window_size - s->high_water)
71551     //        init = s->window_size - s->high_water;
71552     //      zmemzero(s->window + s->high_water, (unsigned)init);
71553     //      s->high_water += init;
71554     //    }
71555     //  }
71556     //
71557     //  Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
71558     //    "not enough room for search");
71559     };
71560
71561     /* ===========================================================================
71562      * Copy without compression as much as possible from the input stream, return
71563      * the current block state.
71564      * This function does not insert new strings in the dictionary since
71565      * uncompressible data is probably not useful. This function is used
71566      * only for the level=0 compression option.
71567      * NOTE: this function should be optimized to avoid extra copying from
71568      * window to pending_buf.
71569      */
71570     const deflate_stored = (s, flush) => {
71571
71572       /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
71573        * to pending_buf_size, and each stored block has a 5 byte header:
71574        */
71575       let max_block_size = 0xffff;
71576
71577       if (max_block_size > s.pending_buf_size - 5) {
71578         max_block_size = s.pending_buf_size - 5;
71579       }
71580
71581       /* Copy as much as possible from input to output: */
71582       for (;;) {
71583         /* Fill the window as much as possible: */
71584         if (s.lookahead <= 1) {
71585
71586           //Assert(s->strstart < s->w_size+MAX_DIST(s) ||
71587           //  s->block_start >= (long)s->w_size, "slide too late");
71588     //      if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) ||
71589     //        s.block_start >= s.w_size)) {
71590     //        throw  new Error("slide too late");
71591     //      }
71592
71593           fill_window(s);
71594           if (s.lookahead === 0 && flush === Z_NO_FLUSH$2) {
71595             return BS_NEED_MORE;
71596           }
71597
71598           if (s.lookahead === 0) {
71599             break;
71600           }
71601           /* flush the current block */
71602         }
71603         //Assert(s->block_start >= 0L, "block gone");
71604     //    if (s.block_start < 0) throw new Error("block gone");
71605
71606         s.strstart += s.lookahead;
71607         s.lookahead = 0;
71608
71609         /* Emit a stored block if pending_buf will be full: */
71610         const max_start = s.block_start + max_block_size;
71611
71612         if (s.strstart === 0 || s.strstart >= max_start) {
71613           /* strstart == 0 is possible when wraparound on 16-bit machine */
71614           s.lookahead = s.strstart - max_start;
71615           s.strstart = max_start;
71616           /*** FLUSH_BLOCK(s, 0); ***/
71617           flush_block_only(s, false);
71618           if (s.strm.avail_out === 0) {
71619             return BS_NEED_MORE;
71620           }
71621           /***/
71622
71623
71624         }
71625         /* Flush if we may have to slide, otherwise block_start may become
71626          * negative and the data will be gone:
71627          */
71628         if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) {
71629           /*** FLUSH_BLOCK(s, 0); ***/
71630           flush_block_only(s, false);
71631           if (s.strm.avail_out === 0) {
71632             return BS_NEED_MORE;
71633           }
71634           /***/
71635         }
71636       }
71637
71638       s.insert = 0;
71639
71640       if (flush === Z_FINISH$3) {
71641         /*** FLUSH_BLOCK(s, 1); ***/
71642         flush_block_only(s, true);
71643         if (s.strm.avail_out === 0) {
71644           return BS_FINISH_STARTED;
71645         }
71646         /***/
71647         return BS_FINISH_DONE;
71648       }
71649
71650       if (s.strstart > s.block_start) {
71651         /*** FLUSH_BLOCK(s, 0); ***/
71652         flush_block_only(s, false);
71653         if (s.strm.avail_out === 0) {
71654           return BS_NEED_MORE;
71655         }
71656         /***/
71657       }
71658
71659       return BS_NEED_MORE;
71660     };
71661
71662     /* ===========================================================================
71663      * Compress as much as possible from the input stream, return the current
71664      * block state.
71665      * This function does not perform lazy evaluation of matches and inserts
71666      * new strings in the dictionary only for unmatched strings or for short
71667      * matches. It is used only for the fast compression options.
71668      */
71669     const deflate_fast = (s, flush) => {
71670
71671       let hash_head;        /* head of the hash chain */
71672       let bflush;           /* set if current block must be flushed */
71673
71674       for (;;) {
71675         /* Make sure that we always have enough lookahead, except
71676          * at the end of the input file. We need MAX_MATCH bytes
71677          * for the next match, plus MIN_MATCH bytes to insert the
71678          * string following the next match.
71679          */
71680         if (s.lookahead < MIN_LOOKAHEAD) {
71681           fill_window(s);
71682           if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) {
71683             return BS_NEED_MORE;
71684           }
71685           if (s.lookahead === 0) {
71686             break; /* flush the current block */
71687           }
71688         }
71689
71690         /* Insert the string window[strstart .. strstart+2] in the
71691          * dictionary, and set hash_head to the head of the hash chain:
71692          */
71693         hash_head = 0/*NIL*/;
71694         if (s.lookahead >= MIN_MATCH) {
71695           /*** INSERT_STRING(s, s.strstart, hash_head); ***/
71696           s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);
71697           hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
71698           s.head[s.ins_h] = s.strstart;
71699           /***/
71700         }
71701
71702         /* Find the longest match, discarding those <= prev_length.
71703          * At this point we have always match_length < MIN_MATCH
71704          */
71705         if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {
71706           /* To simplify the code, we prevent matches with the string
71707            * of window index 0 (in particular we have to avoid a match
71708            * of the string with itself at the start of the input file).
71709            */
71710           s.match_length = longest_match(s, hash_head);
71711           /* longest_match() sets match_start */
71712         }
71713         if (s.match_length >= MIN_MATCH) {
71714           // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only
71715
71716           /*** _tr_tally_dist(s, s.strstart - s.match_start,
71717                          s.match_length - MIN_MATCH, bflush); ***/
71718           bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH);
71719
71720           s.lookahead -= s.match_length;
71721
71722           /* Insert new strings in the hash table only if the match length
71723            * is not too large. This saves time but degrades compression.
71724            */
71725           if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) {
71726             s.match_length--; /* string at strstart already in table */
71727             do {
71728               s.strstart++;
71729               /*** INSERT_STRING(s, s.strstart, hash_head); ***/
71730               s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);
71731               hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
71732               s.head[s.ins_h] = s.strstart;
71733               /***/
71734               /* strstart never exceeds WSIZE-MAX_MATCH, so there are
71735                * always MIN_MATCH bytes ahead.
71736                */
71737             } while (--s.match_length !== 0);
71738             s.strstart++;
71739           } else
71740           {
71741             s.strstart += s.match_length;
71742             s.match_length = 0;
71743             s.ins_h = s.window[s.strstart];
71744             /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */
71745             s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]);
71746
71747     //#if MIN_MATCH != 3
71748     //                Call UPDATE_HASH() MIN_MATCH-3 more times
71749     //#endif
71750             /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
71751              * matter since it will be recomputed at next deflate call.
71752              */
71753           }
71754         } else {
71755           /* No match, output a literal byte */
71756           //Tracevv((stderr,"%c", s.window[s.strstart]));
71757           /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
71758           bflush = _tr_tally(s, 0, s.window[s.strstart]);
71759
71760           s.lookahead--;
71761           s.strstart++;
71762         }
71763         if (bflush) {
71764           /*** FLUSH_BLOCK(s, 0); ***/
71765           flush_block_only(s, false);
71766           if (s.strm.avail_out === 0) {
71767             return BS_NEED_MORE;
71768           }
71769           /***/
71770         }
71771       }
71772       s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1);
71773       if (flush === Z_FINISH$3) {
71774         /*** FLUSH_BLOCK(s, 1); ***/
71775         flush_block_only(s, true);
71776         if (s.strm.avail_out === 0) {
71777           return BS_FINISH_STARTED;
71778         }
71779         /***/
71780         return BS_FINISH_DONE;
71781       }
71782       if (s.last_lit) {
71783         /*** FLUSH_BLOCK(s, 0); ***/
71784         flush_block_only(s, false);
71785         if (s.strm.avail_out === 0) {
71786           return BS_NEED_MORE;
71787         }
71788         /***/
71789       }
71790       return BS_BLOCK_DONE;
71791     };
71792
71793     /* ===========================================================================
71794      * Same as above, but achieves better compression. We use a lazy
71795      * evaluation for matches: a match is finally adopted only if there is
71796      * no better match at the next window position.
71797      */
71798     const deflate_slow = (s, flush) => {
71799
71800       let hash_head;          /* head of hash chain */
71801       let bflush;              /* set if current block must be flushed */
71802
71803       let max_insert;
71804
71805       /* Process the input block. */
71806       for (;;) {
71807         /* Make sure that we always have enough lookahead, except
71808          * at the end of the input file. We need MAX_MATCH bytes
71809          * for the next match, plus MIN_MATCH bytes to insert the
71810          * string following the next match.
71811          */
71812         if (s.lookahead < MIN_LOOKAHEAD) {
71813           fill_window(s);
71814           if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) {
71815             return BS_NEED_MORE;
71816           }
71817           if (s.lookahead === 0) { break; } /* flush the current block */
71818         }
71819
71820         /* Insert the string window[strstart .. strstart+2] in the
71821          * dictionary, and set hash_head to the head of the hash chain:
71822          */
71823         hash_head = 0/*NIL*/;
71824         if (s.lookahead >= MIN_MATCH) {
71825           /*** INSERT_STRING(s, s.strstart, hash_head); ***/
71826           s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);
71827           hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
71828           s.head[s.ins_h] = s.strstart;
71829           /***/
71830         }
71831
71832         /* Find the longest match, discarding those <= prev_length.
71833          */
71834         s.prev_length = s.match_length;
71835         s.prev_match = s.match_start;
71836         s.match_length = MIN_MATCH - 1;
71837
71838         if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&
71839             s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {
71840           /* To simplify the code, we prevent matches with the string
71841            * of window index 0 (in particular we have to avoid a match
71842            * of the string with itself at the start of the input file).
71843            */
71844           s.match_length = longest_match(s, hash_head);
71845           /* longest_match() sets match_start */
71846
71847           if (s.match_length <= 5 &&
71848              (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {
71849
71850             /* If prev_match is also MIN_MATCH, match_start is garbage
71851              * but we will ignore the current match anyway.
71852              */
71853             s.match_length = MIN_MATCH - 1;
71854           }
71855         }
71856         /* If there was a match at the previous step and the current
71857          * match is not better, output the previous match:
71858          */
71859         if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) {
71860           max_insert = s.strstart + s.lookahead - MIN_MATCH;
71861           /* Do not insert strings in hash table beyond this. */
71862
71863           //check_match(s, s.strstart-1, s.prev_match, s.prev_length);
71864
71865           /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,
71866                          s.prev_length - MIN_MATCH, bflush);***/
71867           bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH);
71868           /* Insert in hash table all strings up to the end of the match.
71869            * strstart-1 and strstart are already inserted. If there is not
71870            * enough lookahead, the last two strings are not inserted in
71871            * the hash table.
71872            */
71873           s.lookahead -= s.prev_length - 1;
71874           s.prev_length -= 2;
71875           do {
71876             if (++s.strstart <= max_insert) {
71877               /*** INSERT_STRING(s, s.strstart, hash_head); ***/
71878               s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);
71879               hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
71880               s.head[s.ins_h] = s.strstart;
71881               /***/
71882             }
71883           } while (--s.prev_length !== 0);
71884           s.match_available = 0;
71885           s.match_length = MIN_MATCH - 1;
71886           s.strstart++;
71887
71888           if (bflush) {
71889             /*** FLUSH_BLOCK(s, 0); ***/
71890             flush_block_only(s, false);
71891             if (s.strm.avail_out === 0) {
71892               return BS_NEED_MORE;
71893             }
71894             /***/
71895           }
71896
71897         } else if (s.match_available) {
71898           /* If there was no match at the previous position, output a
71899            * single literal. If there was a match but the current match
71900            * is longer, truncate the previous match to a single literal.
71901            */
71902           //Tracevv((stderr,"%c", s->window[s->strstart-1]));
71903           /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
71904           bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);
71905
71906           if (bflush) {
71907             /*** FLUSH_BLOCK_ONLY(s, 0) ***/
71908             flush_block_only(s, false);
71909             /***/
71910           }
71911           s.strstart++;
71912           s.lookahead--;
71913           if (s.strm.avail_out === 0) {
71914             return BS_NEED_MORE;
71915           }
71916         } else {
71917           /* There is no previous match to compare with, wait for
71918            * the next step to decide.
71919            */
71920           s.match_available = 1;
71921           s.strstart++;
71922           s.lookahead--;
71923         }
71924       }
71925       //Assert (flush != Z_NO_FLUSH, "no flush?");
71926       if (s.match_available) {
71927         //Tracevv((stderr,"%c", s->window[s->strstart-1]));
71928         /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
71929         bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);
71930
71931         s.match_available = 0;
71932       }
71933       s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1;
71934       if (flush === Z_FINISH$3) {
71935         /*** FLUSH_BLOCK(s, 1); ***/
71936         flush_block_only(s, true);
71937         if (s.strm.avail_out === 0) {
71938           return BS_FINISH_STARTED;
71939         }
71940         /***/
71941         return BS_FINISH_DONE;
71942       }
71943       if (s.last_lit) {
71944         /*** FLUSH_BLOCK(s, 0); ***/
71945         flush_block_only(s, false);
71946         if (s.strm.avail_out === 0) {
71947           return BS_NEED_MORE;
71948         }
71949         /***/
71950       }
71951
71952       return BS_BLOCK_DONE;
71953     };
71954
71955
71956     /* ===========================================================================
71957      * For Z_RLE, simply look for runs of bytes, generate matches only of distance
71958      * one.  Do not maintain a hash table.  (It will be regenerated if this run of
71959      * deflate switches away from Z_RLE.)
71960      */
71961     const deflate_rle = (s, flush) => {
71962
71963       let bflush;            /* set if current block must be flushed */
71964       let prev;              /* byte at distance one to match */
71965       let scan, strend;      /* scan goes up to strend for length of run */
71966
71967       const _win = s.window;
71968
71969       for (;;) {
71970         /* Make sure that we always have enough lookahead, except
71971          * at the end of the input file. We need MAX_MATCH bytes
71972          * for the longest run, plus one for the unrolled loop.
71973          */
71974         if (s.lookahead <= MAX_MATCH) {
71975           fill_window(s);
71976           if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH$2) {
71977             return BS_NEED_MORE;
71978           }
71979           if (s.lookahead === 0) { break; } /* flush the current block */
71980         }
71981
71982         /* See how many times the previous byte repeats */
71983         s.match_length = 0;
71984         if (s.lookahead >= MIN_MATCH && s.strstart > 0) {
71985           scan = s.strstart - 1;
71986           prev = _win[scan];
71987           if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
71988             strend = s.strstart + MAX_MATCH;
71989             do {
71990               /*jshint noempty:false*/
71991             } while (prev === _win[++scan] && prev === _win[++scan] &&
71992                      prev === _win[++scan] && prev === _win[++scan] &&
71993                      prev === _win[++scan] && prev === _win[++scan] &&
71994                      prev === _win[++scan] && prev === _win[++scan] &&
71995                      scan < strend);
71996             s.match_length = MAX_MATCH - (strend - scan);
71997             if (s.match_length > s.lookahead) {
71998               s.match_length = s.lookahead;
71999             }
72000           }
72001           //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
72002         }
72003
72004         /* Emit match if have run of MIN_MATCH or longer, else emit literal */
72005         if (s.match_length >= MIN_MATCH) {
72006           //check_match(s, s.strstart, s.strstart - 1, s.match_length);
72007
72008           /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/
72009           bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH);
72010
72011           s.lookahead -= s.match_length;
72012           s.strstart += s.match_length;
72013           s.match_length = 0;
72014         } else {
72015           /* No match, output a literal byte */
72016           //Tracevv((stderr,"%c", s->window[s->strstart]));
72017           /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
72018           bflush = _tr_tally(s, 0, s.window[s.strstart]);
72019
72020           s.lookahead--;
72021           s.strstart++;
72022         }
72023         if (bflush) {
72024           /*** FLUSH_BLOCK(s, 0); ***/
72025           flush_block_only(s, false);
72026           if (s.strm.avail_out === 0) {
72027             return BS_NEED_MORE;
72028           }
72029           /***/
72030         }
72031       }
72032       s.insert = 0;
72033       if (flush === Z_FINISH$3) {
72034         /*** FLUSH_BLOCK(s, 1); ***/
72035         flush_block_only(s, true);
72036         if (s.strm.avail_out === 0) {
72037           return BS_FINISH_STARTED;
72038         }
72039         /***/
72040         return BS_FINISH_DONE;
72041       }
72042       if (s.last_lit) {
72043         /*** FLUSH_BLOCK(s, 0); ***/
72044         flush_block_only(s, false);
72045         if (s.strm.avail_out === 0) {
72046           return BS_NEED_MORE;
72047         }
72048         /***/
72049       }
72050       return BS_BLOCK_DONE;
72051     };
72052
72053     /* ===========================================================================
72054      * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
72055      * (It will be regenerated if this run of deflate switches away from Huffman.)
72056      */
72057     const deflate_huff = (s, flush) => {
72058
72059       let bflush;             /* set if current block must be flushed */
72060
72061       for (;;) {
72062         /* Make sure that we have a literal to write. */
72063         if (s.lookahead === 0) {
72064           fill_window(s);
72065           if (s.lookahead === 0) {
72066             if (flush === Z_NO_FLUSH$2) {
72067               return BS_NEED_MORE;
72068             }
72069             break;      /* flush the current block */
72070           }
72071         }
72072
72073         /* Output a literal byte */
72074         s.match_length = 0;
72075         //Tracevv((stderr,"%c", s->window[s->strstart]));
72076         /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
72077         bflush = _tr_tally(s, 0, s.window[s.strstart]);
72078         s.lookahead--;
72079         s.strstart++;
72080         if (bflush) {
72081           /*** FLUSH_BLOCK(s, 0); ***/
72082           flush_block_only(s, false);
72083           if (s.strm.avail_out === 0) {
72084             return BS_NEED_MORE;
72085           }
72086           /***/
72087         }
72088       }
72089       s.insert = 0;
72090       if (flush === Z_FINISH$3) {
72091         /*** FLUSH_BLOCK(s, 1); ***/
72092         flush_block_only(s, true);
72093         if (s.strm.avail_out === 0) {
72094           return BS_FINISH_STARTED;
72095         }
72096         /***/
72097         return BS_FINISH_DONE;
72098       }
72099       if (s.last_lit) {
72100         /*** FLUSH_BLOCK(s, 0); ***/
72101         flush_block_only(s, false);
72102         if (s.strm.avail_out === 0) {
72103           return BS_NEED_MORE;
72104         }
72105         /***/
72106       }
72107       return BS_BLOCK_DONE;
72108     };
72109
72110     /* Values for max_lazy_match, good_match and max_chain_length, depending on
72111      * the desired pack level (0..9). The values given below have been tuned to
72112      * exclude worst case performance for pathological files. Better values may be
72113      * found for specific files.
72114      */
72115     function Config(good_length, max_lazy, nice_length, max_chain, func) {
72116
72117       this.good_length = good_length;
72118       this.max_lazy = max_lazy;
72119       this.nice_length = nice_length;
72120       this.max_chain = max_chain;
72121       this.func = func;
72122     }
72123
72124     const configuration_table = [
72125       /*      good lazy nice chain */
72126       new Config(0, 0, 0, 0, deflate_stored),          /* 0 store only */
72127       new Config(4, 4, 8, 4, deflate_fast),            /* 1 max speed, no lazy matches */
72128       new Config(4, 5, 16, 8, deflate_fast),           /* 2 */
72129       new Config(4, 6, 32, 32, deflate_fast),          /* 3 */
72130
72131       new Config(4, 4, 16, 16, deflate_slow),          /* 4 lazy matches */
72132       new Config(8, 16, 32, 32, deflate_slow),         /* 5 */
72133       new Config(8, 16, 128, 128, deflate_slow),       /* 6 */
72134       new Config(8, 32, 128, 256, deflate_slow),       /* 7 */
72135       new Config(32, 128, 258, 1024, deflate_slow),    /* 8 */
72136       new Config(32, 258, 258, 4096, deflate_slow)     /* 9 max compression */
72137     ];
72138
72139
72140     /* ===========================================================================
72141      * Initialize the "longest match" routines for a new zlib stream
72142      */
72143     const lm_init = (s) => {
72144
72145       s.window_size = 2 * s.w_size;
72146
72147       /*** CLEAR_HASH(s); ***/
72148       zero(s.head); // Fill with NIL (= 0);
72149
72150       /* Set the default configuration parameters:
72151        */
72152       s.max_lazy_match = configuration_table[s.level].max_lazy;
72153       s.good_match = configuration_table[s.level].good_length;
72154       s.nice_match = configuration_table[s.level].nice_length;
72155       s.max_chain_length = configuration_table[s.level].max_chain;
72156
72157       s.strstart = 0;
72158       s.block_start = 0;
72159       s.lookahead = 0;
72160       s.insert = 0;
72161       s.match_length = s.prev_length = MIN_MATCH - 1;
72162       s.match_available = 0;
72163       s.ins_h = 0;
72164     };
72165
72166
72167     function DeflateState() {
72168       this.strm = null;            /* pointer back to this zlib stream */
72169       this.status = 0;            /* as the name implies */
72170       this.pending_buf = null;      /* output still pending */
72171       this.pending_buf_size = 0;  /* size of pending_buf */
72172       this.pending_out = 0;       /* next pending byte to output to the stream */
72173       this.pending = 0;           /* nb of bytes in the pending buffer */
72174       this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */
72175       this.gzhead = null;         /* gzip header information to write */
72176       this.gzindex = 0;           /* where in extra, name, or comment */
72177       this.method = Z_DEFLATED$2; /* can only be DEFLATED */
72178       this.last_flush = -1;   /* value of flush param for previous deflate call */
72179
72180       this.w_size = 0;  /* LZ77 window size (32K by default) */
72181       this.w_bits = 0;  /* log2(w_size)  (8..16) */
72182       this.w_mask = 0;  /* w_size - 1 */
72183
72184       this.window = null;
72185       /* Sliding window. Input bytes are read into the second half of the window,
72186        * and move to the first half later to keep a dictionary of at least wSize
72187        * bytes. With this organization, matches are limited to a distance of
72188        * wSize-MAX_MATCH bytes, but this ensures that IO is always
72189        * performed with a length multiple of the block size.
72190        */
72191
72192       this.window_size = 0;
72193       /* Actual size of window: 2*wSize, except when the user input buffer
72194        * is directly used as sliding window.
72195        */
72196
72197       this.prev = null;
72198       /* Link to older string with same hash index. To limit the size of this
72199        * array to 64K, this link is maintained only for the last 32K strings.
72200        * An index in this array is thus a window index modulo 32K.
72201        */
72202
72203       this.head = null;   /* Heads of the hash chains or NIL. */
72204
72205       this.ins_h = 0;       /* hash index of string to be inserted */
72206       this.hash_size = 0;   /* number of elements in hash table */
72207       this.hash_bits = 0;   /* log2(hash_size) */
72208       this.hash_mask = 0;   /* hash_size-1 */
72209
72210       this.hash_shift = 0;
72211       /* Number of bits by which ins_h must be shifted at each input
72212        * step. It must be such that after MIN_MATCH steps, the oldest
72213        * byte no longer takes part in the hash key, that is:
72214        *   hash_shift * MIN_MATCH >= hash_bits
72215        */
72216
72217       this.block_start = 0;
72218       /* Window position at the beginning of the current output block. Gets
72219        * negative when the window is moved backwards.
72220        */
72221
72222       this.match_length = 0;      /* length of best match */
72223       this.prev_match = 0;        /* previous match */
72224       this.match_available = 0;   /* set if previous match exists */
72225       this.strstart = 0;          /* start of string to insert */
72226       this.match_start = 0;       /* start of matching string */
72227       this.lookahead = 0;         /* number of valid bytes ahead in window */
72228
72229       this.prev_length = 0;
72230       /* Length of the best match at previous step. Matches not greater than this
72231        * are discarded. This is used in the lazy match evaluation.
72232        */
72233
72234       this.max_chain_length = 0;
72235       /* To speed up deflation, hash chains are never searched beyond this
72236        * length.  A higher limit improves compression ratio but degrades the
72237        * speed.
72238        */
72239
72240       this.max_lazy_match = 0;
72241       /* Attempt to find a better match only when the current match is strictly
72242        * smaller than this value. This mechanism is used only for compression
72243        * levels >= 4.
72244        */
72245       // That's alias to max_lazy_match, don't use directly
72246       //this.max_insert_length = 0;
72247       /* Insert new strings in the hash table only if the match length is not
72248        * greater than this length. This saves time but degrades compression.
72249        * max_insert_length is used only for compression levels <= 3.
72250        */
72251
72252       this.level = 0;     /* compression level (1..9) */
72253       this.strategy = 0;  /* favor or force Huffman coding*/
72254
72255       this.good_match = 0;
72256       /* Use a faster search when the previous match is longer than this */
72257
72258       this.nice_match = 0; /* Stop searching when current match exceeds this */
72259
72260                   /* used by trees.c: */
72261
72262       /* Didn't use ct_data typedef below to suppress compiler warning */
72263
72264       // struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
72265       // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
72266       // struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
72267
72268       // Use flat array of DOUBLE size, with interleaved fata,
72269       // because JS does not support effective
72270       this.dyn_ltree  = new Uint16Array(HEAP_SIZE * 2);
72271       this.dyn_dtree  = new Uint16Array((2 * D_CODES + 1) * 2);
72272       this.bl_tree    = new Uint16Array((2 * BL_CODES + 1) * 2);
72273       zero(this.dyn_ltree);
72274       zero(this.dyn_dtree);
72275       zero(this.bl_tree);
72276
72277       this.l_desc   = null;         /* desc. for literal tree */
72278       this.d_desc   = null;         /* desc. for distance tree */
72279       this.bl_desc  = null;         /* desc. for bit length tree */
72280
72281       //ush bl_count[MAX_BITS+1];
72282       this.bl_count = new Uint16Array(MAX_BITS + 1);
72283       /* number of codes at each bit length for an optimal tree */
72284
72285       //int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
72286       this.heap = new Uint16Array(2 * L_CODES + 1);  /* heap used to build the Huffman trees */
72287       zero(this.heap);
72288
72289       this.heap_len = 0;               /* number of elements in the heap */
72290       this.heap_max = 0;               /* element of largest frequency */
72291       /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
72292        * The same heap array is used to build all trees.
72293        */
72294
72295       this.depth = new Uint16Array(2 * L_CODES + 1); //uch depth[2*L_CODES+1];
72296       zero(this.depth);
72297       /* Depth of each subtree used as tie breaker for trees of equal frequency
72298        */
72299
72300       this.l_buf = 0;          /* buffer index for literals or lengths */
72301
72302       this.lit_bufsize = 0;
72303       /* Size of match buffer for literals/lengths.  There are 4 reasons for
72304        * limiting lit_bufsize to 64K:
72305        *   - frequencies can be kept in 16 bit counters
72306        *   - if compression is not successful for the first block, all input
72307        *     data is still in the window so we can still emit a stored block even
72308        *     when input comes from standard input.  (This can also be done for
72309        *     all blocks if lit_bufsize is not greater than 32K.)
72310        *   - if compression is not successful for a file smaller than 64K, we can
72311        *     even emit a stored file instead of a stored block (saving 5 bytes).
72312        *     This is applicable only for zip (not gzip or zlib).
72313        *   - creating new Huffman trees less frequently may not provide fast
72314        *     adaptation to changes in the input data statistics. (Take for
72315        *     example a binary file with poorly compressible code followed by
72316        *     a highly compressible string table.) Smaller buffer sizes give
72317        *     fast adaptation but have of course the overhead of transmitting
72318        *     trees more frequently.
72319        *   - I can't count above 4
72320        */
72321
72322       this.last_lit = 0;      /* running index in l_buf */
72323
72324       this.d_buf = 0;
72325       /* Buffer index for distances. To simplify the code, d_buf and l_buf have
72326        * the same number of elements. To use different lengths, an extra flag
72327        * array would be necessary.
72328        */
72329
72330       this.opt_len = 0;       /* bit length of current block with optimal trees */
72331       this.static_len = 0;    /* bit length of current block with static trees */
72332       this.matches = 0;       /* number of string matches in current block */
72333       this.insert = 0;        /* bytes at end of window left to insert */
72334
72335
72336       this.bi_buf = 0;
72337       /* Output buffer. bits are inserted starting at the bottom (least
72338        * significant bits).
72339        */
72340       this.bi_valid = 0;
72341       /* Number of valid bits in bi_buf.  All bits above the last valid bit
72342        * are always zero.
72343        */
72344
72345       // Used for window memory init. We safely ignore it for JS. That makes
72346       // sense only for pointers and memory check tools.
72347       //this.high_water = 0;
72348       /* High water mark offset in window for initialized bytes -- bytes above
72349        * this are set to zero in order to avoid memory check warnings when
72350        * longest match routines access bytes past the input.  This is then
72351        * updated to the new high water mark.
72352        */
72353     }
72354
72355
72356     const deflateResetKeep = (strm) => {
72357
72358       if (!strm || !strm.state) {
72359         return err(strm, Z_STREAM_ERROR$2);
72360       }
72361
72362       strm.total_in = strm.total_out = 0;
72363       strm.data_type = Z_UNKNOWN;
72364
72365       const s = strm.state;
72366       s.pending = 0;
72367       s.pending_out = 0;
72368
72369       if (s.wrap < 0) {
72370         s.wrap = -s.wrap;
72371         /* was made negative by deflate(..., Z_FINISH); */
72372       }
72373       s.status = (s.wrap ? INIT_STATE : BUSY_STATE);
72374       strm.adler = (s.wrap === 2) ?
72375         0  // crc32(0, Z_NULL, 0)
72376       :
72377         1; // adler32(0, Z_NULL, 0)
72378       s.last_flush = Z_NO_FLUSH$2;
72379       _tr_init(s);
72380       return Z_OK$3;
72381     };
72382
72383
72384     const deflateReset = (strm) => {
72385
72386       const ret = deflateResetKeep(strm);
72387       if (ret === Z_OK$3) {
72388         lm_init(strm.state);
72389       }
72390       return ret;
72391     };
72392
72393
72394     const deflateSetHeader = (strm, head) => {
72395
72396       if (!strm || !strm.state) { return Z_STREAM_ERROR$2; }
72397       if (strm.state.wrap !== 2) { return Z_STREAM_ERROR$2; }
72398       strm.state.gzhead = head;
72399       return Z_OK$3;
72400     };
72401
72402
72403     const deflateInit2 = (strm, level, method, windowBits, memLevel, strategy) => {
72404
72405       if (!strm) { // === Z_NULL
72406         return Z_STREAM_ERROR$2;
72407       }
72408       let wrap = 1;
72409
72410       if (level === Z_DEFAULT_COMPRESSION$1) {
72411         level = 6;
72412       }
72413
72414       if (windowBits < 0) { /* suppress zlib wrapper */
72415         wrap = 0;
72416         windowBits = -windowBits;
72417       }
72418
72419       else if (windowBits > 15) {
72420         wrap = 2;           /* write gzip wrapper instead */
72421         windowBits -= 16;
72422       }
72423
72424
72425       if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED$2 ||
72426         windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
72427         strategy < 0 || strategy > Z_FIXED) {
72428         return err(strm, Z_STREAM_ERROR$2);
72429       }
72430
72431
72432       if (windowBits === 8) {
72433         windowBits = 9;
72434       }
72435       /* until 256-byte window bug fixed */
72436
72437       const s = new DeflateState();
72438
72439       strm.state = s;
72440       s.strm = strm;
72441
72442       s.wrap = wrap;
72443       s.gzhead = null;
72444       s.w_bits = windowBits;
72445       s.w_size = 1 << s.w_bits;
72446       s.w_mask = s.w_size - 1;
72447
72448       s.hash_bits = memLevel + 7;
72449       s.hash_size = 1 << s.hash_bits;
72450       s.hash_mask = s.hash_size - 1;
72451       s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH);
72452
72453       s.window = new Uint8Array(s.w_size * 2);
72454       s.head = new Uint16Array(s.hash_size);
72455       s.prev = new Uint16Array(s.w_size);
72456
72457       // Don't need mem init magic for JS.
72458       //s.high_water = 0;  /* nothing written to s->window yet */
72459
72460       s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
72461
72462       s.pending_buf_size = s.lit_bufsize * 4;
72463
72464       //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
72465       //s->pending_buf = (uchf *) overlay;
72466       s.pending_buf = new Uint8Array(s.pending_buf_size);
72467
72468       // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)
72469       //s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
72470       s.d_buf = 1 * s.lit_bufsize;
72471
72472       //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
72473       s.l_buf = (1 + 2) * s.lit_bufsize;
72474
72475       s.level = level;
72476       s.strategy = strategy;
72477       s.method = method;
72478
72479       return deflateReset(strm);
72480     };
72481
72482     const deflateInit = (strm, level) => {
72483
72484       return deflateInit2(strm, level, Z_DEFLATED$2, MAX_WBITS$1, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY$1);
72485     };
72486
72487
72488     const deflate$2 = (strm, flush) => {
72489
72490       let beg, val; // for gzip header write only
72491
72492       if (!strm || !strm.state ||
72493         flush > Z_BLOCK$1 || flush < 0) {
72494         return strm ? err(strm, Z_STREAM_ERROR$2) : Z_STREAM_ERROR$2;
72495       }
72496
72497       const s = strm.state;
72498
72499       if (!strm.output ||
72500           (!strm.input && strm.avail_in !== 0) ||
72501           (s.status === FINISH_STATE && flush !== Z_FINISH$3)) {
72502         return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR$1 : Z_STREAM_ERROR$2);
72503       }
72504
72505       s.strm = strm; /* just in case */
72506       const old_flush = s.last_flush;
72507       s.last_flush = flush;
72508
72509       /* Write the header */
72510       if (s.status === INIT_STATE) {
72511
72512         if (s.wrap === 2) { // GZIP header
72513           strm.adler = 0;  //crc32(0L, Z_NULL, 0);
72514           put_byte(s, 31);
72515           put_byte(s, 139);
72516           put_byte(s, 8);
72517           if (!s.gzhead) { // s->gzhead == Z_NULL
72518             put_byte(s, 0);
72519             put_byte(s, 0);
72520             put_byte(s, 0);
72521             put_byte(s, 0);
72522             put_byte(s, 0);
72523             put_byte(s, s.level === 9 ? 2 :
72524                         (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
72525                          4 : 0));
72526             put_byte(s, OS_CODE);
72527             s.status = BUSY_STATE;
72528           }
72529           else {
72530             put_byte(s, (s.gzhead.text ? 1 : 0) +
72531                         (s.gzhead.hcrc ? 2 : 0) +
72532                         (!s.gzhead.extra ? 0 : 4) +
72533                         (!s.gzhead.name ? 0 : 8) +
72534                         (!s.gzhead.comment ? 0 : 16)
72535             );
72536             put_byte(s, s.gzhead.time & 0xff);
72537             put_byte(s, (s.gzhead.time >> 8) & 0xff);
72538             put_byte(s, (s.gzhead.time >> 16) & 0xff);
72539             put_byte(s, (s.gzhead.time >> 24) & 0xff);
72540             put_byte(s, s.level === 9 ? 2 :
72541                         (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
72542                          4 : 0));
72543             put_byte(s, s.gzhead.os & 0xff);
72544             if (s.gzhead.extra && s.gzhead.extra.length) {
72545               put_byte(s, s.gzhead.extra.length & 0xff);
72546               put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
72547             }
72548             if (s.gzhead.hcrc) {
72549               strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending, 0);
72550             }
72551             s.gzindex = 0;
72552             s.status = EXTRA_STATE;
72553           }
72554         }
72555         else // DEFLATE header
72556         {
72557           let header = (Z_DEFLATED$2 + ((s.w_bits - 8) << 4)) << 8;
72558           let level_flags = -1;
72559
72560           if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {
72561             level_flags = 0;
72562           } else if (s.level < 6) {
72563             level_flags = 1;
72564           } else if (s.level === 6) {
72565             level_flags = 2;
72566           } else {
72567             level_flags = 3;
72568           }
72569           header |= (level_flags << 6);
72570           if (s.strstart !== 0) { header |= PRESET_DICT; }
72571           header += 31 - (header % 31);
72572
72573           s.status = BUSY_STATE;
72574           putShortMSB(s, header);
72575
72576           /* Save the adler32 of the preset dictionary: */
72577           if (s.strstart !== 0) {
72578             putShortMSB(s, strm.adler >>> 16);
72579             putShortMSB(s, strm.adler & 0xffff);
72580           }
72581           strm.adler = 1; // adler32(0L, Z_NULL, 0);
72582         }
72583       }
72584
72585     //#ifdef GZIP
72586       if (s.status === EXTRA_STATE) {
72587         if (s.gzhead.extra/* != Z_NULL*/) {
72588           beg = s.pending;  /* start of bytes to update crc */
72589
72590           while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {
72591             if (s.pending === s.pending_buf_size) {
72592               if (s.gzhead.hcrc && s.pending > beg) {
72593                 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
72594               }
72595               flush_pending(strm);
72596               beg = s.pending;
72597               if (s.pending === s.pending_buf_size) {
72598                 break;
72599               }
72600             }
72601             put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
72602             s.gzindex++;
72603           }
72604           if (s.gzhead.hcrc && s.pending > beg) {
72605             strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
72606           }
72607           if (s.gzindex === s.gzhead.extra.length) {
72608             s.gzindex = 0;
72609             s.status = NAME_STATE;
72610           }
72611         }
72612         else {
72613           s.status = NAME_STATE;
72614         }
72615       }
72616       if (s.status === NAME_STATE) {
72617         if (s.gzhead.name/* != Z_NULL*/) {
72618           beg = s.pending;  /* start of bytes to update crc */
72619           //int val;
72620
72621           do {
72622             if (s.pending === s.pending_buf_size) {
72623               if (s.gzhead.hcrc && s.pending > beg) {
72624                 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
72625               }
72626               flush_pending(strm);
72627               beg = s.pending;
72628               if (s.pending === s.pending_buf_size) {
72629                 val = 1;
72630                 break;
72631               }
72632             }
72633             // JS specific: little magic to add zero terminator to end of string
72634             if (s.gzindex < s.gzhead.name.length) {
72635               val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
72636             } else {
72637               val = 0;
72638             }
72639             put_byte(s, val);
72640           } while (val !== 0);
72641
72642           if (s.gzhead.hcrc && s.pending > beg) {
72643             strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
72644           }
72645           if (val === 0) {
72646             s.gzindex = 0;
72647             s.status = COMMENT_STATE;
72648           }
72649         }
72650         else {
72651           s.status = COMMENT_STATE;
72652         }
72653       }
72654       if (s.status === COMMENT_STATE) {
72655         if (s.gzhead.comment/* != Z_NULL*/) {
72656           beg = s.pending;  /* start of bytes to update crc */
72657           //int val;
72658
72659           do {
72660             if (s.pending === s.pending_buf_size) {
72661               if (s.gzhead.hcrc && s.pending > beg) {
72662                 strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
72663               }
72664               flush_pending(strm);
72665               beg = s.pending;
72666               if (s.pending === s.pending_buf_size) {
72667                 val = 1;
72668                 break;
72669               }
72670             }
72671             // JS specific: little magic to add zero terminator to end of string
72672             if (s.gzindex < s.gzhead.comment.length) {
72673               val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
72674             } else {
72675               val = 0;
72676             }
72677             put_byte(s, val);
72678           } while (val !== 0);
72679
72680           if (s.gzhead.hcrc && s.pending > beg) {
72681             strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
72682           }
72683           if (val === 0) {
72684             s.status = HCRC_STATE;
72685           }
72686         }
72687         else {
72688           s.status = HCRC_STATE;
72689         }
72690       }
72691       if (s.status === HCRC_STATE) {
72692         if (s.gzhead.hcrc) {
72693           if (s.pending + 2 > s.pending_buf_size) {
72694             flush_pending(strm);
72695           }
72696           if (s.pending + 2 <= s.pending_buf_size) {
72697             put_byte(s, strm.adler & 0xff);
72698             put_byte(s, (strm.adler >> 8) & 0xff);
72699             strm.adler = 0; //crc32(0L, Z_NULL, 0);
72700             s.status = BUSY_STATE;
72701           }
72702         }
72703         else {
72704           s.status = BUSY_STATE;
72705         }
72706       }
72707     //#endif
72708
72709       /* Flush as much pending output as possible */
72710       if (s.pending !== 0) {
72711         flush_pending(strm);
72712         if (strm.avail_out === 0) {
72713           /* Since avail_out is 0, deflate will be called again with
72714            * more output space, but possibly with both pending and
72715            * avail_in equal to zero. There won't be anything to do,
72716            * but this is not an error situation so make sure we
72717            * return OK instead of BUF_ERROR at next call of deflate:
72718            */
72719           s.last_flush = -1;
72720           return Z_OK$3;
72721         }
72722
72723         /* Make sure there is something to do and avoid duplicate consecutive
72724          * flushes. For repeated and useless calls with Z_FINISH, we keep
72725          * returning Z_STREAM_END instead of Z_BUF_ERROR.
72726          */
72727       } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&
72728         flush !== Z_FINISH$3) {
72729         return err(strm, Z_BUF_ERROR$1);
72730       }
72731
72732       /* User must not provide more input after the first FINISH: */
72733       if (s.status === FINISH_STATE && strm.avail_in !== 0) {
72734         return err(strm, Z_BUF_ERROR$1);
72735       }
72736
72737       /* Start a new block or continue the current one.
72738        */
72739       if (strm.avail_in !== 0 || s.lookahead !== 0 ||
72740         (flush !== Z_NO_FLUSH$2 && s.status !== FINISH_STATE)) {
72741         let bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) :
72742           (s.strategy === Z_RLE ? deflate_rle(s, flush) :
72743             configuration_table[s.level].func(s, flush));
72744
72745         if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {
72746           s.status = FINISH_STATE;
72747         }
72748         if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {
72749           if (strm.avail_out === 0) {
72750             s.last_flush = -1;
72751             /* avoid BUF_ERROR next call, see above */
72752           }
72753           return Z_OK$3;
72754           /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
72755            * of deflate should use the same flush parameter to make sure
72756            * that the flush is complete. So we don't have to output an
72757            * empty block here, this will be done at next call. This also
72758            * ensures that for a very small output buffer, we emit at most
72759            * one empty block.
72760            */
72761         }
72762         if (bstate === BS_BLOCK_DONE) {
72763           if (flush === Z_PARTIAL_FLUSH) {
72764             _tr_align(s);
72765           }
72766           else if (flush !== Z_BLOCK$1) { /* FULL_FLUSH or SYNC_FLUSH */
72767
72768             _tr_stored_block(s, 0, 0, false);
72769             /* For a full flush, this empty block will be recognized
72770              * as a special marker by inflate_sync().
72771              */
72772             if (flush === Z_FULL_FLUSH$1) {
72773               /*** CLEAR_HASH(s); ***/             /* forget history */
72774               zero(s.head); // Fill with NIL (= 0);
72775
72776               if (s.lookahead === 0) {
72777                 s.strstart = 0;
72778                 s.block_start = 0;
72779                 s.insert = 0;
72780               }
72781             }
72782           }
72783           flush_pending(strm);
72784           if (strm.avail_out === 0) {
72785             s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */
72786             return Z_OK$3;
72787           }
72788         }
72789       }
72790       //Assert(strm->avail_out > 0, "bug2");
72791       //if (strm.avail_out <= 0) { throw new Error("bug2");}
72792
72793       if (flush !== Z_FINISH$3) { return Z_OK$3; }
72794       if (s.wrap <= 0) { return Z_STREAM_END$3; }
72795
72796       /* Write the trailer */
72797       if (s.wrap === 2) {
72798         put_byte(s, strm.adler & 0xff);
72799         put_byte(s, (strm.adler >> 8) & 0xff);
72800         put_byte(s, (strm.adler >> 16) & 0xff);
72801         put_byte(s, (strm.adler >> 24) & 0xff);
72802         put_byte(s, strm.total_in & 0xff);
72803         put_byte(s, (strm.total_in >> 8) & 0xff);
72804         put_byte(s, (strm.total_in >> 16) & 0xff);
72805         put_byte(s, (strm.total_in >> 24) & 0xff);
72806       }
72807       else
72808       {
72809         putShortMSB(s, strm.adler >>> 16);
72810         putShortMSB(s, strm.adler & 0xffff);
72811       }
72812
72813       flush_pending(strm);
72814       /* If avail_out is zero, the application will call deflate again
72815        * to flush the rest.
72816        */
72817       if (s.wrap > 0) { s.wrap = -s.wrap; }
72818       /* write the trailer only once! */
72819       return s.pending !== 0 ? Z_OK$3 : Z_STREAM_END$3;
72820     };
72821
72822
72823     const deflateEnd = (strm) => {
72824
72825       if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
72826         return Z_STREAM_ERROR$2;
72827       }
72828
72829       const status = strm.state.status;
72830       if (status !== INIT_STATE &&
72831         status !== EXTRA_STATE &&
72832         status !== NAME_STATE &&
72833         status !== COMMENT_STATE &&
72834         status !== HCRC_STATE &&
72835         status !== BUSY_STATE &&
72836         status !== FINISH_STATE
72837       ) {
72838         return err(strm, Z_STREAM_ERROR$2);
72839       }
72840
72841       strm.state = null;
72842
72843       return status === BUSY_STATE ? err(strm, Z_DATA_ERROR$2) : Z_OK$3;
72844     };
72845
72846
72847     /* =========================================================================
72848      * Initializes the compression dictionary from the given byte
72849      * sequence without producing any compressed output.
72850      */
72851     const deflateSetDictionary = (strm, dictionary) => {
72852
72853       let dictLength = dictionary.length;
72854
72855       if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
72856         return Z_STREAM_ERROR$2;
72857       }
72858
72859       const s = strm.state;
72860       const wrap = s.wrap;
72861
72862       if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {
72863         return Z_STREAM_ERROR$2;
72864       }
72865
72866       /* when using zlib wrappers, compute Adler-32 for provided dictionary */
72867       if (wrap === 1) {
72868         /* adler32(strm->adler, dictionary, dictLength); */
72869         strm.adler = adler32_1(strm.adler, dictionary, dictLength, 0);
72870       }
72871
72872       s.wrap = 0;   /* avoid computing Adler-32 in read_buf */
72873
72874       /* if dictionary would fill window, just replace the history */
72875       if (dictLength >= s.w_size) {
72876         if (wrap === 0) {            /* already empty otherwise */
72877           /*** CLEAR_HASH(s); ***/
72878           zero(s.head); // Fill with NIL (= 0);
72879           s.strstart = 0;
72880           s.block_start = 0;
72881           s.insert = 0;
72882         }
72883         /* use the tail */
72884         // dictionary = dictionary.slice(dictLength - s.w_size);
72885         let tmpDict = new Uint8Array(s.w_size);
72886         tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0);
72887         dictionary = tmpDict;
72888         dictLength = s.w_size;
72889       }
72890       /* insert dictionary into window and hash */
72891       const avail = strm.avail_in;
72892       const next = strm.next_in;
72893       const input = strm.input;
72894       strm.avail_in = dictLength;
72895       strm.next_in = 0;
72896       strm.input = dictionary;
72897       fill_window(s);
72898       while (s.lookahead >= MIN_MATCH) {
72899         let str = s.strstart;
72900         let n = s.lookahead - (MIN_MATCH - 1);
72901         do {
72902           /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
72903           s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]);
72904
72905           s.prev[str & s.w_mask] = s.head[s.ins_h];
72906
72907           s.head[s.ins_h] = str;
72908           str++;
72909         } while (--n);
72910         s.strstart = str;
72911         s.lookahead = MIN_MATCH - 1;
72912         fill_window(s);
72913       }
72914       s.strstart += s.lookahead;
72915       s.block_start = s.strstart;
72916       s.insert = s.lookahead;
72917       s.lookahead = 0;
72918       s.match_length = s.prev_length = MIN_MATCH - 1;
72919       s.match_available = 0;
72920       strm.next_in = next;
72921       strm.input = input;
72922       strm.avail_in = avail;
72923       s.wrap = wrap;
72924       return Z_OK$3;
72925     };
72926
72927
72928     var deflateInit_1 = deflateInit;
72929     var deflateInit2_1 = deflateInit2;
72930     var deflateReset_1 = deflateReset;
72931     var deflateResetKeep_1 = deflateResetKeep;
72932     var deflateSetHeader_1 = deflateSetHeader;
72933     var deflate_2$1 = deflate$2;
72934     var deflateEnd_1 = deflateEnd;
72935     var deflateSetDictionary_1 = deflateSetDictionary;
72936     var deflateInfo = 'pako deflate (from Nodeca project)';
72937
72938     /* Not implemented
72939     module.exports.deflateBound = deflateBound;
72940     module.exports.deflateCopy = deflateCopy;
72941     module.exports.deflateParams = deflateParams;
72942     module.exports.deflatePending = deflatePending;
72943     module.exports.deflatePrime = deflatePrime;
72944     module.exports.deflateTune = deflateTune;
72945     */
72946
72947     var deflate_1$2 = {
72948         deflateInit: deflateInit_1,
72949         deflateInit2: deflateInit2_1,
72950         deflateReset: deflateReset_1,
72951         deflateResetKeep: deflateResetKeep_1,
72952         deflateSetHeader: deflateSetHeader_1,
72953         deflate: deflate_2$1,
72954         deflateEnd: deflateEnd_1,
72955         deflateSetDictionary: deflateSetDictionary_1,
72956         deflateInfo: deflateInfo
72957     };
72958
72959     const _has = (obj, key) => {
72960       return Object.prototype.hasOwnProperty.call(obj, key);
72961     };
72962
72963     var assign = function (obj /*from1, from2, from3, ...*/) {
72964       const sources = Array.prototype.slice.call(arguments, 1);
72965       while (sources.length) {
72966         const source = sources.shift();
72967         if (!source) { continue; }
72968
72969         if (typeof source !== 'object') {
72970           throw new TypeError(source + 'must be non-object');
72971         }
72972
72973         for (const p in source) {
72974           if (_has(source, p)) {
72975             obj[p] = source[p];
72976           }
72977         }
72978       }
72979
72980       return obj;
72981     };
72982
72983
72984     // Join array of chunks to single array.
72985     var flattenChunks = (chunks) => {
72986       // calculate data length
72987       let len = 0;
72988
72989       for (let i = 0, l = chunks.length; i < l; i++) {
72990         len += chunks[i].length;
72991       }
72992
72993       // join chunks
72994       const result = new Uint8Array(len);
72995
72996       for (let i = 0, pos = 0, l = chunks.length; i < l; i++) {
72997         let chunk = chunks[i];
72998         result.set(chunk, pos);
72999         pos += chunk.length;
73000       }
73001
73002       return result;
73003     };
73004
73005     var common = {
73006         assign: assign,
73007         flattenChunks: flattenChunks
73008     };
73009
73010     // String encode/decode helpers
73011
73012
73013     // Quick check if we can use fast array to bin string conversion
73014     //
73015     // - apply(Array) can fail on Android 2.2
73016     // - apply(Uint8Array) can fail on iOS 5.1 Safari
73017     //
73018     let STR_APPLY_UIA_OK = true;
73019
73020     try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }
73021
73022
73023     // Table with utf8 lengths (calculated by first byte of sequence)
73024     // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
73025     // because max possible codepoint is 0x10ffff
73026     const _utf8len = new Uint8Array(256);
73027     for (let q = 0; q < 256; q++) {
73028       _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
73029     }
73030     _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start
73031
73032
73033     // convert string to array (typed, when possible)
73034     var string2buf = (str) => {
73035       if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) {
73036         return new TextEncoder().encode(str);
73037       }
73038
73039       let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
73040
73041       // count binary size
73042       for (m_pos = 0; m_pos < str_len; m_pos++) {
73043         c = str.charCodeAt(m_pos);
73044         if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
73045           c2 = str.charCodeAt(m_pos + 1);
73046           if ((c2 & 0xfc00) === 0xdc00) {
73047             c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
73048             m_pos++;
73049           }
73050         }
73051         buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
73052       }
73053
73054       // allocate buffer
73055       buf = new Uint8Array(buf_len);
73056
73057       // convert
73058       for (i = 0, m_pos = 0; i < buf_len; m_pos++) {
73059         c = str.charCodeAt(m_pos);
73060         if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
73061           c2 = str.charCodeAt(m_pos + 1);
73062           if ((c2 & 0xfc00) === 0xdc00) {
73063             c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
73064             m_pos++;
73065           }
73066         }
73067         if (c < 0x80) {
73068           /* one byte */
73069           buf[i++] = c;
73070         } else if (c < 0x800) {
73071           /* two bytes */
73072           buf[i++] = 0xC0 | (c >>> 6);
73073           buf[i++] = 0x80 | (c & 0x3f);
73074         } else if (c < 0x10000) {
73075           /* three bytes */
73076           buf[i++] = 0xE0 | (c >>> 12);
73077           buf[i++] = 0x80 | (c >>> 6 & 0x3f);
73078           buf[i++] = 0x80 | (c & 0x3f);
73079         } else {
73080           /* four bytes */
73081           buf[i++] = 0xf0 | (c >>> 18);
73082           buf[i++] = 0x80 | (c >>> 12 & 0x3f);
73083           buf[i++] = 0x80 | (c >>> 6 & 0x3f);
73084           buf[i++] = 0x80 | (c & 0x3f);
73085         }
73086       }
73087
73088       return buf;
73089     };
73090
73091     // Helper
73092     const buf2binstring = (buf, len) => {
73093       // On Chrome, the arguments in a function call that are allowed is `65534`.
73094       // If the length of the buffer is smaller than that, we can use this optimization,
73095       // otherwise we will take a slower path.
73096       if (len < 65534) {
73097         if (buf.subarray && STR_APPLY_UIA_OK) {
73098           return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len));
73099         }
73100       }
73101
73102       let result = '';
73103       for (let i = 0; i < len; i++) {
73104         result += String.fromCharCode(buf[i]);
73105       }
73106       return result;
73107     };
73108
73109
73110     // convert array to string
73111     var buf2string = (buf, max) => {
73112       const len = max || buf.length;
73113
73114       if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) {
73115         return new TextDecoder().decode(buf.subarray(0, max));
73116       }
73117
73118       let i, out;
73119
73120       // Reserve max possible length (2 words per char)
73121       // NB: by unknown reasons, Array is significantly faster for
73122       //     String.fromCharCode.apply than Uint16Array.
73123       const utf16buf = new Array(len * 2);
73124
73125       for (out = 0, i = 0; i < len;) {
73126         let c = buf[i++];
73127         // quick process ascii
73128         if (c < 0x80) { utf16buf[out++] = c; continue; }
73129
73130         let c_len = _utf8len[c];
73131         // skip 5 & 6 byte codes
73132         if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }
73133
73134         // apply mask on first byte
73135         c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
73136         // join the rest
73137         while (c_len > 1 && i < len) {
73138           c = (c << 6) | (buf[i++] & 0x3f);
73139           c_len--;
73140         }
73141
73142         // terminated by end of string?
73143         if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
73144
73145         if (c < 0x10000) {
73146           utf16buf[out++] = c;
73147         } else {
73148           c -= 0x10000;
73149           utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
73150           utf16buf[out++] = 0xdc00 | (c & 0x3ff);
73151         }
73152       }
73153
73154       return buf2binstring(utf16buf, out);
73155     };
73156
73157
73158     // Calculate max possible position in utf8 buffer,
73159     // that will not break sequence. If that's not possible
73160     // - (very small limits) return max size as is.
73161     //
73162     // buf[] - utf8 bytes array
73163     // max   - length limit (mandatory);
73164     var utf8border = (buf, max) => {
73165
73166       max = max || buf.length;
73167       if (max > buf.length) { max = buf.length; }
73168
73169       // go back from last position, until start of sequence found
73170       let pos = max - 1;
73171       while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
73172
73173       // Very small and broken sequence,
73174       // return max, because we should return something anyway.
73175       if (pos < 0) { return max; }
73176
73177       // If we came to start of buffer - that means buffer is too small,
73178       // return max too.
73179       if (pos === 0) { return max; }
73180
73181       return (pos + _utf8len[buf[pos]] > max) ? pos : max;
73182     };
73183
73184     var strings = {
73185         string2buf: string2buf,
73186         buf2string: buf2string,
73187         utf8border: utf8border
73188     };
73189
73190     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
73191     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
73192     //
73193     // This software is provided 'as-is', without any express or implied
73194     // warranty. In no event will the authors be held liable for any damages
73195     // arising from the use of this software.
73196     //
73197     // Permission is granted to anyone to use this software for any purpose,
73198     // including commercial applications, and to alter it and redistribute it
73199     // freely, subject to the following restrictions:
73200     //
73201     // 1. The origin of this software must not be misrepresented; you must not
73202     //   claim that you wrote the original software. If you use this software
73203     //   in a product, an acknowledgment in the product documentation would be
73204     //   appreciated but is not required.
73205     // 2. Altered source versions must be plainly marked as such, and must not be
73206     //   misrepresented as being the original software.
73207     // 3. This notice may not be removed or altered from any source distribution.
73208
73209     function ZStream() {
73210       /* next input byte */
73211       this.input = null; // JS specific, because we have no pointers
73212       this.next_in = 0;
73213       /* number of bytes available at input */
73214       this.avail_in = 0;
73215       /* total number of input bytes read so far */
73216       this.total_in = 0;
73217       /* next output byte should be put there */
73218       this.output = null; // JS specific, because we have no pointers
73219       this.next_out = 0;
73220       /* remaining free space at output */
73221       this.avail_out = 0;
73222       /* total number of bytes output so far */
73223       this.total_out = 0;
73224       /* last error message, NULL if no error */
73225       this.msg = ''/*Z_NULL*/;
73226       /* not visible by applications */
73227       this.state = null;
73228       /* best guess about the data type: binary or text */
73229       this.data_type = 2/*Z_UNKNOWN*/;
73230       /* adler32 value of the uncompressed data */
73231       this.adler = 0;
73232     }
73233
73234     var zstream = ZStream;
73235
73236     const toString$1 = Object.prototype.toString;
73237
73238     /* Public constants ==========================================================*/
73239     /* ===========================================================================*/
73240
73241     const {
73242       Z_NO_FLUSH: Z_NO_FLUSH$1, Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH: Z_FINISH$2,
73243       Z_OK: Z_OK$2, Z_STREAM_END: Z_STREAM_END$2,
73244       Z_DEFAULT_COMPRESSION,
73245       Z_DEFAULT_STRATEGY,
73246       Z_DEFLATED: Z_DEFLATED$1
73247     } = constants$2;
73248
73249     /* ===========================================================================*/
73250
73251
73252     /**
73253      * class Deflate
73254      *
73255      * Generic JS-style wrapper for zlib calls. If you don't need
73256      * streaming behaviour - use more simple functions: [[deflate]],
73257      * [[deflateRaw]] and [[gzip]].
73258      **/
73259
73260     /* internal
73261      * Deflate.chunks -> Array
73262      *
73263      * Chunks of output data, if [[Deflate#onData]] not overridden.
73264      **/
73265
73266     /**
73267      * Deflate.result -> Uint8Array
73268      *
73269      * Compressed result, generated by default [[Deflate#onData]]
73270      * and [[Deflate#onEnd]] handlers. Filled after you push last chunk
73271      * (call [[Deflate#push]] with `Z_FINISH` / `true` param).
73272      **/
73273
73274     /**
73275      * Deflate.err -> Number
73276      *
73277      * Error code after deflate finished. 0 (Z_OK) on success.
73278      * You will not need it in real life, because deflate errors
73279      * are possible only on wrong options or bad `onData` / `onEnd`
73280      * custom handlers.
73281      **/
73282
73283     /**
73284      * Deflate.msg -> String
73285      *
73286      * Error message, if [[Deflate.err]] != 0
73287      **/
73288
73289
73290     /**
73291      * new Deflate(options)
73292      * - options (Object): zlib deflate options.
73293      *
73294      * Creates new deflator instance with specified params. Throws exception
73295      * on bad params. Supported options:
73296      *
73297      * - `level`
73298      * - `windowBits`
73299      * - `memLevel`
73300      * - `strategy`
73301      * - `dictionary`
73302      *
73303      * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
73304      * for more information on these.
73305      *
73306      * Additional options, for internal needs:
73307      *
73308      * - `chunkSize` - size of generated data chunks (16K by default)
73309      * - `raw` (Boolean) - do raw deflate
73310      * - `gzip` (Boolean) - create gzip wrapper
73311      * - `header` (Object) - custom header for gzip
73312      *   - `text` (Boolean) - true if compressed data believed to be text
73313      *   - `time` (Number) - modification time, unix timestamp
73314      *   - `os` (Number) - operation system code
73315      *   - `extra` (Array) - array of bytes with extra data (max 65536)
73316      *   - `name` (String) - file name (binary string)
73317      *   - `comment` (String) - comment (binary string)
73318      *   - `hcrc` (Boolean) - true if header crc should be added
73319      *
73320      * ##### Example:
73321      *
73322      * ```javascript
73323      * const pako = require('pako')
73324      *   , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])
73325      *   , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);
73326      *
73327      * const deflate = new pako.Deflate({ level: 3});
73328      *
73329      * deflate.push(chunk1, false);
73330      * deflate.push(chunk2, true);  // true -> last chunk
73331      *
73332      * if (deflate.err) { throw new Error(deflate.err); }
73333      *
73334      * console.log(deflate.result);
73335      * ```
73336      **/
73337     function Deflate$1(options) {
73338       this.options = common.assign({
73339         level: Z_DEFAULT_COMPRESSION,
73340         method: Z_DEFLATED$1,
73341         chunkSize: 16384,
73342         windowBits: 15,
73343         memLevel: 8,
73344         strategy: Z_DEFAULT_STRATEGY
73345       }, options || {});
73346
73347       let opt = this.options;
73348
73349       if (opt.raw && (opt.windowBits > 0)) {
73350         opt.windowBits = -opt.windowBits;
73351       }
73352
73353       else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {
73354         opt.windowBits += 16;
73355       }
73356
73357       this.err    = 0;      // error code, if happens (0 = Z_OK)
73358       this.msg    = '';     // error message
73359       this.ended  = false;  // used to avoid multiple onEnd() calls
73360       this.chunks = [];     // chunks of compressed data
73361
73362       this.strm = new zstream();
73363       this.strm.avail_out = 0;
73364
73365       let status = deflate_1$2.deflateInit2(
73366         this.strm,
73367         opt.level,
73368         opt.method,
73369         opt.windowBits,
73370         opt.memLevel,
73371         opt.strategy
73372       );
73373
73374       if (status !== Z_OK$2) {
73375         throw new Error(messages[status]);
73376       }
73377
73378       if (opt.header) {
73379         deflate_1$2.deflateSetHeader(this.strm, opt.header);
73380       }
73381
73382       if (opt.dictionary) {
73383         let dict;
73384         // Convert data if needed
73385         if (typeof opt.dictionary === 'string') {
73386           // If we need to compress text, change encoding to utf8.
73387           dict = strings.string2buf(opt.dictionary);
73388         } else if (toString$1.call(opt.dictionary) === '[object ArrayBuffer]') {
73389           dict = new Uint8Array(opt.dictionary);
73390         } else {
73391           dict = opt.dictionary;
73392         }
73393
73394         status = deflate_1$2.deflateSetDictionary(this.strm, dict);
73395
73396         if (status !== Z_OK$2) {
73397           throw new Error(messages[status]);
73398         }
73399
73400         this._dict_set = true;
73401       }
73402     }
73403
73404     /**
73405      * Deflate#push(data[, flush_mode]) -> Boolean
73406      * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be
73407      *   converted to utf8 byte sequence.
73408      * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
73409      *   See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.
73410      *
73411      * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
73412      * new compressed chunks. Returns `true` on success. The last data block must
73413      * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending
73414      * buffers and call [[Deflate#onEnd]].
73415      *
73416      * On fail call [[Deflate#onEnd]] with error code and return false.
73417      *
73418      * ##### Example
73419      *
73420      * ```javascript
73421      * push(chunk, false); // push one of data chunks
73422      * ...
73423      * push(chunk, true);  // push last chunk
73424      * ```
73425      **/
73426     Deflate$1.prototype.push = function (data, flush_mode) {
73427       const strm = this.strm;
73428       const chunkSize = this.options.chunkSize;
73429       let status, _flush_mode;
73430
73431       if (this.ended) { return false; }
73432
73433       if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
73434       else _flush_mode = flush_mode === true ? Z_FINISH$2 : Z_NO_FLUSH$1;
73435
73436       // Convert data if needed
73437       if (typeof data === 'string') {
73438         // If we need to compress text, change encoding to utf8.
73439         strm.input = strings.string2buf(data);
73440       } else if (toString$1.call(data) === '[object ArrayBuffer]') {
73441         strm.input = new Uint8Array(data);
73442       } else {
73443         strm.input = data;
73444       }
73445
73446       strm.next_in = 0;
73447       strm.avail_in = strm.input.length;
73448
73449       for (;;) {
73450         if (strm.avail_out === 0) {
73451           strm.output = new Uint8Array(chunkSize);
73452           strm.next_out = 0;
73453           strm.avail_out = chunkSize;
73454         }
73455
73456         // Make sure avail_out > 6 to avoid repeating markers
73457         if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) {
73458           this.onData(strm.output.subarray(0, strm.next_out));
73459           strm.avail_out = 0;
73460           continue;
73461         }
73462
73463         status = deflate_1$2.deflate(strm, _flush_mode);
73464
73465         // Ended => flush and finish
73466         if (status === Z_STREAM_END$2) {
73467           if (strm.next_out > 0) {
73468             this.onData(strm.output.subarray(0, strm.next_out));
73469           }
73470           status = deflate_1$2.deflateEnd(this.strm);
73471           this.onEnd(status);
73472           this.ended = true;
73473           return status === Z_OK$2;
73474         }
73475
73476         // Flush if out buffer full
73477         if (strm.avail_out === 0) {
73478           this.onData(strm.output);
73479           continue;
73480         }
73481
73482         // Flush if requested and has data
73483         if (_flush_mode > 0 && strm.next_out > 0) {
73484           this.onData(strm.output.subarray(0, strm.next_out));
73485           strm.avail_out = 0;
73486           continue;
73487         }
73488
73489         if (strm.avail_in === 0) break;
73490       }
73491
73492       return true;
73493     };
73494
73495
73496     /**
73497      * Deflate#onData(chunk) -> Void
73498      * - chunk (Uint8Array): output data.
73499      *
73500      * By default, stores data blocks in `chunks[]` property and glue
73501      * those in `onEnd`. Override this handler, if you need another behaviour.
73502      **/
73503     Deflate$1.prototype.onData = function (chunk) {
73504       this.chunks.push(chunk);
73505     };
73506
73507
73508     /**
73509      * Deflate#onEnd(status) -> Void
73510      * - status (Number): deflate status. 0 (Z_OK) on success,
73511      *   other if not.
73512      *
73513      * Called once after you tell deflate that the input stream is
73514      * complete (Z_FINISH). By default - join collected chunks,
73515      * free memory and fill `results` / `err` properties.
73516      **/
73517     Deflate$1.prototype.onEnd = function (status) {
73518       // On success - join
73519       if (status === Z_OK$2) {
73520         this.result = common.flattenChunks(this.chunks);
73521       }
73522       this.chunks = [];
73523       this.err = status;
73524       this.msg = this.strm.msg;
73525     };
73526
73527     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
73528     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
73529     //
73530     // This software is provided 'as-is', without any express or implied
73531     // warranty. In no event will the authors be held liable for any damages
73532     // arising from the use of this software.
73533     //
73534     // Permission is granted to anyone to use this software for any purpose,
73535     // including commercial applications, and to alter it and redistribute it
73536     // freely, subject to the following restrictions:
73537     //
73538     // 1. The origin of this software must not be misrepresented; you must not
73539     //   claim that you wrote the original software. If you use this software
73540     //   in a product, an acknowledgment in the product documentation would be
73541     //   appreciated but is not required.
73542     // 2. Altered source versions must be plainly marked as such, and must not be
73543     //   misrepresented as being the original software.
73544     // 3. This notice may not be removed or altered from any source distribution.
73545
73546     // See state defs from inflate.js
73547     const BAD$1 = 30;       /* got a data error -- remain here until reset */
73548     const TYPE$1 = 12;      /* i: waiting for type bits, including last-flag bit */
73549
73550     /*
73551        Decode literal, length, and distance codes and write out the resulting
73552        literal and match bytes until either not enough input or output is
73553        available, an end-of-block is encountered, or a data error is encountered.
73554        When large enough input and output buffers are supplied to inflate(), for
73555        example, a 16K input buffer and a 64K output buffer, more than 95% of the
73556        inflate execution time is spent in this routine.
73557
73558        Entry assumptions:
73559
73560             state.mode === LEN
73561             strm.avail_in >= 6
73562             strm.avail_out >= 258
73563             start >= strm.avail_out
73564             state.bits < 8
73565
73566        On return, state.mode is one of:
73567
73568             LEN -- ran out of enough output space or enough available input
73569             TYPE -- reached end of block code, inflate() to interpret next block
73570             BAD -- error in block data
73571
73572        Notes:
73573
73574         - The maximum input bits used by a length/distance pair is 15 bits for the
73575           length code, 5 bits for the length extra, 15 bits for the distance code,
73576           and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
73577           Therefore if strm.avail_in >= 6, then there is enough input to avoid
73578           checking for available input while decoding.
73579
73580         - The maximum bytes that a single length/distance pair can output is 258
73581           bytes, which is the maximum length that can be coded.  inflate_fast()
73582           requires strm.avail_out >= 258 for each loop to avoid checking for
73583           output space.
73584      */
73585     var inffast = function inflate_fast(strm, start) {
73586       let _in;                    /* local strm.input */
73587       let last;                   /* have enough input while in < last */
73588       let _out;                   /* local strm.output */
73589       let beg;                    /* inflate()'s initial strm.output */
73590       let end;                    /* while out < end, enough space available */
73591     //#ifdef INFLATE_STRICT
73592       let dmax;                   /* maximum distance from zlib header */
73593     //#endif
73594       let wsize;                  /* window size or zero if not using window */
73595       let whave;                  /* valid bytes in the window */
73596       let wnext;                  /* window write index */
73597       // Use `s_window` instead `window`, avoid conflict with instrumentation tools
73598       let s_window;               /* allocated sliding window, if wsize != 0 */
73599       let hold;                   /* local strm.hold */
73600       let bits;                   /* local strm.bits */
73601       let lcode;                  /* local strm.lencode */
73602       let dcode;                  /* local strm.distcode */
73603       let lmask;                  /* mask for first level of length codes */
73604       let dmask;                  /* mask for first level of distance codes */
73605       let here;                   /* retrieved table entry */
73606       let op;                     /* code bits, operation, extra bits, or */
73607                                   /*  window position, window bytes to copy */
73608       let len;                    /* match length, unused bytes */
73609       let dist;                   /* match distance */
73610       let from;                   /* where to copy match from */
73611       let from_source;
73612
73613
73614       let input, output; // JS specific, because we have no pointers
73615
73616       /* copy state to local variables */
73617       const state = strm.state;
73618       //here = state.here;
73619       _in = strm.next_in;
73620       input = strm.input;
73621       last = _in + (strm.avail_in - 5);
73622       _out = strm.next_out;
73623       output = strm.output;
73624       beg = _out - (start - strm.avail_out);
73625       end = _out + (strm.avail_out - 257);
73626     //#ifdef INFLATE_STRICT
73627       dmax = state.dmax;
73628     //#endif
73629       wsize = state.wsize;
73630       whave = state.whave;
73631       wnext = state.wnext;
73632       s_window = state.window;
73633       hold = state.hold;
73634       bits = state.bits;
73635       lcode = state.lencode;
73636       dcode = state.distcode;
73637       lmask = (1 << state.lenbits) - 1;
73638       dmask = (1 << state.distbits) - 1;
73639
73640
73641       /* decode literals and length/distances until end-of-block or not enough
73642          input data or output space */
73643
73644       top:
73645       do {
73646         if (bits < 15) {
73647           hold += input[_in++] << bits;
73648           bits += 8;
73649           hold += input[_in++] << bits;
73650           bits += 8;
73651         }
73652
73653         here = lcode[hold & lmask];
73654
73655         dolen:
73656         for (;;) { // Goto emulation
73657           op = here >>> 24/*here.bits*/;
73658           hold >>>= op;
73659           bits -= op;
73660           op = (here >>> 16) & 0xff/*here.op*/;
73661           if (op === 0) {                          /* literal */
73662             //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
73663             //        "inflate:         literal '%c'\n" :
73664             //        "inflate:         literal 0x%02x\n", here.val));
73665             output[_out++] = here & 0xffff/*here.val*/;
73666           }
73667           else if (op & 16) {                     /* length base */
73668             len = here & 0xffff/*here.val*/;
73669             op &= 15;                           /* number of extra bits */
73670             if (op) {
73671               if (bits < op) {
73672                 hold += input[_in++] << bits;
73673                 bits += 8;
73674               }
73675               len += hold & ((1 << op) - 1);
73676               hold >>>= op;
73677               bits -= op;
73678             }
73679             //Tracevv((stderr, "inflate:         length %u\n", len));
73680             if (bits < 15) {
73681               hold += input[_in++] << bits;
73682               bits += 8;
73683               hold += input[_in++] << bits;
73684               bits += 8;
73685             }
73686             here = dcode[hold & dmask];
73687
73688             dodist:
73689             for (;;) { // goto emulation
73690               op = here >>> 24/*here.bits*/;
73691               hold >>>= op;
73692               bits -= op;
73693               op = (here >>> 16) & 0xff/*here.op*/;
73694
73695               if (op & 16) {                      /* distance base */
73696                 dist = here & 0xffff/*here.val*/;
73697                 op &= 15;                       /* number of extra bits */
73698                 if (bits < op) {
73699                   hold += input[_in++] << bits;
73700                   bits += 8;
73701                   if (bits < op) {
73702                     hold += input[_in++] << bits;
73703                     bits += 8;
73704                   }
73705                 }
73706                 dist += hold & ((1 << op) - 1);
73707     //#ifdef INFLATE_STRICT
73708                 if (dist > dmax) {
73709                   strm.msg = 'invalid distance too far back';
73710                   state.mode = BAD$1;
73711                   break top;
73712                 }
73713     //#endif
73714                 hold >>>= op;
73715                 bits -= op;
73716                 //Tracevv((stderr, "inflate:         distance %u\n", dist));
73717                 op = _out - beg;                /* max distance in output */
73718                 if (dist > op) {                /* see if copy from window */
73719                   op = dist - op;               /* distance back in window */
73720                   if (op > whave) {
73721                     if (state.sane) {
73722                       strm.msg = 'invalid distance too far back';
73723                       state.mode = BAD$1;
73724                       break top;
73725                     }
73726
73727     // (!) This block is disabled in zlib defaults,
73728     // don't enable it for binary compatibility
73729     //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
73730     //                if (len <= op - whave) {
73731     //                  do {
73732     //                    output[_out++] = 0;
73733     //                  } while (--len);
73734     //                  continue top;
73735     //                }
73736     //                len -= op - whave;
73737     //                do {
73738     //                  output[_out++] = 0;
73739     //                } while (--op > whave);
73740     //                if (op === 0) {
73741     //                  from = _out - dist;
73742     //                  do {
73743     //                    output[_out++] = output[from++];
73744     //                  } while (--len);
73745     //                  continue top;
73746     //                }
73747     //#endif
73748                   }
73749                   from = 0; // window index
73750                   from_source = s_window;
73751                   if (wnext === 0) {           /* very common case */
73752                     from += wsize - op;
73753                     if (op < len) {         /* some from window */
73754                       len -= op;
73755                       do {
73756                         output[_out++] = s_window[from++];
73757                       } while (--op);
73758                       from = _out - dist;  /* rest from output */
73759                       from_source = output;
73760                     }
73761                   }
73762                   else if (wnext < op) {      /* wrap around window */
73763                     from += wsize + wnext - op;
73764                     op -= wnext;
73765                     if (op < len) {         /* some from end of window */
73766                       len -= op;
73767                       do {
73768                         output[_out++] = s_window[from++];
73769                       } while (--op);
73770                       from = 0;
73771                       if (wnext < len) {  /* some from start of window */
73772                         op = wnext;
73773                         len -= op;
73774                         do {
73775                           output[_out++] = s_window[from++];
73776                         } while (--op);
73777                         from = _out - dist;      /* rest from output */
73778                         from_source = output;
73779                       }
73780                     }
73781                   }
73782                   else {                      /* contiguous in window */
73783                     from += wnext - op;
73784                     if (op < len) {         /* some from window */
73785                       len -= op;
73786                       do {
73787                         output[_out++] = s_window[from++];
73788                       } while (--op);
73789                       from = _out - dist;  /* rest from output */
73790                       from_source = output;
73791                     }
73792                   }
73793                   while (len > 2) {
73794                     output[_out++] = from_source[from++];
73795                     output[_out++] = from_source[from++];
73796                     output[_out++] = from_source[from++];
73797                     len -= 3;
73798                   }
73799                   if (len) {
73800                     output[_out++] = from_source[from++];
73801                     if (len > 1) {
73802                       output[_out++] = from_source[from++];
73803                     }
73804                   }
73805                 }
73806                 else {
73807                   from = _out - dist;          /* copy direct from output */
73808                   do {                        /* minimum length is three */
73809                     output[_out++] = output[from++];
73810                     output[_out++] = output[from++];
73811                     output[_out++] = output[from++];
73812                     len -= 3;
73813                   } while (len > 2);
73814                   if (len) {
73815                     output[_out++] = output[from++];
73816                     if (len > 1) {
73817                       output[_out++] = output[from++];
73818                     }
73819                   }
73820                 }
73821               }
73822               else if ((op & 64) === 0) {          /* 2nd level distance code */
73823                 here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
73824                 continue dodist;
73825               }
73826               else {
73827                 strm.msg = 'invalid distance code';
73828                 state.mode = BAD$1;
73829                 break top;
73830               }
73831
73832               break; // need to emulate goto via "continue"
73833             }
73834           }
73835           else if ((op & 64) === 0) {              /* 2nd level length code */
73836             here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
73837             continue dolen;
73838           }
73839           else if (op & 32) {                     /* end-of-block */
73840             //Tracevv((stderr, "inflate:         end of block\n"));
73841             state.mode = TYPE$1;
73842             break top;
73843           }
73844           else {
73845             strm.msg = 'invalid literal/length code';
73846             state.mode = BAD$1;
73847             break top;
73848           }
73849
73850           break; // need to emulate goto via "continue"
73851         }
73852       } while (_in < last && _out < end);
73853
73854       /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
73855       len = bits >> 3;
73856       _in -= len;
73857       bits -= len << 3;
73858       hold &= (1 << bits) - 1;
73859
73860       /* update state and return */
73861       strm.next_in = _in;
73862       strm.next_out = _out;
73863       strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
73864       strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
73865       state.hold = hold;
73866       state.bits = bits;
73867       return;
73868     };
73869
73870     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
73871     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
73872     //
73873     // This software is provided 'as-is', without any express or implied
73874     // warranty. In no event will the authors be held liable for any damages
73875     // arising from the use of this software.
73876     //
73877     // Permission is granted to anyone to use this software for any purpose,
73878     // including commercial applications, and to alter it and redistribute it
73879     // freely, subject to the following restrictions:
73880     //
73881     // 1. The origin of this software must not be misrepresented; you must not
73882     //   claim that you wrote the original software. If you use this software
73883     //   in a product, an acknowledgment in the product documentation would be
73884     //   appreciated but is not required.
73885     // 2. Altered source versions must be plainly marked as such, and must not be
73886     //   misrepresented as being the original software.
73887     // 3. This notice may not be removed or altered from any source distribution.
73888
73889     const MAXBITS = 15;
73890     const ENOUGH_LENS$1 = 852;
73891     const ENOUGH_DISTS$1 = 592;
73892     //const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
73893
73894     const CODES$1 = 0;
73895     const LENS$1 = 1;
73896     const DISTS$1 = 2;
73897
73898     const lbase = new Uint16Array([ /* Length codes 257..285 base */
73899       3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
73900       35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
73901     ]);
73902
73903     const lext = new Uint8Array([ /* Length codes 257..285 extra */
73904       16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
73905       19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
73906     ]);
73907
73908     const dbase = new Uint16Array([ /* Distance codes 0..29 base */
73909       1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
73910       257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
73911       8193, 12289, 16385, 24577, 0, 0
73912     ]);
73913
73914     const dext = new Uint8Array([ /* Distance codes 0..29 extra */
73915       16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
73916       23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
73917       28, 28, 29, 29, 64, 64
73918     ]);
73919
73920     const inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) =>
73921     {
73922       const bits = opts.bits;
73923           //here = opts.here; /* table entry for duplication */
73924
73925       let len = 0;               /* a code's length in bits */
73926       let sym = 0;               /* index of code symbols */
73927       let min = 0, max = 0;          /* minimum and maximum code lengths */
73928       let root = 0;              /* number of index bits for root table */
73929       let curr = 0;              /* number of index bits for current table */
73930       let drop = 0;              /* code bits to drop for sub-table */
73931       let left = 0;                   /* number of prefix codes available */
73932       let used = 0;              /* code entries in table used */
73933       let huff = 0;              /* Huffman code */
73934       let incr;              /* for incrementing code, index */
73935       let fill;              /* index for replicating entries */
73936       let low;               /* low bits for current root entry */
73937       let mask;              /* mask for low root bits */
73938       let next;             /* next available space in table */
73939       let base = null;     /* base value table to use */
73940       let base_index = 0;
73941     //  let shoextra;    /* extra bits table to use */
73942       let end;                    /* use base and extra for symbol > end */
73943       const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1];    /* number of codes of each length */
73944       const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1];     /* offsets in table for each length */
73945       let extra = null;
73946       let extra_index = 0;
73947
73948       let here_bits, here_op, here_val;
73949
73950       /*
73951        Process a set of code lengths to create a canonical Huffman code.  The
73952        code lengths are lens[0..codes-1].  Each length corresponds to the
73953        symbols 0..codes-1.  The Huffman code is generated by first sorting the
73954        symbols by length from short to long, and retaining the symbol order
73955        for codes with equal lengths.  Then the code starts with all zero bits
73956        for the first code of the shortest length, and the codes are integer
73957        increments for the same length, and zeros are appended as the length
73958        increases.  For the deflate format, these bits are stored backwards
73959        from their more natural integer increment ordering, and so when the
73960        decoding tables are built in the large loop below, the integer codes
73961        are incremented backwards.
73962
73963        This routine assumes, but does not check, that all of the entries in
73964        lens[] are in the range 0..MAXBITS.  The caller must assure this.
73965        1..MAXBITS is interpreted as that code length.  zero means that that
73966        symbol does not occur in this code.
73967
73968        The codes are sorted by computing a count of codes for each length,
73969        creating from that a table of starting indices for each length in the
73970        sorted table, and then entering the symbols in order in the sorted
73971        table.  The sorted table is work[], with that space being provided by
73972        the caller.
73973
73974        The length counts are used for other purposes as well, i.e. finding
73975        the minimum and maximum length codes, determining if there are any
73976        codes at all, checking for a valid set of lengths, and looking ahead
73977        at length counts to determine sub-table sizes when building the
73978        decoding tables.
73979        */
73980
73981       /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
73982       for (len = 0; len <= MAXBITS; len++) {
73983         count[len] = 0;
73984       }
73985       for (sym = 0; sym < codes; sym++) {
73986         count[lens[lens_index + sym]]++;
73987       }
73988
73989       /* bound code lengths, force root to be within code lengths */
73990       root = bits;
73991       for (max = MAXBITS; max >= 1; max--) {
73992         if (count[max] !== 0) { break; }
73993       }
73994       if (root > max) {
73995         root = max;
73996       }
73997       if (max === 0) {                     /* no symbols to code at all */
73998         //table.op[opts.table_index] = 64;  //here.op = (var char)64;    /* invalid code marker */
73999         //table.bits[opts.table_index] = 1;   //here.bits = (var char)1;
74000         //table.val[opts.table_index++] = 0;   //here.val = (var short)0;
74001         table[table_index++] = (1 << 24) | (64 << 16) | 0;
74002
74003
74004         //table.op[opts.table_index] = 64;
74005         //table.bits[opts.table_index] = 1;
74006         //table.val[opts.table_index++] = 0;
74007         table[table_index++] = (1 << 24) | (64 << 16) | 0;
74008
74009         opts.bits = 1;
74010         return 0;     /* no symbols, but wait for decoding to report error */
74011       }
74012       for (min = 1; min < max; min++) {
74013         if (count[min] !== 0) { break; }
74014       }
74015       if (root < min) {
74016         root = min;
74017       }
74018
74019       /* check for an over-subscribed or incomplete set of lengths */
74020       left = 1;
74021       for (len = 1; len <= MAXBITS; len++) {
74022         left <<= 1;
74023         left -= count[len];
74024         if (left < 0) {
74025           return -1;
74026         }        /* over-subscribed */
74027       }
74028       if (left > 0 && (type === CODES$1 || max !== 1)) {
74029         return -1;                      /* incomplete set */
74030       }
74031
74032       /* generate offsets into symbol table for each length for sorting */
74033       offs[1] = 0;
74034       for (len = 1; len < MAXBITS; len++) {
74035         offs[len + 1] = offs[len] + count[len];
74036       }
74037
74038       /* sort symbols by length, by symbol order within each length */
74039       for (sym = 0; sym < codes; sym++) {
74040         if (lens[lens_index + sym] !== 0) {
74041           work[offs[lens[lens_index + sym]]++] = sym;
74042         }
74043       }
74044
74045       /*
74046        Create and fill in decoding tables.  In this loop, the table being
74047        filled is at next and has curr index bits.  The code being used is huff
74048        with length len.  That code is converted to an index by dropping drop
74049        bits off of the bottom.  For codes where len is less than drop + curr,
74050        those top drop + curr - len bits are incremented through all values to
74051        fill the table with replicated entries.
74052
74053        root is the number of index bits for the root table.  When len exceeds
74054        root, sub-tables are created pointed to by the root entry with an index
74055        of the low root bits of huff.  This is saved in low to check for when a
74056        new sub-table should be started.  drop is zero when the root table is
74057        being filled, and drop is root when sub-tables are being filled.
74058
74059        When a new sub-table is needed, it is necessary to look ahead in the
74060        code lengths to determine what size sub-table is needed.  The length
74061        counts are used for this, and so count[] is decremented as codes are
74062        entered in the tables.
74063
74064        used keeps track of how many table entries have been allocated from the
74065        provided *table space.  It is checked for LENS and DIST tables against
74066        the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
74067        the initial root table size constants.  See the comments in inftrees.h
74068        for more information.
74069
74070        sym increments through all symbols, and the loop terminates when
74071        all codes of length max, i.e. all codes, have been processed.  This
74072        routine permits incomplete codes, so another loop after this one fills
74073        in the rest of the decoding tables with invalid code markers.
74074        */
74075
74076       /* set up for code type */
74077       // poor man optimization - use if-else instead of switch,
74078       // to avoid deopts in old v8
74079       if (type === CODES$1) {
74080         base = extra = work;    /* dummy value--not used */
74081         end = 19;
74082
74083       } else if (type === LENS$1) {
74084         base = lbase;
74085         base_index -= 257;
74086         extra = lext;
74087         extra_index -= 257;
74088         end = 256;
74089
74090       } else {                    /* DISTS */
74091         base = dbase;
74092         extra = dext;
74093         end = -1;
74094       }
74095
74096       /* initialize opts for loop */
74097       huff = 0;                   /* starting code */
74098       sym = 0;                    /* starting code symbol */
74099       len = min;                  /* starting code length */
74100       next = table_index;              /* current table to fill in */
74101       curr = root;                /* current table index bits */
74102       drop = 0;                   /* current bits to drop from code for index */
74103       low = -1;                   /* trigger new sub-table when len > root */
74104       used = 1 << root;          /* use root table entries */
74105       mask = used - 1;            /* mask for comparing low */
74106
74107       /* check available table space */
74108       if ((type === LENS$1 && used > ENOUGH_LENS$1) ||
74109         (type === DISTS$1 && used > ENOUGH_DISTS$1)) {
74110         return 1;
74111       }
74112
74113       /* process all codes and make table entries */
74114       for (;;) {
74115         /* create table entry */
74116         here_bits = len - drop;
74117         if (work[sym] < end) {
74118           here_op = 0;
74119           here_val = work[sym];
74120         }
74121         else if (work[sym] > end) {
74122           here_op = extra[extra_index + work[sym]];
74123           here_val = base[base_index + work[sym]];
74124         }
74125         else {
74126           here_op = 32 + 64;         /* end of block */
74127           here_val = 0;
74128         }
74129
74130         /* replicate for those indices with low len bits equal to huff */
74131         incr = 1 << (len - drop);
74132         fill = 1 << curr;
74133         min = fill;                 /* save offset to next table */
74134         do {
74135           fill -= incr;
74136           table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
74137         } while (fill !== 0);
74138
74139         /* backwards increment the len-bit code huff */
74140         incr = 1 << (len - 1);
74141         while (huff & incr) {
74142           incr >>= 1;
74143         }
74144         if (incr !== 0) {
74145           huff &= incr - 1;
74146           huff += incr;
74147         } else {
74148           huff = 0;
74149         }
74150
74151         /* go to next symbol, update count, len */
74152         sym++;
74153         if (--count[len] === 0) {
74154           if (len === max) { break; }
74155           len = lens[lens_index + work[sym]];
74156         }
74157
74158         /* create new sub-table if needed */
74159         if (len > root && (huff & mask) !== low) {
74160           /* if first time, transition to sub-tables */
74161           if (drop === 0) {
74162             drop = root;
74163           }
74164
74165           /* increment past last table */
74166           next += min;            /* here min is 1 << curr */
74167
74168           /* determine length of next table */
74169           curr = len - drop;
74170           left = 1 << curr;
74171           while (curr + drop < max) {
74172             left -= count[curr + drop];
74173             if (left <= 0) { break; }
74174             curr++;
74175             left <<= 1;
74176           }
74177
74178           /* check for enough space */
74179           used += 1 << curr;
74180           if ((type === LENS$1 && used > ENOUGH_LENS$1) ||
74181             (type === DISTS$1 && used > ENOUGH_DISTS$1)) {
74182             return 1;
74183           }
74184
74185           /* point entry in root table to sub-table */
74186           low = huff & mask;
74187           /*table.op[low] = curr;
74188           table.bits[low] = root;
74189           table.val[low] = next - opts.table_index;*/
74190           table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
74191         }
74192       }
74193
74194       /* fill in remaining table entry if code is incomplete (guaranteed to have
74195        at most one remaining entry, since if the code is incomplete, the
74196        maximum code length that was allowed to get this far is one bit) */
74197       if (huff !== 0) {
74198         //table.op[next + huff] = 64;            /* invalid code marker */
74199         //table.bits[next + huff] = len - drop;
74200         //table.val[next + huff] = 0;
74201         table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
74202       }
74203
74204       /* set return parameters */
74205       //opts.table_index += used;
74206       opts.bits = root;
74207       return 0;
74208     };
74209
74210
74211     var inftrees = inflate_table;
74212
74213     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
74214     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
74215     //
74216     // This software is provided 'as-is', without any express or implied
74217     // warranty. In no event will the authors be held liable for any damages
74218     // arising from the use of this software.
74219     //
74220     // Permission is granted to anyone to use this software for any purpose,
74221     // including commercial applications, and to alter it and redistribute it
74222     // freely, subject to the following restrictions:
74223     //
74224     // 1. The origin of this software must not be misrepresented; you must not
74225     //   claim that you wrote the original software. If you use this software
74226     //   in a product, an acknowledgment in the product documentation would be
74227     //   appreciated but is not required.
74228     // 2. Altered source versions must be plainly marked as such, and must not be
74229     //   misrepresented as being the original software.
74230     // 3. This notice may not be removed or altered from any source distribution.
74231
74232
74233
74234
74235
74236
74237     const CODES = 0;
74238     const LENS = 1;
74239     const DISTS = 2;
74240
74241     /* Public constants ==========================================================*/
74242     /* ===========================================================================*/
74243
74244     const {
74245       Z_FINISH: Z_FINISH$1, Z_BLOCK, Z_TREES,
74246       Z_OK: Z_OK$1, Z_STREAM_END: Z_STREAM_END$1, Z_NEED_DICT: Z_NEED_DICT$1, Z_STREAM_ERROR: Z_STREAM_ERROR$1, Z_DATA_ERROR: Z_DATA_ERROR$1, Z_MEM_ERROR: Z_MEM_ERROR$1, Z_BUF_ERROR,
74247       Z_DEFLATED
74248     } = constants$2;
74249
74250
74251     /* STATES ====================================================================*/
74252     /* ===========================================================================*/
74253
74254
74255     const    HEAD = 1;       /* i: waiting for magic header */
74256     const    FLAGS = 2;      /* i: waiting for method and flags (gzip) */
74257     const    TIME = 3;       /* i: waiting for modification time (gzip) */
74258     const    OS = 4;         /* i: waiting for extra flags and operating system (gzip) */
74259     const    EXLEN = 5;      /* i: waiting for extra length (gzip) */
74260     const    EXTRA = 6;      /* i: waiting for extra bytes (gzip) */
74261     const    NAME = 7;       /* i: waiting for end of file name (gzip) */
74262     const    COMMENT = 8;    /* i: waiting for end of comment (gzip) */
74263     const    HCRC = 9;       /* i: waiting for header crc (gzip) */
74264     const    DICTID = 10;    /* i: waiting for dictionary check value */
74265     const    DICT = 11;      /* waiting for inflateSetDictionary() call */
74266     const        TYPE = 12;      /* i: waiting for type bits, including last-flag bit */
74267     const        TYPEDO = 13;    /* i: same, but skip check to exit inflate on new block */
74268     const        STORED = 14;    /* i: waiting for stored size (length and complement) */
74269     const        COPY_ = 15;     /* i/o: same as COPY below, but only first time in */
74270     const        COPY = 16;      /* i/o: waiting for input or output to copy stored block */
74271     const        TABLE = 17;     /* i: waiting for dynamic block table lengths */
74272     const        LENLENS = 18;   /* i: waiting for code length code lengths */
74273     const        CODELENS = 19;  /* i: waiting for length/lit and distance code lengths */
74274     const            LEN_ = 20;      /* i: same as LEN below, but only first time in */
74275     const            LEN = 21;       /* i: waiting for length/lit/eob code */
74276     const            LENEXT = 22;    /* i: waiting for length extra bits */
74277     const            DIST = 23;      /* i: waiting for distance code */
74278     const            DISTEXT = 24;   /* i: waiting for distance extra bits */
74279     const            MATCH = 25;     /* o: waiting for output space to copy string */
74280     const            LIT = 26;       /* o: waiting for output space to write literal */
74281     const    CHECK = 27;     /* i: waiting for 32-bit check value */
74282     const    LENGTH = 28;    /* i: waiting for 32-bit length (gzip) */
74283     const    DONE = 29;      /* finished check, done -- remain here until reset */
74284     const    BAD = 30;       /* got a data error -- remain here until reset */
74285     const    MEM = 31;       /* got an inflate() memory error -- remain here until reset */
74286     const    SYNC = 32;      /* looking for synchronization bytes to restart inflate() */
74287
74288     /* ===========================================================================*/
74289
74290
74291
74292     const ENOUGH_LENS = 852;
74293     const ENOUGH_DISTS = 592;
74294     //const ENOUGH =  (ENOUGH_LENS+ENOUGH_DISTS);
74295
74296     const MAX_WBITS = 15;
74297     /* 32K LZ77 window */
74298     const DEF_WBITS = MAX_WBITS;
74299
74300
74301     const zswap32 = (q) => {
74302
74303       return  (((q >>> 24) & 0xff) +
74304               ((q >>> 8) & 0xff00) +
74305               ((q & 0xff00) << 8) +
74306               ((q & 0xff) << 24));
74307     };
74308
74309
74310     function InflateState() {
74311       this.mode = 0;             /* current inflate mode */
74312       this.last = false;          /* true if processing last block */
74313       this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */
74314       this.havedict = false;      /* true if dictionary provided */
74315       this.flags = 0;             /* gzip header method and flags (0 if zlib) */
74316       this.dmax = 0;              /* zlib header max distance (INFLATE_STRICT) */
74317       this.check = 0;             /* protected copy of check value */
74318       this.total = 0;             /* protected copy of output count */
74319       // TODO: may be {}
74320       this.head = null;           /* where to save gzip header information */
74321
74322       /* sliding window */
74323       this.wbits = 0;             /* log base 2 of requested window size */
74324       this.wsize = 0;             /* window size or zero if not using window */
74325       this.whave = 0;             /* valid bytes in the window */
74326       this.wnext = 0;             /* window write index */
74327       this.window = null;         /* allocated sliding window, if needed */
74328
74329       /* bit accumulator */
74330       this.hold = 0;              /* input bit accumulator */
74331       this.bits = 0;              /* number of bits in "in" */
74332
74333       /* for string and stored block copying */
74334       this.length = 0;            /* literal or length of data to copy */
74335       this.offset = 0;            /* distance back to copy string from */
74336
74337       /* for table and code decoding */
74338       this.extra = 0;             /* extra bits needed */
74339
74340       /* fixed and dynamic code tables */
74341       this.lencode = null;          /* starting table for length/literal codes */
74342       this.distcode = null;         /* starting table for distance codes */
74343       this.lenbits = 0;           /* index bits for lencode */
74344       this.distbits = 0;          /* index bits for distcode */
74345
74346       /* dynamic table building */
74347       this.ncode = 0;             /* number of code length code lengths */
74348       this.nlen = 0;              /* number of length code lengths */
74349       this.ndist = 0;             /* number of distance code lengths */
74350       this.have = 0;              /* number of code lengths in lens[] */
74351       this.next = null;              /* next available space in codes[] */
74352
74353       this.lens = new Uint16Array(320); /* temporary storage for code lengths */
74354       this.work = new Uint16Array(288); /* work area for code table building */
74355
74356       /*
74357        because we don't have pointers in js, we use lencode and distcode directly
74358        as buffers so we don't need codes
74359       */
74360       //this.codes = new Int32Array(ENOUGH);       /* space for code tables */
74361       this.lendyn = null;              /* dynamic table for length/literal codes (JS specific) */
74362       this.distdyn = null;             /* dynamic table for distance codes (JS specific) */
74363       this.sane = 0;                   /* if false, allow invalid distance too far */
74364       this.back = 0;                   /* bits back of last unprocessed length/lit */
74365       this.was = 0;                    /* initial length of match */
74366     }
74367
74368
74369     const inflateResetKeep = (strm) => {
74370
74371       if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
74372       const state = strm.state;
74373       strm.total_in = strm.total_out = state.total = 0;
74374       strm.msg = ''; /*Z_NULL*/
74375       if (state.wrap) {       /* to support ill-conceived Java test suite */
74376         strm.adler = state.wrap & 1;
74377       }
74378       state.mode = HEAD;
74379       state.last = 0;
74380       state.havedict = 0;
74381       state.dmax = 32768;
74382       state.head = null/*Z_NULL*/;
74383       state.hold = 0;
74384       state.bits = 0;
74385       //state.lencode = state.distcode = state.next = state.codes;
74386       state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS);
74387       state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS);
74388
74389       state.sane = 1;
74390       state.back = -1;
74391       //Tracev((stderr, "inflate: reset\n"));
74392       return Z_OK$1;
74393     };
74394
74395
74396     const inflateReset = (strm) => {
74397
74398       if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
74399       const state = strm.state;
74400       state.wsize = 0;
74401       state.whave = 0;
74402       state.wnext = 0;
74403       return inflateResetKeep(strm);
74404
74405     };
74406
74407
74408     const inflateReset2 = (strm, windowBits) => {
74409       let wrap;
74410
74411       /* get the state */
74412       if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
74413       const state = strm.state;
74414
74415       /* extract wrap request from windowBits parameter */
74416       if (windowBits < 0) {
74417         wrap = 0;
74418         windowBits = -windowBits;
74419       }
74420       else {
74421         wrap = (windowBits >> 4) + 1;
74422         if (windowBits < 48) {
74423           windowBits &= 15;
74424         }
74425       }
74426
74427       /* set number of window bits, free window if different */
74428       if (windowBits && (windowBits < 8 || windowBits > 15)) {
74429         return Z_STREAM_ERROR$1;
74430       }
74431       if (state.window !== null && state.wbits !== windowBits) {
74432         state.window = null;
74433       }
74434
74435       /* update state and reset the rest of it */
74436       state.wrap = wrap;
74437       state.wbits = windowBits;
74438       return inflateReset(strm);
74439     };
74440
74441
74442     const inflateInit2 = (strm, windowBits) => {
74443
74444       if (!strm) { return Z_STREAM_ERROR$1; }
74445       //strm.msg = Z_NULL;                 /* in case we return an error */
74446
74447       const state = new InflateState();
74448
74449       //if (state === Z_NULL) return Z_MEM_ERROR;
74450       //Tracev((stderr, "inflate: allocated\n"));
74451       strm.state = state;
74452       state.window = null/*Z_NULL*/;
74453       const ret = inflateReset2(strm, windowBits);
74454       if (ret !== Z_OK$1) {
74455         strm.state = null/*Z_NULL*/;
74456       }
74457       return ret;
74458     };
74459
74460
74461     const inflateInit = (strm) => {
74462
74463       return inflateInit2(strm, DEF_WBITS);
74464     };
74465
74466
74467     /*
74468      Return state with length and distance decoding tables and index sizes set to
74469      fixed code decoding.  Normally this returns fixed tables from inffixed.h.
74470      If BUILDFIXED is defined, then instead this routine builds the tables the
74471      first time it's called, and returns those tables the first time and
74472      thereafter.  This reduces the size of the code by about 2K bytes, in
74473      exchange for a little execution time.  However, BUILDFIXED should not be
74474      used for threaded applications, since the rewriting of the tables and virgin
74475      may not be thread-safe.
74476      */
74477     let virgin = true;
74478
74479     let lenfix, distfix; // We have no pointers in JS, so keep tables separate
74480
74481
74482     const fixedtables = (state) => {
74483
74484       /* build fixed huffman tables if first call (may not be thread safe) */
74485       if (virgin) {
74486         lenfix = new Int32Array(512);
74487         distfix = new Int32Array(32);
74488
74489         /* literal/length table */
74490         let sym = 0;
74491         while (sym < 144) { state.lens[sym++] = 8; }
74492         while (sym < 256) { state.lens[sym++] = 9; }
74493         while (sym < 280) { state.lens[sym++] = 7; }
74494         while (sym < 288) { state.lens[sym++] = 8; }
74495
74496         inftrees(LENS,  state.lens, 0, 288, lenfix,   0, state.work, { bits: 9 });
74497
74498         /* distance table */
74499         sym = 0;
74500         while (sym < 32) { state.lens[sym++] = 5; }
74501
74502         inftrees(DISTS, state.lens, 0, 32,   distfix, 0, state.work, { bits: 5 });
74503
74504         /* do this just once */
74505         virgin = false;
74506       }
74507
74508       state.lencode = lenfix;
74509       state.lenbits = 9;
74510       state.distcode = distfix;
74511       state.distbits = 5;
74512     };
74513
74514
74515     /*
74516      Update the window with the last wsize (normally 32K) bytes written before
74517      returning.  If window does not exist yet, create it.  This is only called
74518      when a window is already in use, or when output has been written during this
74519      inflate call, but the end of the deflate stream has not been reached yet.
74520      It is also called to create a window for dictionary data when a dictionary
74521      is loaded.
74522
74523      Providing output buffers larger than 32K to inflate() should provide a speed
74524      advantage, since only the last 32K of output is copied to the sliding window
74525      upon return from inflate(), and since all distances after the first 32K of
74526      output will fall in the output data, making match copies simpler and faster.
74527      The advantage may be dependent on the size of the processor's data caches.
74528      */
74529     const updatewindow = (strm, src, end, copy) => {
74530
74531       let dist;
74532       const state = strm.state;
74533
74534       /* if it hasn't been done already, allocate space for the window */
74535       if (state.window === null) {
74536         state.wsize = 1 << state.wbits;
74537         state.wnext = 0;
74538         state.whave = 0;
74539
74540         state.window = new Uint8Array(state.wsize);
74541       }
74542
74543       /* copy state->wsize or less output bytes into the circular window */
74544       if (copy >= state.wsize) {
74545         state.window.set(src.subarray(end - state.wsize, end), 0);
74546         state.wnext = 0;
74547         state.whave = state.wsize;
74548       }
74549       else {
74550         dist = state.wsize - state.wnext;
74551         if (dist > copy) {
74552           dist = copy;
74553         }
74554         //zmemcpy(state->window + state->wnext, end - copy, dist);
74555         state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext);
74556         copy -= dist;
74557         if (copy) {
74558           //zmemcpy(state->window, end - copy, copy);
74559           state.window.set(src.subarray(end - copy, end), 0);
74560           state.wnext = copy;
74561           state.whave = state.wsize;
74562         }
74563         else {
74564           state.wnext += dist;
74565           if (state.wnext === state.wsize) { state.wnext = 0; }
74566           if (state.whave < state.wsize) { state.whave += dist; }
74567         }
74568       }
74569       return 0;
74570     };
74571
74572
74573     const inflate$2 = (strm, flush) => {
74574
74575       let state;
74576       let input, output;          // input/output buffers
74577       let next;                   /* next input INDEX */
74578       let put;                    /* next output INDEX */
74579       let have, left;             /* available input and output */
74580       let hold;                   /* bit buffer */
74581       let bits;                   /* bits in bit buffer */
74582       let _in, _out;              /* save starting available input and output */
74583       let copy;                   /* number of stored or match bytes to copy */
74584       let from;                   /* where to copy match bytes from */
74585       let from_source;
74586       let here = 0;               /* current decoding table entry */
74587       let here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
74588       //let last;                   /* parent table entry */
74589       let last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
74590       let len;                    /* length to copy for repeats, bits to drop */
74591       let ret;                    /* return code */
74592       const hbuf = new Uint8Array(4);    /* buffer for gzip header crc calculation */
74593       let opts;
74594
74595       let n; // temporary variable for NEED_BITS
74596
74597       const order = /* permutation of code lengths */
74598         new Uint8Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]);
74599
74600
74601       if (!strm || !strm.state || !strm.output ||
74602           (!strm.input && strm.avail_in !== 0)) {
74603         return Z_STREAM_ERROR$1;
74604       }
74605
74606       state = strm.state;
74607       if (state.mode === TYPE) { state.mode = TYPEDO; }    /* skip check */
74608
74609
74610       //--- LOAD() ---
74611       put = strm.next_out;
74612       output = strm.output;
74613       left = strm.avail_out;
74614       next = strm.next_in;
74615       input = strm.input;
74616       have = strm.avail_in;
74617       hold = state.hold;
74618       bits = state.bits;
74619       //---
74620
74621       _in = have;
74622       _out = left;
74623       ret = Z_OK$1;
74624
74625       inf_leave: // goto emulation
74626       for (;;) {
74627         switch (state.mode) {
74628           case HEAD:
74629             if (state.wrap === 0) {
74630               state.mode = TYPEDO;
74631               break;
74632             }
74633             //=== NEEDBITS(16);
74634             while (bits < 16) {
74635               if (have === 0) { break inf_leave; }
74636               have--;
74637               hold += input[next++] << bits;
74638               bits += 8;
74639             }
74640             //===//
74641             if ((state.wrap & 2) && hold === 0x8b1f) {  /* gzip header */
74642               state.check = 0/*crc32(0L, Z_NULL, 0)*/;
74643               //=== CRC2(state.check, hold);
74644               hbuf[0] = hold & 0xff;
74645               hbuf[1] = (hold >>> 8) & 0xff;
74646               state.check = crc32_1(state.check, hbuf, 2, 0);
74647               //===//
74648
74649               //=== INITBITS();
74650               hold = 0;
74651               bits = 0;
74652               //===//
74653               state.mode = FLAGS;
74654               break;
74655             }
74656             state.flags = 0;           /* expect zlib header */
74657             if (state.head) {
74658               state.head.done = false;
74659             }
74660             if (!(state.wrap & 1) ||   /* check if zlib header allowed */
74661               (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
74662               strm.msg = 'incorrect header check';
74663               state.mode = BAD;
74664               break;
74665             }
74666             if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {
74667               strm.msg = 'unknown compression method';
74668               state.mode = BAD;
74669               break;
74670             }
74671             //--- DROPBITS(4) ---//
74672             hold >>>= 4;
74673             bits -= 4;
74674             //---//
74675             len = (hold & 0x0f)/*BITS(4)*/ + 8;
74676             if (state.wbits === 0) {
74677               state.wbits = len;
74678             }
74679             else if (len > state.wbits) {
74680               strm.msg = 'invalid window size';
74681               state.mode = BAD;
74682               break;
74683             }
74684
74685             // !!! pako patch. Force use `options.windowBits` if passed.
74686             // Required to always use max window size by default.
74687             state.dmax = 1 << state.wbits;
74688             //state.dmax = 1 << len;
74689
74690             //Tracev((stderr, "inflate:   zlib header ok\n"));
74691             strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
74692             state.mode = hold & 0x200 ? DICTID : TYPE;
74693             //=== INITBITS();
74694             hold = 0;
74695             bits = 0;
74696             //===//
74697             break;
74698           case FLAGS:
74699             //=== NEEDBITS(16); */
74700             while (bits < 16) {
74701               if (have === 0) { break inf_leave; }
74702               have--;
74703               hold += input[next++] << bits;
74704               bits += 8;
74705             }
74706             //===//
74707             state.flags = hold;
74708             if ((state.flags & 0xff) !== Z_DEFLATED) {
74709               strm.msg = 'unknown compression method';
74710               state.mode = BAD;
74711               break;
74712             }
74713             if (state.flags & 0xe000) {
74714               strm.msg = 'unknown header flags set';
74715               state.mode = BAD;
74716               break;
74717             }
74718             if (state.head) {
74719               state.head.text = ((hold >> 8) & 1);
74720             }
74721             if (state.flags & 0x0200) {
74722               //=== CRC2(state.check, hold);
74723               hbuf[0] = hold & 0xff;
74724               hbuf[1] = (hold >>> 8) & 0xff;
74725               state.check = crc32_1(state.check, hbuf, 2, 0);
74726               //===//
74727             }
74728             //=== INITBITS();
74729             hold = 0;
74730             bits = 0;
74731             //===//
74732             state.mode = TIME;
74733             /* falls through */
74734           case TIME:
74735             //=== NEEDBITS(32); */
74736             while (bits < 32) {
74737               if (have === 0) { break inf_leave; }
74738               have--;
74739               hold += input[next++] << bits;
74740               bits += 8;
74741             }
74742             //===//
74743             if (state.head) {
74744               state.head.time = hold;
74745             }
74746             if (state.flags & 0x0200) {
74747               //=== CRC4(state.check, hold)
74748               hbuf[0] = hold & 0xff;
74749               hbuf[1] = (hold >>> 8) & 0xff;
74750               hbuf[2] = (hold >>> 16) & 0xff;
74751               hbuf[3] = (hold >>> 24) & 0xff;
74752               state.check = crc32_1(state.check, hbuf, 4, 0);
74753               //===
74754             }
74755             //=== INITBITS();
74756             hold = 0;
74757             bits = 0;
74758             //===//
74759             state.mode = OS;
74760             /* falls through */
74761           case OS:
74762             //=== NEEDBITS(16); */
74763             while (bits < 16) {
74764               if (have === 0) { break inf_leave; }
74765               have--;
74766               hold += input[next++] << bits;
74767               bits += 8;
74768             }
74769             //===//
74770             if (state.head) {
74771               state.head.xflags = (hold & 0xff);
74772               state.head.os = (hold >> 8);
74773             }
74774             if (state.flags & 0x0200) {
74775               //=== CRC2(state.check, hold);
74776               hbuf[0] = hold & 0xff;
74777               hbuf[1] = (hold >>> 8) & 0xff;
74778               state.check = crc32_1(state.check, hbuf, 2, 0);
74779               //===//
74780             }
74781             //=== INITBITS();
74782             hold = 0;
74783             bits = 0;
74784             //===//
74785             state.mode = EXLEN;
74786             /* falls through */
74787           case EXLEN:
74788             if (state.flags & 0x0400) {
74789               //=== NEEDBITS(16); */
74790               while (bits < 16) {
74791                 if (have === 0) { break inf_leave; }
74792                 have--;
74793                 hold += input[next++] << bits;
74794                 bits += 8;
74795               }
74796               //===//
74797               state.length = hold;
74798               if (state.head) {
74799                 state.head.extra_len = hold;
74800               }
74801               if (state.flags & 0x0200) {
74802                 //=== CRC2(state.check, hold);
74803                 hbuf[0] = hold & 0xff;
74804                 hbuf[1] = (hold >>> 8) & 0xff;
74805                 state.check = crc32_1(state.check, hbuf, 2, 0);
74806                 //===//
74807               }
74808               //=== INITBITS();
74809               hold = 0;
74810               bits = 0;
74811               //===//
74812             }
74813             else if (state.head) {
74814               state.head.extra = null/*Z_NULL*/;
74815             }
74816             state.mode = EXTRA;
74817             /* falls through */
74818           case EXTRA:
74819             if (state.flags & 0x0400) {
74820               copy = state.length;
74821               if (copy > have) { copy = have; }
74822               if (copy) {
74823                 if (state.head) {
74824                   len = state.head.extra_len - state.length;
74825                   if (!state.head.extra) {
74826                     // Use untyped array for more convenient processing later
74827                     state.head.extra = new Uint8Array(state.head.extra_len);
74828                   }
74829                   state.head.extra.set(
74830                     input.subarray(
74831                       next,
74832                       // extra field is limited to 65536 bytes
74833                       // - no need for additional size check
74834                       next + copy
74835                     ),
74836                     /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
74837                     len
74838                   );
74839                   //zmemcpy(state.head.extra + len, next,
74840                   //        len + copy > state.head.extra_max ?
74841                   //        state.head.extra_max - len : copy);
74842                 }
74843                 if (state.flags & 0x0200) {
74844                   state.check = crc32_1(state.check, input, copy, next);
74845                 }
74846                 have -= copy;
74847                 next += copy;
74848                 state.length -= copy;
74849               }
74850               if (state.length) { break inf_leave; }
74851             }
74852             state.length = 0;
74853             state.mode = NAME;
74854             /* falls through */
74855           case NAME:
74856             if (state.flags & 0x0800) {
74857               if (have === 0) { break inf_leave; }
74858               copy = 0;
74859               do {
74860                 // TODO: 2 or 1 bytes?
74861                 len = input[next + copy++];
74862                 /* use constant limit because in js we should not preallocate memory */
74863                 if (state.head && len &&
74864                     (state.length < 65536 /*state.head.name_max*/)) {
74865                   state.head.name += String.fromCharCode(len);
74866                 }
74867               } while (len && copy < have);
74868
74869               if (state.flags & 0x0200) {
74870                 state.check = crc32_1(state.check, input, copy, next);
74871               }
74872               have -= copy;
74873               next += copy;
74874               if (len) { break inf_leave; }
74875             }
74876             else if (state.head) {
74877               state.head.name = null;
74878             }
74879             state.length = 0;
74880             state.mode = COMMENT;
74881             /* falls through */
74882           case COMMENT:
74883             if (state.flags & 0x1000) {
74884               if (have === 0) { break inf_leave; }
74885               copy = 0;
74886               do {
74887                 len = input[next + copy++];
74888                 /* use constant limit because in js we should not preallocate memory */
74889                 if (state.head && len &&
74890                     (state.length < 65536 /*state.head.comm_max*/)) {
74891                   state.head.comment += String.fromCharCode(len);
74892                 }
74893               } while (len && copy < have);
74894               if (state.flags & 0x0200) {
74895                 state.check = crc32_1(state.check, input, copy, next);
74896               }
74897               have -= copy;
74898               next += copy;
74899               if (len) { break inf_leave; }
74900             }
74901             else if (state.head) {
74902               state.head.comment = null;
74903             }
74904             state.mode = HCRC;
74905             /* falls through */
74906           case HCRC:
74907             if (state.flags & 0x0200) {
74908               //=== NEEDBITS(16); */
74909               while (bits < 16) {
74910                 if (have === 0) { break inf_leave; }
74911                 have--;
74912                 hold += input[next++] << bits;
74913                 bits += 8;
74914               }
74915               //===//
74916               if (hold !== (state.check & 0xffff)) {
74917                 strm.msg = 'header crc mismatch';
74918                 state.mode = BAD;
74919                 break;
74920               }
74921               //=== INITBITS();
74922               hold = 0;
74923               bits = 0;
74924               //===//
74925             }
74926             if (state.head) {
74927               state.head.hcrc = ((state.flags >> 9) & 1);
74928               state.head.done = true;
74929             }
74930             strm.adler = state.check = 0;
74931             state.mode = TYPE;
74932             break;
74933           case DICTID:
74934             //=== NEEDBITS(32); */
74935             while (bits < 32) {
74936               if (have === 0) { break inf_leave; }
74937               have--;
74938               hold += input[next++] << bits;
74939               bits += 8;
74940             }
74941             //===//
74942             strm.adler = state.check = zswap32(hold);
74943             //=== INITBITS();
74944             hold = 0;
74945             bits = 0;
74946             //===//
74947             state.mode = DICT;
74948             /* falls through */
74949           case DICT:
74950             if (state.havedict === 0) {
74951               //--- RESTORE() ---
74952               strm.next_out = put;
74953               strm.avail_out = left;
74954               strm.next_in = next;
74955               strm.avail_in = have;
74956               state.hold = hold;
74957               state.bits = bits;
74958               //---
74959               return Z_NEED_DICT$1;
74960             }
74961             strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
74962             state.mode = TYPE;
74963             /* falls through */
74964           case TYPE:
74965             if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }
74966             /* falls through */
74967           case TYPEDO:
74968             if (state.last) {
74969               //--- BYTEBITS() ---//
74970               hold >>>= bits & 7;
74971               bits -= bits & 7;
74972               //---//
74973               state.mode = CHECK;
74974               break;
74975             }
74976             //=== NEEDBITS(3); */
74977             while (bits < 3) {
74978               if (have === 0) { break inf_leave; }
74979               have--;
74980               hold += input[next++] << bits;
74981               bits += 8;
74982             }
74983             //===//
74984             state.last = (hold & 0x01)/*BITS(1)*/;
74985             //--- DROPBITS(1) ---//
74986             hold >>>= 1;
74987             bits -= 1;
74988             //---//
74989
74990             switch ((hold & 0x03)/*BITS(2)*/) {
74991               case 0:                             /* stored block */
74992                 //Tracev((stderr, "inflate:     stored block%s\n",
74993                 //        state.last ? " (last)" : ""));
74994                 state.mode = STORED;
74995                 break;
74996               case 1:                             /* fixed block */
74997                 fixedtables(state);
74998                 //Tracev((stderr, "inflate:     fixed codes block%s\n",
74999                 //        state.last ? " (last)" : ""));
75000                 state.mode = LEN_;             /* decode codes */
75001                 if (flush === Z_TREES) {
75002                   //--- DROPBITS(2) ---//
75003                   hold >>>= 2;
75004                   bits -= 2;
75005                   //---//
75006                   break inf_leave;
75007                 }
75008                 break;
75009               case 2:                             /* dynamic block */
75010                 //Tracev((stderr, "inflate:     dynamic codes block%s\n",
75011                 //        state.last ? " (last)" : ""));
75012                 state.mode = TABLE;
75013                 break;
75014               case 3:
75015                 strm.msg = 'invalid block type';
75016                 state.mode = BAD;
75017             }
75018             //--- DROPBITS(2) ---//
75019             hold >>>= 2;
75020             bits -= 2;
75021             //---//
75022             break;
75023           case STORED:
75024             //--- BYTEBITS() ---// /* go to byte boundary */
75025             hold >>>= bits & 7;
75026             bits -= bits & 7;
75027             //---//
75028             //=== NEEDBITS(32); */
75029             while (bits < 32) {
75030               if (have === 0) { break inf_leave; }
75031               have--;
75032               hold += input[next++] << bits;
75033               bits += 8;
75034             }
75035             //===//
75036             if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
75037               strm.msg = 'invalid stored block lengths';
75038               state.mode = BAD;
75039               break;
75040             }
75041             state.length = hold & 0xffff;
75042             //Tracev((stderr, "inflate:       stored length %u\n",
75043             //        state.length));
75044             //=== INITBITS();
75045             hold = 0;
75046             bits = 0;
75047             //===//
75048             state.mode = COPY_;
75049             if (flush === Z_TREES) { break inf_leave; }
75050             /* falls through */
75051           case COPY_:
75052             state.mode = COPY;
75053             /* falls through */
75054           case COPY:
75055             copy = state.length;
75056             if (copy) {
75057               if (copy > have) { copy = have; }
75058               if (copy > left) { copy = left; }
75059               if (copy === 0) { break inf_leave; }
75060               //--- zmemcpy(put, next, copy); ---
75061               output.set(input.subarray(next, next + copy), put);
75062               //---//
75063               have -= copy;
75064               next += copy;
75065               left -= copy;
75066               put += copy;
75067               state.length -= copy;
75068               break;
75069             }
75070             //Tracev((stderr, "inflate:       stored end\n"));
75071             state.mode = TYPE;
75072             break;
75073           case TABLE:
75074             //=== NEEDBITS(14); */
75075             while (bits < 14) {
75076               if (have === 0) { break inf_leave; }
75077               have--;
75078               hold += input[next++] << bits;
75079               bits += 8;
75080             }
75081             //===//
75082             state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
75083             //--- DROPBITS(5) ---//
75084             hold >>>= 5;
75085             bits -= 5;
75086             //---//
75087             state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
75088             //--- DROPBITS(5) ---//
75089             hold >>>= 5;
75090             bits -= 5;
75091             //---//
75092             state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
75093             //--- DROPBITS(4) ---//
75094             hold >>>= 4;
75095             bits -= 4;
75096             //---//
75097     //#ifndef PKZIP_BUG_WORKAROUND
75098             if (state.nlen > 286 || state.ndist > 30) {
75099               strm.msg = 'too many length or distance symbols';
75100               state.mode = BAD;
75101               break;
75102             }
75103     //#endif
75104             //Tracev((stderr, "inflate:       table sizes ok\n"));
75105             state.have = 0;
75106             state.mode = LENLENS;
75107             /* falls through */
75108           case LENLENS:
75109             while (state.have < state.ncode) {
75110               //=== NEEDBITS(3);
75111               while (bits < 3) {
75112                 if (have === 0) { break inf_leave; }
75113                 have--;
75114                 hold += input[next++] << bits;
75115                 bits += 8;
75116               }
75117               //===//
75118               state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
75119               //--- DROPBITS(3) ---//
75120               hold >>>= 3;
75121               bits -= 3;
75122               //---//
75123             }
75124             while (state.have < 19) {
75125               state.lens[order[state.have++]] = 0;
75126             }
75127             // We have separate tables & no pointers. 2 commented lines below not needed.
75128             //state.next = state.codes;
75129             //state.lencode = state.next;
75130             // Switch to use dynamic table
75131             state.lencode = state.lendyn;
75132             state.lenbits = 7;
75133
75134             opts = { bits: state.lenbits };
75135             ret = inftrees(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);
75136             state.lenbits = opts.bits;
75137
75138             if (ret) {
75139               strm.msg = 'invalid code lengths set';
75140               state.mode = BAD;
75141               break;
75142             }
75143             //Tracev((stderr, "inflate:       code lengths ok\n"));
75144             state.have = 0;
75145             state.mode = CODELENS;
75146             /* falls through */
75147           case CODELENS:
75148             while (state.have < state.nlen + state.ndist) {
75149               for (;;) {
75150                 here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
75151                 here_bits = here >>> 24;
75152                 here_op = (here >>> 16) & 0xff;
75153                 here_val = here & 0xffff;
75154
75155                 if ((here_bits) <= bits) { break; }
75156                 //--- PULLBYTE() ---//
75157                 if (have === 0) { break inf_leave; }
75158                 have--;
75159                 hold += input[next++] << bits;
75160                 bits += 8;
75161                 //---//
75162               }
75163               if (here_val < 16) {
75164                 //--- DROPBITS(here.bits) ---//
75165                 hold >>>= here_bits;
75166                 bits -= here_bits;
75167                 //---//
75168                 state.lens[state.have++] = here_val;
75169               }
75170               else {
75171                 if (here_val === 16) {
75172                   //=== NEEDBITS(here.bits + 2);
75173                   n = here_bits + 2;
75174                   while (bits < n) {
75175                     if (have === 0) { break inf_leave; }
75176                     have--;
75177                     hold += input[next++] << bits;
75178                     bits += 8;
75179                   }
75180                   //===//
75181                   //--- DROPBITS(here.bits) ---//
75182                   hold >>>= here_bits;
75183                   bits -= here_bits;
75184                   //---//
75185                   if (state.have === 0) {
75186                     strm.msg = 'invalid bit length repeat';
75187                     state.mode = BAD;
75188                     break;
75189                   }
75190                   len = state.lens[state.have - 1];
75191                   copy = 3 + (hold & 0x03);//BITS(2);
75192                   //--- DROPBITS(2) ---//
75193                   hold >>>= 2;
75194                   bits -= 2;
75195                   //---//
75196                 }
75197                 else if (here_val === 17) {
75198                   //=== NEEDBITS(here.bits + 3);
75199                   n = here_bits + 3;
75200                   while (bits < n) {
75201                     if (have === 0) { break inf_leave; }
75202                     have--;
75203                     hold += input[next++] << bits;
75204                     bits += 8;
75205                   }
75206                   //===//
75207                   //--- DROPBITS(here.bits) ---//
75208                   hold >>>= here_bits;
75209                   bits -= here_bits;
75210                   //---//
75211                   len = 0;
75212                   copy = 3 + (hold & 0x07);//BITS(3);
75213                   //--- DROPBITS(3) ---//
75214                   hold >>>= 3;
75215                   bits -= 3;
75216                   //---//
75217                 }
75218                 else {
75219                   //=== NEEDBITS(here.bits + 7);
75220                   n = here_bits + 7;
75221                   while (bits < n) {
75222                     if (have === 0) { break inf_leave; }
75223                     have--;
75224                     hold += input[next++] << bits;
75225                     bits += 8;
75226                   }
75227                   //===//
75228                   //--- DROPBITS(here.bits) ---//
75229                   hold >>>= here_bits;
75230                   bits -= here_bits;
75231                   //---//
75232                   len = 0;
75233                   copy = 11 + (hold & 0x7f);//BITS(7);
75234                   //--- DROPBITS(7) ---//
75235                   hold >>>= 7;
75236                   bits -= 7;
75237                   //---//
75238                 }
75239                 if (state.have + copy > state.nlen + state.ndist) {
75240                   strm.msg = 'invalid bit length repeat';
75241                   state.mode = BAD;
75242                   break;
75243                 }
75244                 while (copy--) {
75245                   state.lens[state.have++] = len;
75246                 }
75247               }
75248             }
75249
75250             /* handle error breaks in while */
75251             if (state.mode === BAD) { break; }
75252
75253             /* check for end-of-block code (better have one) */
75254             if (state.lens[256] === 0) {
75255               strm.msg = 'invalid code -- missing end-of-block';
75256               state.mode = BAD;
75257               break;
75258             }
75259
75260             /* build code tables -- note: do not change the lenbits or distbits
75261                values here (9 and 6) without reading the comments in inftrees.h
75262                concerning the ENOUGH constants, which depend on those values */
75263             state.lenbits = 9;
75264
75265             opts = { bits: state.lenbits };
75266             ret = inftrees(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
75267             // We have separate tables & no pointers. 2 commented lines below not needed.
75268             // state.next_index = opts.table_index;
75269             state.lenbits = opts.bits;
75270             // state.lencode = state.next;
75271
75272             if (ret) {
75273               strm.msg = 'invalid literal/lengths set';
75274               state.mode = BAD;
75275               break;
75276             }
75277
75278             state.distbits = 6;
75279             //state.distcode.copy(state.codes);
75280             // Switch to use dynamic table
75281             state.distcode = state.distdyn;
75282             opts = { bits: state.distbits };
75283             ret = inftrees(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
75284             // We have separate tables & no pointers. 2 commented lines below not needed.
75285             // state.next_index = opts.table_index;
75286             state.distbits = opts.bits;
75287             // state.distcode = state.next;
75288
75289             if (ret) {
75290               strm.msg = 'invalid distances set';
75291               state.mode = BAD;
75292               break;
75293             }
75294             //Tracev((stderr, 'inflate:       codes ok\n'));
75295             state.mode = LEN_;
75296             if (flush === Z_TREES) { break inf_leave; }
75297             /* falls through */
75298           case LEN_:
75299             state.mode = LEN;
75300             /* falls through */
75301           case LEN:
75302             if (have >= 6 && left >= 258) {
75303               //--- RESTORE() ---
75304               strm.next_out = put;
75305               strm.avail_out = left;
75306               strm.next_in = next;
75307               strm.avail_in = have;
75308               state.hold = hold;
75309               state.bits = bits;
75310               //---
75311               inffast(strm, _out);
75312               //--- LOAD() ---
75313               put = strm.next_out;
75314               output = strm.output;
75315               left = strm.avail_out;
75316               next = strm.next_in;
75317               input = strm.input;
75318               have = strm.avail_in;
75319               hold = state.hold;
75320               bits = state.bits;
75321               //---
75322
75323               if (state.mode === TYPE) {
75324                 state.back = -1;
75325               }
75326               break;
75327             }
75328             state.back = 0;
75329             for (;;) {
75330               here = state.lencode[hold & ((1 << state.lenbits) - 1)];  /*BITS(state.lenbits)*/
75331               here_bits = here >>> 24;
75332               here_op = (here >>> 16) & 0xff;
75333               here_val = here & 0xffff;
75334
75335               if (here_bits <= bits) { break; }
75336               //--- PULLBYTE() ---//
75337               if (have === 0) { break inf_leave; }
75338               have--;
75339               hold += input[next++] << bits;
75340               bits += 8;
75341               //---//
75342             }
75343             if (here_op && (here_op & 0xf0) === 0) {
75344               last_bits = here_bits;
75345               last_op = here_op;
75346               last_val = here_val;
75347               for (;;) {
75348                 here = state.lencode[last_val +
75349                         ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
75350                 here_bits = here >>> 24;
75351                 here_op = (here >>> 16) & 0xff;
75352                 here_val = here & 0xffff;
75353
75354                 if ((last_bits + here_bits) <= bits) { break; }
75355                 //--- PULLBYTE() ---//
75356                 if (have === 0) { break inf_leave; }
75357                 have--;
75358                 hold += input[next++] << bits;
75359                 bits += 8;
75360                 //---//
75361               }
75362               //--- DROPBITS(last.bits) ---//
75363               hold >>>= last_bits;
75364               bits -= last_bits;
75365               //---//
75366               state.back += last_bits;
75367             }
75368             //--- DROPBITS(here.bits) ---//
75369             hold >>>= here_bits;
75370             bits -= here_bits;
75371             //---//
75372             state.back += here_bits;
75373             state.length = here_val;
75374             if (here_op === 0) {
75375               //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
75376               //        "inflate:         literal '%c'\n" :
75377               //        "inflate:         literal 0x%02x\n", here.val));
75378               state.mode = LIT;
75379               break;
75380             }
75381             if (here_op & 32) {
75382               //Tracevv((stderr, "inflate:         end of block\n"));
75383               state.back = -1;
75384               state.mode = TYPE;
75385               break;
75386             }
75387             if (here_op & 64) {
75388               strm.msg = 'invalid literal/length code';
75389               state.mode = BAD;
75390               break;
75391             }
75392             state.extra = here_op & 15;
75393             state.mode = LENEXT;
75394             /* falls through */
75395           case LENEXT:
75396             if (state.extra) {
75397               //=== NEEDBITS(state.extra);
75398               n = state.extra;
75399               while (bits < n) {
75400                 if (have === 0) { break inf_leave; }
75401                 have--;
75402                 hold += input[next++] << bits;
75403                 bits += 8;
75404               }
75405               //===//
75406               state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
75407               //--- DROPBITS(state.extra) ---//
75408               hold >>>= state.extra;
75409               bits -= state.extra;
75410               //---//
75411               state.back += state.extra;
75412             }
75413             //Tracevv((stderr, "inflate:         length %u\n", state.length));
75414             state.was = state.length;
75415             state.mode = DIST;
75416             /* falls through */
75417           case DIST:
75418             for (;;) {
75419               here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/
75420               here_bits = here >>> 24;
75421               here_op = (here >>> 16) & 0xff;
75422               here_val = here & 0xffff;
75423
75424               if ((here_bits) <= bits) { break; }
75425               //--- PULLBYTE() ---//
75426               if (have === 0) { break inf_leave; }
75427               have--;
75428               hold += input[next++] << bits;
75429               bits += 8;
75430               //---//
75431             }
75432             if ((here_op & 0xf0) === 0) {
75433               last_bits = here_bits;
75434               last_op = here_op;
75435               last_val = here_val;
75436               for (;;) {
75437                 here = state.distcode[last_val +
75438                         ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
75439                 here_bits = here >>> 24;
75440                 here_op = (here >>> 16) & 0xff;
75441                 here_val = here & 0xffff;
75442
75443                 if ((last_bits + here_bits) <= bits) { break; }
75444                 //--- PULLBYTE() ---//
75445                 if (have === 0) { break inf_leave; }
75446                 have--;
75447                 hold += input[next++] << bits;
75448                 bits += 8;
75449                 //---//
75450               }
75451               //--- DROPBITS(last.bits) ---//
75452               hold >>>= last_bits;
75453               bits -= last_bits;
75454               //---//
75455               state.back += last_bits;
75456             }
75457             //--- DROPBITS(here.bits) ---//
75458             hold >>>= here_bits;
75459             bits -= here_bits;
75460             //---//
75461             state.back += here_bits;
75462             if (here_op & 64) {
75463               strm.msg = 'invalid distance code';
75464               state.mode = BAD;
75465               break;
75466             }
75467             state.offset = here_val;
75468             state.extra = (here_op) & 15;
75469             state.mode = DISTEXT;
75470             /* falls through */
75471           case DISTEXT:
75472             if (state.extra) {
75473               //=== NEEDBITS(state.extra);
75474               n = state.extra;
75475               while (bits < n) {
75476                 if (have === 0) { break inf_leave; }
75477                 have--;
75478                 hold += input[next++] << bits;
75479                 bits += 8;
75480               }
75481               //===//
75482               state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
75483               //--- DROPBITS(state.extra) ---//
75484               hold >>>= state.extra;
75485               bits -= state.extra;
75486               //---//
75487               state.back += state.extra;
75488             }
75489     //#ifdef INFLATE_STRICT
75490             if (state.offset > state.dmax) {
75491               strm.msg = 'invalid distance too far back';
75492               state.mode = BAD;
75493               break;
75494             }
75495     //#endif
75496             //Tracevv((stderr, "inflate:         distance %u\n", state.offset));
75497             state.mode = MATCH;
75498             /* falls through */
75499           case MATCH:
75500             if (left === 0) { break inf_leave; }
75501             copy = _out - left;
75502             if (state.offset > copy) {         /* copy from window */
75503               copy = state.offset - copy;
75504               if (copy > state.whave) {
75505                 if (state.sane) {
75506                   strm.msg = 'invalid distance too far back';
75507                   state.mode = BAD;
75508                   break;
75509                 }
75510     // (!) This block is disabled in zlib defaults,
75511     // don't enable it for binary compatibility
75512     //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
75513     //          Trace((stderr, "inflate.c too far\n"));
75514     //          copy -= state.whave;
75515     //          if (copy > state.length) { copy = state.length; }
75516     //          if (copy > left) { copy = left; }
75517     //          left -= copy;
75518     //          state.length -= copy;
75519     //          do {
75520     //            output[put++] = 0;
75521     //          } while (--copy);
75522     //          if (state.length === 0) { state.mode = LEN; }
75523     //          break;
75524     //#endif
75525               }
75526               if (copy > state.wnext) {
75527                 copy -= state.wnext;
75528                 from = state.wsize - copy;
75529               }
75530               else {
75531                 from = state.wnext - copy;
75532               }
75533               if (copy > state.length) { copy = state.length; }
75534               from_source = state.window;
75535             }
75536             else {                              /* copy from output */
75537               from_source = output;
75538               from = put - state.offset;
75539               copy = state.length;
75540             }
75541             if (copy > left) { copy = left; }
75542             left -= copy;
75543             state.length -= copy;
75544             do {
75545               output[put++] = from_source[from++];
75546             } while (--copy);
75547             if (state.length === 0) { state.mode = LEN; }
75548             break;
75549           case LIT:
75550             if (left === 0) { break inf_leave; }
75551             output[put++] = state.length;
75552             left--;
75553             state.mode = LEN;
75554             break;
75555           case CHECK:
75556             if (state.wrap) {
75557               //=== NEEDBITS(32);
75558               while (bits < 32) {
75559                 if (have === 0) { break inf_leave; }
75560                 have--;
75561                 // Use '|' instead of '+' to make sure that result is signed
75562                 hold |= input[next++] << bits;
75563                 bits += 8;
75564               }
75565               //===//
75566               _out -= left;
75567               strm.total_out += _out;
75568               state.total += _out;
75569               if (_out) {
75570                 strm.adler = state.check =
75571                     /*UPDATE(state.check, put - _out, _out);*/
75572                     (state.flags ? crc32_1(state.check, output, _out, put - _out) : adler32_1(state.check, output, _out, put - _out));
75573
75574               }
75575               _out = left;
75576               // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too
75577               if ((state.flags ? hold : zswap32(hold)) !== state.check) {
75578                 strm.msg = 'incorrect data check';
75579                 state.mode = BAD;
75580                 break;
75581               }
75582               //=== INITBITS();
75583               hold = 0;
75584               bits = 0;
75585               //===//
75586               //Tracev((stderr, "inflate:   check matches trailer\n"));
75587             }
75588             state.mode = LENGTH;
75589             /* falls through */
75590           case LENGTH:
75591             if (state.wrap && state.flags) {
75592               //=== NEEDBITS(32);
75593               while (bits < 32) {
75594                 if (have === 0) { break inf_leave; }
75595                 have--;
75596                 hold += input[next++] << bits;
75597                 bits += 8;
75598               }
75599               //===//
75600               if (hold !== (state.total & 0xffffffff)) {
75601                 strm.msg = 'incorrect length check';
75602                 state.mode = BAD;
75603                 break;
75604               }
75605               //=== INITBITS();
75606               hold = 0;
75607               bits = 0;
75608               //===//
75609               //Tracev((stderr, "inflate:   length matches trailer\n"));
75610             }
75611             state.mode = DONE;
75612             /* falls through */
75613           case DONE:
75614             ret = Z_STREAM_END$1;
75615             break inf_leave;
75616           case BAD:
75617             ret = Z_DATA_ERROR$1;
75618             break inf_leave;
75619           case MEM:
75620             return Z_MEM_ERROR$1;
75621           case SYNC:
75622             /* falls through */
75623           default:
75624             return Z_STREAM_ERROR$1;
75625         }
75626       }
75627
75628       // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"
75629
75630       /*
75631          Return from inflate(), updating the total counts and the check value.
75632          If there was no progress during the inflate() call, return a buffer
75633          error.  Call updatewindow() to create and/or update the window state.
75634          Note: a memory error from inflate() is non-recoverable.
75635        */
75636
75637       //--- RESTORE() ---
75638       strm.next_out = put;
75639       strm.avail_out = left;
75640       strm.next_in = next;
75641       strm.avail_in = have;
75642       state.hold = hold;
75643       state.bits = bits;
75644       //---
75645
75646       if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&
75647                           (state.mode < CHECK || flush !== Z_FINISH$1))) {
75648         if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ;
75649       }
75650       _in -= strm.avail_in;
75651       _out -= strm.avail_out;
75652       strm.total_in += _in;
75653       strm.total_out += _out;
75654       state.total += _out;
75655       if (state.wrap && _out) {
75656         strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/
75657           (state.flags ? crc32_1(state.check, output, _out, strm.next_out - _out) : adler32_1(state.check, output, _out, strm.next_out - _out));
75658       }
75659       strm.data_type = state.bits + (state.last ? 64 : 0) +
75660                         (state.mode === TYPE ? 128 : 0) +
75661                         (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
75662       if (((_in === 0 && _out === 0) || flush === Z_FINISH$1) && ret === Z_OK$1) {
75663         ret = Z_BUF_ERROR;
75664       }
75665       return ret;
75666     };
75667
75668
75669     const inflateEnd = (strm) => {
75670
75671       if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {
75672         return Z_STREAM_ERROR$1;
75673       }
75674
75675       let state = strm.state;
75676       if (state.window) {
75677         state.window = null;
75678       }
75679       strm.state = null;
75680       return Z_OK$1;
75681     };
75682
75683
75684     const inflateGetHeader = (strm, head) => {
75685
75686       /* check state */
75687       if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
75688       const state = strm.state;
75689       if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR$1; }
75690
75691       /* save header structure */
75692       state.head = head;
75693       head.done = false;
75694       return Z_OK$1;
75695     };
75696
75697
75698     const inflateSetDictionary = (strm, dictionary) => {
75699       const dictLength = dictionary.length;
75700
75701       let state;
75702       let dictid;
75703       let ret;
75704
75705       /* check state */
75706       if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR$1; }
75707       state = strm.state;
75708
75709       if (state.wrap !== 0 && state.mode !== DICT) {
75710         return Z_STREAM_ERROR$1;
75711       }
75712
75713       /* check for correct dictionary identifier */
75714       if (state.mode === DICT) {
75715         dictid = 1; /* adler32(0, null, 0)*/
75716         /* dictid = adler32(dictid, dictionary, dictLength); */
75717         dictid = adler32_1(dictid, dictionary, dictLength, 0);
75718         if (dictid !== state.check) {
75719           return Z_DATA_ERROR$1;
75720         }
75721       }
75722       /* copy dictionary to window using updatewindow(), which will amend the
75723        existing dictionary if appropriate */
75724       ret = updatewindow(strm, dictionary, dictLength, dictLength);
75725       if (ret) {
75726         state.mode = MEM;
75727         return Z_MEM_ERROR$1;
75728       }
75729       state.havedict = 1;
75730       // Tracev((stderr, "inflate:   dictionary set\n"));
75731       return Z_OK$1;
75732     };
75733
75734
75735     var inflateReset_1 = inflateReset;
75736     var inflateReset2_1 = inflateReset2;
75737     var inflateResetKeep_1 = inflateResetKeep;
75738     var inflateInit_1 = inflateInit;
75739     var inflateInit2_1 = inflateInit2;
75740     var inflate_2$1 = inflate$2;
75741     var inflateEnd_1 = inflateEnd;
75742     var inflateGetHeader_1 = inflateGetHeader;
75743     var inflateSetDictionary_1 = inflateSetDictionary;
75744     var inflateInfo = 'pako inflate (from Nodeca project)';
75745
75746     /* Not implemented
75747     module.exports.inflateCopy = inflateCopy;
75748     module.exports.inflateGetDictionary = inflateGetDictionary;
75749     module.exports.inflateMark = inflateMark;
75750     module.exports.inflatePrime = inflatePrime;
75751     module.exports.inflateSync = inflateSync;
75752     module.exports.inflateSyncPoint = inflateSyncPoint;
75753     module.exports.inflateUndermine = inflateUndermine;
75754     */
75755
75756     var inflate_1$2 = {
75757         inflateReset: inflateReset_1,
75758         inflateReset2: inflateReset2_1,
75759         inflateResetKeep: inflateResetKeep_1,
75760         inflateInit: inflateInit_1,
75761         inflateInit2: inflateInit2_1,
75762         inflate: inflate_2$1,
75763         inflateEnd: inflateEnd_1,
75764         inflateGetHeader: inflateGetHeader_1,
75765         inflateSetDictionary: inflateSetDictionary_1,
75766         inflateInfo: inflateInfo
75767     };
75768
75769     // (C) 1995-2013 Jean-loup Gailly and Mark Adler
75770     // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
75771     //
75772     // This software is provided 'as-is', without any express or implied
75773     // warranty. In no event will the authors be held liable for any damages
75774     // arising from the use of this software.
75775     //
75776     // Permission is granted to anyone to use this software for any purpose,
75777     // including commercial applications, and to alter it and redistribute it
75778     // freely, subject to the following restrictions:
75779     //
75780     // 1. The origin of this software must not be misrepresented; you must not
75781     //   claim that you wrote the original software. If you use this software
75782     //   in a product, an acknowledgment in the product documentation would be
75783     //   appreciated but is not required.
75784     // 2. Altered source versions must be plainly marked as such, and must not be
75785     //   misrepresented as being the original software.
75786     // 3. This notice may not be removed or altered from any source distribution.
75787
75788     function GZheader() {
75789       /* true if compressed data believed to be text */
75790       this.text       = 0;
75791       /* modification time */
75792       this.time       = 0;
75793       /* extra flags (not used when writing a gzip file) */
75794       this.xflags     = 0;
75795       /* operating system */
75796       this.os         = 0;
75797       /* pointer to extra field or Z_NULL if none */
75798       this.extra      = null;
75799       /* extra field length (valid if extra != Z_NULL) */
75800       this.extra_len  = 0; // Actually, we don't need it in JS,
75801                            // but leave for few code modifications
75802
75803       //
75804       // Setup limits is not necessary because in js we should not preallocate memory
75805       // for inflate use constant limit in 65536 bytes
75806       //
75807
75808       /* space at extra (only when reading header) */
75809       // this.extra_max  = 0;
75810       /* pointer to zero-terminated file name or Z_NULL */
75811       this.name       = '';
75812       /* space at name (only when reading header) */
75813       // this.name_max   = 0;
75814       /* pointer to zero-terminated comment or Z_NULL */
75815       this.comment    = '';
75816       /* space at comment (only when reading header) */
75817       // this.comm_max   = 0;
75818       /* true if there was or will be a header crc */
75819       this.hcrc       = 0;
75820       /* true when done reading gzip header (not used when writing a gzip file) */
75821       this.done       = false;
75822     }
75823
75824     var gzheader = GZheader;
75825
75826     const toString = Object.prototype.toString;
75827
75828     /* Public constants ==========================================================*/
75829     /* ===========================================================================*/
75830
75831     const {
75832       Z_NO_FLUSH, Z_FINISH,
75833       Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR
75834     } = constants$2;
75835
75836     /* ===========================================================================*/
75837
75838
75839     /**
75840      * class Inflate
75841      *
75842      * Generic JS-style wrapper for zlib calls. If you don't need
75843      * streaming behaviour - use more simple functions: [[inflate]]
75844      * and [[inflateRaw]].
75845      **/
75846
75847     /* internal
75848      * inflate.chunks -> Array
75849      *
75850      * Chunks of output data, if [[Inflate#onData]] not overridden.
75851      **/
75852
75853     /**
75854      * Inflate.result -> Uint8Array|String
75855      *
75856      * Uncompressed result, generated by default [[Inflate#onData]]
75857      * and [[Inflate#onEnd]] handlers. Filled after you push last chunk
75858      * (call [[Inflate#push]] with `Z_FINISH` / `true` param).
75859      **/
75860
75861     /**
75862      * Inflate.err -> Number
75863      *
75864      * Error code after inflate finished. 0 (Z_OK) on success.
75865      * Should be checked if broken data possible.
75866      **/
75867
75868     /**
75869      * Inflate.msg -> String
75870      *
75871      * Error message, if [[Inflate.err]] != 0
75872      **/
75873
75874
75875     /**
75876      * new Inflate(options)
75877      * - options (Object): zlib inflate options.
75878      *
75879      * Creates new inflator instance with specified params. Throws exception
75880      * on bad params. Supported options:
75881      *
75882      * - `windowBits`
75883      * - `dictionary`
75884      *
75885      * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
75886      * for more information on these.
75887      *
75888      * Additional options, for internal needs:
75889      *
75890      * - `chunkSize` - size of generated data chunks (16K by default)
75891      * - `raw` (Boolean) - do raw inflate
75892      * - `to` (String) - if equal to 'string', then result will be converted
75893      *   from utf8 to utf16 (javascript) string. When string output requested,
75894      *   chunk length can differ from `chunkSize`, depending on content.
75895      *
75896      * By default, when no options set, autodetect deflate/gzip data format via
75897      * wrapper header.
75898      *
75899      * ##### Example:
75900      *
75901      * ```javascript
75902      * const pako = require('pako')
75903      * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])
75904      * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);
75905      *
75906      * const inflate = new pako.Inflate({ level: 3});
75907      *
75908      * inflate.push(chunk1, false);
75909      * inflate.push(chunk2, true);  // true -> last chunk
75910      *
75911      * if (inflate.err) { throw new Error(inflate.err); }
75912      *
75913      * console.log(inflate.result);
75914      * ```
75915      **/
75916     function Inflate$1(options) {
75917       this.options = common.assign({
75918         chunkSize: 1024 * 64,
75919         windowBits: 15,
75920         to: ''
75921       }, options || {});
75922
75923       const opt = this.options;
75924
75925       // Force window size for `raw` data, if not set directly,
75926       // because we have no header for autodetect.
75927       if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {
75928         opt.windowBits = -opt.windowBits;
75929         if (opt.windowBits === 0) { opt.windowBits = -15; }
75930       }
75931
75932       // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate
75933       if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&
75934           !(options && options.windowBits)) {
75935         opt.windowBits += 32;
75936       }
75937
75938       // Gzip header has no info about windows size, we can do autodetect only
75939       // for deflate. So, if window size not set, force it to max when gzip possible
75940       if ((opt.windowBits > 15) && (opt.windowBits < 48)) {
75941         // bit 3 (16) -> gzipped data
75942         // bit 4 (32) -> autodetect gzip/deflate
75943         if ((opt.windowBits & 15) === 0) {
75944           opt.windowBits |= 15;
75945         }
75946       }
75947
75948       this.err    = 0;      // error code, if happens (0 = Z_OK)
75949       this.msg    = '';     // error message
75950       this.ended  = false;  // used to avoid multiple onEnd() calls
75951       this.chunks = [];     // chunks of compressed data
75952
75953       this.strm   = new zstream();
75954       this.strm.avail_out = 0;
75955
75956       let status  = inflate_1$2.inflateInit2(
75957         this.strm,
75958         opt.windowBits
75959       );
75960
75961       if (status !== Z_OK) {
75962         throw new Error(messages[status]);
75963       }
75964
75965       this.header = new gzheader();
75966
75967       inflate_1$2.inflateGetHeader(this.strm, this.header);
75968
75969       // Setup dictionary
75970       if (opt.dictionary) {
75971         // Convert data if needed
75972         if (typeof opt.dictionary === 'string') {
75973           opt.dictionary = strings.string2buf(opt.dictionary);
75974         } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {
75975           opt.dictionary = new Uint8Array(opt.dictionary);
75976         }
75977         if (opt.raw) { //In raw mode we need to set the dictionary early
75978           status = inflate_1$2.inflateSetDictionary(this.strm, opt.dictionary);
75979           if (status !== Z_OK) {
75980             throw new Error(messages[status]);
75981           }
75982         }
75983       }
75984     }
75985
75986     /**
75987      * Inflate#push(data[, flush_mode]) -> Boolean
75988      * - data (Uint8Array|ArrayBuffer): input data
75989      * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE
75990      *   flush modes. See constants. Skipped or `false` means Z_NO_FLUSH,
75991      *   `true` means Z_FINISH.
75992      *
75993      * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
75994      * new output chunks. Returns `true` on success. If end of stream detected,
75995      * [[Inflate#onEnd]] will be called.
75996      *
75997      * `flush_mode` is not needed for normal operation, because end of stream
75998      * detected automatically. You may try to use it for advanced things, but
75999      * this functionality was not tested.
76000      *
76001      * On fail call [[Inflate#onEnd]] with error code and return false.
76002      *
76003      * ##### Example
76004      *
76005      * ```javascript
76006      * push(chunk, false); // push one of data chunks
76007      * ...
76008      * push(chunk, true);  // push last chunk
76009      * ```
76010      **/
76011     Inflate$1.prototype.push = function (data, flush_mode) {
76012       const strm = this.strm;
76013       const chunkSize = this.options.chunkSize;
76014       const dictionary = this.options.dictionary;
76015       let status, _flush_mode, last_avail_out;
76016
76017       if (this.ended) return false;
76018
76019       if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
76020       else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH;
76021
76022       // Convert data if needed
76023       if (toString.call(data) === '[object ArrayBuffer]') {
76024         strm.input = new Uint8Array(data);
76025       } else {
76026         strm.input = data;
76027       }
76028
76029       strm.next_in = 0;
76030       strm.avail_in = strm.input.length;
76031
76032       for (;;) {
76033         if (strm.avail_out === 0) {
76034           strm.output = new Uint8Array(chunkSize);
76035           strm.next_out = 0;
76036           strm.avail_out = chunkSize;
76037         }
76038
76039         status = inflate_1$2.inflate(strm, _flush_mode);
76040
76041         if (status === Z_NEED_DICT && dictionary) {
76042           status = inflate_1$2.inflateSetDictionary(strm, dictionary);
76043
76044           if (status === Z_OK) {
76045             status = inflate_1$2.inflate(strm, _flush_mode);
76046           } else if (status === Z_DATA_ERROR) {
76047             // Replace code with more verbose
76048             status = Z_NEED_DICT;
76049           }
76050         }
76051
76052         // Skip snyc markers if more data follows and not raw mode
76053         while (strm.avail_in > 0 &&
76054                status === Z_STREAM_END &&
76055                strm.state.wrap > 0 &&
76056                data[strm.next_in] !== 0)
76057         {
76058           inflate_1$2.inflateReset(strm);
76059           status = inflate_1$2.inflate(strm, _flush_mode);
76060         }
76061
76062         switch (status) {
76063           case Z_STREAM_ERROR:
76064           case Z_DATA_ERROR:
76065           case Z_NEED_DICT:
76066           case Z_MEM_ERROR:
76067             this.onEnd(status);
76068             this.ended = true;
76069             return false;
76070         }
76071
76072         // Remember real `avail_out` value, because we may patch out buffer content
76073         // to align utf8 strings boundaries.
76074         last_avail_out = strm.avail_out;
76075
76076         if (strm.next_out) {
76077           if (strm.avail_out === 0 || status === Z_STREAM_END) {
76078
76079             if (this.options.to === 'string') {
76080
76081               let next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
76082
76083               let tail = strm.next_out - next_out_utf8;
76084               let utf8str = strings.buf2string(strm.output, next_out_utf8);
76085
76086               // move tail & realign counters
76087               strm.next_out = tail;
76088               strm.avail_out = chunkSize - tail;
76089               if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0);
76090
76091               this.onData(utf8str);
76092
76093             } else {
76094               this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out));
76095             }
76096           }
76097         }
76098
76099         // Must repeat iteration if out buffer is full
76100         if (status === Z_OK && last_avail_out === 0) continue;
76101
76102         // Finalize if end of stream reached.
76103         if (status === Z_STREAM_END) {
76104           status = inflate_1$2.inflateEnd(this.strm);
76105           this.onEnd(status);
76106           this.ended = true;
76107           return true;
76108         }
76109
76110         if (strm.avail_in === 0) break;
76111       }
76112
76113       return true;
76114     };
76115
76116
76117     /**
76118      * Inflate#onData(chunk) -> Void
76119      * - chunk (Uint8Array|String): output data. When string output requested,
76120      *   each chunk will be string.
76121      *
76122      * By default, stores data blocks in `chunks[]` property and glue
76123      * those in `onEnd`. Override this handler, if you need another behaviour.
76124      **/
76125     Inflate$1.prototype.onData = function (chunk) {
76126       this.chunks.push(chunk);
76127     };
76128
76129
76130     /**
76131      * Inflate#onEnd(status) -> Void
76132      * - status (Number): inflate status. 0 (Z_OK) on success,
76133      *   other if not.
76134      *
76135      * Called either after you tell inflate that the input stream is
76136      * complete (Z_FINISH). By default - join collected chunks,
76137      * free memory and fill `results` / `err` properties.
76138      **/
76139     Inflate$1.prototype.onEnd = function (status) {
76140       // On success - join
76141       if (status === Z_OK) {
76142         if (this.options.to === 'string') {
76143           this.result = this.chunks.join('');
76144         } else {
76145           this.result = common.flattenChunks(this.chunks);
76146         }
76147       }
76148       this.chunks = [];
76149       this.err = status;
76150       this.msg = this.strm.msg;
76151     };
76152
76153
76154     /**
76155      * inflate(data[, options]) -> Uint8Array|String
76156      * - data (Uint8Array): input data to decompress.
76157      * - options (Object): zlib inflate options.
76158      *
76159      * Decompress `data` with inflate/ungzip and `options`. Autodetect
76160      * format via wrapper header by default. That's why we don't provide
76161      * separate `ungzip` method.
76162      *
76163      * Supported options are:
76164      *
76165      * - windowBits
76166      *
76167      * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
76168      * for more information.
76169      *
76170      * Sugar (options):
76171      *
76172      * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
76173      *   negative windowBits implicitly.
76174      * - `to` (String) - if equal to 'string', then result will be converted
76175      *   from utf8 to utf16 (javascript) string. When string output requested,
76176      *   chunk length can differ from `chunkSize`, depending on content.
76177      *
76178      *
76179      * ##### Example:
76180      *
76181      * ```javascript
76182      * const pako = require('pako');
76183      * const input = pako.deflate(new Uint8Array([1,2,3,4,5,6,7,8,9]));
76184      * let output;
76185      *
76186      * try {
76187      *   output = pako.inflate(input);
76188      * } catch (err) {
76189      *   console.log(err);
76190      * }
76191      * ```
76192      **/
76193     function inflate$1(input, options) {
76194       const inflator = new Inflate$1(options);
76195
76196       inflator.push(input);
76197
76198       // That will never happens, if you don't cheat with options :)
76199       if (inflator.err) throw inflator.msg || messages[inflator.err];
76200
76201       return inflator.result;
76202     }
76203
76204
76205     /**
76206      * inflateRaw(data[, options]) -> Uint8Array|String
76207      * - data (Uint8Array): input data to decompress.
76208      * - options (Object): zlib inflate options.
76209      *
76210      * The same as [[inflate]], but creates raw data, without wrapper
76211      * (header and adler32 crc).
76212      **/
76213     function inflateRaw$1(input, options) {
76214       options = options || {};
76215       options.raw = true;
76216       return inflate$1(input, options);
76217     }
76218
76219
76220     /**
76221      * ungzip(data[, options]) -> Uint8Array|String
76222      * - data (Uint8Array): input data to decompress.
76223      * - options (Object): zlib inflate options.
76224      *
76225      * Just shortcut to [[inflate]], because it autodetects format
76226      * by header.content. Done for convenience.
76227      **/
76228
76229
76230     var Inflate_1$1 = Inflate$1;
76231     var inflate_2 = inflate$1;
76232     var inflateRaw_1$1 = inflateRaw$1;
76233     var ungzip$1 = inflate$1;
76234     var constants = constants$2;
76235
76236     var inflate_1$1 = {
76237         Inflate: Inflate_1$1,
76238         inflate: inflate_2,
76239         inflateRaw: inflateRaw_1$1,
76240         ungzip: ungzip$1,
76241         constants: constants
76242     };
76243
76244     const { Inflate, inflate, inflateRaw, ungzip } = inflate_1$1;
76245     var inflate_1 = inflate;
76246
76247     var ieee754$1 = {};
76248
76249     /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
76250
76251     ieee754$1.read = function (buffer, offset, isLE, mLen, nBytes) {
76252       var e, m;
76253       var eLen = (nBytes * 8) - mLen - 1;
76254       var eMax = (1 << eLen) - 1;
76255       var eBias = eMax >> 1;
76256       var nBits = -7;
76257       var i = isLE ? (nBytes - 1) : 0;
76258       var d = isLE ? -1 : 1;
76259       var s = buffer[offset + i];
76260
76261       i += d;
76262
76263       e = s & ((1 << (-nBits)) - 1);
76264       s >>= (-nBits);
76265       nBits += eLen;
76266       for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
76267
76268       m = e & ((1 << (-nBits)) - 1);
76269       e >>= (-nBits);
76270       nBits += mLen;
76271       for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
76272
76273       if (e === 0) {
76274         e = 1 - eBias;
76275       } else if (e === eMax) {
76276         return m ? NaN : ((s ? -1 : 1) * Infinity)
76277       } else {
76278         m = m + Math.pow(2, mLen);
76279         e = e - eBias;
76280       }
76281       return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
76282     };
76283
76284     ieee754$1.write = function (buffer, value, offset, isLE, mLen, nBytes) {
76285       var e, m, c;
76286       var eLen = (nBytes * 8) - mLen - 1;
76287       var eMax = (1 << eLen) - 1;
76288       var eBias = eMax >> 1;
76289       var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0);
76290       var i = isLE ? 0 : (nBytes - 1);
76291       var d = isLE ? 1 : -1;
76292       var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
76293
76294       value = Math.abs(value);
76295
76296       if (isNaN(value) || value === Infinity) {
76297         m = isNaN(value) ? 1 : 0;
76298         e = eMax;
76299       } else {
76300         e = Math.floor(Math.log(value) / Math.LN2);
76301         if (value * (c = Math.pow(2, -e)) < 1) {
76302           e--;
76303           c *= 2;
76304         }
76305         if (e + eBias >= 1) {
76306           value += rt / c;
76307         } else {
76308           value += rt * Math.pow(2, 1 - eBias);
76309         }
76310         if (value * c >= 2) {
76311           e++;
76312           c /= 2;
76313         }
76314
76315         if (e + eBias >= eMax) {
76316           m = 0;
76317           e = eMax;
76318         } else if (e + eBias >= 1) {
76319           m = ((value * c) - 1) * Math.pow(2, mLen);
76320           e = e + eBias;
76321         } else {
76322           m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
76323           e = 0;
76324         }
76325       }
76326
76327       for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
76328
76329       e = (e << mLen) | m;
76330       eLen += mLen;
76331       for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
76332
76333       buffer[offset + i - d] |= s * 128;
76334     };
76335
76336     var pbf = Pbf;
76337
76338     var ieee754 = ieee754$1;
76339
76340     function Pbf(buf) {
76341         this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf || 0);
76342         this.pos = 0;
76343         this.type = 0;
76344         this.length = this.buf.length;
76345     }
76346
76347     Pbf.Varint  = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
76348     Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64
76349     Pbf.Bytes   = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields
76350     Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32
76351
76352     var SHIFT_LEFT_32 = (1 << 16) * (1 << 16),
76353         SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;
76354
76355     // Threshold chosen based on both benchmarking and knowledge about browser string
76356     // data structures (which currently switch structure types at 12 bytes or more)
76357     var TEXT_DECODER_MIN_LENGTH = 12;
76358     var utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf8');
76359
76360     Pbf.prototype = {
76361
76362         destroy: function() {
76363             this.buf = null;
76364         },
76365
76366         // === READING =================================================================
76367
76368         readFields: function(readField, result, end) {
76369             end = end || this.length;
76370
76371             while (this.pos < end) {
76372                 var val = this.readVarint(),
76373                     tag = val >> 3,
76374                     startPos = this.pos;
76375
76376                 this.type = val & 0x7;
76377                 readField(tag, result, this);
76378
76379                 if (this.pos === startPos) this.skip(val);
76380             }
76381             return result;
76382         },
76383
76384         readMessage: function(readField, result) {
76385             return this.readFields(readField, result, this.readVarint() + this.pos);
76386         },
76387
76388         readFixed32: function() {
76389             var val = readUInt32(this.buf, this.pos);
76390             this.pos += 4;
76391             return val;
76392         },
76393
76394         readSFixed32: function() {
76395             var val = readInt32(this.buf, this.pos);
76396             this.pos += 4;
76397             return val;
76398         },
76399
76400         // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
76401
76402         readFixed64: function() {
76403             var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
76404             this.pos += 8;
76405             return val;
76406         },
76407
76408         readSFixed64: function() {
76409             var val = readUInt32(this.buf, this.pos) + readInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
76410             this.pos += 8;
76411             return val;
76412         },
76413
76414         readFloat: function() {
76415             var val = ieee754.read(this.buf, this.pos, true, 23, 4);
76416             this.pos += 4;
76417             return val;
76418         },
76419
76420         readDouble: function() {
76421             var val = ieee754.read(this.buf, this.pos, true, 52, 8);
76422             this.pos += 8;
76423             return val;
76424         },
76425
76426         readVarint: function(isSigned) {
76427             var buf = this.buf,
76428                 val, b;
76429
76430             b = buf[this.pos++]; val  =  b & 0x7f;        if (b < 0x80) return val;
76431             b = buf[this.pos++]; val |= (b & 0x7f) << 7;  if (b < 0x80) return val;
76432             b = buf[this.pos++]; val |= (b & 0x7f) << 14; if (b < 0x80) return val;
76433             b = buf[this.pos++]; val |= (b & 0x7f) << 21; if (b < 0x80) return val;
76434             b = buf[this.pos];   val |= (b & 0x0f) << 28;
76435
76436             return readVarintRemainder(val, isSigned, this);
76437         },
76438
76439         readVarint64: function() { // for compatibility with v2.0.1
76440             return this.readVarint(true);
76441         },
76442
76443         readSVarint: function() {
76444             var num = this.readVarint();
76445             return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding
76446         },
76447
76448         readBoolean: function() {
76449             return Boolean(this.readVarint());
76450         },
76451
76452         readString: function() {
76453             var end = this.readVarint() + this.pos;
76454             var pos = this.pos;
76455             this.pos = end;
76456
76457             if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {
76458                 // longer strings are fast with the built-in browser TextDecoder API
76459                 return readUtf8TextDecoder(this.buf, pos, end);
76460             }
76461             // short strings are fast with our custom implementation
76462             return readUtf8(this.buf, pos, end);
76463         },
76464
76465         readBytes: function() {
76466             var end = this.readVarint() + this.pos,
76467                 buffer = this.buf.subarray(this.pos, end);
76468             this.pos = end;
76469             return buffer;
76470         },
76471
76472         // verbose for performance reasons; doesn't affect gzipped size
76473
76474         readPackedVarint: function(arr, isSigned) {
76475             if (this.type !== Pbf.Bytes) return arr.push(this.readVarint(isSigned));
76476             var end = readPackedEnd(this);
76477             arr = arr || [];
76478             while (this.pos < end) arr.push(this.readVarint(isSigned));
76479             return arr;
76480         },
76481         readPackedSVarint: function(arr) {
76482             if (this.type !== Pbf.Bytes) return arr.push(this.readSVarint());
76483             var end = readPackedEnd(this);
76484             arr = arr || [];
76485             while (this.pos < end) arr.push(this.readSVarint());
76486             return arr;
76487         },
76488         readPackedBoolean: function(arr) {
76489             if (this.type !== Pbf.Bytes) return arr.push(this.readBoolean());
76490             var end = readPackedEnd(this);
76491             arr = arr || [];
76492             while (this.pos < end) arr.push(this.readBoolean());
76493             return arr;
76494         },
76495         readPackedFloat: function(arr) {
76496             if (this.type !== Pbf.Bytes) return arr.push(this.readFloat());
76497             var end = readPackedEnd(this);
76498             arr = arr || [];
76499             while (this.pos < end) arr.push(this.readFloat());
76500             return arr;
76501         },
76502         readPackedDouble: function(arr) {
76503             if (this.type !== Pbf.Bytes) return arr.push(this.readDouble());
76504             var end = readPackedEnd(this);
76505             arr = arr || [];
76506             while (this.pos < end) arr.push(this.readDouble());
76507             return arr;
76508         },
76509         readPackedFixed32: function(arr) {
76510             if (this.type !== Pbf.Bytes) return arr.push(this.readFixed32());
76511             var end = readPackedEnd(this);
76512             arr = arr || [];
76513             while (this.pos < end) arr.push(this.readFixed32());
76514             return arr;
76515         },
76516         readPackedSFixed32: function(arr) {
76517             if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed32());
76518             var end = readPackedEnd(this);
76519             arr = arr || [];
76520             while (this.pos < end) arr.push(this.readSFixed32());
76521             return arr;
76522         },
76523         readPackedFixed64: function(arr) {
76524             if (this.type !== Pbf.Bytes) return arr.push(this.readFixed64());
76525             var end = readPackedEnd(this);
76526             arr = arr || [];
76527             while (this.pos < end) arr.push(this.readFixed64());
76528             return arr;
76529         },
76530         readPackedSFixed64: function(arr) {
76531             if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed64());
76532             var end = readPackedEnd(this);
76533             arr = arr || [];
76534             while (this.pos < end) arr.push(this.readSFixed64());
76535             return arr;
76536         },
76537
76538         skip: function(val) {
76539             var type = val & 0x7;
76540             if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {}
76541             else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos;
76542             else if (type === Pbf.Fixed32) this.pos += 4;
76543             else if (type === Pbf.Fixed64) this.pos += 8;
76544             else throw new Error('Unimplemented type: ' + type);
76545         },
76546
76547         // === WRITING =================================================================
76548
76549         writeTag: function(tag, type) {
76550             this.writeVarint((tag << 3) | type);
76551         },
76552
76553         realloc: function(min) {
76554             var length = this.length || 16;
76555
76556             while (length < this.pos + min) length *= 2;
76557
76558             if (length !== this.length) {
76559                 var buf = new Uint8Array(length);
76560                 buf.set(this.buf);
76561                 this.buf = buf;
76562                 this.length = length;
76563             }
76564         },
76565
76566         finish: function() {
76567             this.length = this.pos;
76568             this.pos = 0;
76569             return this.buf.subarray(0, this.length);
76570         },
76571
76572         writeFixed32: function(val) {
76573             this.realloc(4);
76574             writeInt32(this.buf, val, this.pos);
76575             this.pos += 4;
76576         },
76577
76578         writeSFixed32: function(val) {
76579             this.realloc(4);
76580             writeInt32(this.buf, val, this.pos);
76581             this.pos += 4;
76582         },
76583
76584         writeFixed64: function(val) {
76585             this.realloc(8);
76586             writeInt32(this.buf, val & -1, this.pos);
76587             writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
76588             this.pos += 8;
76589         },
76590
76591         writeSFixed64: function(val) {
76592             this.realloc(8);
76593             writeInt32(this.buf, val & -1, this.pos);
76594             writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
76595             this.pos += 8;
76596         },
76597
76598         writeVarint: function(val) {
76599             val = +val || 0;
76600
76601             if (val > 0xfffffff || val < 0) {
76602                 writeBigVarint(val, this);
76603                 return;
76604             }
76605
76606             this.realloc(4);
76607
76608             this.buf[this.pos++] =           val & 0x7f  | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
76609             this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
76610             this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
76611             this.buf[this.pos++] =   (val >>> 7) & 0x7f;
76612         },
76613
76614         writeSVarint: function(val) {
76615             this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
76616         },
76617
76618         writeBoolean: function(val) {
76619             this.writeVarint(Boolean(val));
76620         },
76621
76622         writeString: function(str) {
76623             str = String(str);
76624             this.realloc(str.length * 4);
76625
76626             this.pos++; // reserve 1 byte for short string length
76627
76628             var startPos = this.pos;
76629             // write the string directly to the buffer and see how much was written
76630             this.pos = writeUtf8(this.buf, str, this.pos);
76631             var len = this.pos - startPos;
76632
76633             if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);
76634
76635             // finally, write the message length in the reserved place and restore the position
76636             this.pos = startPos - 1;
76637             this.writeVarint(len);
76638             this.pos += len;
76639         },
76640
76641         writeFloat: function(val) {
76642             this.realloc(4);
76643             ieee754.write(this.buf, val, this.pos, true, 23, 4);
76644             this.pos += 4;
76645         },
76646
76647         writeDouble: function(val) {
76648             this.realloc(8);
76649             ieee754.write(this.buf, val, this.pos, true, 52, 8);
76650             this.pos += 8;
76651         },
76652
76653         writeBytes: function(buffer) {
76654             var len = buffer.length;
76655             this.writeVarint(len);
76656             this.realloc(len);
76657             for (var i = 0; i < len; i++) this.buf[this.pos++] = buffer[i];
76658         },
76659
76660         writeRawMessage: function(fn, obj) {
76661             this.pos++; // reserve 1 byte for short message length
76662
76663             // write the message directly to the buffer and see how much was written
76664             var startPos = this.pos;
76665             fn(obj, this);
76666             var len = this.pos - startPos;
76667
76668             if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);
76669
76670             // finally, write the message length in the reserved place and restore the position
76671             this.pos = startPos - 1;
76672             this.writeVarint(len);
76673             this.pos += len;
76674         },
76675
76676         writeMessage: function(tag, fn, obj) {
76677             this.writeTag(tag, Pbf.Bytes);
76678             this.writeRawMessage(fn, obj);
76679         },
76680
76681         writePackedVarint:   function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedVarint, arr);   },
76682         writePackedSVarint:  function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedSVarint, arr);  },
76683         writePackedBoolean:  function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedBoolean, arr);  },
76684         writePackedFloat:    function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedFloat, arr);    },
76685         writePackedDouble:   function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedDouble, arr);   },
76686         writePackedFixed32:  function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedFixed32, arr);  },
76687         writePackedSFixed32: function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedSFixed32, arr); },
76688         writePackedFixed64:  function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedFixed64, arr);  },
76689         writePackedSFixed64: function(tag, arr) { if (arr.length) this.writeMessage(tag, writePackedSFixed64, arr); },
76690
76691         writeBytesField: function(tag, buffer) {
76692             this.writeTag(tag, Pbf.Bytes);
76693             this.writeBytes(buffer);
76694         },
76695         writeFixed32Field: function(tag, val) {
76696             this.writeTag(tag, Pbf.Fixed32);
76697             this.writeFixed32(val);
76698         },
76699         writeSFixed32Field: function(tag, val) {
76700             this.writeTag(tag, Pbf.Fixed32);
76701             this.writeSFixed32(val);
76702         },
76703         writeFixed64Field: function(tag, val) {
76704             this.writeTag(tag, Pbf.Fixed64);
76705             this.writeFixed64(val);
76706         },
76707         writeSFixed64Field: function(tag, val) {
76708             this.writeTag(tag, Pbf.Fixed64);
76709             this.writeSFixed64(val);
76710         },
76711         writeVarintField: function(tag, val) {
76712             this.writeTag(tag, Pbf.Varint);
76713             this.writeVarint(val);
76714         },
76715         writeSVarintField: function(tag, val) {
76716             this.writeTag(tag, Pbf.Varint);
76717             this.writeSVarint(val);
76718         },
76719         writeStringField: function(tag, str) {
76720             this.writeTag(tag, Pbf.Bytes);
76721             this.writeString(str);
76722         },
76723         writeFloatField: function(tag, val) {
76724             this.writeTag(tag, Pbf.Fixed32);
76725             this.writeFloat(val);
76726         },
76727         writeDoubleField: function(tag, val) {
76728             this.writeTag(tag, Pbf.Fixed64);
76729             this.writeDouble(val);
76730         },
76731         writeBooleanField: function(tag, val) {
76732             this.writeVarintField(tag, Boolean(val));
76733         }
76734     };
76735
76736     function readVarintRemainder(l, s, p) {
76737         var buf = p.buf,
76738             h, b;
76739
76740         b = buf[p.pos++]; h  = (b & 0x70) >> 4;  if (b < 0x80) return toNum(l, h, s);
76741         b = buf[p.pos++]; h |= (b & 0x7f) << 3;  if (b < 0x80) return toNum(l, h, s);
76742         b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) return toNum(l, h, s);
76743         b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) return toNum(l, h, s);
76744         b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) return toNum(l, h, s);
76745         b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) return toNum(l, h, s);
76746
76747         throw new Error('Expected varint not more than 10 bytes');
76748     }
76749
76750     function readPackedEnd(pbf) {
76751         return pbf.type === Pbf.Bytes ?
76752             pbf.readVarint() + pbf.pos : pbf.pos + 1;
76753     }
76754
76755     function toNum(low, high, isSigned) {
76756         if (isSigned) {
76757             return high * 0x100000000 + (low >>> 0);
76758         }
76759
76760         return ((high >>> 0) * 0x100000000) + (low >>> 0);
76761     }
76762
76763     function writeBigVarint(val, pbf) {
76764         var low, high;
76765
76766         if (val >= 0) {
76767             low  = (val % 0x100000000) | 0;
76768             high = (val / 0x100000000) | 0;
76769         } else {
76770             low  = ~(-val % 0x100000000);
76771             high = ~(-val / 0x100000000);
76772
76773             if (low ^ 0xffffffff) {
76774                 low = (low + 1) | 0;
76775             } else {
76776                 low = 0;
76777                 high = (high + 1) | 0;
76778             }
76779         }
76780
76781         if (val >= 0x10000000000000000 || val < -0x10000000000000000) {
76782             throw new Error('Given varint doesn\'t fit into 10 bytes');
76783         }
76784
76785         pbf.realloc(10);
76786
76787         writeBigVarintLow(low, high, pbf);
76788         writeBigVarintHigh(high, pbf);
76789     }
76790
76791     function writeBigVarintLow(low, high, pbf) {
76792         pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
76793         pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
76794         pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
76795         pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
76796         pbf.buf[pbf.pos]   = low & 0x7f;
76797     }
76798
76799     function writeBigVarintHigh(high, pbf) {
76800         var lsb = (high & 0x07) << 4;
76801
76802         pbf.buf[pbf.pos++] |= lsb         | ((high >>>= 3) ? 0x80 : 0); if (!high) return;
76803         pbf.buf[pbf.pos++]  = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
76804         pbf.buf[pbf.pos++]  = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
76805         pbf.buf[pbf.pos++]  = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
76806         pbf.buf[pbf.pos++]  = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
76807         pbf.buf[pbf.pos++]  = high & 0x7f;
76808     }
76809
76810     function makeRoomForExtraLength(startPos, len, pbf) {
76811         var extraLen =
76812             len <= 0x3fff ? 1 :
76813             len <= 0x1fffff ? 2 :
76814             len <= 0xfffffff ? 3 : Math.floor(Math.log(len) / (Math.LN2 * 7));
76815
76816         // if 1 byte isn't enough for encoding message length, shift the data to the right
76817         pbf.realloc(extraLen);
76818         for (var i = pbf.pos - 1; i >= startPos; i--) pbf.buf[i + extraLen] = pbf.buf[i];
76819     }
76820
76821     function writePackedVarint(arr, pbf)   { for (var i = 0; i < arr.length; i++) pbf.writeVarint(arr[i]);   }
76822     function writePackedSVarint(arr, pbf)  { for (var i = 0; i < arr.length; i++) pbf.writeSVarint(arr[i]);  }
76823     function writePackedFloat(arr, pbf)    { for (var i = 0; i < arr.length; i++) pbf.writeFloat(arr[i]);    }
76824     function writePackedDouble(arr, pbf)   { for (var i = 0; i < arr.length; i++) pbf.writeDouble(arr[i]);   }
76825     function writePackedBoolean(arr, pbf)  { for (var i = 0; i < arr.length; i++) pbf.writeBoolean(arr[i]);  }
76826     function writePackedFixed32(arr, pbf)  { for (var i = 0; i < arr.length; i++) pbf.writeFixed32(arr[i]);  }
76827     function writePackedSFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed32(arr[i]); }
76828     function writePackedFixed64(arr, pbf)  { for (var i = 0; i < arr.length; i++) pbf.writeFixed64(arr[i]);  }
76829     function writePackedSFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]); }
76830
76831     // Buffer code below from https://github.com/feross/buffer, MIT-licensed
76832
76833     function readUInt32(buf, pos) {
76834         return ((buf[pos]) |
76835             (buf[pos + 1] << 8) |
76836             (buf[pos + 2] << 16)) +
76837             (buf[pos + 3] * 0x1000000);
76838     }
76839
76840     function writeInt32(buf, val, pos) {
76841         buf[pos] = val;
76842         buf[pos + 1] = (val >>> 8);
76843         buf[pos + 2] = (val >>> 16);
76844         buf[pos + 3] = (val >>> 24);
76845     }
76846
76847     function readInt32(buf, pos) {
76848         return ((buf[pos]) |
76849             (buf[pos + 1] << 8) |
76850             (buf[pos + 2] << 16)) +
76851             (buf[pos + 3] << 24);
76852     }
76853
76854     function readUtf8(buf, pos, end) {
76855         var str = '';
76856         var i = pos;
76857
76858         while (i < end) {
76859             var b0 = buf[i];
76860             var c = null; // codepoint
76861             var bytesPerSequence =
76862                 b0 > 0xEF ? 4 :
76863                 b0 > 0xDF ? 3 :
76864                 b0 > 0xBF ? 2 : 1;
76865
76866             if (i + bytesPerSequence > end) break;
76867
76868             var b1, b2, b3;
76869
76870             if (bytesPerSequence === 1) {
76871                 if (b0 < 0x80) {
76872                     c = b0;
76873                 }
76874             } else if (bytesPerSequence === 2) {
76875                 b1 = buf[i + 1];
76876                 if ((b1 & 0xC0) === 0x80) {
76877                     c = (b0 & 0x1F) << 0x6 | (b1 & 0x3F);
76878                     if (c <= 0x7F) {
76879                         c = null;
76880                     }
76881                 }
76882             } else if (bytesPerSequence === 3) {
76883                 b1 = buf[i + 1];
76884                 b2 = buf[i + 2];
76885                 if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {
76886                     c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | (b2 & 0x3F);
76887                     if (c <= 0x7FF || (c >= 0xD800 && c <= 0xDFFF)) {
76888                         c = null;
76889                     }
76890                 }
76891             } else if (bytesPerSequence === 4) {
76892                 b1 = buf[i + 1];
76893                 b2 = buf[i + 2];
76894                 b3 = buf[i + 3];
76895                 if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {
76896                     c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | (b3 & 0x3F);
76897                     if (c <= 0xFFFF || c >= 0x110000) {
76898                         c = null;
76899                     }
76900                 }
76901             }
76902
76903             if (c === null) {
76904                 c = 0xFFFD;
76905                 bytesPerSequence = 1;
76906
76907             } else if (c > 0xFFFF) {
76908                 c -= 0x10000;
76909                 str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);
76910                 c = 0xDC00 | c & 0x3FF;
76911             }
76912
76913             str += String.fromCharCode(c);
76914             i += bytesPerSequence;
76915         }
76916
76917         return str;
76918     }
76919
76920     function readUtf8TextDecoder(buf, pos, end) {
76921         return utf8TextDecoder.decode(buf.subarray(pos, end));
76922     }
76923
76924     function writeUtf8(buf, str, pos) {
76925         for (var i = 0, c, lead; i < str.length; i++) {
76926             c = str.charCodeAt(i); // code point
76927
76928             if (c > 0xD7FF && c < 0xE000) {
76929                 if (lead) {
76930                     if (c < 0xDC00) {
76931                         buf[pos++] = 0xEF;
76932                         buf[pos++] = 0xBF;
76933                         buf[pos++] = 0xBD;
76934                         lead = c;
76935                         continue;
76936                     } else {
76937                         c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;
76938                         lead = null;
76939                     }
76940                 } else {
76941                     if (c > 0xDBFF || (i + 1 === str.length)) {
76942                         buf[pos++] = 0xEF;
76943                         buf[pos++] = 0xBF;
76944                         buf[pos++] = 0xBD;
76945                     } else {
76946                         lead = c;
76947                     }
76948                     continue;
76949                 }
76950             } else if (lead) {
76951                 buf[pos++] = 0xEF;
76952                 buf[pos++] = 0xBF;
76953                 buf[pos++] = 0xBD;
76954                 lead = null;
76955             }
76956
76957             if (c < 0x80) {
76958                 buf[pos++] = c;
76959             } else {
76960                 if (c < 0x800) {
76961                     buf[pos++] = c >> 0x6 | 0xC0;
76962                 } else {
76963                     if (c < 0x10000) {
76964                         buf[pos++] = c >> 0xC | 0xE0;
76965                     } else {
76966                         buf[pos++] = c >> 0x12 | 0xF0;
76967                         buf[pos++] = c >> 0xC & 0x3F | 0x80;
76968                     }
76969                     buf[pos++] = c >> 0x6 & 0x3F | 0x80;
76970                 }
76971                 buf[pos++] = c & 0x3F | 0x80;
76972             }
76973         }
76974         return pos;
76975     }
76976
76977     /**
76978      * Decompress and parse an array buffer containing zipped
76979      * json data and return as a json object.
76980      *
76981      * @description Handles array buffers continaing zipped json
76982      * data.
76983      *
76984      * @param {ArrayBuffer} buffer - Array buffer to decompress.
76985      * @returns {Object} Parsed object.
76986      */
76987     function decompress(buffer) {
76988         const inflated = inflate_1(buffer, { to: "string" });
76989         return JSON.parse(inflated);
76990     }
76991     /**
76992      * Retrieves a resource as an array buffer and returns a promise
76993      * to the buffer.
76994      *
76995      * @description Rejects the promise on request failure.
76996      *
76997      * @param {string} url - URL for resource to retrieve.
76998      * @param {Promise} [abort] - Optional promise for aborting
76999      * the request through rejection.
77000      * @returns {Promise<ArrayBuffer>} Promise to the array buffer
77001      * resource.
77002      */
77003     function fetchArrayBuffer(url, abort) {
77004         const method = "GET";
77005         const responseType = "arraybuffer";
77006         return xhrFetch(url, method, responseType, [], null, abort);
77007     }
77008     function xhrFetch(url, method, responseType, headers, body, abort) {
77009         const xhr = new XMLHttpRequest();
77010         const promise = new Promise((resolve, reject) => {
77011             xhr.open(method, url, true);
77012             for (const header of headers) {
77013                 xhr.setRequestHeader(header.name, header.value);
77014             }
77015             xhr.responseType = responseType;
77016             xhr.timeout = 15000;
77017             xhr.onload = () => {
77018                 var _a;
77019                 if (xhr.status !== 200) {
77020                     const error = (_a = xhr.response) !== null && _a !== void 0 ? _a : new MapillaryError(`Response status error: ${url}`);
77021                     reject(error);
77022                 }
77023                 if (!xhr.response) {
77024                     reject(new MapillaryError(`Response empty: ${url}`));
77025                 }
77026                 resolve(xhr.response);
77027             };
77028             xhr.onerror = () => {
77029                 reject(new MapillaryError(`Request error: ${url}`));
77030             };
77031             xhr.ontimeout = () => {
77032                 reject(new MapillaryError(`Request timeout: ${url}`));
77033             };
77034             xhr.onabort = () => {
77035                 reject(new MapillaryError(`Request aborted: ${url}`));
77036             };
77037             xhr.send(method === "POST" ? body : null);
77038         });
77039         if (!!abort) {
77040             abort.catch(() => { xhr.abort(); });
77041         }
77042         return promise;
77043     }
77044     /**
77045      * Read the fields of a protobuf array buffer into a mesh
77046      * object.
77047      *
77048      * @param {ArrayBuffer} buffer - Protobuf array buffer
77049      * to read from.
77050      * @returns {MeshContract} Mesh object.
77051      */
77052     function readMeshPbf(buffer) {
77053         const pbf$1 = new pbf(buffer);
77054         const mesh = { faces: [], vertices: [] };
77055         return pbf$1.readFields(readMeshPbfField, mesh);
77056     }
77057     function readMeshPbfField(tag, mesh, pbf) {
77058         if (tag === 1) {
77059             mesh.vertices.push(pbf.readFloat());
77060         }
77061         else if (tag === 2) {
77062             mesh.faces.push(pbf.readVarint());
77063         }
77064         else {
77065             console.warn(`Unsupported pbf tag (${tag})`);
77066         }
77067     }
77068
77069     /**
77070      * @class DataProviderBase
77071      *
77072      * @classdesc Base class to extend if implementing a data provider
77073      * class.
77074      *
77075      * @fires datacreate
77076      *
77077      * @example
77078      * ```js
77079      * class MyDataProvider extends DataProviderBase {
77080      *   constructor() {
77081      *     super(new S2GeometryProvider());
77082      *   }
77083      *   ...
77084      * }
77085      * ```
77086      */
77087     class DataProviderBase extends EventEmitter {
77088         /**
77089          * Create a new data provider base instance.
77090          *
77091          * @param {IGeometryProvider} geometry - Geometry
77092          * provider instance.
77093          */
77094         constructor(_geometry) {
77095             super();
77096             this._geometry = _geometry;
77097         }
77098         /**
77099          * Get geometry property.
77100          *
77101          * @returns {IGeometryProvider} Geometry provider instance.
77102          */
77103         get geometry() {
77104             return this._geometry;
77105         }
77106         fire(type, event) {
77107             super.fire(type, event);
77108         }
77109         /**
77110          * Get core images in a geometry cell.
77111          *
77112          * @param {string} cellId - The id of the geometry cell.
77113          * @returns {Promise<CoreImagesContract>} Promise to
77114          * the core images of the requested geometry cell id.
77115          * @throws Rejects the promise on errors.
77116          */
77117         getCoreImages(cellId) {
77118             return Promise.reject(new MapillaryError("Not implemented"));
77119         }
77120         /**
77121          * Get a cluster reconstruction.
77122          *
77123          * @param {string} url - URL for the cluster reconstruction
77124          * to retrieve.
77125          * @param {Promise} [abort] - Optional promise for aborting
77126          * the request through rejection.
77127          * @returns {Promise<ClusterContract>} Promise to the
77128          * cluster reconstruction.
77129          * @throws Rejects the promise on errors.
77130          */
77131         getCluster(url, abort) {
77132             return Promise.reject(new MapillaryError("Not implemented"));
77133         }
77134         /**
77135          * Get spatial images.
77136          *
77137          * @param {Array<string>} imageIds - The ids for the
77138          * images to retrieve.
77139          * @returns {Promise<SpatialImagesContract>} Promise to
77140          * the spatial images of the requested image ids.
77141          * @throws Rejects the promise on errors.
77142          */
77143         getSpatialImages(imageIds) {
77144             return Promise.reject(new MapillaryError("Not implemented"));
77145         }
77146         /**
77147          * Get complete images.
77148          *
77149          * @param {Array<string>} imageIds - The ids for the
77150          * images to retrieve.
77151          * @returns {Promise<ImagesContract>} Promise to the images of the
77152          * requested image ids.
77153          * @throws Rejects the promise on errors.
77154          */
77155         getImages(imageIds) {
77156             return Promise.reject(new MapillaryError("Not implemented"));
77157         }
77158         /**
77159          * Get an image as an array buffer.
77160          *
77161          * @param {string} url - URL for image to retrieve.
77162          * @param {Promise<void>} [abort] - Optional promise for aborting
77163          * the request through rejection.
77164          * @returns {Promise<ArrayBuffer>} Promise to the array
77165          * buffer containing the image.
77166          * @throws Rejects the promise on errors.
77167          */
77168         getImageBuffer(url, abort) {
77169             return Promise.reject(new MapillaryError("Not implemented"));
77170         }
77171         /**
77172          * Get image tiles urls for a tile level.
77173          *
77174          * @param {ImageTilesRequestContract} tiles - Tiles to request
77175          * @returns {Promise<ImageTilesContract>} Promise to the
77176          * image tiles response contract
77177          *
77178          * @throws Rejects the promise on errors.
77179          *
77180          * @example
77181          * ```js
77182          * var tileRequest = { imageId: 'image-id', z: 12 };
77183          * provider.getImageTiles(tileRequest)
77184          *   .then((response) => console.log(response));
77185          * ```
77186          */
77187         getImageTiles(tiles) {
77188             return Promise.reject(new MapillaryError("Not implemented"));
77189         }
77190         /**
77191          * Get a mesh.
77192          *
77193          * @param {string} url - URL for mesh to retrieve.
77194          * @param {Promise<void>} [abort] - Optional promise for aborting
77195          * the request through rejection.
77196          * @returns {Promise<MeshContract>} Promise to the mesh.
77197          * @throws Rejects the promise on errors.
77198          */
77199         getMesh(url, abort) {
77200             return Promise.reject(new MapillaryError("Not implemented"));
77201         }
77202         /**
77203          * Get sequence.
77204          *
77205          * @param {Array<string>} sequenceId - The id for the
77206          * sequence to retrieve.
77207          * @returns {Promise} Promise to the sequences of the
77208          * requested image ids.
77209          * @throws Rejects the promise on errors.
77210          */
77211         getSequence(sequenceId) {
77212             return Promise.reject(new MapillaryError("Not implemented"));
77213         }
77214         off(type, handler) {
77215             super.off(type, handler);
77216         }
77217         on(type, handler) {
77218             super.on(type, handler);
77219         }
77220         /**
77221          * Set an access token for authenticated API requests of
77222          * protected resources.
77223          *
77224          * @param {string} [accessToken] accessToken - User access
77225          * token or client access token.
77226          */
77227         setAccessToken(accessToken) {
77228             throw new MapillaryError("Not implemented");
77229         }
77230     }
77231
77232     /**
77233      * @class GeometryProviderBase
77234      *
77235      * @classdesc Base class to extend if implementing a geometry
77236      * provider class.
77237      *
77238      * @example
77239      * ```js
77240      * class MyGeometryProvider extends GeometryProviderBase {
77241      *      ...
77242      * }
77243      * ```
77244      */
77245     class GeometryProviderBase {
77246         /**
77247          * Create a new geometry provider base instance.
77248          */
77249         constructor() { }
77250         /**
77251          * Convert a geodetic bounding box to the the minimum set
77252          * of cell ids containing the bounding box.
77253          *
77254          * @description The bounding box needs
77255          * to be sufficiently small to be contained in an area with the size
77256          * of maximally four tiles. Up to nine adjacent tiles may be returned.
77257          *
77258          * @param {LngLat} sw - South west corner of bounding box.
77259          * @param {LngLat} ne - North east corner of bounding box.
77260          *
77261          * @returns {Array<string>} Array of cell ids.
77262          */
77263         bboxToCellIds(sw, ne) {
77264             throw new MapillaryError("Not implemented");
77265         }
77266         /**
77267          * Get the cell ids of all adjacent cells.
77268          *
77269          * @description In the case of approximately rectangular cells
77270          * this is typically the eight orthogonally and diagonally adjacent
77271          * cells.
77272          *
77273          * @param {string} cellId - Id of cell.
77274          * @returns {Array<string>} Array of cell ids. No specific
77275          * order is guaranteed.
77276          */
77277         getAdjacent(cellId) {
77278             throw new MapillaryError("Not implemented");
77279         }
77280         /**
77281          * Get the vertices of a cell.
77282          *
77283          * @description The vertices form an unclosed
77284          * clockwise polygon in the 2D longitude, latitude
77285          * space. No assumption on the position of the first
77286          * vertex relative to the others can be made.
77287          *
77288          * @param {string} cellId - Id of cell.
77289          * @returns {Array<LngLat>} Unclosed clockwise polygon.
77290          */
77291         getVertices(cellId) {
77292             throw new MapillaryError("Not implemented");
77293         }
77294         /**
77295          * Convert geodetic coordinates to a cell id.
77296          *
77297          * @param {LngLat} lngLat - Longitude, latitude to convert.
77298          * @returns {string} Cell id for the longitude, latitude.
77299          */
77300         lngLatToCellId(lngLat) {
77301             throw new MapillaryError("Not implemented");
77302         }
77303         /** @ignore */
77304         _approxBboxToCellIds(sw, ne) {
77305             if (ne.lat <= sw.lat || ne.lng <= sw.lng) {
77306                 throw new MapillaryError("North east needs to be top right of south west");
77307             }
77308             const centerLat = (sw.lat + ne.lat) / 2;
77309             const centerLng = (sw.lng + ne.lng) / 2;
77310             const enu = geodeticToEnu(ne.lng, ne.lat, 0, centerLng, centerLat, 0);
77311             const threshold = Math.max(enu[0], enu[1]);
77312             return this._lngLatToCellIds({ lat: centerLat, lng: centerLng }, threshold);
77313         }
77314         /** @ignore */
77315         _enuToGeodetic(point, reference) {
77316             const [lng, lat] = enuToGeodetic(point[0], point[1], point[2], reference.lng, reference.lat, 0);
77317             return { lat, lng };
77318         }
77319         /** @ignore */
77320         _getLngLatBoundingBoxCorners(lngLat, threshold) {
77321             return [
77322                 [-threshold, threshold, 0],
77323                 [threshold, threshold, 0],
77324                 [threshold, -threshold, 0],
77325                 [-threshold, -threshold, 0],
77326             ].map((point) => {
77327                 return this._enuToGeodetic(point, lngLat);
77328             });
77329         }
77330         /**
77331          * Convert a geodetic square to cell ids.
77332          *
77333          * The square is specified as a longitude, latitude
77334          * and a threshold from the position using Manhattan distance.
77335          *
77336          * @param {LngLat} lngLat - Longitude, latitude.
77337          * @param {number} threshold - Threshold of the conversion in meters.
77338          *
77339          * @returns {Array<string>} Array of cell ids reachable within
77340          * the threshold.
77341          *
77342          * @ignore
77343          */
77344         _lngLatToCellIds(lngLat, threshold) {
77345             const cellId = this.lngLatToCellId(lngLat);
77346             const bboxCorners = this._getLngLatBoundingBoxCorners(lngLat, threshold);
77347             for (const corner of bboxCorners) {
77348                 const cid = this.lngLatToCellId(corner);
77349                 if (cid !== cellId) {
77350                     return [cellId, ...this.getAdjacent(cellId)];
77351                 }
77352             }
77353             return [cellId];
77354         }
77355     }
77356
77357     var s2geometry = {exports: {}};
77358
77359     var long = {exports: {}};
77360
77361     /*
77362      Copyright 2013 Daniel Wirtz <dcode@dcode.io>
77363      Copyright 2009 The Closure Library Authors. All Rights Reserved.
77364
77365      Licensed under the Apache License, Version 2.0 (the "License");
77366      you may not use this file except in compliance with the License.
77367      You may obtain a copy of the License at
77368
77369      http://www.apache.org/licenses/LICENSE-2.0
77370
77371      Unless required by applicable law or agreed to in writing, software
77372      distributed under the License is distributed on an "AS-IS" BASIS,
77373      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77374      See the License for the specific language governing permissions and
77375      limitations under the License.
77376      */
77377
77378     (function (module) {
77379     /**
77380      * @license long.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
77381      * Released under the Apache License, Version 2.0
77382      * see: https://github.com/dcodeIO/long.js for details
77383      */
77384     (function(global, factory) {
77385
77386         /* AMD */ if (typeof commonjsRequire === 'function' && 'object' === "object" && module && module["exports"])
77387             module["exports"] = factory();
77388         /* Global */ else
77389             (global["dcodeIO"] = global["dcodeIO"] || {})["Long"] = factory();
77390
77391     })(commonjsGlobal, function() {
77392
77393         /**
77394          * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
77395          *  See the from* functions below for more convenient ways of constructing Longs.
77396          * @exports Long
77397          * @class A Long class for representing a 64 bit two's-complement integer value.
77398          * @param {number} low The low (signed) 32 bits of the long
77399          * @param {number} high The high (signed) 32 bits of the long
77400          * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
77401          * @constructor
77402          */
77403         function Long(low, high, unsigned) {
77404
77405             /**
77406              * The low 32 bits as a signed value.
77407              * @type {number}
77408              */
77409             this.low = low | 0;
77410
77411             /**
77412              * The high 32 bits as a signed value.
77413              * @type {number}
77414              */
77415             this.high = high | 0;
77416
77417             /**
77418              * Whether unsigned or not.
77419              * @type {boolean}
77420              */
77421             this.unsigned = !!unsigned;
77422         }
77423
77424         // The internal representation of a long is the two given signed, 32-bit values.
77425         // We use 32-bit pieces because these are the size of integers on which
77426         // Javascript performs bit-operations.  For operations like addition and
77427         // multiplication, we split each number into 16 bit pieces, which can easily be
77428         // multiplied within Javascript's floating-point representation without overflow
77429         // or change in sign.
77430         //
77431         // In the algorithms below, we frequently reduce the negative case to the
77432         // positive case by negating the input(s) and then post-processing the result.
77433         // Note that we must ALWAYS check specially whether those values are MIN_VALUE
77434         // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
77435         // a positive number, it overflows back into a negative).  Not handling this
77436         // case would often result in infinite recursion.
77437         //
77438         // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
77439         // methods on which they depend.
77440
77441         /**
77442          * An indicator used to reliably determine if an object is a Long or not.
77443          * @type {boolean}
77444          * @const
77445          * @private
77446          */
77447         Long.prototype.__isLong__;
77448
77449         Object.defineProperty(Long.prototype, "__isLong__", {
77450             value: true,
77451             enumerable: false,
77452             configurable: false
77453         });
77454
77455         /**
77456          * @function
77457          * @param {*} obj Object
77458          * @returns {boolean}
77459          * @inner
77460          */
77461         function isLong(obj) {
77462             return (obj && obj["__isLong__"]) === true;
77463         }
77464
77465         /**
77466          * Tests if the specified object is a Long.
77467          * @function
77468          * @param {*} obj Object
77469          * @returns {boolean}
77470          */
77471         Long.isLong = isLong;
77472
77473         /**
77474          * A cache of the Long representations of small integer values.
77475          * @type {!Object}
77476          * @inner
77477          */
77478         var INT_CACHE = {};
77479
77480         /**
77481          * A cache of the Long representations of small unsigned integer values.
77482          * @type {!Object}
77483          * @inner
77484          */
77485         var UINT_CACHE = {};
77486
77487         /**
77488          * @param {number} value
77489          * @param {boolean=} unsigned
77490          * @returns {!Long}
77491          * @inner
77492          */
77493         function fromInt(value, unsigned) {
77494             var obj, cachedObj, cache;
77495             if (unsigned) {
77496                 value >>>= 0;
77497                 if (cache = (0 <= value && value < 256)) {
77498                     cachedObj = UINT_CACHE[value];
77499                     if (cachedObj)
77500                         return cachedObj;
77501                 }
77502                 obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true);
77503                 if (cache)
77504                     UINT_CACHE[value] = obj;
77505                 return obj;
77506             } else {
77507                 value |= 0;
77508                 if (cache = (-128 <= value && value < 128)) {
77509                     cachedObj = INT_CACHE[value];
77510                     if (cachedObj)
77511                         return cachedObj;
77512                 }
77513                 obj = fromBits(value, value < 0 ? -1 : 0, false);
77514                 if (cache)
77515                     INT_CACHE[value] = obj;
77516                 return obj;
77517             }
77518         }
77519
77520         /**
77521          * Returns a Long representing the given 32 bit integer value.
77522          * @function
77523          * @param {number} value The 32 bit integer in question
77524          * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
77525          * @returns {!Long} The corresponding Long value
77526          */
77527         Long.fromInt = fromInt;
77528
77529         /**
77530          * @param {number} value
77531          * @param {boolean=} unsigned
77532          * @returns {!Long}
77533          * @inner
77534          */
77535         function fromNumber(value, unsigned) {
77536             if (isNaN(value) || !isFinite(value))
77537                 return unsigned ? UZERO : ZERO;
77538             if (unsigned) {
77539                 if (value < 0)
77540                     return UZERO;
77541                 if (value >= TWO_PWR_64_DBL)
77542                     return MAX_UNSIGNED_VALUE;
77543             } else {
77544                 if (value <= -TWO_PWR_63_DBL)
77545                     return MIN_VALUE;
77546                 if (value + 1 >= TWO_PWR_63_DBL)
77547                     return MAX_VALUE;
77548             }
77549             if (value < 0)
77550                 return fromNumber(-value, unsigned).neg();
77551             return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
77552         }
77553
77554         /**
77555          * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
77556          * @function
77557          * @param {number} value The number in question
77558          * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
77559          * @returns {!Long} The corresponding Long value
77560          */
77561         Long.fromNumber = fromNumber;
77562
77563         /**
77564          * @param {number} lowBits
77565          * @param {number} highBits
77566          * @param {boolean=} unsigned
77567          * @returns {!Long}
77568          * @inner
77569          */
77570         function fromBits(lowBits, highBits, unsigned) {
77571             return new Long(lowBits, highBits, unsigned);
77572         }
77573
77574         /**
77575          * Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is
77576          *  assumed to use 32 bits.
77577          * @function
77578          * @param {number} lowBits The low 32 bits
77579          * @param {number} highBits The high 32 bits
77580          * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
77581          * @returns {!Long} The corresponding Long value
77582          */
77583         Long.fromBits = fromBits;
77584
77585         /**
77586          * @function
77587          * @param {number} base
77588          * @param {number} exponent
77589          * @returns {number}
77590          * @inner
77591          */
77592         var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4)
77593
77594         /**
77595          * @param {string} str
77596          * @param {(boolean|number)=} unsigned
77597          * @param {number=} radix
77598          * @returns {!Long}
77599          * @inner
77600          */
77601         function fromString(str, unsigned, radix) {
77602             if (str.length === 0)
77603                 throw Error('empty string');
77604             if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
77605                 return ZERO;
77606             if (typeof unsigned === 'number') {
77607                 // For goog.math.long compatibility
77608                 radix = unsigned,
77609                 unsigned = false;
77610             } else {
77611                 unsigned = !! unsigned;
77612             }
77613             radix = radix || 10;
77614             if (radix < 2 || 36 < radix)
77615                 throw RangeError('radix');
77616
77617             var p;
77618             if ((p = str.indexOf('-')) > 0)
77619                 throw Error('interior hyphen');
77620             else if (p === 0) {
77621                 return fromString(str.substring(1), unsigned, radix).neg();
77622             }
77623
77624             // Do several (8) digits each time through the loop, so as to
77625             // minimize the calls to the very expensive emulated div.
77626             var radixToPower = fromNumber(pow_dbl(radix, 8));
77627
77628             var result = ZERO;
77629             for (var i = 0; i < str.length; i += 8) {
77630                 var size = Math.min(8, str.length - i),
77631                     value = parseInt(str.substring(i, i + size), radix);
77632                 if (size < 8) {
77633                     var power = fromNumber(pow_dbl(radix, size));
77634                     result = result.mul(power).add(fromNumber(value));
77635                 } else {
77636                     result = result.mul(radixToPower);
77637                     result = result.add(fromNumber(value));
77638                 }
77639             }
77640             result.unsigned = unsigned;
77641             return result;
77642         }
77643
77644         /**
77645          * Returns a Long representation of the given string, written using the specified radix.
77646          * @function
77647          * @param {string} str The textual representation of the Long
77648          * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed
77649          * @param {number=} radix The radix in which the text is written (2-36), defaults to 10
77650          * @returns {!Long} The corresponding Long value
77651          */
77652         Long.fromString = fromString;
77653
77654         /**
77655          * @function
77656          * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val
77657          * @returns {!Long}
77658          * @inner
77659          */
77660         function fromValue(val) {
77661             if (val /* is compatible */ instanceof Long)
77662                 return val;
77663             if (typeof val === 'number')
77664                 return fromNumber(val);
77665             if (typeof val === 'string')
77666                 return fromString(val);
77667             // Throws for non-objects, converts non-instanceof Long:
77668             return fromBits(val.low, val.high, val.unsigned);
77669         }
77670
77671         /**
77672          * Converts the specified value to a Long.
77673          * @function
77674          * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val Value
77675          * @returns {!Long}
77676          */
77677         Long.fromValue = fromValue;
77678
77679         // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
77680         // no runtime penalty for these.
77681
77682         /**
77683          * @type {number}
77684          * @const
77685          * @inner
77686          */
77687         var TWO_PWR_16_DBL = 1 << 16;
77688
77689         /**
77690          * @type {number}
77691          * @const
77692          * @inner
77693          */
77694         var TWO_PWR_24_DBL = 1 << 24;
77695
77696         /**
77697          * @type {number}
77698          * @const
77699          * @inner
77700          */
77701         var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
77702
77703         /**
77704          * @type {number}
77705          * @const
77706          * @inner
77707          */
77708         var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;
77709
77710         /**
77711          * @type {number}
77712          * @const
77713          * @inner
77714          */
77715         var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;
77716
77717         /**
77718          * @type {!Long}
77719          * @const
77720          * @inner
77721          */
77722         var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL);
77723
77724         /**
77725          * @type {!Long}
77726          * @inner
77727          */
77728         var ZERO = fromInt(0);
77729
77730         /**
77731          * Signed zero.
77732          * @type {!Long}
77733          */
77734         Long.ZERO = ZERO;
77735
77736         /**
77737          * @type {!Long}
77738          * @inner
77739          */
77740         var UZERO = fromInt(0, true);
77741
77742         /**
77743          * Unsigned zero.
77744          * @type {!Long}
77745          */
77746         Long.UZERO = UZERO;
77747
77748         /**
77749          * @type {!Long}
77750          * @inner
77751          */
77752         var ONE = fromInt(1);
77753
77754         /**
77755          * Signed one.
77756          * @type {!Long}
77757          */
77758         Long.ONE = ONE;
77759
77760         /**
77761          * @type {!Long}
77762          * @inner
77763          */
77764         var UONE = fromInt(1, true);
77765
77766         /**
77767          * Unsigned one.
77768          * @type {!Long}
77769          */
77770         Long.UONE = UONE;
77771
77772         /**
77773          * @type {!Long}
77774          * @inner
77775          */
77776         var NEG_ONE = fromInt(-1);
77777
77778         /**
77779          * Signed negative one.
77780          * @type {!Long}
77781          */
77782         Long.NEG_ONE = NEG_ONE;
77783
77784         /**
77785          * @type {!Long}
77786          * @inner
77787          */
77788         var MAX_VALUE = fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false);
77789
77790         /**
77791          * Maximum signed value.
77792          * @type {!Long}
77793          */
77794         Long.MAX_VALUE = MAX_VALUE;
77795
77796         /**
77797          * @type {!Long}
77798          * @inner
77799          */
77800         var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true);
77801
77802         /**
77803          * Maximum unsigned value.
77804          * @type {!Long}
77805          */
77806         Long.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE;
77807
77808         /**
77809          * @type {!Long}
77810          * @inner
77811          */
77812         var MIN_VALUE = fromBits(0, 0x80000000|0, false);
77813
77814         /**
77815          * Minimum signed value.
77816          * @type {!Long}
77817          */
77818         Long.MIN_VALUE = MIN_VALUE;
77819
77820         /**
77821          * @alias Long.prototype
77822          * @inner
77823          */
77824         var LongPrototype = Long.prototype;
77825
77826         /**
77827          * Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
77828          * @returns {number}
77829          */
77830         LongPrototype.toInt = function toInt() {
77831             return this.unsigned ? this.low >>> 0 : this.low;
77832         };
77833
77834         /**
77835          * Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa).
77836          * @returns {number}
77837          */
77838         LongPrototype.toNumber = function toNumber() {
77839             if (this.unsigned)
77840                 return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0);
77841             return this.high * TWO_PWR_32_DBL + (this.low >>> 0);
77842         };
77843
77844         /**
77845          * Converts the Long to a string written in the specified radix.
77846          * @param {number=} radix Radix (2-36), defaults to 10
77847          * @returns {string}
77848          * @override
77849          * @throws {RangeError} If `radix` is out of range
77850          */
77851         LongPrototype.toString = function toString(radix) {
77852             radix = radix || 10;
77853             if (radix < 2 || 36 < radix)
77854                 throw RangeError('radix');
77855             if (this.isZero())
77856                 return '0';
77857             if (this.isNegative()) { // Unsigned Longs are never negative
77858                 if (this.eq(MIN_VALUE)) {
77859                     // We need to change the Long value before it can be negated, so we remove
77860                     // the bottom-most digit in this base and then recurse to do the rest.
77861                     var radixLong = fromNumber(radix),
77862                         div = this.div(radixLong),
77863                         rem1 = div.mul(radixLong).sub(this);
77864                     return div.toString(radix) + rem1.toInt().toString(radix);
77865                 } else
77866                     return '-' + this.neg().toString(radix);
77867             }
77868
77869             // Do several (6) digits each time through the loop, so as to
77870             // minimize the calls to the very expensive emulated div.
77871             var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned),
77872                 rem = this;
77873             var result = '';
77874             while (true) {
77875                 var remDiv = rem.div(radixToPower),
77876                     intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0,
77877                     digits = intval.toString(radix);
77878                 rem = remDiv;
77879                 if (rem.isZero())
77880                     return digits + result;
77881                 else {
77882                     while (digits.length < 6)
77883                         digits = '0' + digits;
77884                     result = '' + digits + result;
77885                 }
77886             }
77887         };
77888
77889         /**
77890          * Gets the high 32 bits as a signed integer.
77891          * @returns {number} Signed high bits
77892          */
77893         LongPrototype.getHighBits = function getHighBits() {
77894             return this.high;
77895         };
77896
77897         /**
77898          * Gets the high 32 bits as an unsigned integer.
77899          * @returns {number} Unsigned high bits
77900          */
77901         LongPrototype.getHighBitsUnsigned = function getHighBitsUnsigned() {
77902             return this.high >>> 0;
77903         };
77904
77905         /**
77906          * Gets the low 32 bits as a signed integer.
77907          * @returns {number} Signed low bits
77908          */
77909         LongPrototype.getLowBits = function getLowBits() {
77910             return this.low;
77911         };
77912
77913         /**
77914          * Gets the low 32 bits as an unsigned integer.
77915          * @returns {number} Unsigned low bits
77916          */
77917         LongPrototype.getLowBitsUnsigned = function getLowBitsUnsigned() {
77918             return this.low >>> 0;
77919         };
77920
77921         /**
77922          * Gets the number of bits needed to represent the absolute value of this Long.
77923          * @returns {number}
77924          */
77925         LongPrototype.getNumBitsAbs = function getNumBitsAbs() {
77926             if (this.isNegative()) // Unsigned Longs are never negative
77927                 return this.eq(MIN_VALUE) ? 64 : this.neg().getNumBitsAbs();
77928             var val = this.high != 0 ? this.high : this.low;
77929             for (var bit = 31; bit > 0; bit--)
77930                 if ((val & (1 << bit)) != 0)
77931                     break;
77932             return this.high != 0 ? bit + 33 : bit + 1;
77933         };
77934
77935         /**
77936          * Tests if this Long's value equals zero.
77937          * @returns {boolean}
77938          */
77939         LongPrototype.isZero = function isZero() {
77940             return this.high === 0 && this.low === 0;
77941         };
77942
77943         /**
77944          * Tests if this Long's value is negative.
77945          * @returns {boolean}
77946          */
77947         LongPrototype.isNegative = function isNegative() {
77948             return !this.unsigned && this.high < 0;
77949         };
77950
77951         /**
77952          * Tests if this Long's value is positive.
77953          * @returns {boolean}
77954          */
77955         LongPrototype.isPositive = function isPositive() {
77956             return this.unsigned || this.high >= 0;
77957         };
77958
77959         /**
77960          * Tests if this Long's value is odd.
77961          * @returns {boolean}
77962          */
77963         LongPrototype.isOdd = function isOdd() {
77964             return (this.low & 1) === 1;
77965         };
77966
77967         /**
77968          * Tests if this Long's value is even.
77969          * @returns {boolean}
77970          */
77971         LongPrototype.isEven = function isEven() {
77972             return (this.low & 1) === 0;
77973         };
77974
77975         /**
77976          * Tests if this Long's value equals the specified's.
77977          * @param {!Long|number|string} other Other value
77978          * @returns {boolean}
77979          */
77980         LongPrototype.equals = function equals(other) {
77981             if (!isLong(other))
77982                 other = fromValue(other);
77983             if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1)
77984                 return false;
77985             return this.high === other.high && this.low === other.low;
77986         };
77987
77988         /**
77989          * Tests if this Long's value equals the specified's. This is an alias of {@link Long#equals}.
77990          * @function
77991          * @param {!Long|number|string} other Other value
77992          * @returns {boolean}
77993          */
77994         LongPrototype.eq = LongPrototype.equals;
77995
77996         /**
77997          * Tests if this Long's value differs from the specified's.
77998          * @param {!Long|number|string} other Other value
77999          * @returns {boolean}
78000          */
78001         LongPrototype.notEquals = function notEquals(other) {
78002             return !this.eq(/* validates */ other);
78003         };
78004
78005         /**
78006          * Tests if this Long's value differs from the specified's. This is an alias of {@link Long#notEquals}.
78007          * @function
78008          * @param {!Long|number|string} other Other value
78009          * @returns {boolean}
78010          */
78011         LongPrototype.neq = LongPrototype.notEquals;
78012
78013         /**
78014          * Tests if this Long's value is less than the specified's.
78015          * @param {!Long|number|string} other Other value
78016          * @returns {boolean}
78017          */
78018         LongPrototype.lessThan = function lessThan(other) {
78019             return this.comp(/* validates */ other) < 0;
78020         };
78021
78022         /**
78023          * Tests if this Long's value is less than the specified's. This is an alias of {@link Long#lessThan}.
78024          * @function
78025          * @param {!Long|number|string} other Other value
78026          * @returns {boolean}
78027          */
78028         LongPrototype.lt = LongPrototype.lessThan;
78029
78030         /**
78031          * Tests if this Long's value is less than or equal the specified's.
78032          * @param {!Long|number|string} other Other value
78033          * @returns {boolean}
78034          */
78035         LongPrototype.lessThanOrEqual = function lessThanOrEqual(other) {
78036             return this.comp(/* validates */ other) <= 0;
78037         };
78038
78039         /**
78040          * Tests if this Long's value is less than or equal the specified's. This is an alias of {@link Long#lessThanOrEqual}.
78041          * @function
78042          * @param {!Long|number|string} other Other value
78043          * @returns {boolean}
78044          */
78045         LongPrototype.lte = LongPrototype.lessThanOrEqual;
78046
78047         /**
78048          * Tests if this Long's value is greater than the specified's.
78049          * @param {!Long|number|string} other Other value
78050          * @returns {boolean}
78051          */
78052         LongPrototype.greaterThan = function greaterThan(other) {
78053             return this.comp(/* validates */ other) > 0;
78054         };
78055
78056         /**
78057          * Tests if this Long's value is greater than the specified's. This is an alias of {@link Long#greaterThan}.
78058          * @function
78059          * @param {!Long|number|string} other Other value
78060          * @returns {boolean}
78061          */
78062         LongPrototype.gt = LongPrototype.greaterThan;
78063
78064         /**
78065          * Tests if this Long's value is greater than or equal the specified's.
78066          * @param {!Long|number|string} other Other value
78067          * @returns {boolean}
78068          */
78069         LongPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) {
78070             return this.comp(/* validates */ other) >= 0;
78071         };
78072
78073         /**
78074          * Tests if this Long's value is greater than or equal the specified's. This is an alias of {@link Long#greaterThanOrEqual}.
78075          * @function
78076          * @param {!Long|number|string} other Other value
78077          * @returns {boolean}
78078          */
78079         LongPrototype.gte = LongPrototype.greaterThanOrEqual;
78080
78081         /**
78082          * Compares this Long's value with the specified's.
78083          * @param {!Long|number|string} other Other value
78084          * @returns {number} 0 if they are the same, 1 if the this is greater and -1
78085          *  if the given one is greater
78086          */
78087         LongPrototype.compare = function compare(other) {
78088             if (!isLong(other))
78089                 other = fromValue(other);
78090             if (this.eq(other))
78091                 return 0;
78092             var thisNeg = this.isNegative(),
78093                 otherNeg = other.isNegative();
78094             if (thisNeg && !otherNeg)
78095                 return -1;
78096             if (!thisNeg && otherNeg)
78097                 return 1;
78098             // At this point the sign bits are the same
78099             if (!this.unsigned)
78100                 return this.sub(other).isNegative() ? -1 : 1;
78101             // Both are positive if at least one is unsigned
78102             return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
78103         };
78104
78105         /**
78106          * Compares this Long's value with the specified's. This is an alias of {@link Long#compare}.
78107          * @function
78108          * @param {!Long|number|string} other Other value
78109          * @returns {number} 0 if they are the same, 1 if the this is greater and -1
78110          *  if the given one is greater
78111          */
78112         LongPrototype.comp = LongPrototype.compare;
78113
78114         /**
78115          * Negates this Long's value.
78116          * @returns {!Long} Negated Long
78117          */
78118         LongPrototype.negate = function negate() {
78119             if (!this.unsigned && this.eq(MIN_VALUE))
78120                 return MIN_VALUE;
78121             return this.not().add(ONE);
78122         };
78123
78124         /**
78125          * Negates this Long's value. This is an alias of {@link Long#negate}.
78126          * @function
78127          * @returns {!Long} Negated Long
78128          */
78129         LongPrototype.neg = LongPrototype.negate;
78130
78131         /**
78132          * Returns the sum of this and the specified Long.
78133          * @param {!Long|number|string} addend Addend
78134          * @returns {!Long} Sum
78135          */
78136         LongPrototype.add = function add(addend) {
78137             if (!isLong(addend))
78138                 addend = fromValue(addend);
78139
78140             // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
78141
78142             var a48 = this.high >>> 16;
78143             var a32 = this.high & 0xFFFF;
78144             var a16 = this.low >>> 16;
78145             var a00 = this.low & 0xFFFF;
78146
78147             var b48 = addend.high >>> 16;
78148             var b32 = addend.high & 0xFFFF;
78149             var b16 = addend.low >>> 16;
78150             var b00 = addend.low & 0xFFFF;
78151
78152             var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
78153             c00 += a00 + b00;
78154             c16 += c00 >>> 16;
78155             c00 &= 0xFFFF;
78156             c16 += a16 + b16;
78157             c32 += c16 >>> 16;
78158             c16 &= 0xFFFF;
78159             c32 += a32 + b32;
78160             c48 += c32 >>> 16;
78161             c32 &= 0xFFFF;
78162             c48 += a48 + b48;
78163             c48 &= 0xFFFF;
78164             return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
78165         };
78166
78167         /**
78168          * Returns the difference of this and the specified Long.
78169          * @param {!Long|number|string} subtrahend Subtrahend
78170          * @returns {!Long} Difference
78171          */
78172         LongPrototype.subtract = function subtract(subtrahend) {
78173             if (!isLong(subtrahend))
78174                 subtrahend = fromValue(subtrahend);
78175             return this.add(subtrahend.neg());
78176         };
78177
78178         /**
78179          * Returns the difference of this and the specified Long. This is an alias of {@link Long#subtract}.
78180          * @function
78181          * @param {!Long|number|string} subtrahend Subtrahend
78182          * @returns {!Long} Difference
78183          */
78184         LongPrototype.sub = LongPrototype.subtract;
78185
78186         /**
78187          * Returns the product of this and the specified Long.
78188          * @param {!Long|number|string} multiplier Multiplier
78189          * @returns {!Long} Product
78190          */
78191         LongPrototype.multiply = function multiply(multiplier) {
78192             if (this.isZero())
78193                 return ZERO;
78194             if (!isLong(multiplier))
78195                 multiplier = fromValue(multiplier);
78196             if (multiplier.isZero())
78197                 return ZERO;
78198             if (this.eq(MIN_VALUE))
78199                 return multiplier.isOdd() ? MIN_VALUE : ZERO;
78200             if (multiplier.eq(MIN_VALUE))
78201                 return this.isOdd() ? MIN_VALUE : ZERO;
78202
78203             if (this.isNegative()) {
78204                 if (multiplier.isNegative())
78205                     return this.neg().mul(multiplier.neg());
78206                 else
78207                     return this.neg().mul(multiplier).neg();
78208             } else if (multiplier.isNegative())
78209                 return this.mul(multiplier.neg()).neg();
78210
78211             // If both longs are small, use float multiplication
78212             if (this.lt(TWO_PWR_24) && multiplier.lt(TWO_PWR_24))
78213                 return fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned);
78214
78215             // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
78216             // We can skip products that would overflow.
78217
78218             var a48 = this.high >>> 16;
78219             var a32 = this.high & 0xFFFF;
78220             var a16 = this.low >>> 16;
78221             var a00 = this.low & 0xFFFF;
78222
78223             var b48 = multiplier.high >>> 16;
78224             var b32 = multiplier.high & 0xFFFF;
78225             var b16 = multiplier.low >>> 16;
78226             var b00 = multiplier.low & 0xFFFF;
78227
78228             var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
78229             c00 += a00 * b00;
78230             c16 += c00 >>> 16;
78231             c00 &= 0xFFFF;
78232             c16 += a16 * b00;
78233             c32 += c16 >>> 16;
78234             c16 &= 0xFFFF;
78235             c16 += a00 * b16;
78236             c32 += c16 >>> 16;
78237             c16 &= 0xFFFF;
78238             c32 += a32 * b00;
78239             c48 += c32 >>> 16;
78240             c32 &= 0xFFFF;
78241             c32 += a16 * b16;
78242             c48 += c32 >>> 16;
78243             c32 &= 0xFFFF;
78244             c32 += a00 * b32;
78245             c48 += c32 >>> 16;
78246             c32 &= 0xFFFF;
78247             c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
78248             c48 &= 0xFFFF;
78249             return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
78250         };
78251
78252         /**
78253          * Returns the product of this and the specified Long. This is an alias of {@link Long#multiply}.
78254          * @function
78255          * @param {!Long|number|string} multiplier Multiplier
78256          * @returns {!Long} Product
78257          */
78258         LongPrototype.mul = LongPrototype.multiply;
78259
78260         /**
78261          * Returns this Long divided by the specified. The result is signed if this Long is signed or
78262          *  unsigned if this Long is unsigned.
78263          * @param {!Long|number|string} divisor Divisor
78264          * @returns {!Long} Quotient
78265          */
78266         LongPrototype.divide = function divide(divisor) {
78267             if (!isLong(divisor))
78268                 divisor = fromValue(divisor);
78269             if (divisor.isZero())
78270                 throw Error('division by zero');
78271             if (this.isZero())
78272                 return this.unsigned ? UZERO : ZERO;
78273             var approx, rem, res;
78274             if (!this.unsigned) {
78275                 // This section is only relevant for signed longs and is derived from the
78276                 // closure library as a whole.
78277                 if (this.eq(MIN_VALUE)) {
78278                     if (divisor.eq(ONE) || divisor.eq(NEG_ONE))
78279                         return MIN_VALUE;  // recall that -MIN_VALUE == MIN_VALUE
78280                     else if (divisor.eq(MIN_VALUE))
78281                         return ONE;
78282                     else {
78283                         // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
78284                         var halfThis = this.shr(1);
78285                         approx = halfThis.div(divisor).shl(1);
78286                         if (approx.eq(ZERO)) {
78287                             return divisor.isNegative() ? ONE : NEG_ONE;
78288                         } else {
78289                             rem = this.sub(divisor.mul(approx));
78290                             res = approx.add(rem.div(divisor));
78291                             return res;
78292                         }
78293                     }
78294                 } else if (divisor.eq(MIN_VALUE))
78295                     return this.unsigned ? UZERO : ZERO;
78296                 if (this.isNegative()) {
78297                     if (divisor.isNegative())
78298                         return this.neg().div(divisor.neg());
78299                     return this.neg().div(divisor).neg();
78300                 } else if (divisor.isNegative())
78301                     return this.div(divisor.neg()).neg();
78302                 res = ZERO;
78303             } else {
78304                 // The algorithm below has not been made for unsigned longs. It's therefore
78305                 // required to take special care of the MSB prior to running it.
78306                 if (!divisor.unsigned)
78307                     divisor = divisor.toUnsigned();
78308                 if (divisor.gt(this))
78309                     return UZERO;
78310                 if (divisor.gt(this.shru(1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true
78311                     return UONE;
78312                 res = UZERO;
78313             }
78314
78315             // Repeat the following until the remainder is less than other:  find a
78316             // floating-point that approximates remainder / other *from below*, add this
78317             // into the result, and subtract it from the remainder.  It is critical that
78318             // the approximate value is less than or equal to the real value so that the
78319             // remainder never becomes negative.
78320             rem = this;
78321             while (rem.gte(divisor)) {
78322                 // Approximate the result of division. This may be a little greater or
78323                 // smaller than the actual value.
78324                 approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber()));
78325
78326                 // We will tweak the approximate result by changing it in the 48-th digit or
78327                 // the smallest non-fractional digit, whichever is larger.
78328                 var log2 = Math.ceil(Math.log(approx) / Math.LN2),
78329                     delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48),
78330
78331                 // Decrease the approximation until it is smaller than the remainder.  Note
78332                 // that if it is too large, the product overflows and is negative.
78333                     approxRes = fromNumber(approx),
78334                     approxRem = approxRes.mul(divisor);
78335                 while (approxRem.isNegative() || approxRem.gt(rem)) {
78336                     approx -= delta;
78337                     approxRes = fromNumber(approx, this.unsigned);
78338                     approxRem = approxRes.mul(divisor);
78339                 }
78340
78341                 // We know the answer can't be zero... and actually, zero would cause
78342                 // infinite recursion since we would make no progress.
78343                 if (approxRes.isZero())
78344                     approxRes = ONE;
78345
78346                 res = res.add(approxRes);
78347                 rem = rem.sub(approxRem);
78348             }
78349             return res;
78350         };
78351
78352         /**
78353          * Returns this Long divided by the specified. This is an alias of {@link Long#divide}.
78354          * @function
78355          * @param {!Long|number|string} divisor Divisor
78356          * @returns {!Long} Quotient
78357          */
78358         LongPrototype.div = LongPrototype.divide;
78359
78360         /**
78361          * Returns this Long modulo the specified.
78362          * @param {!Long|number|string} divisor Divisor
78363          * @returns {!Long} Remainder
78364          */
78365         LongPrototype.modulo = function modulo(divisor) {
78366             if (!isLong(divisor))
78367                 divisor = fromValue(divisor);
78368             return this.sub(this.div(divisor).mul(divisor));
78369         };
78370
78371         /**
78372          * Returns this Long modulo the specified. This is an alias of {@link Long#modulo}.
78373          * @function
78374          * @param {!Long|number|string} divisor Divisor
78375          * @returns {!Long} Remainder
78376          */
78377         LongPrototype.mod = LongPrototype.modulo;
78378
78379         /**
78380          * Returns the bitwise NOT of this Long.
78381          * @returns {!Long}
78382          */
78383         LongPrototype.not = function not() {
78384             return fromBits(~this.low, ~this.high, this.unsigned);
78385         };
78386
78387         /**
78388          * Returns the bitwise AND of this Long and the specified.
78389          * @param {!Long|number|string} other Other Long
78390          * @returns {!Long}
78391          */
78392         LongPrototype.and = function and(other) {
78393             if (!isLong(other))
78394                 other = fromValue(other);
78395             return fromBits(this.low & other.low, this.high & other.high, this.unsigned);
78396         };
78397
78398         /**
78399          * Returns the bitwise OR of this Long and the specified.
78400          * @param {!Long|number|string} other Other Long
78401          * @returns {!Long}
78402          */
78403         LongPrototype.or = function or(other) {
78404             if (!isLong(other))
78405                 other = fromValue(other);
78406             return fromBits(this.low | other.low, this.high | other.high, this.unsigned);
78407         };
78408
78409         /**
78410          * Returns the bitwise XOR of this Long and the given one.
78411          * @param {!Long|number|string} other Other Long
78412          * @returns {!Long}
78413          */
78414         LongPrototype.xor = function xor(other) {
78415             if (!isLong(other))
78416                 other = fromValue(other);
78417             return fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned);
78418         };
78419
78420         /**
78421          * Returns this Long with bits shifted to the left by the given amount.
78422          * @param {number|!Long} numBits Number of bits
78423          * @returns {!Long} Shifted Long
78424          */
78425         LongPrototype.shiftLeft = function shiftLeft(numBits) {
78426             if (isLong(numBits))
78427                 numBits = numBits.toInt();
78428             if ((numBits &= 63) === 0)
78429                 return this;
78430             else if (numBits < 32)
78431                 return fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned);
78432             else
78433                 return fromBits(0, this.low << (numBits - 32), this.unsigned);
78434         };
78435
78436         /**
78437          * Returns this Long with bits shifted to the left by the given amount. This is an alias of {@link Long#shiftLeft}.
78438          * @function
78439          * @param {number|!Long} numBits Number of bits
78440          * @returns {!Long} Shifted Long
78441          */
78442         LongPrototype.shl = LongPrototype.shiftLeft;
78443
78444         /**
78445          * Returns this Long with bits arithmetically shifted to the right by the given amount.
78446          * @param {number|!Long} numBits Number of bits
78447          * @returns {!Long} Shifted Long
78448          */
78449         LongPrototype.shiftRight = function shiftRight(numBits) {
78450             if (isLong(numBits))
78451                 numBits = numBits.toInt();
78452             if ((numBits &= 63) === 0)
78453                 return this;
78454             else if (numBits < 32)
78455                 return fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned);
78456             else
78457                 return fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned);
78458         };
78459
78460         /**
78461          * Returns this Long with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Long#shiftRight}.
78462          * @function
78463          * @param {number|!Long} numBits Number of bits
78464          * @returns {!Long} Shifted Long
78465          */
78466         LongPrototype.shr = LongPrototype.shiftRight;
78467
78468         /**
78469          * Returns this Long with bits logically shifted to the right by the given amount.
78470          * @param {number|!Long} numBits Number of bits
78471          * @returns {!Long} Shifted Long
78472          */
78473         LongPrototype.shiftRightUnsigned = function shiftRightUnsigned(numBits) {
78474             if (isLong(numBits))
78475                 numBits = numBits.toInt();
78476             numBits &= 63;
78477             if (numBits === 0)
78478                 return this;
78479             else {
78480                 var high = this.high;
78481                 if (numBits < 32) {
78482                     var low = this.low;
78483                     return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned);
78484                 } else if (numBits === 32)
78485                     return fromBits(high, 0, this.unsigned);
78486                 else
78487                     return fromBits(high >>> (numBits - 32), 0, this.unsigned);
78488             }
78489         };
78490
78491         /**
78492          * Returns this Long with bits logically shifted to the right by the given amount. This is an alias of {@link Long#shiftRightUnsigned}.
78493          * @function
78494          * @param {number|!Long} numBits Number of bits
78495          * @returns {!Long} Shifted Long
78496          */
78497         LongPrototype.shru = LongPrototype.shiftRightUnsigned;
78498
78499         /**
78500          * Converts this Long to signed.
78501          * @returns {!Long} Signed long
78502          */
78503         LongPrototype.toSigned = function toSigned() {
78504             if (!this.unsigned)
78505                 return this;
78506             return fromBits(this.low, this.high, false);
78507         };
78508
78509         /**
78510          * Converts this Long to unsigned.
78511          * @returns {!Long} Unsigned long
78512          */
78513         LongPrototype.toUnsigned = function toUnsigned() {
78514             if (this.unsigned)
78515                 return this;
78516             return fromBits(this.low, this.high, true);
78517         };
78518
78519         /**
78520          * Converts this Long to its byte representation.
78521          * @param {boolean=} le Whether little or big endian, defaults to big endian
78522          * @returns {!Array.<number>} Byte representation
78523          */
78524         LongPrototype.toBytes = function(le) {
78525             return le ? this.toBytesLE() : this.toBytesBE();
78526         };
78527
78528         /**
78529          * Converts this Long to its little endian byte representation.
78530          * @returns {!Array.<number>} Little endian byte representation
78531          */
78532         LongPrototype.toBytesLE = function() {
78533             var hi = this.high,
78534                 lo = this.low;
78535             return [
78536                  lo         & 0xff,
78537                 (lo >>>  8) & 0xff,
78538                 (lo >>> 16) & 0xff,
78539                 (lo >>> 24) & 0xff,
78540                  hi         & 0xff,
78541                 (hi >>>  8) & 0xff,
78542                 (hi >>> 16) & 0xff,
78543                 (hi >>> 24) & 0xff
78544             ];
78545         };
78546
78547         /**
78548          * Converts this Long to its big endian byte representation.
78549          * @returns {!Array.<number>} Big endian byte representation
78550          */
78551         LongPrototype.toBytesBE = function() {
78552             var hi = this.high,
78553                 lo = this.low;
78554             return [
78555                 (hi >>> 24) & 0xff,
78556                 (hi >>> 16) & 0xff,
78557                 (hi >>>  8) & 0xff,
78558                  hi         & 0xff,
78559                 (lo >>> 24) & 0xff,
78560                 (lo >>> 16) & 0xff,
78561                 (lo >>>  8) & 0xff,
78562                  lo         & 0xff
78563             ];
78564         };
78565
78566         return Long;
78567     });
78568     }(long));
78569
78570     (function (module) {
78571     /// S2 Geometry functions
78572     // the regional scoreboard is based on a level 6 S2 Cell
78573     // - https://docs.google.com/presentation/d/1Hl4KapfAENAOf4gv-pSngKwvS_jwNVHRPZTTDzXXn6Q/view?pli=1#slide=id.i22
78574     // at the time of writing there's no actual API for the intel map to retrieve scoreboard data,
78575     // but it's still useful to plot the score cells on the intel map
78576
78577
78578     // the S2 geometry is based on projecting the earth sphere onto a cube, with some scaling of face coordinates to
78579     // keep things close to approximate equal area for adjacent cells
78580     // to convert a lat,lng into a cell id:
78581     // - convert lat,lng to x,y,z
78582     // - convert x,y,z into face,u,v
78583     // - u,v scaled to s,t with quadratic formula
78584     // - s,t converted to integer i,j offsets
78585     // - i,j converted to a position along a Hubbert space-filling curve
78586     // - combine face,position to get the cell id
78587
78588     //NOTE: compared to the google S2 geometry library, we vary from their code in the following ways
78589     // - cell IDs: they combine face and the hilbert curve position into a single 64 bit number. this gives efficient space
78590     //             and speed. javascript doesn't have appropriate data types, and speed is not cricical, so we use
78591     //             as [face,[bitpair,bitpair,...]] instead
78592     // - i,j: they always use 30 bits, adjusting as needed. we use 0 to (1<<level)-1 instead
78593     //        (so GetSizeIJ for a cell is always 1)
78594
78595     (function (exports) {
78596
78597     var S2 = exports.S2 = { L: {} };
78598
78599     S2.L.LatLng = function (/*Number*/ rawLat, /*Number*/ rawLng, /*Boolean*/ noWrap) {
78600       var lat = parseFloat(rawLat, 10);
78601       var lng = parseFloat(rawLng, 10);
78602
78603       if (isNaN(lat) || isNaN(lng)) {
78604         throw new Error('Invalid LatLng object: (' + rawLat + ', ' + rawLng + ')');
78605       }
78606
78607       if (noWrap !== true) {
78608         lat = Math.max(Math.min(lat, 90), -90);                 // clamp latitude into -90..90
78609         lng = (lng + 180) % 360 + ((lng < -180 || lng === 180) ? 180 : -180);   // wrap longtitude into -180..180
78610       }
78611
78612       return { lat: lat, lng: lng };
78613     };
78614
78615     S2.L.LatLng.DEG_TO_RAD = Math.PI / 180;
78616     S2.L.LatLng.RAD_TO_DEG = 180 / Math.PI;
78617
78618     /*
78619     S2.LatLngToXYZ = function(latLng) {
78620       // http://stackoverflow.com/questions/8981943/lat-long-to-x-y-z-position-in-js-not-working
78621       var lat = latLng.lat;
78622       var lon = latLng.lng;
78623       var DEG_TO_RAD = Math.PI / 180.0;
78624
78625       var phi = lat * DEG_TO_RAD;
78626       var theta = lon * DEG_TO_RAD;
78627
78628       var cosLat = Math.cos(phi);
78629       var sinLat = Math.sin(phi);
78630       var cosLon = Math.cos(theta);
78631       var sinLon = Math.sin(theta);
78632       var rad = 500.0;
78633
78634       return [
78635         rad * cosLat * cosLon
78636       , rad * cosLat * sinLon
78637       , rad * sinLat
78638       ];
78639     };
78640     */
78641     S2.LatLngToXYZ = function(latLng) {
78642       var d2r = S2.L.LatLng.DEG_TO_RAD;
78643
78644       var phi = latLng.lat*d2r;
78645       var theta = latLng.lng*d2r;
78646
78647       var cosphi = Math.cos(phi);
78648
78649       return [Math.cos(theta)*cosphi, Math.sin(theta)*cosphi, Math.sin(phi)];
78650     };
78651
78652     S2.XYZToLatLng = function(xyz) {
78653       var r2d = S2.L.LatLng.RAD_TO_DEG;
78654
78655       var lat = Math.atan2(xyz[2], Math.sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]));
78656       var lng = Math.atan2(xyz[1], xyz[0]);
78657
78658       return S2.L.LatLng(lat*r2d, lng*r2d);
78659     };
78660
78661     var largestAbsComponent = function(xyz) {
78662       var temp = [Math.abs(xyz[0]), Math.abs(xyz[1]), Math.abs(xyz[2])];
78663
78664       if (temp[0] > temp[1]) {
78665         if (temp[0] > temp[2]) {
78666           return 0;
78667         } else {
78668           return 2;
78669         }
78670       } else {
78671         if (temp[1] > temp[2]) {
78672           return 1;
78673         } else {
78674           return 2;
78675         }
78676       }
78677
78678     };
78679
78680     var faceXYZToUV = function(face,xyz) {
78681       var u,v;
78682
78683       switch (face) {
78684         case 0: u =  xyz[1]/xyz[0]; v =  xyz[2]/xyz[0]; break;
78685         case 1: u = -xyz[0]/xyz[1]; v =  xyz[2]/xyz[1]; break;
78686         case 2: u = -xyz[0]/xyz[2]; v = -xyz[1]/xyz[2]; break;
78687         case 3: u =  xyz[2]/xyz[0]; v =  xyz[1]/xyz[0]; break;
78688         case 4: u =  xyz[2]/xyz[1]; v = -xyz[0]/xyz[1]; break;
78689         case 5: u = -xyz[1]/xyz[2]; v = -xyz[0]/xyz[2]; break;
78690         default: throw {error: 'Invalid face'};
78691       }
78692
78693       return [u,v];
78694     };
78695
78696
78697
78698
78699     S2.XYZToFaceUV = function(xyz) {
78700       var face = largestAbsComponent(xyz);
78701
78702       if (xyz[face] < 0) {
78703         face += 3;
78704       }
78705
78706       var uv = faceXYZToUV (face,xyz);
78707
78708       return [face, uv];
78709     };
78710
78711     S2.FaceUVToXYZ = function(face,uv) {
78712       var u = uv[0];
78713       var v = uv[1];
78714
78715       switch (face) {
78716         case 0: return [ 1, u, v];
78717         case 1: return [-u, 1, v];
78718         case 2: return [-u,-v, 1];
78719         case 3: return [-1,-v,-u];
78720         case 4: return [ v,-1,-u];
78721         case 5: return [ v, u,-1];
78722         default: throw {error: 'Invalid face'};
78723       }
78724     };
78725
78726     var singleSTtoUV = function(st) {
78727       if (st >= 0.5) {
78728         return (1/3.0) * (4*st*st - 1);
78729       } else {
78730         return (1/3.0) * (1 - (4*(1-st)*(1-st)));
78731       }
78732     };
78733
78734     S2.STToUV = function(st) {
78735       return [singleSTtoUV(st[0]), singleSTtoUV(st[1])];
78736     };
78737
78738
78739     var singleUVtoST = function(uv) {
78740       if (uv >= 0) {
78741         return 0.5 * Math.sqrt (1 + 3*uv);
78742       } else {
78743         return 1 - 0.5 * Math.sqrt (1 - 3*uv);
78744       }
78745     };
78746     S2.UVToST = function(uv) {
78747       return [singleUVtoST(uv[0]), singleUVtoST(uv[1])];
78748     };
78749
78750
78751     S2.STToIJ = function(st,order) {
78752       var maxSize = (1<<order);
78753
78754       var singleSTtoIJ = function(st) {
78755         var ij = Math.floor(st * maxSize);
78756         return Math.max(0, Math.min(maxSize-1, ij));
78757       };
78758
78759       return [singleSTtoIJ(st[0]), singleSTtoIJ(st[1])];
78760     };
78761
78762
78763     S2.IJToST = function(ij,order,offsets) {
78764       var maxSize = (1<<order);
78765
78766       return [
78767         (ij[0]+offsets[0])/maxSize,
78768         (ij[1]+offsets[1])/maxSize
78769       ];
78770     };
78771
78772
78773
78774     var rotateAndFlipQuadrant = function(n, point, rx, ry)
78775     {
78776         if(ry == 0)
78777         {
78778                 if(rx == 1){
78779                         point.x = n - 1 - point.x;
78780                         point.y = n - 1 - point.y;
78781
78782                 }
78783
78784         var x = point.x;
78785                 point.x = point.y;
78786                 point.y = x;
78787         }
78788
78789     };
78790
78791
78792
78793
78794
78795     // hilbert space-filling curve
78796     // based on http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves
78797     // note: rather then calculating the final integer hilbert position, we just return the list of quads
78798     // this ensures no precision issues whth large orders (S3 cell IDs use up to 30), and is more
78799     // convenient for pulling out the individual bits as needed later
78800     var pointToHilbertQuadList = function(x,y,order,face) {
78801       var hilbertMap = {
78802         'a': [ [0,'d'], [1,'a'], [3,'b'], [2,'a'] ],
78803         'b': [ [2,'b'], [1,'b'], [3,'a'], [0,'c'] ],
78804         'c': [ [2,'c'], [3,'d'], [1,'c'], [0,'b'] ],
78805         'd': [ [0,'a'], [3,'c'], [1,'d'], [2,'d'] ]
78806       };
78807
78808       if ('number' !== typeof face) {
78809         console.warn(new Error("called pointToHilbertQuadList without face value, defaulting to '0'").stack);
78810       }
78811       var currentSquare = (face % 2) ? 'd' : 'a';
78812       var positions = [];
78813
78814       for (var i=order-1; i>=0; i--) {
78815
78816         var mask = 1<<i;
78817
78818         var quad_x = x&mask ? 1 : 0;
78819         var quad_y = y&mask ? 1 : 0;
78820
78821         var t = hilbertMap[currentSquare][quad_x*2+quad_y];
78822
78823         positions.push(t[0]);
78824
78825         currentSquare = t[1];
78826       }
78827
78828       return positions;
78829     };
78830
78831     // S2Cell class
78832
78833     S2.S2Cell = function(){};
78834
78835     S2.S2Cell.FromHilbertQuadKey = function(hilbertQuadkey) {
78836       var parts = hilbertQuadkey.split('/');
78837       var face = parseInt(parts[0]);
78838       var position = parts[1];
78839       var maxLevel = position.length;
78840       var point = {
78841         x : 0,
78842         y: 0
78843       };
78844       var i;
78845       var level;
78846       var bit;
78847       var rx, ry;
78848       var val;
78849
78850         for(i = maxLevel - 1; i >= 0; i--) {
78851
78852                 level = maxLevel - i;
78853                 bit = position[i];
78854                 rx = 0;
78855         ry = 0;
78856                 if (bit === '1') {
78857                         ry = 1;
78858                 }
78859                 else if (bit === '2') {
78860                         rx = 1;
78861                         ry = 1;
78862                 }
78863                 else if (bit === '3') {
78864                         rx = 1;
78865                 }
78866
78867                 val = Math.pow(2, level - 1);
78868                 rotateAndFlipQuadrant(val, point, rx, ry);
78869
78870                 point.x += val * rx;
78871                 point.y += val * ry;
78872
78873         }
78874
78875       if (face % 2 === 1) {
78876         var t = point.x;
78877         point.x = point.y;
78878         point.y = t;
78879       }
78880
78881
78882       return S2.S2Cell.FromFaceIJ(parseInt(face), [point.x, point.y], level);
78883     };
78884
78885     //static method to construct
78886     S2.S2Cell.FromLatLng = function(latLng, level) {
78887       if ((!latLng.lat && latLng.lat !== 0) || (!latLng.lng && latLng.lng !== 0)) {
78888         throw new Error("Pass { lat: lat, lng: lng } to S2.S2Cell.FromLatLng");
78889       }
78890       var xyz = S2.LatLngToXYZ(latLng);
78891
78892       var faceuv = S2.XYZToFaceUV(xyz);
78893       var st = S2.UVToST(faceuv[1]);
78894
78895       var ij = S2.STToIJ(st,level);
78896
78897       return S2.S2Cell.FromFaceIJ (faceuv[0], ij, level);
78898     };
78899
78900     /*
78901     S2.faceIjLevelToXyz = function (face, ij, level) {
78902       var st = S2.IJToST(ij, level, [0.5, 0.5]);
78903       var uv = S2.STToUV(st);
78904       var xyz = S2.FaceUVToXYZ(face, uv);
78905
78906       return S2.XYZToLatLng(xyz);
78907       return xyz;
78908     };
78909     */
78910
78911     S2.S2Cell.FromFaceIJ = function(face,ij,level) {
78912       var cell = new S2.S2Cell();
78913       cell.face = face;
78914       cell.ij = ij;
78915       cell.level = level;
78916
78917       return cell;
78918     };
78919
78920
78921     S2.S2Cell.prototype.toString = function() {
78922       return 'F'+this.face+'ij['+this.ij[0]+','+this.ij[1]+']@'+this.level;
78923     };
78924
78925     S2.S2Cell.prototype.getLatLng = function() {
78926       var st = S2.IJToST(this.ij,this.level, [0.5,0.5]);
78927       var uv = S2.STToUV(st);
78928       var xyz = S2.FaceUVToXYZ(this.face, uv);
78929
78930       return S2.XYZToLatLng(xyz);
78931     };
78932
78933     S2.S2Cell.prototype.getCornerLatLngs = function() {
78934       var result = [];
78935       var offsets = [
78936         [ 0.0, 0.0 ],
78937         [ 0.0, 1.0 ],
78938         [ 1.0, 1.0 ],
78939         [ 1.0, 0.0 ]
78940       ];
78941
78942       for (var i=0; i<4; i++) {
78943         var st = S2.IJToST(this.ij, this.level, offsets[i]);
78944         var uv = S2.STToUV(st);
78945         var xyz = S2.FaceUVToXYZ(this.face, uv);
78946
78947         result.push ( S2.XYZToLatLng(xyz) );
78948       }
78949       return result;
78950     };
78951
78952
78953     S2.S2Cell.prototype.getFaceAndQuads = function () {
78954       var quads = pointToHilbertQuadList(this.ij[0], this.ij[1], this.level, this.face);
78955
78956       return [this.face,quads];
78957     };
78958     S2.S2Cell.prototype.toHilbertQuadkey = function () {
78959       var quads = pointToHilbertQuadList(this.ij[0], this.ij[1], this.level, this.face);
78960
78961       return this.face.toString(10) + '/' + quads.join('');
78962     };
78963
78964     S2.latLngToNeighborKeys = S2.S2Cell.latLngToNeighborKeys = function (lat, lng, level) {
78965       return S2.S2Cell.FromLatLng({ lat: lat, lng: lng }, level).getNeighbors().map(function (cell) {
78966         return cell.toHilbertQuadkey();
78967       });
78968     };
78969     S2.S2Cell.prototype.getNeighbors = function() {
78970
78971       var fromFaceIJWrap = function(face,ij,level) {
78972         var maxSize = (1<<level);
78973         if (ij[0]>=0 && ij[1]>=0 && ij[0]<maxSize && ij[1]<maxSize) {
78974           // no wrapping out of bounds
78975           return S2.S2Cell.FromFaceIJ(face,ij,level);
78976         } else {
78977           // the new i,j are out of range.
78978           // with the assumption that they're only a little past the borders we can just take the points as
78979           // just beyond the cube face, project to XYZ, then re-create FaceUV from the XYZ vector
78980
78981           var st = S2.IJToST(ij,level,[0.5,0.5]);
78982           var uv = S2.STToUV(st);
78983           var xyz = S2.FaceUVToXYZ(face,uv);
78984           var faceuv = S2.XYZToFaceUV(xyz);
78985           face = faceuv[0];
78986           uv = faceuv[1];
78987           st = S2.UVToST(uv);
78988           ij = S2.STToIJ(st,level);
78989           return S2.S2Cell.FromFaceIJ (face, ij, level);
78990         }
78991       };
78992
78993       var face = this.face;
78994       var i = this.ij[0];
78995       var j = this.ij[1];
78996       var level = this.level;
78997
78998
78999       return [
79000         fromFaceIJWrap(face, [i-1,j], level),
79001         fromFaceIJWrap(face, [i,j-1], level),
79002         fromFaceIJWrap(face, [i+1,j], level),
79003         fromFaceIJWrap(face, [i,j+1], level)
79004       ];
79005
79006     };
79007
79008     //
79009     // Functional Style
79010     //
79011     S2.FACE_BITS = 3;
79012     S2.MAX_LEVEL = 30;
79013     S2.POS_BITS = (2 * S2.MAX_LEVEL) + 1; // 61 (60 bits of data, 1 bit lsb marker)
79014
79015     S2.facePosLevelToId = S2.S2Cell.facePosLevelToId = S2.fromFacePosLevel = function (faceN, posS, levelN) {
79016       var Long = exports.dcodeIO && exports.dcodeIO.Long || long.exports;
79017       var faceB;
79018       var posB;
79019       var bin;
79020
79021       if (!levelN) {
79022         levelN = posS.length;
79023       }
79024       if (posS.length > levelN) {
79025         posS = posS.substr(0, levelN);
79026       }
79027
79028       // 3-bit face value
79029       faceB = Long.fromString(faceN.toString(10), true, 10).toString(2);
79030       while (faceB.length < S2.FACE_BITS) {
79031         faceB = '0' + faceB;
79032       }
79033
79034       // 60-bit position value
79035       posB = Long.fromString(posS, true, 4).toString(2);
79036       while (posB.length < (2 * levelN)) {
79037         posB = '0' + posB;
79038       }
79039
79040       bin = faceB + posB;
79041       // 1-bit lsb marker
79042       bin += '1';
79043       // n-bit padding to 64-bits
79044       while (bin.length < (S2.FACE_BITS + S2.POS_BITS)) {
79045         bin += '0';
79046       }
79047
79048       return Long.fromString(bin, true, 2).toString(10);
79049     };
79050
79051     S2.keyToId = S2.S2Cell.keyToId
79052     = S2.toId = S2.toCellId = S2.fromKey
79053     = function (key) {
79054       var parts = key.split('/');
79055
79056       return S2.fromFacePosLevel(parts[0], parts[1], parts[1].length);
79057     };
79058
79059     S2.idToKey = S2.S2Cell.idToKey
79060     = S2.S2Cell.toKey = S2.toKey
79061     = S2.fromId = S2.fromCellId
79062     = S2.S2Cell.toHilbertQuadkey  = S2.toHilbertQuadkey
79063     = function (idS) {
79064       var Long = exports.dcodeIO && exports.dcodeIO.Long || long.exports;
79065       var bin = Long.fromString(idS, true, 10).toString(2);
79066
79067       while (bin.length < (S2.FACE_BITS + S2.POS_BITS)) {
79068         bin = '0' + bin;
79069       }
79070
79071       // MUST come AFTER binstr has been left-padded with '0's
79072       var lsbIndex = bin.lastIndexOf('1');
79073       // substr(start, len)
79074       // substring(start, end) // includes start, does not include end
79075       var faceB = bin.substring(0, 3);
79076       // posB will always be a multiple of 2 (or it's invalid)
79077       var posB = bin.substring(3, lsbIndex);
79078       var levelN = posB.length / 2;
79079
79080       var faceS = Long.fromString(faceB, true, 2).toString(10);
79081       var posS = Long.fromString(posB, true, 2).toString(4);
79082
79083       while (posS.length < levelN) {
79084         posS = '0' + posS;
79085       }
79086
79087       return faceS + '/' + posS;
79088     };
79089
79090     S2.keyToLatLng = S2.S2Cell.keyToLatLng = function (key) {
79091       var cell2 = S2.S2Cell.FromHilbertQuadKey(key);
79092       return cell2.getLatLng();
79093     };
79094
79095     S2.idToLatLng = S2.S2Cell.idToLatLng = function (id) {
79096       var key = S2.idToKey(id);
79097       return S2.keyToLatLng(key);
79098     };
79099
79100     S2.S2Cell.latLngToKey = S2.latLngToKey
79101     = S2.latLngToQuadkey = function (lat, lng, level) {
79102       if (isNaN(level) || level < 1 || level > 30) {
79103         throw new Error("'level' is not a number between 1 and 30 (but it should be)");
79104       }
79105       // TODO
79106       //
79107       // S2.idToLatLng(id)
79108       // S2.keyToLatLng(key)
79109       // S2.nextFace(key)     // prevent wrapping on nextKey
79110       // S2.prevFace(key)     // prevent wrapping on prevKey
79111       //
79112       // .toKeyArray(id)  // face,quadtree
79113       // .toKey(id)       // hilbert
79114       // .toPoint(id)     // ij
79115       // .toId(key)       // uint64 (as string)
79116       // .toLong(key)     // long.js
79117       // .toLatLng(id)    // object? or array?, or string (with comma)?
79118       //
79119       // maybe S2.HQ.x, S2.GPS.x, S2.CI.x?
79120       return S2.S2Cell.FromLatLng({ lat: lat, lng: lng }, level).toHilbertQuadkey();
79121     };
79122
79123     S2.stepKey = function (key, num) {
79124       var Long = exports.dcodeIO && exports.dcodeIO.Long || long.exports;
79125       var parts = key.split('/');
79126
79127       var faceS = parts[0];
79128       var posS = parts[1];
79129       var level = parts[1].length;
79130
79131       var posL = Long.fromString(posS, true, 4);
79132       // TODO handle wrapping (0 === pos + 1)
79133       // (only on the 12 edges of the globe)
79134       var otherL;
79135       if (num > 0) {
79136         otherL = posL.add(Math.abs(num));
79137       }
79138       else if (num < 0) {
79139         otherL = posL.subtract(Math.abs(num));
79140       }
79141       var otherS = otherL.toString(4);
79142
79143       if ('0' === otherS) {
79144         console.warning(new Error("face/position wrapping is not yet supported"));
79145       }
79146
79147       while (otherS.length < level) {
79148         otherS = '0' + otherS;
79149       }
79150
79151       return faceS + '/' + otherS;
79152     };
79153
79154     S2.S2Cell.prevKey = S2.prevKey = function (key) {
79155       return S2.stepKey(key, -1);
79156     };
79157
79158     S2.S2Cell.nextKey = S2.nextKey = function (key) {
79159       return S2.stepKey(key, 1);
79160     };
79161
79162     })(module.exports );
79163     }(s2geometry));
79164
79165     /**
79166      * @class S2GeometryProvider
79167      *
79168      * @classdesc Geometry provider based on S2 cells.
79169      *
79170      * @example
79171      * ```js
79172      * class MyDataProvider extends DataProviderBase {
79173      *      ...
79174      * }
79175      *
79176      * const geometryProvider = new S2GeometryProvider();
79177      * const dataProvider = new MyDataProvider(geometryProvider);
79178      * ```
79179      */
79180     class S2GeometryProvider extends GeometryProviderBase {
79181         /**
79182          * Create a new S2 geometry provider instance.
79183          */
79184         constructor(_level = 17) {
79185             super();
79186             this._level = _level;
79187         }
79188         /** @inheritdoc */
79189         bboxToCellIds(sw, ne) {
79190             return this._approxBboxToCellIds(sw, ne);
79191         }
79192         /** @inheritdoc */
79193         getAdjacent(cellId) {
79194             const k = s2geometry.exports.S2.idToKey(cellId);
79195             const position = k.split('/')[1];
79196             const level = position.length;
79197             const [a0, a1, a2, a3] = this._getNeighbors(k, level);
79198             const existing = [k, a0, a1, a2, a3];
79199             const others = Array
79200                 .from(new Set([
79201                 ...this._getNeighbors(a0, level),
79202                 ...this._getNeighbors(a1, level),
79203                 ...this._getNeighbors(a2, level),
79204                 ...this._getNeighbors(a3, level),
79205             ].filter((o) => {
79206                 return !existing.includes(o);
79207             })));
79208             const adjacent = [a0, a1, a2, a3];
79209             for (const other of others) {
79210                 let count = 0;
79211                 for (const n of this._getNeighbors(other, level)) {
79212                     if (existing.includes(n)) {
79213                         count++;
79214                     }
79215                 }
79216                 if (count === 2) {
79217                     adjacent.push(other);
79218                 }
79219             }
79220             return adjacent.map((a) => s2geometry.exports.S2.keyToId(a));
79221         }
79222         /** @inheritdoc */
79223         getVertices(cellId) {
79224             const key = s2geometry.exports.S2.idToKey(cellId);
79225             const cell = s2geometry.exports.S2.S2Cell.FromHilbertQuadKey(key);
79226             return cell
79227                 .getCornerLatLngs()
79228                 .map((c) => {
79229                 return { lat: c.lat, lng: c.lng };
79230             });
79231         }
79232         /** @inheritdoc */
79233         lngLatToCellId(lngLat) {
79234             return this._lngLatToId(lngLat, this._level);
79235         }
79236         _getNeighbors(s2key, level) {
79237             const latlng = s2geometry.exports.S2.keyToLatLng(s2key);
79238             const neighbors = s2geometry.exports.S2.latLngToNeighborKeys(latlng.lat, latlng.lng, level);
79239             return neighbors;
79240         }
79241         _lngLatToId(lngLat, level) {
79242             const s2key = s2geometry.exports.S2.latLngToKey(lngLat.lat, lngLat.lng, level);
79243             return s2geometry.exports.S2.keyToId(s2key);
79244         }
79245     }
79246
79247     function convertCameraType(graphCameraType) {
79248         switch (graphCameraType) {
79249             case "equirectangular":
79250             case "spherical":
79251                 return "spherical";
79252             case "fisheye":
79253                 return "fisheye";
79254             default:
79255                 return "perspective";
79256         }
79257     }
79258     class GraphConverter {
79259         clusterReconstruction(source) {
79260             const id = null;
79261             const points = source.points;
79262             const normalize = 1 / 255;
79263             for (const pointId in points) {
79264                 if (!points.hasOwnProperty(pointId)) {
79265                     continue;
79266                 }
79267                 const color = points[pointId].color;
79268                 color[0] *= normalize;
79269                 color[1] *= normalize;
79270                 color[2] *= normalize;
79271             }
79272             const lla = source.reference_lla;
79273             const reference = {
79274                 alt: lla.altitude,
79275                 lat: lla.latitude,
79276                 lng: lla.longitude,
79277             };
79278             return {
79279                 id,
79280                 points,
79281                 reference,
79282             };
79283         }
79284         coreImage(source) {
79285             const geometry = this._geometry(source.geometry);
79286             const computedGeometry = this._geometry(source.computed_geometry);
79287             const sequence = { id: source.sequence };
79288             const id = source.id;
79289             return {
79290                 computed_geometry: computedGeometry,
79291                 geometry,
79292                 id,
79293                 sequence,
79294             };
79295         }
79296         spatialImage(source) {
79297             var _a, _b, _c, _d;
79298             source.camera_type = convertCameraType(source.camera_type);
79299             source.merge_id = source.merge_cc ? source.merge_cc.toString() : null;
79300             source.private = null;
79301             const thumbUrl = source.camera_type === 'spherical' ?
79302                 source.thumb_2048_url : source.thumb_1024_url;
79303             source.thumb = (_a = source.thumb) !== null && _a !== void 0 ? _a : { id: null, url: thumbUrl };
79304             source.cluster = (_b = source.sfm_cluster) !== null && _b !== void 0 ? _b : { id: null, url: null };
79305             source.creator = { id: null, username: null };
79306             source.owner = (_c = source.organization) !== null && _c !== void 0 ? _c : { id: null };
79307             source.mesh = (_d = source.mesh) !== null && _d !== void 0 ? _d : { id: null, url: null };
79308             return source;
79309         }
79310         _geometry(geometry) {
79311             const coords = geometry === null || geometry === void 0 ? void 0 : geometry.coordinates;
79312             const lngLat = coords ?
79313                 {
79314                     lat: coords[1],
79315                     lng: coords[0],
79316                 } : null;
79317             return lngLat;
79318         }
79319     }
79320
79321     class GraphQueryCreator {
79322         constructor() {
79323             this.imagesPath = 'images';
79324             this.sequencePath = 'image_ids';
79325             this._imageTilesPath = 'tiles';
79326             this.coreFields = ['computed_geometry', 'geometry', 'sequence'];
79327             this.idFields = ['id'];
79328             this.spatialFields = [
79329                 'altitude',
79330                 'atomic_scale',
79331                 'camera_parameters',
79332                 'camera_type',
79333                 'captured_at',
79334                 'compass_angle',
79335                 'computed_altitude',
79336                 'computed_compass_angle',
79337                 'computed_rotation',
79338                 'exif_orientation',
79339                 'height',
79340                 'merge_cc',
79341                 'mesh',
79342                 'organization',
79343                 'quality_score',
79344                 'sfm_cluster',
79345                 'thumb_1024_url',
79346                 'thumb_2048_url',
79347                 'width',
79348             ];
79349             this.imageTileFields = ['url', 'z', 'x', 'y'];
79350         }
79351         images(imageIds, fields) {
79352             return `image_ids=${imageIds.join(',')}&fields=${fields.join(',')}`;
79353         }
79354         imagesS2(cellId, fields) {
79355             return `s2=${cellId}&fields=${fields.join(',')}`;
79356         }
79357         imageTiles(z, fields) {
79358             return `z=${z}&fields=${fields.join(',')}`;
79359         }
79360         imageTilesPath(imageId) {
79361             return `${imageId}/${this._imageTilesPath}`;
79362         }
79363         sequence(sequenceId) {
79364             return `sequence_id=${sequenceId}`;
79365         }
79366     }
79367
79368     class GraphDataProvider extends DataProviderBase {
79369         constructor(options, geometry, converter, queryCreator) {
79370             var _a;
79371             super(geometry !== null && geometry !== void 0 ? geometry : new S2GeometryProvider());
79372             this._convert = converter !== null && converter !== void 0 ? converter : new GraphConverter();
79373             this._query = queryCreator !== null && queryCreator !== void 0 ? queryCreator : new GraphQueryCreator();
79374             this._method = 'GET';
79375             const opts = options !== null && options !== void 0 ? options : {};
79376             this._endpoint = (_a = opts.endpoint) !== null && _a !== void 0 ? _a : "https://graph.mapillary.com";
79377             this._accessToken = opts.accessToken;
79378         }
79379         getCluster(url, abort) {
79380             return fetchArrayBuffer(url, abort)
79381                 .then((buffer) => {
79382                 const reconstructions = decompress(buffer);
79383                 if (reconstructions.length < 1) {
79384                     throw new Error('Cluster reconstruction empty');
79385                 }
79386                 return this._convert
79387                     .clusterReconstruction(reconstructions[0]);
79388             });
79389         }
79390         getCoreImages(cellId) {
79391             const fields = [
79392                 ...this._query.idFields,
79393                 ...this._query.coreFields,
79394             ];
79395             const query = this._query.imagesS2(cellId, fields);
79396             const url = new URL(this._query.imagesPath, this._endpoint).href;
79397             return this
79398                 ._fetchGraphContract(query, url)
79399                 .then(r => {
79400                 const result = {
79401                     cell_id: cellId,
79402                     images: [],
79403                 };
79404                 const items = r.data;
79405                 for (const item of items) {
79406                     const coreImage = this._convert.coreImage(item);
79407                     result.images.push(coreImage);
79408                 }
79409                 return result;
79410             });
79411         }
79412         getImageBuffer(url, abort) {
79413             return fetchArrayBuffer(url, abort);
79414         }
79415         getImages(imageIds) {
79416             const fields = [
79417                 ...this._query.idFields,
79418                 ...this._query.coreFields,
79419                 ...this._query.spatialFields,
79420             ];
79421             const query = this._query.images(imageIds, fields);
79422             const url = new URL(this._query.imagesPath, this._endpoint).href;
79423             return this
79424                 ._fetchGraphContract(query, url)
79425                 .then(r => {
79426                 const result = [];
79427                 const items = r.data;
79428                 for (const item of items) {
79429                     const coreImage = this._convert.coreImage(item);
79430                     const spatialImage = this._convert.spatialImage(item);
79431                     const image = Object.assign({}, spatialImage, coreImage);
79432                     const contract = {
79433                         node: image,
79434                         node_id: item.id,
79435                     };
79436                     result.push(contract);
79437                 }
79438                 return result;
79439             });
79440         }
79441         getImageTiles(request) {
79442             const fields = [
79443                 ...this._query.imageTileFields,
79444             ];
79445             const query = this._query.imageTiles(request.z, fields);
79446             const url = new URL(this._query.imageTilesPath(request.imageId), this._endpoint).href;
79447             return this
79448                 ._fetchGraphContract(query, url)
79449                 .then(r => {
79450                 const result = {
79451                     node: r.data,
79452                     node_id: request.imageId,
79453                 };
79454                 return result;
79455             });
79456         }
79457         getMesh(url, abort) {
79458             return fetchArrayBuffer(url, abort)
79459                 .then((buffer) => {
79460                 return readMeshPbf(buffer);
79461             });
79462         }
79463         getSequence(sequenceId) {
79464             const query = this._query.sequence(sequenceId);
79465             const url = new URL(this._query.sequencePath, this._endpoint).href;
79466             return this
79467                 ._fetchGraphContract(query, url)
79468                 .then(r => {
79469                 const result = {
79470                     id: sequenceId,
79471                     image_ids: r.data.map(item => item.id),
79472                 };
79473                 return result;
79474             });
79475         }
79476         getSpatialImages(imageIds) {
79477             const fields = [
79478                 ...this._query.idFields,
79479                 ...this._query.coreFields,
79480                 ...this._query.spatialFields,
79481             ];
79482             const query = this._query.images(imageIds, fields);
79483             const url = new URL(this._query.imagesPath, this._endpoint).href;
79484             return this
79485                 ._fetchGraphContract(query, url)
79486                 .then(r => {
79487                 const result = [];
79488                 const items = r.data;
79489                 for (const item of items) {
79490                     const spatialImage = this._convert.spatialImage(item);
79491                     const contract = {
79492                         node: spatialImage,
79493                         node_id: item.id,
79494                     };
79495                     result.push(contract);
79496                 }
79497                 return result;
79498             });
79499         }
79500         setAccessToken(accessToken) {
79501             this._accessToken = accessToken;
79502         }
79503         _createHeaders() {
79504             const headers = [
79505                 { name: 'Accept', value: 'application/json' },
79506                 {
79507                     name: 'Content-Type',
79508                     value: 'application/x-www-form-urlencoded',
79509                 },
79510             ];
79511             if (this._accessToken) {
79512                 headers.push({
79513                     name: 'Authorization',
79514                     value: `OAuth ${this._accessToken}`,
79515                 });
79516             }
79517             return headers;
79518         }
79519         _fetchGraphContract(body, url) {
79520             const method = this._method;
79521             const headers = this._createHeaders();
79522             const query = `${url}?${body}`;
79523             return xhrFetch(query, method, "json", headers, null, null)
79524                 .catch((error) => {
79525                 const message = this._makeErrorMessage(error);
79526                 throw new MapillaryError(message);
79527             });
79528         }
79529         _makeErrorMessage(graphError) {
79530             const error = graphError.error;
79531             const message = error ?
79532                 `${error.code} (${error.type}, ${error.fbtrace_id}): ${error.message}` :
79533                 "Failed to fetch data";
79534             return message;
79535         }
79536     }
79537
79538     /**
79539      * @class Marker
79540      *
79541      * @classdesc Represents an abstract marker class that should be extended
79542      * by marker implementations used in the marker component.
79543      */
79544     class Marker {
79545         constructor(id, lngLat) {
79546             this._id = id;
79547             this._lngLat = lngLat;
79548         }
79549         /**
79550          * Get id.
79551          * @returns {string} The id of the marker.
79552          */
79553         get id() {
79554             return this._id;
79555         }
79556         /**
79557          * Get geometry.
79558          *
79559          * @ignore
79560          */
79561         get geometry() {
79562             return this._geometry;
79563         }
79564         /**
79565          * Get lngLat.
79566          * @returns {LngLat} The geographic coordinates of the marker.
79567          */
79568         get lngLat() {
79569             return this._lngLat;
79570         }
79571         /** @ignore */
79572         createGeometry(position) {
79573             if (!!this._geometry) {
79574                 return;
79575             }
79576             this._createGeometry(position);
79577             // update matrix world if raycasting occurs before first render
79578             this._geometry.updateMatrixWorld(true);
79579         }
79580         /** @ignore */
79581         disposeGeometry() {
79582             if (!this._geometry) {
79583                 return;
79584             }
79585             this._disposeGeometry();
79586             this._geometry = undefined;
79587         }
79588         /** @ignore */
79589         getInteractiveObjects() {
79590             if (!this._geometry) {
79591                 return [];
79592             }
79593             return this._getInteractiveObjects();
79594         }
79595         /** @ignore */
79596         lerpAltitude(alt, alpha) {
79597             if (!this._geometry) {
79598                 return;
79599             }
79600             this._geometry.position.z =
79601                 (1 - alpha) * this._geometry.position.z + alpha * alt;
79602         }
79603         /** @ignore */
79604         updatePosition(position, lngLat) {
79605             if (!!lngLat) {
79606                 this._lngLat.lat = lngLat.lat;
79607                 this._lngLat.lng = lngLat.lng;
79608             }
79609             if (!this._geometry) {
79610                 return;
79611             }
79612             this._geometry.position.fromArray(position);
79613             this._geometry.updateMatrixWorld(true);
79614         }
79615     }
79616
79617     /**
79618      * @class CircleMarker
79619      *
79620      * @classdesc Non-interactive marker with a flat circle shape. The circle
79621      * marker can not be configured to be interactive.
79622      *
79623      * Circle marker properties can not be updated after creation.
79624      *
79625      * To create and add one `CircleMarker` with default configuration
79626      * and one with configuration use
79627      *
79628      * @example
79629      * ```js
79630      * var defaultMarker = new CircleMarker(
79631      *     "id-1",
79632      *     { lat: 0, lng: 0, });
79633      *
79634      * var configuredMarker = new CircleMarker(
79635      *     "id-2",
79636      *     { lat: 0, lng: 0, },
79637      *     {
79638      *         color: "#0ff",
79639      *         opacity: 0.3,
79640      *         radius: 0.7,
79641      *     });
79642      *
79643      * markerComponent.add([defaultMarker, configuredMarker]);
79644      * ```
79645      */
79646     class CircleMarker extends Marker {
79647         constructor(id, lngLat, options) {
79648             super(id, lngLat);
79649             options = !!options ? options : {};
79650             this._color = options.color != null ? options.color : 0xffffff;
79651             this._opacity = options.opacity != null ? options.opacity : 0.4;
79652             this._radius = options.radius != null ? options.radius : 1;
79653         }
79654         _createGeometry(position) {
79655             const circle = new Mesh(new CircleGeometry(this._radius, 16), new MeshBasicMaterial({
79656                 color: this._color,
79657                 opacity: this._opacity,
79658                 transparent: true,
79659             }));
79660             circle.up.fromArray([0, 0, 1]);
79661             circle.renderOrder = -1;
79662             const group = new Object3D();
79663             group.add(circle);
79664             group.position.fromArray(position);
79665             this._geometry = group;
79666         }
79667         _disposeGeometry() {
79668             for (let mesh of this._geometry.children) {
79669                 mesh.geometry.dispose();
79670                 mesh.material.dispose();
79671             }
79672         }
79673         _getInteractiveObjects() {
79674             return [];
79675         }
79676     }
79677
79678     /**
79679      * @class SimpleMarker
79680      *
79681      * @classdesc Interactive marker with ice cream shape. The sphere
79682      * inside the ice cream can be configured to be interactive.
79683      *
79684      * Simple marker properties can not be updated after creation.
79685      *
79686      * To create and add one `SimpleMarker` with default configuration
79687      * (non-interactive) and one interactive with configuration use
79688      *
79689      * @example
79690      * ```js
79691      * var defaultMarker = new SimpleMarker(
79692      *     "id-1",
79693      *     { lat: 0, lng: 0, });
79694      *
79695      * var interactiveMarker = new SimpleMarker(
79696      *     "id-2",
79697      *     { lat: 0, lng: 0, },
79698      *     {
79699      *         ballColor: "#00f",
79700      *         ballOpacity: 0.5,
79701      *         color: "#00f",
79702      *         interactive: true,
79703      *         opacity: 0.3,
79704      *         radius: 0.7,
79705      *     });
79706      *
79707      * markerComponent.add([defaultMarker, interactiveMarker]);
79708      * ```
79709      */
79710     class SimpleMarker extends Marker {
79711         constructor(id, lngLat, options) {
79712             super(id, lngLat);
79713             options = !!options ? options : {};
79714             this._ballColor = options.ballColor != null ? options.ballColor : 0xff0000;
79715             this._ballOpacity = options.ballOpacity != null ? options.ballOpacity : 0.8;
79716             this._circleToRayAngle = 2;
79717             this._color = options.color != null ? options.color : 0xff0000;
79718             this._interactive = !!options.interactive;
79719             this._opacity = options.opacity != null ? options.opacity : 0.4;
79720             this._radius = options.radius != null ? options.radius : 1;
79721         }
79722         _createGeometry(position) {
79723             const radius = this._radius;
79724             const height = this._markerHeight(radius);
79725             const markerMaterial = new MeshBasicMaterial({
79726                 color: this._color,
79727                 opacity: this._opacity,
79728                 transparent: true,
79729                 depthWrite: false,
79730             });
79731             const marker = new Mesh(this._createMarkerGeometry(radius, 8, 8), markerMaterial);
79732             const interactive = new Mesh(new SphereGeometry(radius / 2, 8, 8), new MeshBasicMaterial({
79733                 color: this._ballColor,
79734                 opacity: this._ballOpacity,
79735                 transparent: true,
79736             }));
79737             interactive.position.z = height;
79738             interactive.renderOrder = 1;
79739             const group = new Object3D();
79740             group.add(interactive);
79741             group.add(marker);
79742             group.position.fromArray(position);
79743             this._geometry = group;
79744         }
79745         _disposeGeometry() {
79746             for (const mesh of this._geometry.children) {
79747                 mesh.geometry.dispose();
79748                 mesh.material.dispose();
79749             }
79750         }
79751         _getInteractiveObjects() {
79752             return this._interactive ? [this._geometry.children[0]] : [];
79753         }
79754         _markerHeight(radius) {
79755             const t = Math.tan(Math.PI - this._circleToRayAngle);
79756             return radius * Math.sqrt(1 + t * t);
79757         }
79758         _createMarkerGeometry(radius, widthSegments, heightSegments) {
79759             const height = this._markerHeight(radius);
79760             const circleToRayAngle = this._circleToRayAngle;
79761             const indexRows = [];
79762             const positions = new Float32Array(3 * (widthSegments + 1) * (heightSegments + 1));
79763             let positionIndex = 0;
79764             for (let y = 0; y <= heightSegments; ++y) {
79765                 const indexRow = [];
79766                 for (let x = 0; x <= widthSegments; ++x) {
79767                     const u = x / widthSegments * Math.PI * 2;
79768                     const v = y / heightSegments * Math.PI;
79769                     let r = radius;
79770                     if (v > circleToRayAngle) {
79771                         const t = Math.tan(v - circleToRayAngle);
79772                         r = radius * Math.sqrt(1 + t * t);
79773                     }
79774                     const arrayIndex = 3 * positionIndex;
79775                     const sinv = Math.sin(v);
79776                     positions[arrayIndex + 0] = r * Math.cos(u) * sinv;
79777                     positions[arrayIndex + 1] = r * Math.sin(u) * sinv;
79778                     positions[arrayIndex + 2] = r * Math.cos(v) + height;
79779                     indexRow.push(positionIndex++);
79780                 }
79781                 indexRows.push(indexRow);
79782             }
79783             const indices = new Uint16Array(6 * widthSegments * heightSegments);
79784             let index = 0;
79785             for (let y = 0; y < heightSegments; ++y) {
79786                 for (let x = 0; x < widthSegments; ++x) {
79787                     const pi1 = indexRows[y][x + 1];
79788                     const pi2 = indexRows[y][x];
79789                     const pi3 = indexRows[y + 1][x];
79790                     const pi4 = indexRows[y + 1][x + 1];
79791                     indices[index++] = pi1;
79792                     indices[index++] = pi2;
79793                     indices[index++] = pi4;
79794                     indices[index++] = pi2;
79795                     indices[index++] = pi3;
79796                     indices[index++] = pi4;
79797                 }
79798             }
79799             const geometry = new BufferGeometry();
79800             const positionAttribute = new BufferAttribute(positions, 3);
79801             geometry.setAttribute("position", positionAttribute);
79802             geometry.setIndex(new BufferAttribute(indices, 1));
79803             return geometry;
79804         }
79805     }
79806
79807     /**
79808      * @class Popup
79809      *
79810      * @classdesc Popup instance for rendering custom HTML content
79811      * on top of images. Popups are based on 2D basic image coordinates
79812      * (see the {@link Viewer} class documentation for more information about coordinate
79813      * systems) and a certain popup is therefore only relevant to a single image.
79814      * Popups related to a certain image should be removed when moving
79815      * to another image.
79816      *
79817      * A popup must have both its content and its point or rect set to be
79818      * rendered. Popup options can not be updated after creation but the
79819      * basic point or rect as well as its content can be changed by calling
79820      * the appropriate methods.
79821      *
79822      * To create and add one `Popup` with default configuration
79823      * (tooltip visuals and automatic float) and one with specific options
79824      * use
79825      *
79826      * @example
79827      * ```js
79828      * var defaultSpan = document.createElement('span');
79829      * defaultSpan.innerHTML = 'hello default';
79830      *
79831      * var defaultPopup = new Popup();
79832      * defaultPopup.setDOMContent(defaultSpan);
79833      * defaultPopup.setBasicPoint([0.3, 0.3]);
79834      *
79835      * var cleanSpan = document.createElement('span');
79836      * cleanSpan.innerHTML = 'hello clean';
79837      *
79838      * var cleanPopup = new Popup({
79839      *     clean: true,
79840      *     float: Alignment.Top,
79841      *     offset: 10,
79842      *     opacity: 0.7,
79843      * });
79844      *
79845      * cleanPopup.setDOMContent(cleanSpan);
79846      * cleanPopup.setBasicPoint([0.6, 0.6]);
79847      *
79848      * popupComponent.add([defaultPopup, cleanPopup]);
79849      * ```
79850      *
79851      * @description Implementation of API methods and API documentation inspired
79852      * by/used from https://github.com/mapbox/mapbox-gl-js/blob/v0.38.0/src/ui/popup.js
79853      */
79854     class Popup {
79855         constructor(options, viewportCoords, dom) {
79856             this._options = {};
79857             options = !!options ? options : {};
79858             this._options.capturePointer = options.capturePointer === false ?
79859                 options.capturePointer : true;
79860             this._options.clean = options.clean;
79861             this._options.float = options.float;
79862             this._options.offset = options.offset;
79863             this._options.opacity = options.opacity;
79864             this._options.position = options.position;
79865             this._dom = !!dom ? dom : new DOM();
79866             this._viewportCoords = !!viewportCoords ? viewportCoords : new ViewportCoords();
79867             this._notifyChanged$ = new Subject();
79868         }
79869         /**
79870          * @description Internal observable used by the component to
79871          * render the popup when its position or content has changed.
79872          * @ignore
79873          */
79874         get changed$() {
79875             return this._notifyChanged$;
79876         }
79877         /**
79878          * @description Internal method used by the component to
79879          * remove all references to the popup.
79880          * @ignore
79881          */
79882         remove() {
79883             if (this._content && this._content.parentNode) {
79884                 this._content.parentNode.removeChild(this._content);
79885             }
79886             if (this._container) {
79887                 this._container.parentNode.removeChild(this._container);
79888                 delete this._container;
79889             }
79890             if (this._parentContainer) {
79891                 delete this._parentContainer;
79892             }
79893         }
79894         /**
79895          * Sets a 2D basic image coordinates point to the popup's anchor, and
79896          * moves the popup to it.
79897          *
79898          * @description Overwrites any previously set point or rect.
79899          *
79900          * @param {Array<number>} basicPoint - Point in 2D basic image coordinates.
79901          *
79902          * @example
79903          * ```js
79904          * var popup = new Popup();
79905          * popup.setText('hello image');
79906          * popup.setBasicPoint([0.3, 0.3]);
79907          *
79908          * popupComponent.add([popup]);
79909          * ```
79910          */
79911         setBasicPoint(basicPoint) {
79912             this._point = basicPoint.slice();
79913             this._rect = null;
79914             this._notifyChanged$.next(this);
79915         }
79916         /**
79917          * Sets a 2D basic image coordinates rect to the popup's anchor, and
79918          * moves the popup to it.
79919          *
79920          * @description Overwrites any previously set point or rect.
79921          *
79922          * @param {Array<number>} basicRect - Rect in 2D basic image
79923          * coordinates ([topLeftX, topLeftY, bottomRightX, bottomRightY]) .
79924          *
79925          * @example
79926          * ```js
79927          * var popup = new Popup();
79928          * popup.setText('hello image');
79929          * popup.setBasicRect([0.3, 0.3, 0.5, 0.6]);
79930          *
79931          * popupComponent.add([popup]);
79932          * ```
79933          */
79934         setBasicRect(basicRect) {
79935             this._rect = basicRect.slice();
79936             this._point = null;
79937             this._notifyChanged$.next(this);
79938         }
79939         /**
79940          * Sets the popup's content to the element provided as a DOM node.
79941          *
79942          * @param {Node} htmlNode - A DOM node to be used as content for the popup.
79943          *
79944          * @example
79945          * ```js
79946          * var div = document.createElement('div');
79947          * div.innerHTML = 'hello image';
79948          *
79949          * var popup = new Popup();
79950          * popup.setDOMContent(div);
79951          * popup.setBasicPoint([0.3, 0.3]);
79952          *
79953          * popupComponent.add([popup]);
79954          * ```
79955          */
79956         setDOMContent(htmlNode) {
79957             if (this._content && this._content.parentNode) {
79958                 this._content.parentNode.removeChild(this._content);
79959             }
79960             const className = "mapillary-popup-content" +
79961                 (this._options.clean === true ? "-clean" : "") +
79962                 (this._options.capturePointer === true ? " mapillary-popup-capture-pointer" : "");
79963             this._content = this._dom.createElement("div", className, this._container);
79964             this._content.appendChild(htmlNode);
79965             this._notifyChanged$.next(this);
79966         }
79967         /**
79968          * Sets the popup's content to the HTML provided as a string.
79969          *
79970          * @description This method does not perform HTML filtering or sanitization,
79971          * and must be used only with trusted content. Consider
79972          * {@link Popup.setText} if the
79973          * content is an untrusted text string.
79974          *
79975          * @param {string} html - A string representing HTML content for the popup.
79976          *
79977          * @example
79978          * ```js
79979          * var popup = new Popup();
79980          * popup.setHTML('<div>hello image</div>');
79981          * popup.setBasicPoint([0.3, 0.3]);
79982          *
79983          * popupComponent.add([popup]);
79984          * ```
79985          */
79986         setHTML(html) {
79987             const frag = this._dom.document.createDocumentFragment();
79988             const temp = this._dom.createElement("body");
79989             let child;
79990             temp.innerHTML = html;
79991             while (true) {
79992                 child = temp.firstChild;
79993                 if (!child) {
79994                     break;
79995                 }
79996                 frag.appendChild(child);
79997             }
79998             this.setDOMContent(frag);
79999         }
80000         /**
80001          * Sets the popup's content to a string of text.
80002          *
80003          * @description This function creates a Text node in the DOM, so it cannot insert raw HTML.
80004          * Use this method for security against XSS if the popup content is user-provided.
80005          *
80006          * @param {string} text - Textual content for the popup.
80007          *
80008          * @example
80009          * ```js
80010          * var popup = new Popup();
80011          * popup.setText('hello image');
80012          * popup.setBasicPoint([0.3, 0.3]);
80013          *
80014          * popupComponent.add([popup]);
80015          * ```
80016          */
80017         setText(text) {
80018             this.setDOMContent(this._dom.document.createTextNode(text));
80019         }
80020         /**
80021          * @description Internal method for attaching the popup to
80022          * its parent container so that it is rendered in the DOM tree.
80023          * @ignore
80024          */
80025         setParentContainer(parentContainer) {
80026             this._parentContainer = parentContainer;
80027         }
80028         /**
80029          * @description Internal method for updating the rendered
80030          * position of the popup called by the popup component.
80031          * @ignore
80032          */
80033         update(renderCamera, size, transform) {
80034             if (!this._parentContainer || !this._content) {
80035                 return;
80036             }
80037             if (!this._point && !this._rect) {
80038                 return;
80039             }
80040             if (!this._container) {
80041                 this._container = this._dom.createElement("div", "mapillary-popup", this._parentContainer);
80042                 const showTip = this._options.clean !== true &&
80043                     this._options.float !== exports.Alignment.Center;
80044                 if (showTip) {
80045                     const tipClassName = "mapillary-popup-tip" +
80046                         (this._options.capturePointer === true ? " mapillary-popup-capture-pointer" : "");
80047                     this._tip = this._dom.createElement("div", tipClassName, this._container);
80048                     this._dom.createElement("div", "mapillary-popup-tip-inner", this._tip);
80049                 }
80050                 this._container.appendChild(this._content);
80051                 this._parentContainer.appendChild(this._container);
80052                 if (this._options.opacity != null) {
80053                     this._container.style.opacity = this._options.opacity.toString();
80054                 }
80055             }
80056             let pointPixel = null;
80057             let position = this._alignmentToPopupAligment(this._options.position);
80058             let float = this._alignmentToPopupAligment(this._options.float);
80059             const classList = this._container.classList;
80060             if (this._point != null) {
80061                 pointPixel =
80062                     this._viewportCoords.basicToCanvasSafe(this._point[0], this._point[1], { offsetHeight: size.height, offsetWidth: size.width }, transform, renderCamera.perspective);
80063             }
80064             else {
80065                 const alignments = ["center", "top", "bottom", "left", "right", "top-left", "top-right", "bottom-left", "bottom-right"];
80066                 let appliedPosition = null;
80067                 for (const alignment of alignments) {
80068                     if (classList.contains(`mapillary-popup-float-${alignment}`)) {
80069                         appliedPosition = alignment;
80070                         break;
80071                     }
80072                 }
80073                 [pointPixel, position] = this._rectToPixel(this._rect, position, appliedPosition, renderCamera, size, transform);
80074                 if (!float) {
80075                     float = position;
80076                 }
80077             }
80078             if (pointPixel == null) {
80079                 this._container.style.display = "none";
80080                 return;
80081             }
80082             this._container.style.display = "";
80083             if (!float) {
80084                 const width = this._container.offsetWidth;
80085                 const height = this._container.offsetHeight;
80086                 const floats = this._pixelToFloats(pointPixel, size, width, height);
80087                 float = floats.length === 0 ? "top" : floats.join("-");
80088             }
80089             const offset = this._normalizeOffset(this._options.offset);
80090             pointPixel = [pointPixel[0] + offset[float][0], pointPixel[1] + offset[float][1]];
80091             pointPixel = [Math.round(pointPixel[0]), Math.round(pointPixel[1])];
80092             const floatTranslate = {
80093                 "bottom": "translate(-50%,0)",
80094                 "bottom-left": "translate(-100%,0)",
80095                 "bottom-right": "translate(0,0)",
80096                 "center": "translate(-50%,-50%)",
80097                 "left": "translate(-100%,-50%)",
80098                 "right": "translate(0,-50%)",
80099                 "top": "translate(-50%,-100%)",
80100                 "top-left": "translate(-100%,-100%)",
80101                 "top-right": "translate(0,-100%)",
80102             };
80103             for (const key in floatTranslate) {
80104                 if (!floatTranslate.hasOwnProperty(key)) {
80105                     continue;
80106                 }
80107                 classList.remove(`mapillary-popup-float-${key}`);
80108             }
80109             classList.add(`mapillary-popup-float-${float}`);
80110             this._container.style.transform = `${floatTranslate[float]} translate(${pointPixel[0]}px,${pointPixel[1]}px)`;
80111         }
80112         _rectToPixel(rect, position, appliedPosition, renderCamera, size, transform) {
80113             if (!position) {
80114                 const width = this._container.offsetWidth;
80115                 const height = this._container.offsetHeight;
80116                 const floatOffsets = {
80117                     "bottom": [0, height / 2],
80118                     "bottom-left": [-width / 2, height / 2],
80119                     "bottom-right": [width / 2, height / 2],
80120                     "left": [-width / 2, 0],
80121                     "right": [width / 2, 0],
80122                     "top": [0, -height / 2],
80123                     "top-left": [-width / 2, -height / 2],
80124                     "top-right": [width / 2, -height / 2],
80125                 };
80126                 const automaticPositions = ["top", "bottom", "left", "right"];
80127                 let largestVisibleArea = [0, null, null];
80128                 for (const automaticPosition of automaticPositions) {
80129                     const autoPointBasic = this._pointFromRectPosition(rect, automaticPosition);
80130                     const autoPointPixel = this._viewportCoords.basicToCanvasSafe(autoPointBasic[0], autoPointBasic[1], { offsetHeight: size.height, offsetWidth: size.width }, transform, renderCamera.perspective);
80131                     if (autoPointPixel == null) {
80132                         continue;
80133                     }
80134                     const floatOffset = floatOffsets[automaticPosition];
80135                     const offsetedPosition = [autoPointPixel[0] + floatOffset[0], autoPointPixel[1] + floatOffset[1]];
80136                     const staticCoeff = appliedPosition != null && appliedPosition === automaticPosition ? 1 : 0.7;
80137                     const floats = this._pixelToFloats(offsetedPosition, size, width / staticCoeff, height / (2 * staticCoeff));
80138                     if (floats.length === 0 &&
80139                         autoPointPixel[0] > 0 &&
80140                         autoPointPixel[0] < size.width &&
80141                         autoPointPixel[1] > 0 &&
80142                         autoPointPixel[1] < size.height) {
80143                         return [autoPointPixel, automaticPosition];
80144                     }
80145                     const minX = Math.max(offsetedPosition[0] - width / 2, 0);
80146                     const maxX = Math.min(offsetedPosition[0] + width / 2, size.width);
80147                     const minY = Math.max(offsetedPosition[1] - height / 2, 0);
80148                     const maxY = Math.min(offsetedPosition[1] + height / 2, size.height);
80149                     const visibleX = Math.max(0, maxX - minX);
80150                     const visibleY = Math.max(0, maxY - minY);
80151                     const visibleArea = staticCoeff * visibleX * visibleY;
80152                     if (visibleArea > largestVisibleArea[0]) {
80153                         largestVisibleArea[0] = visibleArea;
80154                         largestVisibleArea[1] = autoPointPixel;
80155                         largestVisibleArea[2] = automaticPosition;
80156                     }
80157                 }
80158                 if (largestVisibleArea[0] > 0) {
80159                     return [largestVisibleArea[1], largestVisibleArea[2]];
80160                 }
80161             }
80162             const pointBasic = this._pointFromRectPosition(rect, position);
80163             const pointPixel = this._viewportCoords.basicToCanvasSafe(pointBasic[0], pointBasic[1], { offsetHeight: size.height, offsetWidth: size.width }, transform, renderCamera.perspective);
80164             return [pointPixel, position != null ? position : "top"];
80165         }
80166         _alignmentToPopupAligment(float) {
80167             switch (float) {
80168                 case exports.Alignment.Bottom:
80169                     return "bottom";
80170                 case exports.Alignment.BottomLeft:
80171                     return "bottom-left";
80172                 case exports.Alignment.BottomRight:
80173                     return "bottom-right";
80174                 case exports.Alignment.Center:
80175                     return "center";
80176                 case exports.Alignment.Left:
80177                     return "left";
80178                 case exports.Alignment.Right:
80179                     return "right";
80180                 case exports.Alignment.Top:
80181                     return "top";
80182                 case exports.Alignment.TopLeft:
80183                     return "top-left";
80184                 case exports.Alignment.TopRight:
80185                     return "top-right";
80186                 default:
80187                     return null;
80188             }
80189         }
80190         _normalizeOffset(offset) {
80191             if (offset == null) {
80192                 return this._normalizeOffset(0);
80193             }
80194             if (typeof offset === "number") {
80195                 // input specifies a radius
80196                 const sideOffset = offset;
80197                 const sign = sideOffset >= 0 ? 1 : -1;
80198                 const cornerOffset = sign * Math.round(Math.sqrt(0.5 * Math.pow(sideOffset, 2)));
80199                 return {
80200                     "bottom": [0, sideOffset],
80201                     "bottom-left": [-cornerOffset, cornerOffset],
80202                     "bottom-right": [cornerOffset, cornerOffset],
80203                     "center": [0, 0],
80204                     "left": [-sideOffset, 0],
80205                     "right": [sideOffset, 0],
80206                     "top": [0, -sideOffset],
80207                     "top-left": [-cornerOffset, -cornerOffset],
80208                     "top-right": [cornerOffset, -cornerOffset],
80209                 };
80210             }
80211             else {
80212                 // input specifes a value for each position
80213                 return {
80214                     "bottom": offset.bottom || [0, 0],
80215                     "bottom-left": offset.bottomLeft || [0, 0],
80216                     "bottom-right": offset.bottomRight || [0, 0],
80217                     "center": offset.center || [0, 0],
80218                     "left": offset.left || [0, 0],
80219                     "right": offset.right || [0, 0],
80220                     "top": offset.top || [0, 0],
80221                     "top-left": offset.topLeft || [0, 0],
80222                     "top-right": offset.topRight || [0, 0],
80223                 };
80224             }
80225         }
80226         _pixelToFloats(pointPixel, size, width, height) {
80227             const floats = [];
80228             if (pointPixel[1] < height) {
80229                 floats.push("bottom");
80230             }
80231             else if (pointPixel[1] > size.height - height) {
80232                 floats.push("top");
80233             }
80234             if (pointPixel[0] < width / 2) {
80235                 floats.push("right");
80236             }
80237             else if (pointPixel[0] > size.width - width / 2) {
80238                 floats.push("left");
80239             }
80240             return floats;
80241         }
80242         _pointFromRectPosition(rect, position) {
80243             const x0 = rect[0];
80244             const x1 = rect[0] < rect[2] ? rect[2] : rect[2] + 1;
80245             const y0 = rect[1];
80246             const y1 = rect[3];
80247             switch (position) {
80248                 case "bottom":
80249                     return [(x0 + x1) / 2, y1];
80250                 case "bottom-left":
80251                     return [x0, y1];
80252                 case "bottom-right":
80253                     return [x1, y1];
80254                 case "center":
80255                     return [(x0 + x1) / 2, (y0 + y1) / 2];
80256                 case "left":
80257                     return [x0, (y0 + y1) / 2];
80258                 case "right":
80259                     return [x1, (y0 + y1) / 2];
80260                 case "top":
80261                     return [(x0 + x1) / 2, y0];
80262                 case "top-left":
80263                     return [x0, y0];
80264                 case "top-right":
80265                     return [x1, y0];
80266                 default:
80267                     return [(x0 + x1) / 2, y1];
80268             }
80269         }
80270     }
80271
80272     function isBrowser() {
80273         return (typeof window !== "undefined" &&
80274             typeof document !== "undefined");
80275     }
80276     function isArraySupported() {
80277         return !!(Array.prototype &&
80278             Array.prototype.concat &&
80279             Array.prototype.filter &&
80280             Array.prototype.includes &&
80281             Array.prototype.indexOf &&
80282             Array.prototype.join &&
80283             Array.prototype.map &&
80284             Array.prototype.push &&
80285             Array.prototype.pop &&
80286             Array.prototype.reverse &&
80287             Array.prototype.shift &&
80288             Array.prototype.slice &&
80289             Array.prototype.splice &&
80290             Array.prototype.sort &&
80291             Array.prototype.unshift);
80292     }
80293     function isBlobSupported() {
80294         return ("Blob" in window &&
80295             "URL" in window);
80296     }
80297     function isFunctionSupported() {
80298         return !!(Function.prototype &&
80299             Function.prototype.apply &&
80300             Function.prototype.bind);
80301     }
80302     function isJSONSupported() {
80303         return ("JSON" in window &&
80304             "parse" in JSON &&
80305             "stringify" in JSON);
80306     }
80307     function isMapSupported() {
80308         return "Map" in window;
80309     }
80310     function isObjectSupported() {
80311         return !!(Object.assign &&
80312             Object.keys &&
80313             Object.values);
80314     }
80315     function isPromiseSupported() {
80316         return !!("Promise" in window &&
80317             Promise.resolve &&
80318             Promise.reject &&
80319             Promise.prototype &&
80320             Promise.prototype.catch &&
80321             Promise.prototype.then);
80322     }
80323     function isSetSupported() {
80324         return "Set" in window;
80325     }
80326     let isWebGLSupportedCache = undefined;
80327     function isWebGLSupportedCached() {
80328         if (isWebGLSupportedCache === undefined) {
80329             isWebGLSupportedCache = isWebGLSupported();
80330         }
80331         return isWebGLSupportedCache;
80332     }
80333     function isWebGLSupported() {
80334         const attributes = {
80335             alpha: false,
80336             antialias: false,
80337             depth: true,
80338             failIfMajorPerformanceCaveat: false,
80339             premultipliedAlpha: true,
80340             preserveDrawingBuffer: false,
80341             stencil: true,
80342         };
80343         const canvas = document.createElement("canvas");
80344         const webGL2Context = canvas.getContext("webgl2", attributes);
80345         if (!!webGL2Context) {
80346             return true;
80347         }
80348         const context = canvas.getContext("webgl", attributes) ||
80349             canvas
80350                 .getContext("experimental-webgl", attributes);
80351         if (!context) {
80352             return false;
80353         }
80354         const requiredExtensions = ["OES_standard_derivatives"];
80355         const supportedExtensions = context.getSupportedExtensions();
80356         for (const requiredExtension of requiredExtensions) {
80357             if (supportedExtensions.indexOf(requiredExtension) === -1) {
80358                 return false;
80359             }
80360         }
80361         return true;
80362     }
80363     /**
80364      * Test whether the current browser supports the full
80365      * functionality of MapillaryJS.
80366      *
80367      * @description The full functionality includes WebGL rendering.
80368      *
80369      * @return {boolean}
80370      *
80371      * @example `var supported = isSupported();`
80372      */
80373     function isSupported() {
80374         return isFallbackSupported() &&
80375             isWebGLSupportedCached();
80376     }
80377     /**
80378      * Test whether the current browser supports the fallback
80379      * functionality of MapillaryJS.
80380      *
80381      * @description The fallback functionality does not include WebGL
80382      * rendering, only 2D canvas rendering.
80383      *
80384      * @return {boolean}
80385      *
80386      * @example `var fallbackSupported = isFallbackSupported();`
80387      */
80388     function isFallbackSupported() {
80389         return isBrowser() &&
80390             isArraySupported() &&
80391             isBlobSupported() &&
80392             isFunctionSupported() &&
80393             isJSONSupported() &&
80394             isMapSupported() &&
80395             isObjectSupported() &&
80396             isPromiseSupported() &&
80397             isSetSupported();
80398     }
80399
80400     /**
80401      * Enumeration for camera controls.
80402      *
80403      * @description Specifies different modes for how the
80404      * camera is controlled through pointer, keyboard or
80405      * other modes of input.
80406      *
80407      * @enum {number}
80408      * @readonly
80409      */
80410     exports.CameraControls = void 0;
80411     (function (CameraControls) {
80412         /**
80413          * Control the camera with custom logic by
80414          * attaching a custom camera controls
80415          * instance to the {@link Viewer}.
80416          */
80417         CameraControls[CameraControls["Custom"] = 0] = "Custom";
80418         /**
80419          * Control the camera from a birds perspective
80420          * to get an overview.
80421          */
80422         CameraControls[CameraControls["Earth"] = 1] = "Earth";
80423         /**
80424          * Control the camera in a first person view
80425          * from the street level perspective.
80426          */
80427         CameraControls[CameraControls["Street"] = 2] = "Street";
80428     })(exports.CameraControls || (exports.CameraControls = {}));
80429
80430     /**
80431      * Enumeration for render mode
80432      * @enum {number}
80433      * @readonly
80434      * @description Modes for specifying how rendering is done
80435      * in the viewer. All modes preserves the original aspect
80436      * ratio of the images.
80437      */
80438     exports.RenderMode = void 0;
80439     (function (RenderMode) {
80440         /**
80441          * Displays all content within the viewer.
80442          *
80443          * @description Black bars shown on both
80444          * sides of the content. Bars are shown
80445          * either below and above or to the left
80446          * and right of the content depending on
80447          * the aspect ratio relation between the
80448          * image and the viewer.
80449          */
80450         RenderMode[RenderMode["Letterbox"] = 0] = "Letterbox";
80451         /**
80452          * Fills the viewer by cropping content.
80453          *
80454          * @description Cropping is done either
80455          * in horizontal or vertical direction
80456          * depending on the aspect ratio relation
80457          * between the image and the viewer.
80458          */
80459         RenderMode[RenderMode["Fill"] = 1] = "Fill";
80460     })(exports.RenderMode || (exports.RenderMode = {}));
80461
80462     exports.RenderPass = void 0;
80463     (function (RenderPass) {
80464         /**
80465          * Occurs after the background render pass.
80466          */
80467         RenderPass[RenderPass["Opaque"] = 0] = "Opaque";
80468     })(exports.RenderPass || (exports.RenderPass = {}));
80469
80470     /**
80471      * Enumeration for transition mode
80472      * @enum {number}
80473      * @readonly
80474      * @description Modes for specifying how transitions
80475      * between images are performed.
80476      */
80477     exports.TransitionMode = void 0;
80478     (function (TransitionMode) {
80479         /**
80480          * Default transitions.
80481          *
80482          * @description The viewer dynamically determines
80483          * whether transitions should be performed with or
80484          * without motion and blending for each transition
80485          * based on the underlying data.
80486          */
80487         TransitionMode[TransitionMode["Default"] = 0] = "Default";
80488         /**
80489          * Instantaneous transitions.
80490          *
80491          * @description All transitions are performed
80492          * without motion or blending.
80493          */
80494         TransitionMode[TransitionMode["Instantaneous"] = 1] = "Instantaneous";
80495     })(exports.TransitionMode || (exports.TransitionMode = {}));
80496
80497     class ComponentController {
80498         constructor(container, navigator, observer, key, options, componentService) {
80499             this._container = container;
80500             this._observer = observer;
80501             this._navigator = navigator;
80502             this._options = options != null ? options : {};
80503             this._key = key;
80504             this._navigable = key == null;
80505             this._componentService = !!componentService ?
80506                 componentService :
80507                 new ComponentService(this._container, this._navigator);
80508             this._coverComponent = this._componentService.getCover();
80509             this._initializeComponents();
80510             if (key) {
80511                 this._initilizeCoverComponent();
80512                 this._subscribeCoverComponent();
80513             }
80514             else {
80515                 this._navigator.movedToId$.pipe(first((k) => {
80516                     return k != null;
80517                 }))
80518                     .subscribe((k) => {
80519                     this._key = k;
80520                     this._componentService.deactivateCover();
80521                     this._coverComponent.configure({
80522                         id: this._key,
80523                         state: CoverState.Hidden,
80524                     });
80525                     this._subscribeCoverComponent();
80526                     this._navigator.stateService.start();
80527                     this._navigator.cacheService.start();
80528                     this._navigator.panService.start();
80529                     this._observer.startEmit();
80530                 });
80531             }
80532         }
80533         get navigable() {
80534             return this._navigable;
80535         }
80536         get(name) {
80537             return this._componentService.get(name);
80538         }
80539         activate(name) {
80540             this._componentService.activate(name);
80541         }
80542         activateCover() {
80543             this._coverComponent.configure({ state: CoverState.Visible });
80544         }
80545         deactivate(name) {
80546             this._componentService.deactivate(name);
80547         }
80548         deactivateCover() {
80549             this._coverComponent.configure({ state: CoverState.Loading });
80550         }
80551         remove() {
80552             this._componentService.remove();
80553             if (this._configurationSubscription != null) {
80554                 this._configurationSubscription.unsubscribe();
80555             }
80556         }
80557         _initializeComponents() {
80558             var _a, _b;
80559             const options = this._options;
80560             this._uFalse((_a = options.fallback) === null || _a === void 0 ? void 0 : _a.image, "imagefallback");
80561             this._uFalse((_b = options.fallback) === null || _b === void 0 ? void 0 : _b.navigation, "navigationfallback");
80562             this._uFalse(options.marker, "marker");
80563             this._uFalse(options.popup, "popup");
80564             this._uFalse(options.slider, "slider");
80565             this._uFalse(options.spatial, "spatial");
80566             this._uFalse(options.tag, "tag");
80567             this._uTrue(options.attribution, "attribution");
80568             this._uTrue(options.bearing, "bearing");
80569             this._uTrue(options.cache, "cache");
80570             this._uTrue(options.direction, "direction");
80571             this._uTrue(options.image, "image");
80572             this._uTrue(options.keyboard, "keyboard");
80573             this._uTrue(options.pointer, "pointer");
80574             this._uTrue(options.sequence, "sequence");
80575             this._uTrue(options.zoom, "zoom");
80576         }
80577         _initilizeCoverComponent() {
80578             let options = this._options;
80579             this._coverComponent.configure({ id: this._key });
80580             if (options.cover === undefined || options.cover) {
80581                 this.activateCover();
80582             }
80583             else {
80584                 this.deactivateCover();
80585             }
80586         }
80587         _setNavigable(navigable) {
80588             if (this._navigable === navigable) {
80589                 return;
80590             }
80591             this._navigable = navigable;
80592             this._observer.navigable$.next(navigable);
80593         }
80594         _subscribeCoverComponent() {
80595             this._configurationSubscription =
80596                 this._coverComponent.configuration$.pipe(distinctUntilChanged(undefined, (c) => {
80597                     return c.state;
80598                 }))
80599                     .subscribe((conf) => {
80600                     if (conf.state === CoverState.Loading) {
80601                         this._navigator.stateService.currentId$.pipe(first(), switchMap((key) => {
80602                             const keyChanged = key == null || key !== conf.id;
80603                             if (keyChanged) {
80604                                 this._setNavigable(false);
80605                             }
80606                             return keyChanged ?
80607                                 this._navigator.moveTo$(conf.id) :
80608                                 this._navigator.stateService.currentImage$.pipe(first());
80609                         }))
80610                             .subscribe(() => {
80611                             this._navigator.stateService.start();
80612                             this._navigator.cacheService.start();
80613                             this._navigator.panService.start();
80614                             this._observer.startEmit();
80615                             this._coverComponent.configure({ state: CoverState.Hidden });
80616                             this._componentService.deactivateCover();
80617                             this._setNavigable(true);
80618                         }, (error) => {
80619                             console.error("Failed to deactivate cover.", error);
80620                             this._coverComponent.configure({ state: CoverState.Visible });
80621                         });
80622                     }
80623                     else if (conf.state === CoverState.Visible) {
80624                         this._observer.stopEmit();
80625                         this._navigator.stateService.stop();
80626                         this._navigator.cacheService.stop();
80627                         this._navigator.playService.stop();
80628                         this._navigator.panService.stop();
80629                         this._componentService.activateCover();
80630                         this._setNavigable(conf.id == null);
80631                     }
80632                 });
80633         }
80634         _uFalse(option, name) {
80635             if (option === undefined) {
80636                 this._componentService.deactivate(name);
80637                 return;
80638             }
80639             if (typeof option === "boolean") {
80640                 if (option) {
80641                     this._componentService.activate(name);
80642                 }
80643                 else {
80644                     this._componentService.deactivate(name);
80645                 }
80646                 return;
80647             }
80648             this._componentService.configure(name, option);
80649             this._componentService.activate(name);
80650         }
80651         _uTrue(option, name) {
80652             if (option === undefined) {
80653                 this._componentService.activate(name);
80654                 return;
80655             }
80656             if (typeof option === "boolean") {
80657                 if (option) {
80658                     this._componentService.activate(name);
80659                 }
80660                 else {
80661                     this._componentService.deactivate(name);
80662                 }
80663                 return;
80664             }
80665             this._componentService.configure(name, option);
80666             this._componentService.activate(name);
80667         }
80668     }
80669
80670     class DOMRenderer {
80671         constructor(element, renderService, currentFrame$) {
80672             this._adaptiveOperation$ = new Subject();
80673             this._render$ = new Subject();
80674             this._renderAdaptive$ = new Subject();
80675             this._subscriptions = new SubscriptionHolder();
80676             this._renderService = renderService;
80677             this._currentFrame$ = currentFrame$;
80678             const subs = this._subscriptions;
80679             const rootNode = virtualDom.create(virtualDom.h("div.mapillary-dom-renderer", []));
80680             element.appendChild(rootNode);
80681             this._offset$ = this._adaptiveOperation$.pipe(scan((adaptive, operation) => {
80682                 return operation(adaptive);
80683             }, {
80684                 elementHeight: element.offsetHeight,
80685                 elementWidth: element.offsetWidth,
80686                 imageAspect: 0,
80687                 renderMode: exports.RenderMode.Fill,
80688             }), filter((adaptive) => {
80689                 return adaptive.imageAspect > 0 && adaptive.elementWidth > 0 && adaptive.elementHeight > 0;
80690             }), map((adaptive) => {
80691                 const elementAspect = adaptive.elementWidth / adaptive.elementHeight;
80692                 const ratio = adaptive.imageAspect / elementAspect;
80693                 let verticalOffset = 0;
80694                 let horizontalOffset = 0;
80695                 if (adaptive.renderMode === exports.RenderMode.Letterbox) {
80696                     if (adaptive.imageAspect > elementAspect) {
80697                         verticalOffset = adaptive.elementHeight * (1 - 1 / ratio) / 2;
80698                     }
80699                     else {
80700                         horizontalOffset = adaptive.elementWidth * (1 - ratio) / 2;
80701                     }
80702                 }
80703                 else {
80704                     if (adaptive.imageAspect > elementAspect) {
80705                         horizontalOffset = -adaptive.elementWidth * (ratio - 1) / 2;
80706                     }
80707                     else {
80708                         verticalOffset = -adaptive.elementHeight * (1 / ratio - 1) / 2;
80709                     }
80710                 }
80711                 return {
80712                     bottom: verticalOffset,
80713                     left: horizontalOffset,
80714                     right: horizontalOffset,
80715                     top: verticalOffset,
80716                 };
80717             }));
80718             const imageAspectSubscription = this._currentFrame$.pipe(filter((frame) => {
80719                 return frame.state.currentImage != null;
80720             }), distinctUntilChanged((k1, k2) => {
80721                 return k1 === k2;
80722             }, (frame) => {
80723                 return frame.state.currentImage.id;
80724             }), map((frame) => {
80725                 return frame.state.currentTransform.basicAspect;
80726             }), map((aspect) => {
80727                 return (adaptive) => {
80728                     adaptive.imageAspect = aspect;
80729                     return adaptive;
80730                 };
80731             }))
80732                 .subscribe(this._adaptiveOperation$);
80733             const renderAdaptiveSubscription = combineLatest(this._renderAdaptive$.pipe(scan((vNodeHashes, vNodeHash) => {
80734                 if (vNodeHash.vNode == null) {
80735                     delete vNodeHashes[vNodeHash.name];
80736                 }
80737                 else {
80738                     vNodeHashes[vNodeHash.name] = vNodeHash.vNode;
80739                 }
80740                 return vNodeHashes;
80741             }, {})), this._offset$).pipe(map((vo) => {
80742                 const vNodes = [];
80743                 const hashes = vo[0];
80744                 for (const name in hashes) {
80745                     if (!hashes.hasOwnProperty(name)) {
80746                         continue;
80747                     }
80748                     vNodes.push(hashes[name]);
80749                 }
80750                 const offset = vo[1];
80751                 const properties = {
80752                     style: {
80753                         bottom: offset.bottom + "px",
80754                         left: offset.left + "px",
80755                         "pointer-events": "none",
80756                         position: "absolute",
80757                         right: offset.right + "px",
80758                         top: offset.top + "px",
80759                     },
80760                 };
80761                 return {
80762                     name: "mapillary-dom-adaptive-renderer",
80763                     vNode: virtualDom.h("div.mapillary-dom-adaptive-renderer", properties, vNodes),
80764                 };
80765             }))
80766                 .subscribe(this._render$);
80767             this._vNode$ = this._render$.pipe(scan((vNodeHashes, vNodeHash) => {
80768                 if (vNodeHash.vNode == null) {
80769                     delete vNodeHashes[vNodeHash.name];
80770                 }
80771                 else {
80772                     vNodeHashes[vNodeHash.name] = vNodeHash.vNode;
80773                 }
80774                 return vNodeHashes;
80775             }, {}), map((hashes) => {
80776                 const vNodes = [];
80777                 for (const name in hashes) {
80778                     if (!hashes.hasOwnProperty(name)) {
80779                         continue;
80780                     }
80781                     vNodes.push(hashes[name]);
80782                 }
80783                 return virtualDom.h("div.mapillary-dom-renderer", vNodes);
80784             }));
80785             this._vPatch$ = this._vNode$.pipe(scan((nodePatch, vNode) => {
80786                 nodePatch.vpatch = virtualDom.diff(nodePatch.vNode, vNode);
80787                 nodePatch.vNode = vNode;
80788                 return nodePatch;
80789             }, { vNode: virtualDom.h("div.mapillary-dom-renderer", []), vpatch: null }), pluck("vpatch"));
80790             this._element$ = this._vPatch$.pipe(scan((oldElement, vPatch) => {
80791                 return virtualDom.patch(oldElement, vPatch);
80792             }, rootNode), publishReplay(1), refCount());
80793             subs.push(imageAspectSubscription);
80794             subs.push(renderAdaptiveSubscription);
80795             subs.push(this._element$.subscribe(() => { }));
80796             subs.push(this._renderService.size$.pipe(map((size) => {
80797                 return (adaptive) => {
80798                     adaptive.elementWidth = size.width;
80799                     adaptive.elementHeight = size.height;
80800                     return adaptive;
80801                 };
80802             }))
80803                 .subscribe(this._adaptiveOperation$));
80804             subs.push(this._renderService.renderMode$.pipe(map((renderMode) => {
80805                 return (adaptive) => {
80806                     adaptive.renderMode = renderMode;
80807                     return adaptive;
80808                 };
80809             }))
80810                 .subscribe(this._adaptiveOperation$));
80811         }
80812         get element$() {
80813             return this._element$;
80814         }
80815         get render$() {
80816             return this._render$;
80817         }
80818         get renderAdaptive$() {
80819             return this._renderAdaptive$;
80820         }
80821         clear(name) {
80822             this._renderAdaptive$.next({ name: name, vNode: null });
80823             this._render$.next({ name: name, vNode: null });
80824         }
80825         remove() {
80826             this._subscriptions.unsubscribe();
80827         }
80828     }
80829
80830     class GLRenderer {
80831         constructor(canvas, canvasContainer, renderService) {
80832             this._renderFrame$ = new Subject();
80833             this._renderCameraOperation$ = new Subject();
80834             this._render$ = new Subject();
80835             this._clear$ = new Subject();
80836             this._renderOperation$ = new Subject();
80837             this._rendererOperation$ = new Subject();
80838             this._eraserOperation$ = new Subject();
80839             this._triggerOperation$ = new Subject();
80840             this._subscriptions = new SubscriptionHolder();
80841             this._opaqueRender$ = new Subject();
80842             this._renderService = renderService;
80843             const subs = this._subscriptions;
80844             this._renderer$ = this._rendererOperation$.pipe(scan((renderer, operation) => {
80845                 return operation(renderer);
80846             }, { needsRender: false, renderer: null }), filter((renderer) => {
80847                 return !!renderer.renderer;
80848             }));
80849             this._renderCollection$ = this._renderOperation$.pipe(scan((hashes, operation) => {
80850                 return operation(hashes);
80851             }, {}), share());
80852             this._renderCamera$ = this._renderCameraOperation$.pipe(scan((rc, operation) => {
80853                 return operation(rc);
80854             }, { frameId: -1, needsRender: false, perspective: null }));
80855             this._eraser$ = this._eraserOperation$.pipe(startWith((eraser) => {
80856                 return eraser;
80857             }), scan((eraser, operation) => {
80858                 return operation(eraser);
80859             }, { needsRender: false }));
80860             const trigger$ = this._triggerOperation$.pipe(startWith((trigger) => {
80861                 return trigger;
80862             }), scan((trigger, operation) => {
80863                 return operation(trigger);
80864             }, { needsRender: false }));
80865             const clearColor = new Color(0x0F0F0F);
80866             const renderSubscription = combineLatest(this._renderer$, this._renderCollection$, this._renderCamera$, this._eraser$, trigger$).pipe(map(([renderer, hashes, rc, eraser, trigger]) => {
80867                 const renders = Object.keys(hashes)
80868                     .map((key) => {
80869                     return hashes[key];
80870                 });
80871                 return { camera: rc, eraser: eraser, trigger: trigger, renderer: renderer, renders: renders };
80872             }), filter((co) => {
80873                 let needsRender = co.renderer.needsRender ||
80874                     co.camera.needsRender ||
80875                     co.eraser.needsRender ||
80876                     co.trigger.needsRender;
80877                 const frameId = co.camera.frameId;
80878                 for (const render of co.renders) {
80879                     if (render.frameId !== frameId) {
80880                         return false;
80881                     }
80882                     needsRender = needsRender || render.needsRender;
80883                 }
80884                 return needsRender;
80885             }), distinctUntilChanged((n1, n2) => {
80886                 return n1 === n2;
80887             }, (co) => {
80888                 return co.eraser.needsRender ||
80889                     co.trigger.needsRender ? -co.camera.frameId : co.camera.frameId;
80890             }))
80891                 .subscribe((co) => {
80892                 co.renderer.needsRender = false;
80893                 co.camera.needsRender = false;
80894                 co.eraser.needsRender = false;
80895                 co.trigger.needsRender = false;
80896                 const perspectiveCamera = co.camera.perspective;
80897                 const backgroundRenders = [];
80898                 const opaqueRenders = [];
80899                 for (const render of co.renders) {
80900                     if (render.pass === RenderPass.Background) {
80901                         backgroundRenders.push(render.render);
80902                     }
80903                     else if (render.pass === RenderPass.Opaque) {
80904                         opaqueRenders.push(render.render);
80905                     }
80906                 }
80907                 const renderer = co.renderer.renderer;
80908                 renderer.resetState();
80909                 renderer.setClearColor(clearColor, 1.0);
80910                 renderer.clear();
80911                 for (const renderBackground of backgroundRenders) {
80912                     renderBackground(perspectiveCamera, renderer);
80913                 }
80914                 renderer.clearDepth();
80915                 for (const renderOpaque of opaqueRenders) {
80916                     renderOpaque(perspectiveCamera, renderer);
80917                 }
80918                 renderer.resetState();
80919                 this._opaqueRender$.next();
80920             });
80921             subs.push(renderSubscription);
80922             subs.push(this._renderFrame$.pipe(map((rc) => {
80923                 return (irc) => {
80924                     irc.frameId = rc.frameId;
80925                     irc.perspective = rc.perspective;
80926                     if (rc.changed === true) {
80927                         irc.needsRender = true;
80928                     }
80929                     return irc;
80930                 };
80931             }))
80932                 .subscribe(this._renderCameraOperation$));
80933             this._renderFrameSubscribe();
80934             const renderHash$ = this._render$.pipe(map((hash) => {
80935                 return (hashes) => {
80936                     hashes[hash.name] = hash.renderer;
80937                     return hashes;
80938                 };
80939             }));
80940             const clearHash$ = this._clear$.pipe(map((name) => {
80941                 return (hashes) => {
80942                     delete hashes[name];
80943                     return hashes;
80944                 };
80945             }));
80946             subs.push(merge(renderHash$, clearHash$)
80947                 .subscribe(this._renderOperation$));
80948             this._webGLRenderer$ = this._render$.pipe(first(), map(() => {
80949                 canvasContainer.appendChild(canvas);
80950                 const element = renderService.element;
80951                 const webGLRenderer = new WebGLRenderer({ canvas: canvas });
80952                 webGLRenderer.setPixelRatio(window.devicePixelRatio);
80953                 webGLRenderer.setSize(element.offsetWidth, element.offsetHeight);
80954                 webGLRenderer.autoClear = false;
80955                 return webGLRenderer;
80956             }), publishReplay(1), refCount());
80957             subs.push(this._webGLRenderer$
80958                 .subscribe(() => { }));
80959             const createRenderer$ = this._webGLRenderer$.pipe(first(), map((webGLRenderer) => {
80960                 return (renderer) => {
80961                     renderer.needsRender = true;
80962                     renderer.renderer = webGLRenderer;
80963                     return renderer;
80964                 };
80965             }));
80966             const resizeRenderer$ = this._renderService.size$.pipe(map((size) => {
80967                 return (renderer) => {
80968                     if (renderer.renderer == null) {
80969                         return renderer;
80970                     }
80971                     renderer.renderer.setSize(size.width, size.height);
80972                     renderer.needsRender = true;
80973                     return renderer;
80974                 };
80975             }));
80976             const clearRenderer$ = this._clear$.pipe(map(() => {
80977                 return (renderer) => {
80978                     if (renderer.renderer == null) {
80979                         return renderer;
80980                     }
80981                     renderer.needsRender = true;
80982                     return renderer;
80983                 };
80984             }));
80985             subs.push(merge(createRenderer$, resizeRenderer$, clearRenderer$)
80986                 .subscribe(this._rendererOperation$));
80987             const renderCollectionEmpty$ = this._renderCollection$.pipe(filter((hashes) => {
80988                 return Object.keys(hashes).length === 0;
80989             }), share());
80990             subs.push(renderCollectionEmpty$
80991                 .subscribe(() => {
80992                 if (this._renderFrameSubscription == null) {
80993                     return;
80994                 }
80995                 this._renderFrameSubscription.unsubscribe();
80996                 this._renderFrameSubscription = null;
80997                 this._renderFrameSubscribe();
80998             }));
80999             subs.push(renderCollectionEmpty$.pipe(map(() => {
81000                 return (eraser) => {
81001                     eraser.needsRender = true;
81002                     return eraser;
81003                 };
81004             }))
81005                 .subscribe(this._eraserOperation$));
81006         }
81007         get render$() {
81008             return this._render$;
81009         }
81010         get opaqueRender$() {
81011             return this._opaqueRender$;
81012         }
81013         get webGLRenderer$() {
81014             return this._webGLRenderer$;
81015         }
81016         clear(name) {
81017             this._clear$.next(name);
81018         }
81019         remove() {
81020             this._rendererOperation$.next((renderer) => {
81021                 if (renderer.renderer != null) {
81022                     const extension = renderer.renderer
81023                         .getContext()
81024                         .getExtension('WEBGL_lose_context');
81025                     if (!!extension) {
81026                         extension.loseContext();
81027                     }
81028                     renderer.renderer = null;
81029                 }
81030                 return renderer;
81031             });
81032             if (this._renderFrameSubscription != null) {
81033                 this._renderFrameSubscription.unsubscribe();
81034             }
81035             this._subscriptions.unsubscribe();
81036         }
81037         triggerRerender() {
81038             this._renderService.renderCameraFrame$
81039                 .pipe(skip(1), first())
81040                 .subscribe(() => {
81041                 this._triggerOperation$.next((trigger) => {
81042                     trigger.needsRender = true;
81043                     return trigger;
81044                 });
81045             });
81046         }
81047         _renderFrameSubscribe() {
81048             this._render$.pipe(first(), map(() => {
81049                 return (irc) => {
81050                     irc.needsRender = true;
81051                     return irc;
81052                 };
81053             }))
81054                 .subscribe((operation) => {
81055                 this._renderCameraOperation$.next(operation);
81056             });
81057             this._renderFrameSubscription = this._render$.pipe(first(), mergeMap(() => {
81058                 return this._renderService.renderCameraFrame$;
81059             }))
81060                 .subscribe(this._renderFrame$);
81061         }
81062     }
81063
81064     /**
81065      * @class Camera
81066      *
81067      * @classdesc Holds information about a camera.
81068      */
81069     class Camera {
81070         /**
81071          * Create a new camera instance.
81072          * @param {Transform} [transform] - Optional transform instance.
81073          */
81074         constructor(transform) {
81075             if (transform != null) {
81076                 this._position = new Vector3().fromArray(transform.unprojectSfM([0, 0], 0));
81077                 this._lookat = new Vector3().fromArray(transform.unprojectSfM([0, 0], 10));
81078                 this._up = transform.upVector();
81079                 this._focal = this._getFocal(transform);
81080             }
81081             else {
81082                 this._position = new Vector3(0, 0, 0);
81083                 this._lookat = new Vector3(1, 0, 0);
81084                 this._up = new Vector3(0, 0, 1);
81085                 this._focal = 1;
81086             }
81087         }
81088         /**
81089          * Get position.
81090          * @returns {THREE.Vector3} The position vector.
81091          */
81092         get position() {
81093             return this._position;
81094         }
81095         /**
81096          * Get lookat.
81097          * @returns {THREE.Vector3} The lookat vector.
81098          */
81099         get lookat() {
81100             return this._lookat;
81101         }
81102         /**
81103          * Get up.
81104          * @returns {THREE.Vector3} The up vector.
81105          */
81106         get up() {
81107             return this._up;
81108         }
81109         /**
81110          * Get focal.
81111          * @returns {number} The focal length.
81112          */
81113         get focal() {
81114             return this._focal;
81115         }
81116         /**
81117          * Set focal.
81118          */
81119         set focal(value) {
81120             this._focal = value;
81121         }
81122         /**
81123          * Update this camera to the linearly interpolated value of two other cameras.
81124          *
81125          * @param {Camera} a - First camera.
81126          * @param {Camera} b - Second camera.
81127          * @param {number} alpha - Interpolation value on the interval [0, 1].
81128          */
81129         lerpCameras(a, b, alpha) {
81130             this._position.subVectors(b.position, a.position).multiplyScalar(alpha).add(a.position);
81131             this._lookat.subVectors(b.lookat, a.lookat).multiplyScalar(alpha).add(a.lookat);
81132             this._up.subVectors(b.up, a.up).multiplyScalar(alpha).add(a.up);
81133             this._focal = (1 - alpha) * a.focal + alpha * b.focal;
81134         }
81135         /**
81136          * Copy the properties of another camera to this camera.
81137          *
81138          * @param {Camera} other - Another camera.
81139          */
81140         copy(other) {
81141             this._position.copy(other.position);
81142             this._lookat.copy(other.lookat);
81143             this._up.copy(other.up);
81144             this._focal = other.focal;
81145         }
81146         /**
81147          * Clone this camera.
81148          *
81149          * @returns {Camera} A camera with cloned properties equal to this camera.
81150          */
81151         clone() {
81152             let camera = new Camera();
81153             camera.position.copy(this._position);
81154             camera.lookat.copy(this._lookat);
81155             camera.up.copy(this._up);
81156             camera.focal = this._focal;
81157             return camera;
81158         }
81159         /**
81160          * Determine the distance between this camera and another camera.
81161          *
81162          * @param {Camera} other - Another camera.
81163          * @returns {number} The distance between the cameras.
81164          */
81165         diff(other) {
81166             let pd = this._position.distanceToSquared(other.position);
81167             let ld = this._lookat.distanceToSquared(other.lookat);
81168             let ud = this._up.distanceToSquared(other.up);
81169             let fd = 100 * Math.abs(this._focal - other.focal);
81170             return Math.max(pd, ld, ud, fd);
81171         }
81172         /**
81173          * Get the focal length based on the transform.
81174          *
81175          * @description Returns the focal length corresponding
81176          * to a 90 degree field of view for spherical
81177          * transforms.
81178          *
81179          * Returns the transform focal length for other
81180          * projection types.
81181          *
81182          * @returns {number} Focal length.
81183          */
81184         _getFocal(transform) {
81185             if (!isSpherical(transform.cameraType)) {
81186                 return transform.focal;
81187             }
81188             return 0.5 / Math.tan(Math.PI / 2);
81189         }
81190     }
81191
81192     class RenderCamera {
81193         constructor(elementWidth, elementHeight, renderMode) {
81194             this._spatial = new Spatial();
81195             this._viewportCoords = new ViewportCoords();
81196             this._size = { width: elementWidth, height: elementHeight };
81197             this._initialFov = 60;
81198             this._alpha = -1;
81199             this._stateTransitionAlpha = -1;
81200             this._stateTransitionFov = -1;
81201             this._renderMode = renderMode;
81202             this._zoom = 0;
81203             this._frameId = -1;
81204             this._changed = false;
81205             this._changedForFrame = -1;
81206             this._currentImageId = null;
81207             this._previousImageId = null;
81208             this._currentSpherical = false;
81209             this._previousSpherical = false;
81210             this._state = null;
81211             this._currentProjectedPoints = [];
81212             this._previousProjectedPoints = [];
81213             this._currentFov = this._initialFov;
81214             this._previousFov = this._initialFov;
81215             this._camera = new Camera();
81216             this._perspective = new PerspectiveCamera(this._initialFov, this._computeAspect(elementWidth, elementHeight), 0.1, 10000);
81217             this._perspective.position.copy(this._camera.position);
81218             this._perspective.up.copy(this._camera.up);
81219             this._perspective.lookAt(this._camera.lookat);
81220             this._perspective.updateMatrixWorld(true);
81221             this._perspective.matrixAutoUpdate = false;
81222             this._rotation = { phi: 0, theta: 0 };
81223         }
81224         get alpha() {
81225             return this._alpha;
81226         }
81227         get camera() {
81228             return this._camera;
81229         }
81230         get changed() {
81231             return this._frameId === this._changedForFrame;
81232         }
81233         get frameId() {
81234             return this._frameId;
81235         }
81236         get perspective() {
81237             return this._perspective;
81238         }
81239         get renderMode() {
81240             return this._renderMode;
81241         }
81242         get rotation() {
81243             return this._rotation;
81244         }
81245         get zoom() {
81246             return this._zoom;
81247         }
81248         get size() {
81249             return this._size;
81250         }
81251         getTilt() {
81252             return 90 - this._spatial.radToDeg(this._rotation.theta);
81253         }
81254         fovToZoom(fov) {
81255             fov = Math.min(90, Math.max(0, fov));
81256             const currentFov = this._computeCurrentFov(0);
81257             const actualFov = this._alpha === 1 ?
81258                 currentFov :
81259                 this._interpolateFov(currentFov, this._computePreviousFov(0), this._alpha);
81260             const y0 = Math.tan(actualFov / 2 * Math.PI / 180);
81261             const y1 = Math.tan(fov / 2 * Math.PI / 180);
81262             const zoom = Math.log(y0 / y1) / Math.log(2);
81263             return zoom;
81264         }
81265         setFrame(frame) {
81266             const state = frame.state;
81267             if (state.state !== this._state) {
81268                 this._state = state.state;
81269                 if (this._state !== State.Custom) {
81270                     this.setRenderMode(this._renderMode);
81271                     this.setSize(this._size);
81272                 }
81273                 if (this._state === State.Earth) {
81274                     const y = this._fovToY(this._perspective.fov, this._zoom);
81275                     this._stateTransitionFov = this._yToFov(y, 0);
81276                 }
81277                 this._changed = true;
81278             }
81279             const currentImageId = state.currentImage.id;
81280             const previousImageId = !!state.previousImage ? state.previousImage.id : null;
81281             if (currentImageId !== this._currentImageId) {
81282                 this._currentImageId = currentImageId;
81283                 this._currentSpherical = isSpherical(state.currentTransform.cameraType);
81284                 this._currentProjectedPoints = this._computeProjectedPoints(state.currentTransform);
81285                 this._changed = true;
81286             }
81287             if (previousImageId !== this._previousImageId) {
81288                 this._previousImageId = previousImageId;
81289                 this._previousSpherical =
81290                     isSpherical(state.previousTransform.cameraType);
81291                 this._previousProjectedPoints = this._computeProjectedPoints(state.previousTransform);
81292                 this._changed = true;
81293             }
81294             const zoom = state.zoom;
81295             if (zoom !== this._zoom) {
81296                 this._changed = true;
81297             }
81298             if (this._changed) {
81299                 this._currentFov = this._computeCurrentFov(zoom);
81300                 this._previousFov = this._computePreviousFov(zoom);
81301             }
81302             const alpha = state.alpha;
81303             const sta = state.stateTransitionAlpha;
81304             if (this._changed ||
81305                 alpha !== this._alpha ||
81306                 sta !== this._stateTransitionAlpha) {
81307                 this._alpha = alpha;
81308                 this._stateTransitionAlpha = sta;
81309                 switch (this._state) {
81310                     case State.Earth: {
81311                         const startFov = this._stateTransitionFov;
81312                         const endFov = this._focalToFov(state.camera.focal);
81313                         const fov = MathUtils.lerp(startFov, endFov, sta);
81314                         const y = this._fovToY(fov, 0);
81315                         this._perspective.fov = this._yToFov(y, zoom);
81316                         break;
81317                     }
81318                     case State.Custom:
81319                         break;
81320                     default:
81321                         this._perspective.fov =
81322                             this._interpolateFov(this._currentFov, this._previousFov, this._alpha);
81323                         this._changed = true;
81324                         break;
81325                 }
81326                 this._zoom = zoom;
81327                 if (this._state !== State.Custom) {
81328                     this._perspective.updateProjectionMatrix();
81329                 }
81330             }
81331             const camera = state.camera;
81332             if (this._camera.diff(camera) > 1e-9) {
81333                 this._camera.copy(camera);
81334                 this._rotation = this._computeRotation(camera);
81335                 this._perspective.up.copy(camera.up);
81336                 this._perspective.position.copy(camera.position);
81337                 // Workaround for shaking camera
81338                 this._perspective.matrixAutoUpdate = true;
81339                 this._perspective.lookAt(camera.lookat);
81340                 this._perspective.matrixAutoUpdate = false;
81341                 this._perspective.updateMatrix();
81342                 this._perspective.updateMatrixWorld(false);
81343                 this._changed = true;
81344             }
81345             this._setFrameId(frame.id);
81346         }
81347         setProjectionMatrix(matrix) {
81348             this._perspective.fov = this._focalToFov(matrix[5] / 2);
81349             this._perspective.projectionMatrix.fromArray(matrix);
81350             this._perspective.projectionMatrixInverse
81351                 .copy(this._perspective.projectionMatrix)
81352                 .invert();
81353             this._changed = true;
81354         }
81355         setRenderMode(renderMode) {
81356             this._renderMode = renderMode;
81357             if (this._state === State.Custom) {
81358                 return;
81359             }
81360             this._perspective.fov = this._computeFov();
81361             this._perspective.updateProjectionMatrix();
81362             this._changed = true;
81363         }
81364         setSize(size) {
81365             this._size = size;
81366             if (this._state === State.Custom) {
81367                 return;
81368             }
81369             this._perspective.aspect = this._computeAspect(size.width, size.height);
81370             this._perspective.fov = this._computeFov();
81371             this._perspective.updateProjectionMatrix();
81372             this._changed = true;
81373         }
81374         _computeAspect(elementWidth, elementHeight) {
81375             return elementWidth === 0 ? 0 : elementWidth / elementHeight;
81376         }
81377         _computeCurrentFov(zoom) {
81378             if (this._perspective.aspect === 0) {
81379                 return 0;
81380             }
81381             if (!this._currentImageId) {
81382                 return this._initialFov;
81383             }
81384             return this._currentSpherical ?
81385                 this._yToFov(1, zoom) :
81386                 this._computeVerticalFov(this._currentProjectedPoints, this._renderMode, zoom, this.perspective.aspect);
81387         }
81388         _computeFov() {
81389             this._currentFov = this._computeCurrentFov(this._zoom);
81390             this._previousFov = this._computePreviousFov(this._zoom);
81391             return this._interpolateFov(this._currentFov, this._previousFov, this._alpha);
81392         }
81393         _computePreviousFov(zoom) {
81394             if (this._perspective.aspect === 0) {
81395                 return 0;
81396             }
81397             if (!this._currentImageId) {
81398                 return this._initialFov;
81399             }
81400             return !this._previousImageId ?
81401                 this._currentFov :
81402                 this._previousSpherical ?
81403                     this._yToFov(1, zoom) :
81404                     this._computeVerticalFov(this._previousProjectedPoints, this._renderMode, zoom, this.perspective.aspect);
81405         }
81406         _computeProjectedPoints(transform) {
81407             const vertices = [[0.5, 0], [1, 0]];
81408             const directions = [[0.5, 0], [0, 0.5]];
81409             const pointsPerLine = 100;
81410             return computeProjectedPoints(transform, vertices, directions, pointsPerLine, this._viewportCoords);
81411         }
81412         _computeRequiredVerticalFov(projectedPoint, zoom, aspect) {
81413             const maxY = Math.max(projectedPoint[0] / aspect, projectedPoint[1]);
81414             return this._yToFov(maxY, zoom);
81415         }
81416         _computeRotation(camera) {
81417             let direction = camera.lookat.clone().sub(camera.position);
81418             let up = camera.up.clone();
81419             let phi = this._spatial.azimuthal(direction.toArray(), up.toArray());
81420             let theta = Math.PI / 2 - this._spatial.angleToPlane(direction.toArray(), [0, 0, 1]);
81421             return { phi: phi, theta: theta };
81422         }
81423         _computeVerticalFov(projectedPoints, renderMode, zoom, aspect) {
81424             const fovs = projectedPoints
81425                 .map((projectedPoint) => {
81426                 return this._computeRequiredVerticalFov(projectedPoint, zoom, aspect);
81427             });
81428             const fov = renderMode === exports.RenderMode.Fill ?
81429                 Math.min(...fovs) * 0.995 :
81430                 Math.max(...fovs);
81431             return fov;
81432         }
81433         _yToFov(y, zoom) {
81434             return 2 * Math.atan(y / Math.pow(2, zoom)) * 180 / Math.PI;
81435         }
81436         _focalToFov(focal) {
81437             return 2 * Math.atan2(1, 2 * focal) * 180 / Math.PI;
81438         }
81439         _fovToY(fov, zoom) {
81440             return Math.pow(2, zoom) * Math.tan(Math.PI * fov / 360);
81441         }
81442         _interpolateFov(v1, v2, alpha) {
81443             return alpha * v1 + (1 - alpha) * v2;
81444         }
81445         _setFrameId(frameId) {
81446             this._frameId = frameId;
81447             if (this._changed) {
81448                 this._changed = false;
81449                 this._changedForFrame = frameId;
81450             }
81451         }
81452     }
81453
81454     class RenderService {
81455         constructor(element, currentFrame$, renderMode, renderCamera) {
81456             this._subscriptions = new SubscriptionHolder();
81457             this._element = element;
81458             this._currentFrame$ = currentFrame$;
81459             this._spatial = new Spatial();
81460             renderMode = renderMode != null ? renderMode : exports.RenderMode.Fill;
81461             this._resize$ = new Subject();
81462             this._projectionMatrix$ = new Subject();
81463             this._renderCameraOperation$ =
81464                 new Subject();
81465             this._size$ =
81466                 new BehaviorSubject({
81467                     height: this._element.offsetHeight,
81468                     width: this._element.offsetWidth,
81469                 });
81470             const subs = this._subscriptions;
81471             subs.push(this._resize$.pipe(map(() => {
81472                 return {
81473                     height: this._element.offsetHeight,
81474                     width: this._element.offsetWidth,
81475                 };
81476             }))
81477                 .subscribe(this._size$));
81478             this._renderMode$ = new BehaviorSubject(renderMode);
81479             this._renderCameraHolder$ = this._renderCameraOperation$.pipe(startWith((rc) => {
81480                 return rc;
81481             }), scan((rc, operation) => {
81482                 return operation(rc);
81483             }, renderCamera !== null && renderCamera !== void 0 ? renderCamera : new RenderCamera(this._element.offsetWidth, this._element.offsetHeight, renderMode)), publishReplay(1), refCount());
81484             this._renderCameraFrame$ = this._currentFrame$.pipe(withLatestFrom(this._renderCameraHolder$), tap(([frame, rc]) => {
81485                 rc.setFrame(frame);
81486             }), map((args) => {
81487                 return args[1];
81488             }), publishReplay(1), refCount());
81489             this._renderCamera$ = this._renderCameraFrame$.pipe(filter((rc) => {
81490                 return rc.changed;
81491             }), publishReplay(1), refCount());
81492             this._bearing$ = this._renderCamera$.pipe(map((rc) => {
81493                 let bearing = this._spatial.radToDeg(this._spatial.azimuthalToBearing(rc.rotation.phi));
81494                 return this._spatial.wrap(bearing, 0, 360);
81495             }), publishReplay(1), refCount());
81496             subs.push(this._size$.pipe(skip(1), map((size) => {
81497                 return (rc) => {
81498                     rc.setSize(size);
81499                     return rc;
81500                 };
81501             }))
81502                 .subscribe(this._renderCameraOperation$));
81503             subs.push(this._renderMode$.pipe(skip(1), map((rm) => {
81504                 return (rc) => {
81505                     rc.setRenderMode(rm);
81506                     return rc;
81507                 };
81508             }))
81509                 .subscribe(this._renderCameraOperation$));
81510             subs.push(this._projectionMatrix$.pipe(map((projectionMatrix) => {
81511                 return (rc) => {
81512                     rc.setProjectionMatrix(projectionMatrix);
81513                     return rc;
81514                 };
81515             }))
81516                 .subscribe(this._renderCameraOperation$));
81517             subs.push(this._bearing$.subscribe(() => { }));
81518             subs.push(this._renderCameraHolder$.subscribe(() => { }));
81519             subs.push(this._size$.subscribe(() => { }));
81520             subs.push(this._renderMode$.subscribe(() => { }));
81521             subs.push(this._renderCamera$.subscribe(() => { }));
81522             subs.push(this._renderCameraFrame$.subscribe(() => { }));
81523         }
81524         get bearing$() {
81525             return this._bearing$;
81526         }
81527         get element() {
81528             return this._element;
81529         }
81530         get projectionMatrix$() {
81531             return this._projectionMatrix$;
81532         }
81533         get renderCamera$() {
81534             return this._renderCamera$;
81535         }
81536         get renderCameraFrame$() {
81537             return this._renderCameraFrame$;
81538         }
81539         get renderMode$() {
81540             return this._renderMode$;
81541         }
81542         get resize$() {
81543             return this._resize$;
81544         }
81545         get size$() {
81546             return this._size$;
81547         }
81548         dispose() {
81549             this._subscriptions.unsubscribe();
81550         }
81551     }
81552
81553     class KeyboardService {
81554         constructor(canvasContainer) {
81555             this._keyDown$ = fromEvent(canvasContainer, "keydown");
81556             this._keyUp$ = fromEvent(canvasContainer, "keyup");
81557         }
81558         get keyDown$() {
81559             return this._keyDown$;
81560         }
81561         get keyUp$() {
81562             return this._keyUp$;
81563         }
81564     }
81565
81566     // MouseEvent.button
81567     const LEFT_BUTTON = 0;
81568     const RIGHT_BUTTON = 2;
81569     // MouseEvent.buttons
81570     const BUTTONS_MAP = {
81571         [LEFT_BUTTON]: 1,
81572         [RIGHT_BUTTON]: 2
81573     };
81574     class MouseService {
81575         constructor(container, canvasContainer, domContainer, doc) {
81576             this._subscriptions = new SubscriptionHolder();
81577             const subs = this._subscriptions;
81578             this._activeSubject$ = new BehaviorSubject(false);
81579             this._active$ = this._activeSubject$
81580                 .pipe(distinctUntilChanged(), publishReplay(1), refCount());
81581             this._claimMouse$ = new Subject();
81582             this._claimWheel$ = new Subject();
81583             this._deferPixelClaims$ = new Subject();
81584             this._deferPixels$ = this._deferPixelClaims$
81585                 .pipe(scan((claims, claim) => {
81586                 if (claim.deferPixels == null) {
81587                     delete claims[claim.name];
81588                 }
81589                 else {
81590                     claims[claim.name] = claim.deferPixels;
81591                 }
81592                 return claims;
81593             }, {}), map((claims) => {
81594                 let deferPixelMax = -1;
81595                 for (const key in claims) {
81596                     if (!claims.hasOwnProperty(key)) {
81597                         continue;
81598                     }
81599                     const deferPixels = claims[key];
81600                     if (deferPixels > deferPixelMax) {
81601                         deferPixelMax = deferPixels;
81602                     }
81603                 }
81604                 return deferPixelMax;
81605             }), startWith(-1), publishReplay(1), refCount());
81606             subs.push(this._deferPixels$.subscribe(() => { }));
81607             this._documentMouseMove$ =
81608                 fromEvent(doc, "pointermove")
81609                     .pipe(filter(this._isMousePen));
81610             this._documentMouseUp$ =
81611                 fromEvent(doc, "pointerup")
81612                     .pipe(filter(this._isMousePen));
81613             this._mouseDown$ =
81614                 fromEvent(canvasContainer, "pointerdown")
81615                     .pipe(filter(this._isMousePen));
81616             this._mouseEnter$ =
81617                 fromEvent(canvasContainer, "pointerenter")
81618                     .pipe(filter(this._isMousePen));
81619             this._mouseLeave$ =
81620                 fromEvent(canvasContainer, "pointerleave")
81621                     .pipe(filter(this._isMousePen));
81622             this._mouseMove$ =
81623                 fromEvent(canvasContainer, "pointermove")
81624                     .pipe(filter(this._isMousePen));
81625             this._mouseUp$ =
81626                 fromEvent(canvasContainer, "pointerup")
81627                     .pipe(filter(this._isMousePen));
81628             this._mouseOut$ =
81629                 fromEvent(canvasContainer, "pointerout")
81630                     .pipe(filter(this._isMousePen));
81631             this._mouseOver$ =
81632                 fromEvent(canvasContainer, "pointerover")
81633                     .pipe(filter(this._isMousePen));
81634             this._domMouseDown$ =
81635                 fromEvent(domContainer, "pointerdown")
81636                     .pipe(filter(this._isMousePen));
81637             this._domMouseMove$ =
81638                 fromEvent(domContainer, "pointermove")
81639                     .pipe(filter(this._isMousePen));
81640             this._click$ =
81641                 fromEvent(canvasContainer, "click");
81642             this._contextMenu$ =
81643                 fromEvent(canvasContainer, "contextmenu");
81644             this._windowBlur$ =
81645                 fromEvent(window, "blur");
81646             this._dblClick$ = merge(fromEvent(container, "click"), fromEvent(canvasContainer, "dblclick"))
81647                 .pipe(bufferCount(3, 1), filter((events) => {
81648                 const event1 = events[0];
81649                 const event2 = events[1];
81650                 const event3 = events[2];
81651                 return event1.type === "click" &&
81652                     event2.type === "click" &&
81653                     event3.type === "dblclick" &&
81654                     event1.target.parentNode === canvasContainer &&
81655                     event2.target.parentNode === canvasContainer;
81656             }), map((events) => {
81657                 return events[2];
81658             }), share());
81659             subs.push(merge(this._domMouseDown$, this._domMouseMove$, this._dblClick$, this._contextMenu$)
81660                 .subscribe((event) => {
81661                 event.preventDefault();
81662             }));
81663             this._mouseWheel$ = merge(fromEvent(canvasContainer, "wheel"), fromEvent(domContainer, "wheel"))
81664                 .pipe(share());
81665             this._consistentContextMenu$ =
81666                 merge(this._mouseDown$, this._mouseMove$, this._mouseOut$, this._mouseUp$, this._contextMenu$)
81667                     .pipe(bufferCount(3, 1), filter((events) => {
81668                     // fire context menu on mouse up both on mac and windows
81669                     return events[0].type === "pointerdown" &&
81670                         events[1].type === "contextmenu" &&
81671                         events[2].type === "pointerup";
81672                 }), map((events) => {
81673                     return events[1];
81674                 }), share());
81675             const dragStop$ = merge(this._windowBlur$, this._documentMouseMove$
81676                 .pipe(filter((e) => {
81677                 return this._buttonReleased(e, LEFT_BUTTON);
81678             })), this._documentMouseUp$
81679                 .pipe(filter((e) => {
81680                 return this._mouseButton(e) === LEFT_BUTTON;
81681             })))
81682                 .pipe(share());
81683             const mouseDragInitiate$ = this._createMouseDragInitiate$(LEFT_BUTTON, this._mouseDown$, dragStop$, true)
81684                 .pipe(share());
81685             this._mouseDragStart$ =
81686                 this._createMouseDragStart$(mouseDragInitiate$)
81687                     .pipe(share());
81688             this._mouseDrag$ =
81689                 this._createMouseDrag$(mouseDragInitiate$, dragStop$)
81690                     .pipe(share());
81691             this._mouseDragEnd$ =
81692                 this._createMouseDragEnd$(this._mouseDragStart$, dragStop$)
81693                     .pipe(share());
81694             const domMouseDragInitiate$ = this._createMouseDragInitiate$(LEFT_BUTTON, this._domMouseDown$, dragStop$, false)
81695                 .pipe(share());
81696             this._domMouseDragStart$ =
81697                 this._createMouseDragStart$(domMouseDragInitiate$)
81698                     .pipe(share());
81699             this._domMouseDrag$ =
81700                 this._createMouseDrag$(domMouseDragInitiate$, dragStop$)
81701                     .pipe(share());
81702             this._domMouseDragEnd$ =
81703                 this._createMouseDragEnd$(this._domMouseDragStart$, dragStop$)
81704                     .pipe(share());
81705             const rightDragStop$ = merge(this._windowBlur$, this._documentMouseMove$.pipe(filter((e) => {
81706                 return this._buttonReleased(e, RIGHT_BUTTON);
81707             })), this._documentMouseUp$.pipe(filter((e) => {
81708                 return this._mouseButton(e) === RIGHT_BUTTON;
81709             })))
81710                 .pipe(share());
81711             const mouseRightDragInitiate$ = this._createMouseDragInitiate$(RIGHT_BUTTON, this._mouseDown$, rightDragStop$, true)
81712                 .pipe(share());
81713             this._mouseRightDragStart$ =
81714                 this._createMouseDragStart$(mouseRightDragInitiate$)
81715                     .pipe(share());
81716             this._mouseRightDrag$ =
81717                 this._createMouseDrag$(mouseRightDragInitiate$, rightDragStop$)
81718                     .pipe(share());
81719             this._mouseRightDragEnd$ =
81720                 this._createMouseDragEnd$(this._mouseRightDragStart$, rightDragStop$)
81721                     .pipe(share());
81722             this._proximateClick$ = this._mouseDown$
81723                 .pipe(switchMap((mouseDown) => {
81724                 return this._click$.pipe(takeUntil(this._createDeferredMouseMove$(mouseDown, this._documentMouseMove$)), take(1));
81725             }), share());
81726             this._staticClick$ = this._mouseDown$
81727                 .pipe(switchMap(() => {
81728                 return this._click$.pipe(takeUntil(this._documentMouseMove$), take(1));
81729             }), share());
81730             subs.push(this._mouseDragStart$.subscribe());
81731             subs.push(this._mouseDrag$.subscribe());
81732             subs.push(this._mouseDragEnd$.subscribe());
81733             subs.push(this._domMouseDragStart$.subscribe());
81734             subs.push(this._domMouseDrag$.subscribe());
81735             subs.push(this._domMouseDragEnd$.subscribe());
81736             subs.push(this._mouseRightDragStart$.subscribe());
81737             subs.push(this._mouseRightDrag$.subscribe());
81738             subs.push(this._mouseRightDragEnd$.subscribe());
81739             subs.push(this._staticClick$.subscribe());
81740             this._mouseOwner$ = this._createOwner$(this._claimMouse$)
81741                 .pipe(publishReplay(1), refCount());
81742             this._wheelOwner$ = this._createOwner$(this._claimWheel$)
81743                 .pipe(publishReplay(1), refCount());
81744             subs.push(this._mouseOwner$.subscribe(() => { }));
81745             subs.push(this._wheelOwner$.subscribe(() => { }));
81746         }
81747         get active$() {
81748             return this._active$;
81749         }
81750         get activate$() {
81751             return this._activeSubject$;
81752         }
81753         get documentMouseMove$() {
81754             return this._documentMouseMove$;
81755         }
81756         get documentMouseUp$() {
81757             return this._documentMouseUp$;
81758         }
81759         get domMouseDragStart$() {
81760             return this._domMouseDragStart$;
81761         }
81762         get domMouseDrag$() {
81763             return this._domMouseDrag$;
81764         }
81765         get domMouseDragEnd$() {
81766             return this._domMouseDragEnd$;
81767         }
81768         get domMouseDown$() {
81769             return this._domMouseDown$;
81770         }
81771         get domMouseMove$() {
81772             return this._domMouseMove$;
81773         }
81774         get mouseOwner$() {
81775             return this._mouseOwner$;
81776         }
81777         get mouseDown$() {
81778             return this._mouseDown$;
81779         }
81780         get mouseEnter$() {
81781             return this._mouseEnter$;
81782         }
81783         get mouseMove$() {
81784             return this._mouseMove$;
81785         }
81786         get mouseLeave$() {
81787             return this._mouseLeave$;
81788         }
81789         get mouseOut$() {
81790             return this._mouseOut$;
81791         }
81792         get mouseOver$() {
81793             return this._mouseOver$;
81794         }
81795         get mouseUp$() {
81796             return this._mouseUp$;
81797         }
81798         get click$() {
81799             return this._click$;
81800         }
81801         get dblClick$() {
81802             return this._dblClick$;
81803         }
81804         get contextMenu$() {
81805             return this._consistentContextMenu$;
81806         }
81807         get mouseWheel$() {
81808             return this._mouseWheel$;
81809         }
81810         get mouseDragStart$() {
81811             return this._mouseDragStart$;
81812         }
81813         get mouseDrag$() {
81814             return this._mouseDrag$;
81815         }
81816         get mouseDragEnd$() {
81817             return this._mouseDragEnd$;
81818         }
81819         get mouseRightDragStart$() {
81820             return this._mouseRightDragStart$;
81821         }
81822         get mouseRightDrag$() {
81823             return this._mouseRightDrag$;
81824         }
81825         get mouseRightDragEnd$() {
81826             return this._mouseRightDragEnd$;
81827         }
81828         get proximateClick$() {
81829             return this._proximateClick$;
81830         }
81831         get staticClick$() {
81832             return this._staticClick$;
81833         }
81834         get windowBlur$() {
81835             return this._windowBlur$;
81836         }
81837         dispose() {
81838             this._subscriptions.unsubscribe();
81839         }
81840         claimMouse(name, zindex) {
81841             this._claimMouse$.next({ name: name, zindex: zindex });
81842         }
81843         unclaimMouse(name) {
81844             this._claimMouse$.next({ name: name, zindex: null });
81845         }
81846         deferPixels(name, deferPixels) {
81847             this._deferPixelClaims$.next({ name: name, deferPixels: deferPixels });
81848         }
81849         undeferPixels(name) {
81850             this._deferPixelClaims$.next({ name: name, deferPixels: null });
81851         }
81852         claimWheel(name, zindex) {
81853             this._claimWheel$.next({ name: name, zindex: zindex });
81854         }
81855         unclaimWheel(name) {
81856             this._claimWheel$.next({ name: name, zindex: null });
81857         }
81858         filtered$(name, observable$) {
81859             return this._filtered(name, observable$, this._mouseOwner$);
81860         }
81861         filteredWheel$(name, observable$) {
81862             return this._filtered(name, observable$, this._wheelOwner$);
81863         }
81864         _createDeferredMouseMove$(origin, mouseMove$) {
81865             return mouseMove$.pipe(map((mouseMove) => {
81866                 const deltaX = mouseMove.clientX - origin.clientX;
81867                 const deltaY = mouseMove.clientY - origin.clientY;
81868                 return [mouseMove, Math.sqrt(deltaX * deltaX + deltaY * deltaY)];
81869             }), withLatestFrom(this._deferPixels$), filter(([[, delta], deferPixels]) => {
81870                 return delta > deferPixels;
81871             }), map(([[mouseMove]]) => {
81872                 return mouseMove;
81873             }));
81874         }
81875         _createMouseDrag$(mouseDragStartInitiate$, stop$) {
81876             return mouseDragStartInitiate$.pipe(map(([, mouseMove]) => {
81877                 return mouseMove;
81878             }), switchMap((mouseMove) => {
81879                 return concat(of(mouseMove), this._documentMouseMove$).pipe(takeUntil(stop$));
81880             }));
81881         }
81882         _createMouseDragEnd$(mouseDragStart$, stop$) {
81883             return mouseDragStart$.pipe(switchMap(() => {
81884                 return stop$.pipe(first());
81885             }));
81886         }
81887         _createMouseDragStart$(mouseDragStartInitiate$) {
81888             return mouseDragStartInitiate$.pipe(map(([mouseDown]) => {
81889                 return mouseDown;
81890             }));
81891         }
81892         _createMouseDragInitiate$(button, mouseDown$, stop$, defer) {
81893             return mouseDown$.pipe(filter((mouseDown) => {
81894                 return this._mouseButton(mouseDown) === button;
81895             }), switchMap((mouseDown) => {
81896                 return combineLatest(of(mouseDown), defer ?
81897                     this._createDeferredMouseMove$(mouseDown, this._documentMouseMove$) :
81898                     this._documentMouseMove$).pipe(takeUntil(stop$), take(1));
81899             }));
81900         }
81901         _createOwner$(claim$) {
81902             return claim$.pipe(scan((claims, claim) => {
81903                 if (claim.zindex == null) {
81904                     delete claims[claim.name];
81905                 }
81906                 else {
81907                     claims[claim.name] = claim.zindex;
81908                 }
81909                 return claims;
81910             }, {}), map((claims) => {
81911                 let owner = null;
81912                 let zIndexMax = -1;
81913                 for (const name in claims) {
81914                     if (!claims.hasOwnProperty(name)) {
81915                         continue;
81916                     }
81917                     if (claims[name] > zIndexMax) {
81918                         zIndexMax = claims[name];
81919                         owner = name;
81920                     }
81921                 }
81922                 return owner;
81923             }), startWith(null));
81924         }
81925         _filtered(name, observable$, owner$) {
81926             return observable$.pipe(withLatestFrom(owner$), filter(([, owner]) => {
81927                 return owner === name;
81928             }), map(([item]) => {
81929                 return item;
81930             }));
81931         }
81932         _mouseButton(event) {
81933             const upOrDown = event.type === "pointerdown" || event.type === "pointerup";
81934             const InstallTrigger = window.InstallTrigger;
81935             if (upOrDown &&
81936                 typeof InstallTrigger !== 'undefined' &&
81937                 event.button === RIGHT_BUTTON && event.ctrlKey &&
81938                 window.navigator.platform.toUpperCase().indexOf('MAC') >= 0) {
81939                 // Fix for the fact that Firefox (detected by InstallTrigger)
81940                 // on Mac determines e.button = 2 when using Control + left click.
81941                 return LEFT_BUTTON;
81942             }
81943             return event.button;
81944         }
81945         _buttonReleased(event, button) {
81946             // Right button `mouseup` is not fired in
81947             // Chrome on Mac outside the window or iframe. If
81948             // the button is no longer pressed during move
81949             // it may have been released and drag stop
81950             // should be emitted.
81951             const flag = BUTTONS_MAP[button];
81952             return event.buttons === undefined || (event.buttons & flag) !== flag;
81953         }
81954         _isMousePen(event) {
81955             const type = event.pointerType;
81956             return type === "mouse" || type === "pen";
81957         }
81958     }
81959
81960     class SpriteAtlas {
81961         set json(value) {
81962             this._json = value;
81963         }
81964         set image(value) {
81965             this._image = value;
81966             this._texture = new Texture(this._image);
81967             this._texture.minFilter = NearestFilter;
81968         }
81969         get loaded() {
81970             return !!(this._image && this._json);
81971         }
81972         getGLSprite(name) {
81973             if (!this.loaded) {
81974                 throw new Error("Sprites cannot be retrieved before the atlas is loaded.");
81975             }
81976             let definition = this._json[name];
81977             if (!definition) {
81978                 console.warn("Sprite with key" + name + "does not exist in sprite definition.");
81979                 return new Object3D();
81980             }
81981             let texture = this._texture.clone();
81982             texture.needsUpdate = true;
81983             let width = this._image.width;
81984             let height = this._image.height;
81985             texture.offset.x = definition.x / width;
81986             texture.offset.y = (height - definition.y - definition.height) / height;
81987             texture.repeat.x = definition.width / width;
81988             texture.repeat.y = definition.height / height;
81989             let material = new SpriteMaterial({ map: texture });
81990             return new Sprite(material);
81991         }
81992         getDOMSprite(name, float) {
81993             if (!this.loaded) {
81994                 throw new Error("Sprites cannot be retrieved before the atlas is loaded.");
81995             }
81996             if (float == null) {
81997                 float = exports.Alignment.Center;
81998             }
81999             let definition = this._json[name];
82000             if (!definition) {
82001                 console.warn("Sprite with key" + name + "does not exist in sprite definition.");
82002                 return virtualDom.h("div", {}, []);
82003             }
82004             let clipTop = definition.y;
82005             let clipRigth = definition.x + definition.width;
82006             let clipBottom = definition.y + definition.height;
82007             let clipLeft = definition.x;
82008             let left = -definition.x;
82009             let top = -definition.y;
82010             let height = this._image.height;
82011             let width = this._image.width;
82012             switch (float) {
82013                 case exports.Alignment.Bottom:
82014                 case exports.Alignment.Center:
82015                 case exports.Alignment.Top:
82016                     left -= definition.width / 2;
82017                     break;
82018                 case exports.Alignment.BottomLeft:
82019                 case exports.Alignment.Left:
82020                 case exports.Alignment.TopLeft:
82021                     left -= definition.width;
82022                     break;
82023                 case exports.Alignment.BottomRight:
82024                 case exports.Alignment.Right:
82025                 case exports.Alignment.TopRight:
82026             }
82027             switch (float) {
82028                 case exports.Alignment.Center:
82029                 case exports.Alignment.Left:
82030                 case exports.Alignment.Right:
82031                     top -= definition.height / 2;
82032                     break;
82033                 case exports.Alignment.Top:
82034                 case exports.Alignment.TopLeft:
82035                 case exports.Alignment.TopRight:
82036                     top -= definition.height;
82037                     break;
82038                 case exports.Alignment.Bottom:
82039                 case exports.Alignment.BottomLeft:
82040                 case exports.Alignment.BottomRight:
82041             }
82042             let pixelRatioInverse = 1 / definition.pixelRatio;
82043             clipTop *= pixelRatioInverse;
82044             clipRigth *= pixelRatioInverse;
82045             clipBottom *= pixelRatioInverse;
82046             clipLeft *= pixelRatioInverse;
82047             left *= pixelRatioInverse;
82048             top *= pixelRatioInverse;
82049             height *= pixelRatioInverse;
82050             width *= pixelRatioInverse;
82051             let properties = {
82052                 src: this._image.src,
82053                 style: {
82054                     clip: `rect(${clipTop}px, ${clipRigth}px, ${clipBottom}px, ${clipLeft}px)`,
82055                     height: `${height}px`,
82056                     left: `${left}px`,
82057                     position: "absolute",
82058                     top: `${top}px`,
82059                     width: `${width}px`,
82060                 },
82061             };
82062             return virtualDom.h("img", properties, []);
82063         }
82064     }
82065     class SpriteService {
82066         constructor(sprite) {
82067             this._retina = window.devicePixelRatio > 1;
82068             this._spriteAtlasOperation$ = new Subject();
82069             this._spriteAtlas$ = this._spriteAtlasOperation$.pipe(startWith((atlas) => {
82070                 return atlas;
82071             }), scan((atlas, operation) => {
82072                 return operation(atlas);
82073             }, new SpriteAtlas()), publishReplay(1), refCount());
82074             this._atlasSubscription = this._spriteAtlas$
82075                 .subscribe(() => { });
82076             if (sprite == null) {
82077                 return;
82078             }
82079             let format = this._retina ? "@2x" : "";
82080             let imageXmlHTTP = new XMLHttpRequest();
82081             imageXmlHTTP.open("GET", sprite + format + ".png", true);
82082             imageXmlHTTP.responseType = "arraybuffer";
82083             imageXmlHTTP.onload = () => {
82084                 let image = new Image();
82085                 image.onload = () => {
82086                     this._spriteAtlasOperation$.next((atlas) => {
82087                         atlas.image = image;
82088                         return atlas;
82089                     });
82090                 };
82091                 let blob = new Blob([imageXmlHTTP.response]);
82092                 image.src = window.URL.createObjectURL(blob);
82093             };
82094             imageXmlHTTP.onerror = (error) => {
82095                 console.error(new Error(`Failed to fetch sprite sheet (${sprite}${format}.png)`));
82096             };
82097             imageXmlHTTP.send();
82098             let jsonXmlHTTP = new XMLHttpRequest();
82099             jsonXmlHTTP.open("GET", sprite + format + ".json", true);
82100             jsonXmlHTTP.responseType = "text";
82101             jsonXmlHTTP.onload = () => {
82102                 let json = JSON.parse(jsonXmlHTTP.response);
82103                 this._spriteAtlasOperation$.next((atlas) => {
82104                     atlas.json = json;
82105                     return atlas;
82106                 });
82107             };
82108             jsonXmlHTTP.onerror = (error) => {
82109                 console.error(new Error(`Failed to fetch sheet (${sprite}${format}.json)`));
82110             };
82111             jsonXmlHTTP.send();
82112         }
82113         get spriteAtlas$() {
82114             return this._spriteAtlas$;
82115         }
82116         dispose() {
82117             this._atlasSubscription.unsubscribe();
82118         }
82119     }
82120
82121     class TouchService {
82122         constructor(canvasContainer, domContainer) {
82123             this._subscriptions = new SubscriptionHolder();
82124             const subs = this._subscriptions;
82125             this._activeSubject$ = new BehaviorSubject(false);
82126             this._active$ = this._activeSubject$.pipe(distinctUntilChanged(), publishReplay(1), refCount());
82127             subs.push(fromEvent(domContainer, "touchmove")
82128                 .subscribe((event) => {
82129                 event.preventDefault();
82130             }));
82131             this._touchStart$ = fromEvent(canvasContainer, "touchstart");
82132             this._touchMove$ = fromEvent(canvasContainer, "touchmove");
82133             this._touchEnd$ = fromEvent(canvasContainer, "touchend");
82134             this._touchCancel$ = fromEvent(canvasContainer, "touchcancel");
82135             const tapStart$ = this._touchStart$.pipe(filter((te) => {
82136                 return te.touches.length === 1 && te.targetTouches.length === 1;
82137             }), share());
82138             this._doubleTap$ = tapStart$.pipe(bufferWhen(() => {
82139                 return tapStart$.pipe(first(), switchMap(() => {
82140                     return merge(timer(300), tapStart$).pipe(take(1));
82141                 }));
82142             }), filter((events) => {
82143                 return events.length === 2;
82144             }), map((events) => {
82145                 return events[events.length - 1];
82146             }), share());
82147             subs.push(this._doubleTap$
82148                 .subscribe((event) => {
82149                 event.preventDefault();
82150             }));
82151             this._singleTouchMove$ = this._touchMove$.pipe(filter((te) => {
82152                 return te.touches.length === 1 && te.targetTouches.length === 1;
82153             }), share());
82154             let singleTouchStart$ = merge(this._touchStart$, this._touchEnd$, this._touchCancel$).pipe(filter((te) => {
82155                 return te.touches.length === 1 && te.targetTouches.length === 1;
82156             }));
82157             let multipleTouchStart$ = merge(this._touchStart$, this._touchEnd$, this._touchCancel$).pipe(filter((te) => {
82158                 return te.touches.length >= 1;
82159             }));
82160             let touchStop$ = merge(this._touchEnd$, this._touchCancel$).pipe(filter((te) => {
82161                 return te.touches.length === 0;
82162             }));
82163             this._singleTouchDragStart$ = singleTouchStart$.pipe(mergeMap(() => {
82164                 return this._singleTouchMove$.pipe(takeUntil(merge(touchStop$, multipleTouchStart$)), take(1));
82165             }));
82166             this._singleTouchDragEnd$ = singleTouchStart$.pipe(mergeMap(() => {
82167                 return merge(touchStop$, multipleTouchStart$).pipe(first());
82168             }));
82169             this._singleTouchDrag$ = singleTouchStart$.pipe(switchMap(() => {
82170                 return this._singleTouchMove$.pipe(skip(1), takeUntil(merge(multipleTouchStart$, touchStop$)));
82171             }));
82172             let touchesChanged$ = merge(this._touchStart$, this._touchEnd$, this._touchCancel$);
82173             this._pinchStart$ = touchesChanged$.pipe(filter((te) => {
82174                 return te.touches.length === 2 && te.targetTouches.length === 2;
82175             }));
82176             this._pinchEnd$ = touchesChanged$.pipe(filter((te) => {
82177                 return te.touches.length !== 2 || te.targetTouches.length !== 2;
82178             }));
82179             this._pinchOperation$ = new Subject();
82180             this._pinch$ = this._pinchOperation$.pipe(scan((pinch, operation) => {
82181                 return operation(pinch);
82182             }, {
82183                 changeX: 0,
82184                 changeY: 0,
82185                 clientX: 0,
82186                 clientY: 0,
82187                 distance: 0,
82188                 distanceChange: 0,
82189                 distanceX: 0,
82190                 distanceY: 0,
82191                 originalEvent: null,
82192                 pageX: 0,
82193                 pageY: 0,
82194                 screenX: 0,
82195                 screenY: 0,
82196                 touch1: null,
82197                 touch2: null,
82198             }));
82199             const pinchSubscription = this._touchMove$.pipe(filter((te) => {
82200                 return te.touches.length === 2 && te.targetTouches.length === 2;
82201             }), map((te) => {
82202                 return (previous) => {
82203                     let touch1 = te.touches[0];
82204                     let touch2 = te.touches[1];
82205                     let minX = Math.min(touch1.clientX, touch2.clientX);
82206                     let maxX = Math.max(touch1.clientX, touch2.clientX);
82207                     let minY = Math.min(touch1.clientY, touch2.clientY);
82208                     let maxY = Math.max(touch1.clientY, touch2.clientY);
82209                     let centerClientX = minX + (maxX - minX) / 2;
82210                     let centerClientY = minY + (maxY - minY) / 2;
82211                     let centerPageX = centerClientX + touch1.pageX - touch1.clientX;
82212                     let centerPageY = centerClientY + touch1.pageY - touch1.clientY;
82213                     let centerScreenX = centerClientX + touch1.screenX - touch1.clientX;
82214                     let centerScreenY = centerClientY + touch1.screenY - touch1.clientY;
82215                     let distanceX = Math.abs(touch1.clientX - touch2.clientX);
82216                     let distanceY = Math.abs(touch1.clientY - touch2.clientY);
82217                     let distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
82218                     let distanceChange = distance - previous.distance;
82219                     let changeX = distanceX - previous.distanceX;
82220                     let changeY = distanceY - previous.distanceY;
82221                     let current = {
82222                         changeX: changeX,
82223                         changeY: changeY,
82224                         clientX: centerClientX,
82225                         clientY: centerClientY,
82226                         distance: distance,
82227                         distanceChange: distanceChange,
82228                         distanceX: distanceX,
82229                         distanceY: distanceY,
82230                         originalEvent: te,
82231                         pageX: centerPageX,
82232                         pageY: centerPageY,
82233                         screenX: centerScreenX,
82234                         screenY: centerScreenY,
82235                         touch1: touch1,
82236                         touch2: touch2,
82237                     };
82238                     return current;
82239                 };
82240             }))
82241                 .subscribe(this._pinchOperation$);
82242             subs.push(pinchSubscription);
82243             this._pinchChange$ = this._pinchStart$.pipe(switchMap(() => {
82244                 return this._pinch$.pipe(skip(1), takeUntil(this._pinchEnd$));
82245             }));
82246         }
82247         get active$() {
82248             return this._active$;
82249         }
82250         get activate$() {
82251             return this._activeSubject$;
82252         }
82253         get doubleTap$() {
82254             return this._doubleTap$;
82255         }
82256         get touchStart$() {
82257             return this._touchStart$;
82258         }
82259         get touchMove$() {
82260             return this._touchMove$;
82261         }
82262         get touchEnd$() {
82263             return this._touchEnd$;
82264         }
82265         get touchCancel$() {
82266             return this._touchCancel$;
82267         }
82268         get singleTouchDragStart$() {
82269             return this._singleTouchDragStart$;
82270         }
82271         get singleTouchDrag$() {
82272             return this._singleTouchDrag$;
82273         }
82274         get singleTouchDragEnd$() {
82275             return this._singleTouchDragEnd$;
82276         }
82277         get pinch$() {
82278             return this._pinchChange$;
82279         }
82280         get pinchStart$() {
82281             return this._pinchStart$;
82282         }
82283         get pinchEnd$() {
82284             return this._pinchEnd$;
82285         }
82286         dispose() {
82287             this._subscriptions.unsubscribe();
82288         }
82289     }
82290
82291     class ConfigurationService {
82292         constructor(options) {
82293             var _a, _b, _c, _d;
82294             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";
82295             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";
82296             const exploreUrl = `${scheme}://${host}`;
82297             this._exploreUrl$ = of(exploreUrl);
82298             const imageTiling = (options === null || options === void 0 ? void 0 : options.imageTiling) === false ? false : true;
82299             this._imageTiling$ = of(imageTiling);
82300         }
82301         get exploreUrl$() {
82302             return this._exploreUrl$;
82303         }
82304         get imageTiling$() {
82305             return this._imageTiling$;
82306         }
82307     }
82308
82309     class Container {
82310         constructor(options, stateService, dom) {
82311             var _a;
82312             this._onWindowResize = () => {
82313                 if (this._trackResize) {
82314                     this.renderService.resize$.next();
82315                 }
82316             };
82317             this._dom = dom !== null && dom !== void 0 ? dom : new DOM();
82318             if (typeof options.container === "string") {
82319                 this._container = this._dom.document
82320                     .getElementById(options.container);
82321                 if (!this._container) {
82322                     throw new Error(`Container "${options.container}" not found.`);
82323                 }
82324             }
82325             else if (options.container instanceof HTMLElement) {
82326                 this._container = options.container;
82327             }
82328             else {
82329                 throw new Error(`Invalid type: "container" must be ` +
82330                     `a String or HTMLElement.`);
82331             }
82332             this._trackResize =
82333                 options.trackResize === false ?
82334                     false : true;
82335             this.id = (_a = this._container.id) !== null && _a !== void 0 ? _a : "mapillary-fallback-container-id";
82336             this._container.classList
82337                 .add("mapillary-viewer");
82338             this._canvasContainer = this._dom
82339                 .createElement("div", "mapillary-interactive", this._container);
82340             this._canvas = this._dom
82341                 .createElement("canvas", "mapillary-canvas");
82342             this._canvas.style.position = "absolute";
82343             this._canvas.setAttribute("tabindex", "0");
82344             // Add DOM container after canvas container to
82345             // render DOM elements on top of the interactive
82346             // canvas.
82347             this._domContainer = this._dom
82348                 .createElement("div", "mapillary-dom", this._container);
82349             this.configurationService = new ConfigurationService(options);
82350             this.renderService =
82351                 new RenderService(this._container, stateService.currentState$, options.renderMode);
82352             this.glRenderer =
82353                 new GLRenderer(this._canvas, this._canvasContainer, this.renderService);
82354             this.domRenderer =
82355                 new DOMRenderer(this._domContainer, this.renderService, stateService.currentState$);
82356             this.keyboardService =
82357                 new KeyboardService(this._canvasContainer);
82358             this.mouseService =
82359                 new MouseService(this._container, this._canvasContainer, this._domContainer, document);
82360             this.touchService =
82361                 new TouchService(this._canvasContainer, this._domContainer);
82362             this.spriteService =
82363                 new SpriteService(options.sprite);
82364             window.addEventListener('resize', this._onWindowResize, false);
82365         }
82366         get canvas() {
82367             return !!this._canvas.parentNode ?
82368                 this._canvas : null;
82369         }
82370         get canvasContainer() {
82371             return this._canvasContainer;
82372         }
82373         get container() {
82374             return this._container;
82375         }
82376         get domContainer() {
82377             return this._domContainer;
82378         }
82379         remove() {
82380             window.removeEventListener('resize', this._onWindowResize, false);
82381             this.spriteService.dispose();
82382             this.touchService.dispose();
82383             this.mouseService.dispose();
82384             this.glRenderer.remove();
82385             this.domRenderer.remove();
82386             this.renderService.dispose();
82387             this._removeNode(this._canvasContainer);
82388             this._removeNode(this._domContainer);
82389             this._container.classList
82390                 .remove("mapillary-viewer");
82391         }
82392         _removeNode(node) {
82393             if (node.parentNode) {
82394                 node.parentNode.removeChild(node);
82395             }
82396         }
82397     }
82398
82399     class CacheService {
82400         constructor(_graphService, _stateService, _api) {
82401             this._graphService = _graphService;
82402             this._stateService = _stateService;
82403             this._api = _api;
82404             this._subscriptions = new SubscriptionHolder();
82405             this._started = false;
82406             this._cellDepth = 1;
82407         }
82408         get started() {
82409             return this._started;
82410         }
82411         configure(configuration) {
82412             if (!configuration) {
82413                 this._cellDepth = 1;
82414                 return;
82415             }
82416             this._cellDepth = Math.max(1, Math.min(3, configuration.cellDepth));
82417         }
82418         start() {
82419             if (this._started) {
82420                 return;
82421             }
82422             const subs = this._subscriptions;
82423             subs.push(this._stateService.currentState$
82424                 .pipe(distinctUntilChanged(undefined, (frame) => {
82425                 return frame.state.currentImage.id;
82426             }), map((frame) => {
82427                 const state = frame.state;
82428                 const trajectory = state.trajectory;
82429                 const trajectoryKeys = trajectory
82430                     .map((n) => {
82431                     return n.id;
82432                 });
82433                 const sequenceKey = trajectory[trajectory.length - 1].sequenceId;
82434                 return [
82435                     trajectoryKeys,
82436                     state.currentImage.originalLngLat,
82437                     sequenceKey,
82438                 ];
82439             }), bufferCount(1, 5), withLatestFrom(this._graphService.graphMode$), switchMap(([keepBuffer, graphMode]) => {
82440                 const keepKeys = keepBuffer[0][0];
82441                 const lngLat = keepBuffer[0][1];
82442                 const geometry = this._api.data.geometry;
82443                 const cellId = geometry.lngLatToCellId(lngLat);
82444                 const keepCellIds = connectedComponent(cellId, this._cellDepth, geometry);
82445                 const keepSequenceKey = graphMode === GraphMode.Sequence ?
82446                     keepBuffer[0][2] :
82447                     undefined;
82448                 return this._graphService
82449                     .uncache$(keepKeys, keepCellIds, keepSequenceKey);
82450             }))
82451                 .subscribe(() => { }));
82452             subs.push(this._graphService.graphMode$
82453                 .pipe(skip(1), withLatestFrom(this._stateService.currentState$), switchMap(([mode, frame]) => {
82454                 return mode === GraphMode.Sequence ?
82455                     this._keyToEdges(frame.state.currentImage.id, (image) => {
82456                         return image.sequenceEdges$;
82457                     }) :
82458                     from(frame.state.trajectory
82459                         .map((image) => {
82460                         return image.id;
82461                     })
82462                         .slice(frame.state.currentIndex)).pipe(mergeMap((key) => {
82463                         return this._keyToEdges(key, (image) => {
82464                             return image.spatialEdges$;
82465                         });
82466                     }, 6));
82467             }))
82468                 .subscribe(() => { }));
82469             subs.push(this._graphService.dataAdded$
82470                 .pipe(withLatestFrom(this._stateService.currentId$), switchMap(([_, imageId]) => {
82471                 return this._graphService.cacheImage$(imageId);
82472             }))
82473                 .subscribe(() => { }));
82474             this._started = true;
82475         }
82476         stop() {
82477             if (!this._started) {
82478                 return;
82479             }
82480             this._subscriptions.unsubscribe();
82481             this._started = false;
82482         }
82483         _keyToEdges(key, imageToEdgeMap) {
82484             return this._graphService.cacheImage$(key).pipe(switchMap(imageToEdgeMap), first((status) => {
82485                 return status.cached;
82486             }), timeout(15000), catchError((error) => {
82487                 console.error(`Failed to cache edges (${key}).`, error);
82488                 return empty();
82489             }));
82490         }
82491     }
82492
82493     class LoadingService {
82494         constructor() {
82495             this._loadersSubject$ = new Subject();
82496             this._loaders$ = this._loadersSubject$.pipe(scan((loaders, loader) => {
82497                 if (loader.task !== undefined) {
82498                     loaders[loader.task] = loader.loading;
82499                 }
82500                 return loaders;
82501             }, {}), startWith({}), publishReplay(1), refCount());
82502         }
82503         get loading$() {
82504             return this._loaders$.pipe(map((loaders) => {
82505                 for (const key in loaders) {
82506                     if (!loaders.hasOwnProperty(key)) {
82507                         continue;
82508                     }
82509                     if (loaders[key]) {
82510                         return true;
82511                     }
82512                 }
82513                 return false;
82514             }), debounceTime(100), distinctUntilChanged());
82515         }
82516         taskLoading$(task) {
82517             return this._loaders$.pipe(map((loaders) => {
82518                 return !!loaders[task];
82519             }), debounceTime(100), distinctUntilChanged());
82520         }
82521         startLoading(task) {
82522             this._loadersSubject$.next({ loading: true, task: task });
82523         }
82524         stopLoading(task) {
82525             this._loadersSubject$.next({ loading: false, task: task });
82526         }
82527     }
82528
82529     var PanMode;
82530     (function (PanMode) {
82531         PanMode[PanMode["Disabled"] = 0] = "Disabled";
82532         PanMode[PanMode["Enabled"] = 1] = "Enabled";
82533         PanMode[PanMode["Started"] = 2] = "Started";
82534     })(PanMode || (PanMode = {}));
82535     class PanService {
82536         constructor(graphService, stateService, enabled, graphCalculator, spatial, viewportCoords) {
82537             this._subscriptions = new SubscriptionHolder();
82538             this._graphService = graphService;
82539             this._stateService = stateService;
82540             this._graphCalculator = graphCalculator !== null && graphCalculator !== void 0 ? graphCalculator : new GraphCalculator();
82541             this._spatial = spatial !== null && spatial !== void 0 ? spatial : new Spatial();
82542             this._viewportCoords = viewportCoords !== null && viewportCoords !== void 0 ? viewportCoords : new ViewportCoords();
82543             this._mode = enabled !== false ?
82544                 PanMode.Enabled : PanMode.Disabled;
82545             this._panImagesSubject$ = new Subject();
82546             this._panImages$ = this._panImagesSubject$.pipe(startWith([]), publishReplay(1), refCount());
82547             this._subscriptions.push(this._panImages$.subscribe());
82548         }
82549         get panImages$() {
82550             return this._panImages$;
82551         }
82552         dispose() {
82553             this.stop();
82554             if (this._panImagesSubscription != null) {
82555                 this._panImagesSubscription.unsubscribe();
82556             }
82557             this._subscriptions.unsubscribe();
82558         }
82559         enable() {
82560             if (this._mode !== PanMode.Disabled) {
82561                 return;
82562             }
82563             this._mode = PanMode.Enabled;
82564             this.start();
82565         }
82566         disable() {
82567             if (this._mode === PanMode.Disabled) {
82568                 return;
82569             }
82570             this.stop();
82571             this._mode = PanMode.Disabled;
82572         }
82573         start() {
82574             if (this._mode !== PanMode.Enabled) {
82575                 return;
82576             }
82577             const panImages$ = this._stateService.currentImage$.pipe(switchMap((current) => {
82578                 if (!current.merged || isSpherical(current.cameraType)) {
82579                     return of([]);
82580                 }
82581                 const current$ = of(current);
82582                 const bounds = this._graphCalculator.boundingBoxCorners(current.lngLat, 20);
82583                 const adjacent$ = this._graphService
82584                     .cacheBoundingBox$(bounds[0], bounds[1]).pipe(catchError((error) => {
82585                     console.error(`Failed to cache periphery bounding box (${current.id})`, error);
82586                     return empty();
82587                 }), map((images) => {
82588                     if (isSpherical(current.cameraType)) {
82589                         return [];
82590                     }
82591                     const potential = [];
82592                     for (const image of images) {
82593                         if (image.id === current.id) {
82594                             continue;
82595                         }
82596                         if (image.mergeId !== current.mergeId) {
82597                             continue;
82598                         }
82599                         if (isSpherical(image.cameraType)) {
82600                             continue;
82601                         }
82602                         if (this._distance(image, current) > 4) {
82603                             continue;
82604                         }
82605                         potential.push(image);
82606                     }
82607                     return potential;
82608                 }));
82609                 return combineLatest(current$, adjacent$).pipe(withLatestFrom(this._stateService.reference$), map(([[cn, adjacent], reference]) => {
82610                     const currentDirection = this._spatial.viewingDirection(cn.rotation);
82611                     const currentTranslation = computeTranslation({ lat: cn.lngLat.lat, lng: cn.lngLat.lng, alt: cn.computedAltitude }, cn.rotation, reference);
82612                     const currentTransform = this._createTransform(cn, currentTranslation);
82613                     const currentAzimuthal = this._spatial.wrap(this._spatial.azimuthal(currentDirection.toArray(), currentTransform.upVector().toArray()), 0, 2 * Math.PI);
82614                     const currentProjectedPoints = this._computeProjectedPoints(currentTransform);
82615                     const currentHFov = this._computeHorizontalFov(currentProjectedPoints) / 180 * Math.PI;
82616                     const preferredOverlap = Math.PI / 8;
82617                     let left = undefined;
82618                     let right = undefined;
82619                     for (const a of adjacent) {
82620                         const translation = computeTranslation({ lat: a.lngLat.lat, lng: a.lngLat.lng, alt: a.computedAltitude }, a.rotation, reference);
82621                         const transform = this._createTransform(a, translation);
82622                         const projectedPoints = this._computeProjectedPoints(transform);
82623                         const hFov = this._computeHorizontalFov(projectedPoints) / 180 * Math.PI;
82624                         const direction = this._spatial.viewingDirection(a.rotation);
82625                         const azimuthal = this._spatial.wrap(this._spatial.azimuthal(direction.toArray(), transform.upVector().toArray()), 0, 2 * Math.PI);
82626                         const directionChange = this._spatial.angleBetweenVector2(currentDirection.x, currentDirection.y, direction.x, direction.y);
82627                         let overlap = Number.NEGATIVE_INFINITY;
82628                         if (directionChange > 0) {
82629                             if (currentAzimuthal > azimuthal) {
82630                                 overlap = currentAzimuthal - 2 * Math.PI + currentHFov / 2 - (azimuthal - hFov / 2);
82631                             }
82632                             else {
82633                                 overlap = currentAzimuthal + currentHFov / 2 - (azimuthal - hFov / 2);
82634                             }
82635                         }
82636                         else {
82637                             if (currentAzimuthal < azimuthal) {
82638                                 overlap = azimuthal + hFov / 2 - (currentAzimuthal + 2 * Math.PI - currentHFov / 2);
82639                             }
82640                             else {
82641                                 overlap = azimuthal + hFov / 2 - (currentAzimuthal - currentHFov / 2);
82642                             }
82643                         }
82644                         const nonOverlap = Math.abs(hFov - overlap);
82645                         const distanceCost = this._distance(a, cn);
82646                         const timeCost = Math.min(this._timeDifference(a, cn), 4);
82647                         const overlapCost = 20 * Math.abs(overlap - preferredOverlap);
82648                         const fovCost = Math.min(5, 1 / Math.min(hFov / currentHFov, 1));
82649                         const nonOverlapCost = overlap > 0 ? -2 * nonOverlap : 0;
82650                         const cost = distanceCost + timeCost + overlapCost + fovCost + nonOverlapCost;
82651                         if (overlap > 0 &&
82652                             overlap < 0.5 * currentHFov &&
82653                             overlap < 0.5 * hFov &&
82654                             nonOverlap > 0.5 * currentHFov) {
82655                             if (directionChange > 0) {
82656                                 if (!left) {
82657                                     left = [cost, a, transform, hFov];
82658                                 }
82659                                 else {
82660                                     if (cost < left[0]) {
82661                                         left = [cost, a, transform, hFov];
82662                                     }
82663                                 }
82664                             }
82665                             else {
82666                                 if (!right) {
82667                                     right = [cost, a, transform, hFov];
82668                                 }
82669                                 else {
82670                                     if (cost < right[0]) {
82671                                         right = [cost, a, transform, hFov];
82672                                     }
82673                                 }
82674                             }
82675                         }
82676                     }
82677                     const panImagess = [];
82678                     if (!!left) {
82679                         panImagess.push([left[1], left[2], left[3]]);
82680                     }
82681                     if (!!right) {
82682                         panImagess.push([right[1], right[2], right[3]]);
82683                     }
82684                     return panImagess;
82685                 }), startWith([]));
82686             }));
82687             this._panImagesSubscription = this._stateService.currentState$.pipe(map((frame) => {
82688                 return frame.state.imagesAhead > 0;
82689             }), distinctUntilChanged(), switchMap((traversing) => {
82690                 return traversing ? of([]) : panImages$;
82691             }))
82692                 .subscribe((panImages) => {
82693                 this._panImagesSubject$.next(panImages);
82694             });
82695             this._mode = PanMode.Started;
82696         }
82697         stop() {
82698             if (this._mode !== PanMode.Started) {
82699                 return;
82700             }
82701             this._panImagesSubscription.unsubscribe();
82702             this._panImagesSubject$.next([]);
82703             this._mode = PanMode.Enabled;
82704         }
82705         _distance(image, reference) {
82706             const [x, y, z] = geodeticToEnu(image.lngLat.lng, image.lngLat.lat, image.computedAltitude, reference.lngLat.lng, reference.lngLat.lat, reference.computedAltitude);
82707             return Math.sqrt(x * x + y * y + z * z);
82708         }
82709         _timeDifference(image, reference) {
82710             const milliSecond = (1000 * 60 * 60 * 24 * 30);
82711             return Math.abs(image.capturedAt - reference.capturedAt) / milliSecond;
82712         }
82713         _createTransform(image, translation) {
82714             return new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, image.assetsCached ? image.image : undefined, undefined, image.cameraParameters, image.cameraType);
82715         }
82716         _computeProjectedPoints(transform) {
82717             const vertices = [[1, 0]];
82718             const directions = [[0, 0.5]];
82719             const pointsPerLine = 20;
82720             return computeProjectedPoints(transform, vertices, directions, pointsPerLine, this._viewportCoords);
82721         }
82722         _computeHorizontalFov(projectedPoints) {
82723             const fovs = projectedPoints
82724                 .map((projectedPoint) => {
82725                 return this._coordToFov(projectedPoint[0]);
82726             });
82727             const fov = Math.min(...fovs);
82728             return fov;
82729         }
82730         _coordToFov(x) {
82731             return 2 * Math.atan(x) * 180 / Math.PI;
82732         }
82733     }
82734
82735     /**
82736      * @class API
82737      *
82738      * @classdesc Provides methods for access to the API.
82739      */
82740     class APIWrapper {
82741         constructor(_data) {
82742             this._data = _data;
82743         }
82744         get data() {
82745             return this._data;
82746         }
82747         getCoreImages$(cellId) {
82748             return this._wrap$(this._data.getCoreImages(cellId));
82749         }
82750         getImages$(imageIds) {
82751             return this._wrap$(this._data.getImages(imageIds));
82752         }
82753         getImageTiles$(tiles) {
82754             return this._wrap$(this._data.getImageTiles(tiles));
82755         }
82756         getSequence$(sequenceId) {
82757             return this._wrap$(this._data.getSequence(sequenceId));
82758         }
82759         getSpatialImages$(imageIds) {
82760             return this._wrap$(this._data.getSpatialImages(imageIds));
82761         }
82762         setAccessToken(accessToken) {
82763             this._data.setAccessToken(accessToken);
82764         }
82765         _wrap$(promise) {
82766             return Observable.create((subscriber) => {
82767                 promise.then((value) => {
82768                     subscriber.next(value);
82769                     subscriber.complete();
82770                 }, (error) => {
82771                     subscriber.error(error);
82772                 });
82773             });
82774         }
82775     }
82776
82777     /**
82778      * @class GraphService
82779      *
82780      * @classdesc Represents a service for graph operations.
82781      */
82782     class GraphService {
82783         /**
82784          * Create a new graph service instance.
82785          *
82786          * @param {Graph} graph - Graph instance to be operated on.
82787          */
82788         constructor(graph) {
82789             this._dataAdded$ = new Subject();
82790             this._subscriptions = new SubscriptionHolder();
82791             this._onDataAdded = (event) => {
82792                 this._graph$
82793                     .pipe(first(), mergeMap(graph => {
82794                     return graph.updateCells$(event.cellIds).pipe(tap(() => { graph.resetSpatialEdges(); }));
82795                 }))
82796                     .subscribe(cellId => { this._dataAdded$.next(cellId); });
82797             };
82798             const subs = this._subscriptions;
82799             this._graph$ = concat(of(graph), graph.changed$).pipe(publishReplay(1), refCount());
82800             subs.push(this._graph$.subscribe(() => { }));
82801             this._graphMode = GraphMode.Spatial;
82802             this._graphModeSubject$ = new Subject();
82803             this._graphMode$ = this._graphModeSubject$.pipe(startWith(this._graphMode), publishReplay(1), refCount());
82804             subs.push(this._graphMode$.subscribe(() => { }));
82805             this._firstGraphSubjects$ = [];
82806             this._initializeCacheSubscriptions = [];
82807             this._sequenceSubscriptions = [];
82808             this._spatialSubscriptions = [];
82809             graph.api.data.on("datacreate", this._onDataAdded);
82810         }
82811         /**
82812          * Get dataAdded$.
82813          *
82814          * @returns {Observable<string>} Observable emitting
82815          * a cell id every time data has been added to a cell.
82816          */
82817         get dataAdded$() {
82818             return this._dataAdded$;
82819         }
82820         /**
82821          * Get filter observable.
82822          *
82823          * @desciption Emits the filter every time it has changed.
82824          *
82825          * @returns {Observable<FilterFunction>} Observable
82826          * emitting the filter function every time it is set.
82827          */
82828         get filter$() {
82829             return this._graph$.pipe(first(), mergeMap((graph) => {
82830                 return graph.filter$;
82831             }));
82832         }
82833         /**
82834          * Get graph mode observable.
82835          *
82836          * @description Emits the current graph mode.
82837          *
82838          * @returns {Observable<GraphMode>} Observable
82839          * emitting the current graph mode when it changes.
82840          */
82841         get graphMode$() {
82842             return this._graphMode$;
82843         }
82844         /**
82845          * Cache full images in a bounding box.
82846          *
82847          * @description When called, the full properties of
82848          * the image are retrieved. The image cache is not initialized
82849          * for any new images retrieved and the image assets are not
82850          * retrieved, {@link cacheImage$} needs to be called for caching
82851          * assets.
82852          *
82853          * @param {LngLat} sw - South west corner of bounding box.
82854          * @param {LngLat} ne - North east corner of bounding box.
82855          * @return {Observable<Array<Image>>} Observable emitting a single item,
82856          * the images of the bounding box, when they have all been retrieved.
82857          * @throws {Error} Propagates any IO image caching errors to the caller.
82858          */
82859         cacheBoundingBox$(sw, ne) {
82860             return this._graph$.pipe(first(), mergeMap((graph) => {
82861                 return graph.cacheBoundingBox$(sw, ne);
82862             }));
82863         }
82864         /**
82865          * Cache full images in a cell.
82866          *
82867          * @description When called, the full properties of
82868          * the image are retrieved. The image cache is not initialized
82869          * for any new images retrieved and the image assets are not
82870          * retrieved, {@link cacheImage$} needs to be called for caching
82871          * assets.
82872          *
82873          * @param {string} cellId - Id of the cell.
82874          * @return {Observable<Array<Image>>} Observable emitting a single item,
82875          * the images of the cell, when they have all been retrieved.
82876          * @throws {Error} Propagates any IO image caching errors to the caller.
82877          */
82878         cacheCell$(cellId) {
82879             return this._graph$.pipe(first(), mergeMap((graph) => {
82880                 return graph.cacheCell$(cellId);
82881             }));
82882         }
82883         /**
82884          * Cache a image in the graph and retrieve it.
82885          *
82886          * @description When called, the full properties of
82887          * the image are retrieved and the image cache is initialized.
82888          * After that the image assets are cached and the image
82889          * is emitted to the observable when.
82890          * In parallel to caching the image assets, the sequence and
82891          * spatial edges of the image are cached. For this, the sequence
82892          * of the image and the required tiles and spatial images are
82893          * retrieved. The sequence and spatial edges may be set before
82894          * or after the image is returned.
82895          *
82896          * @param {string} id - Id of the image to cache.
82897          * @return {Observable<Image>} Observable emitting a single item,
82898          * the image, when it has been retrieved and its assets are cached.
82899          * @throws {Error} Propagates any IO image caching errors to the caller.
82900          */
82901         cacheImage$(id) {
82902             const firstGraphSubject$ = new Subject();
82903             this._firstGraphSubjects$.push(firstGraphSubject$);
82904             const firstGraph$ = firstGraphSubject$.pipe(publishReplay(1), refCount());
82905             const image$ = firstGraph$.pipe(map((graph) => {
82906                 return graph.getNode(id);
82907             }), mergeMap((image) => {
82908                 return image.assetsCached ?
82909                     of(image) :
82910                     image.cacheAssets$();
82911             }), publishReplay(1), refCount());
82912             image$.subscribe(undefined, (error) => {
82913                 console.error(`Failed to cache image (${id}).`, error);
82914             });
82915             let initializeCacheSubscription;
82916             initializeCacheSubscription = this._graph$.pipe(first(), mergeMap((graph) => {
82917                 if (graph.isCachingFull(id) || !graph.hasNode(id)) {
82918                     return graph.cacheFull$(id);
82919                 }
82920                 if (graph.isCachingFill(id) || !graph.getNode(id).complete) {
82921                     return graph.cacheFill$(id);
82922                 }
82923                 return of(graph);
82924             }), tap((graph) => {
82925                 if (!graph.hasNode(id)) {
82926                     throw new GraphMapillaryError(`Failed to cache image (${id})`);
82927                 }
82928                 if (!graph.hasInitializedCache(id)) {
82929                     graph.initializeCache(id);
82930                 }
82931             }), finalize(() => {
82932                 if (initializeCacheSubscription == null) {
82933                     return;
82934                 }
82935                 this._removeFromArray(initializeCacheSubscription, this._initializeCacheSubscriptions);
82936                 this._removeFromArray(firstGraphSubject$, this._firstGraphSubjects$);
82937             }))
82938                 .subscribe((graph) => {
82939                 firstGraphSubject$.next(graph);
82940                 firstGraphSubject$.complete();
82941             }, (error) => {
82942                 firstGraphSubject$.error(error);
82943             });
82944             if (!initializeCacheSubscription.closed) {
82945                 this._initializeCacheSubscriptions.push(initializeCacheSubscription);
82946             }
82947             const graphSequence$ = firstGraph$.pipe(catchError(() => {
82948                 return empty();
82949             }), mergeMap((graph) => {
82950                 if (graph.isCachingNodeSequence(id) || !graph.hasNodeSequence(id)) {
82951                     return graph.cacheNodeSequence$(id);
82952                 }
82953                 return of(graph);
82954             }), publishReplay(1), refCount());
82955             let sequenceSubscription;
82956             sequenceSubscription = graphSequence$.pipe(tap((graph) => {
82957                 if (!graph.getNode(id).sequenceEdges.cached) {
82958                     graph.cacheSequenceEdges(id);
82959                 }
82960             }), finalize(() => {
82961                 if (sequenceSubscription == null) {
82962                     return;
82963                 }
82964                 this._removeFromArray(sequenceSubscription, this._sequenceSubscriptions);
82965             }))
82966                 .subscribe(() => { return; }, (error) => {
82967                 console.error(`Failed to cache sequence edges (${id}).`, error);
82968             });
82969             if (!sequenceSubscription.closed) {
82970                 this._sequenceSubscriptions.push(sequenceSubscription);
82971             }
82972             if (this._graphMode === GraphMode.Spatial) {
82973                 let spatialSubscription;
82974                 spatialSubscription = firstGraph$.pipe(catchError(() => {
82975                     return empty();
82976                 }), expand((graph) => {
82977                     if (graph.hasTiles(id)) {
82978                         return empty();
82979                     }
82980                     return from(graph.cacheTiles$(id)).pipe(mergeMap((graph$) => {
82981                         return graph$.pipe(mergeMap((g) => {
82982                             if (g.isCachingTiles(id)) {
82983                                 return empty();
82984                             }
82985                             return of(g);
82986                         }), catchError((error) => {
82987                             console.error(`Failed to cache tile data (${id}).`, error);
82988                             return empty();
82989                         }));
82990                     }));
82991                 }), takeLast(1), mergeMap((graph) => {
82992                     if (graph.hasSpatialArea(id)) {
82993                         return of(graph);
82994                     }
82995                     return from(graph.cacheSpatialArea$(id)).pipe(mergeMap((graph$) => {
82996                         return graph$.pipe(catchError((error) => {
82997                             console.error(`Failed to cache spatial images (${id}).`, error);
82998                             return empty();
82999                         }));
83000                     }));
83001                 }), takeLast(1), mergeMap((graph) => {
83002                     return graph.hasNodeSequence(id) ?
83003                         of(graph) :
83004                         graph.cacheNodeSequence$(id);
83005                 }), tap((graph) => {
83006                     if (!graph.getNode(id).spatialEdges.cached) {
83007                         graph.cacheSpatialEdges(id);
83008                     }
83009                 }), finalize(() => {
83010                     if (spatialSubscription == null) {
83011                         return;
83012                     }
83013                     this._removeFromArray(spatialSubscription, this._spatialSubscriptions);
83014                 }))
83015                     .subscribe(() => { return; }, (error) => {
83016                     const message = `Failed to cache spatial edges (${id}).`;
83017                     console.error(message, error);
83018                 });
83019                 if (!spatialSubscription.closed) {
83020                     this._spatialSubscriptions.push(spatialSubscription);
83021                 }
83022             }
83023             return image$.pipe(first((image) => {
83024                 return image.assetsCached;
83025             }));
83026         }
83027         /**
83028          * Cache a sequence in the graph and retrieve it.
83029          *
83030          * @param {string} sequenceId - Sequence id.
83031          * @returns {Observable<Sequence>} Observable emitting a single item,
83032          * the sequence, when it has been retrieved and its assets are cached.
83033          * @throws {Error} Propagates any IO image caching errors to the caller.
83034          */
83035         cacheSequence$(sequenceId) {
83036             return this._graph$.pipe(first(), mergeMap((graph) => {
83037                 if (graph.isCachingSequence(sequenceId) || !graph.hasSequence(sequenceId)) {
83038                     return graph.cacheSequence$(sequenceId);
83039                 }
83040                 return of(graph);
83041             }), map((graph) => {
83042                 return graph.getSequence(sequenceId);
83043             }));
83044         }
83045         /**
83046          * Cache a sequence and its images in the graph and retrieve the sequence.
83047          *
83048          * @description Caches a sequence and its assets are cached and
83049          * retrieves all images belonging to the sequence. The image assets
83050          * or edges will not be cached.
83051          *
83052          * @param {string} sequenceId - Sequence id.
83053          * @param {string} referenceImageId - Id of image to use as reference
83054          * for optimized caching.
83055          * @returns {Observable<Sequence>} Observable emitting a single item,
83056          * the sequence, when it has been retrieved, its assets are cached and
83057          * all images belonging to the sequence has been retrieved.
83058          * @throws {Error} Propagates any IO image caching errors to the caller.
83059          */
83060         cacheSequenceImages$(sequenceId, referenceImageId) {
83061             return this._graph$.pipe(first(), mergeMap((graph) => {
83062                 if (graph.isCachingSequence(sequenceId) || !graph.hasSequence(sequenceId)) {
83063                     return graph.cacheSequence$(sequenceId);
83064                 }
83065                 return of(graph);
83066             }), mergeMap((graph) => {
83067                 if (graph.isCachingSequenceNodes(sequenceId) || !graph.hasSequenceNodes(sequenceId)) {
83068                     return graph.cacheSequenceNodes$(sequenceId, referenceImageId);
83069                 }
83070                 return of(graph);
83071             }), map((graph) => {
83072                 return graph.getSequence(sequenceId);
83073             }));
83074         }
83075         /**
83076          * Dispose the graph service and its children.
83077          */
83078         dispose() {
83079             this._graph$
83080                 .pipe(first())
83081                 .subscribe((graph) => { graph.unsubscribe(); });
83082             this._subscriptions.unsubscribe();
83083         }
83084         /**
83085          * Set a spatial edge filter on the graph.
83086          *
83087          * @description Resets the spatial edges of all cached images.
83088          *
83089          * @param {FilterExpression} filter - Filter expression to be applied.
83090          * @return {Observable<Graph>} Observable emitting a single item,
83091          * the graph, when the spatial edges have been reset.
83092          */
83093         setFilter$(filter) {
83094             this._resetSubscriptions(this._spatialSubscriptions);
83095             return this._graph$.pipe(first(), tap((graph) => {
83096                 graph.resetSpatialEdges();
83097                 graph.setFilter(filter);
83098             }), map(() => {
83099                 return undefined;
83100             }));
83101         }
83102         /**
83103          * Set the graph mode.
83104          *
83105          * @description If graph mode is set to spatial, caching
83106          * is performed with emphasis on spatial edges. If graph
83107          * mode is set to sequence no tile data is requested and
83108          * no spatial edges are computed.
83109          *
83110          * When setting graph mode to sequence all spatial
83111          * subscriptions are aborted.
83112          *
83113          * @param {GraphMode} mode - Graph mode to set.
83114          */
83115         setGraphMode(mode) {
83116             if (this._graphMode === mode) {
83117                 return;
83118             }
83119             if (mode === GraphMode.Sequence) {
83120                 this._resetSubscriptions(this._spatialSubscriptions);
83121             }
83122             this._graphMode = mode;
83123             this._graphModeSubject$.next(this._graphMode);
83124         }
83125         /**
83126          * Reset the graph.
83127          *
83128          * @description Resets the graph but keeps the images of the
83129          * supplied ids.
83130          *
83131          * @param {Array<string>} keepIds - Ids of images to keep in graph.
83132          * @return {Observable<Image>} Observable emitting a single item,
83133          * the graph, when it has been reset.
83134          */
83135         reset$(keepIds) {
83136             this._abortSubjects(this._firstGraphSubjects$);
83137             this._resetSubscriptions(this._initializeCacheSubscriptions);
83138             this._resetSubscriptions(this._sequenceSubscriptions);
83139             this._resetSubscriptions(this._spatialSubscriptions);
83140             return this._graph$.pipe(first(), tap((graph) => {
83141                 graph.reset(keepIds);
83142             }), map(() => {
83143                 return undefined;
83144             }));
83145         }
83146         /**
83147          * Uncache the graph.
83148          *
83149          * @description Uncaches the graph by removing tiles, images and
83150          * sequences. Keeps the images of the supplied ids and the tiles
83151          * related to those images.
83152          *
83153          * @param {Array<string>} keepIds - Ids of images to keep in graph.
83154          * @param {Array<string>} keepCellIds - Ids of cells to keep in graph.
83155          * @param {string} keepSequenceId - Optional id of sequence
83156          * for which the belonging images should not be disposed or
83157          * removed from the graph. These images may still be uncached if
83158          * not specified in keep ids param.
83159          * @return {Observable<Graph>} Observable emitting a single item,
83160          * the graph, when the graph has been uncached.
83161          */
83162         uncache$(keepIds, keepCellIds, keepSequenceId) {
83163             return this._graph$.pipe(first(), tap((graph) => {
83164                 graph.uncache(keepIds, keepCellIds, keepSequenceId);
83165             }), map(() => {
83166                 return undefined;
83167             }));
83168         }
83169         _abortSubjects(subjects) {
83170             for (const subject of subjects.slice()) {
83171                 this._removeFromArray(subject, subjects);
83172                 subject.error(new Error("Cache image request was aborted."));
83173             }
83174         }
83175         _removeFromArray(object, objects) {
83176             const index = objects.indexOf(object);
83177             if (index !== -1) {
83178                 objects.splice(index, 1);
83179             }
83180         }
83181         _resetSubscriptions(subscriptions) {
83182             for (const subscription of subscriptions.slice()) {
83183                 this._removeFromArray(subscription, subscriptions);
83184                 if (!subscription.closed) {
83185                     subscription.unsubscribe();
83186                 }
83187             }
83188         }
83189     }
83190
83191     class FrameGenerator {
83192         constructor(root) {
83193             if (root.requestAnimationFrame) {
83194                 this._cancelAnimationFrame = root.cancelAnimationFrame.bind(root);
83195                 this._requestAnimationFrame = root.requestAnimationFrame.bind(root);
83196             }
83197             else if (root.mozRequestAnimationFrame) {
83198                 this._cancelAnimationFrame = root.mozCancelAnimationFrame.bind(root);
83199                 this._requestAnimationFrame = root.mozRequestAnimationFrame.bind(root);
83200             }
83201             else if (root.webkitRequestAnimationFrame) {
83202                 this._cancelAnimationFrame = root.webkitCancelAnimationFrame.bind(root);
83203                 this._requestAnimationFrame = root.webkitRequestAnimationFrame.bind(root);
83204             }
83205             else if (root.msRequestAnimationFrame) {
83206                 this._cancelAnimationFrame = root.msCancelAnimationFrame.bind(root);
83207                 this._requestAnimationFrame = root.msRequestAnimationFrame.bind(root);
83208             }
83209             else if (root.oRequestAnimationFrame) {
83210                 this._cancelAnimationFrame = root.oCancelAnimationFrame.bind(root);
83211                 this._requestAnimationFrame = root.oRequestAnimationFrame.bind(root);
83212             }
83213             else {
83214                 this._cancelAnimationFrame = root.clearTimeout.bind(root);
83215                 this._requestAnimationFrame = (cb) => { return root.setTimeout(cb, 1000 / 60); };
83216             }
83217         }
83218         get cancelAnimationFrame() {
83219             return this._cancelAnimationFrame;
83220         }
83221         get requestAnimationFrame() {
83222             return this._requestAnimationFrame;
83223         }
83224     }
83225
83226     class StateBase {
83227         constructor(state) {
83228             this._spatial = new Spatial();
83229             this._referenceThreshold = 0.01;
83230             this._transitionMode = state.transitionMode;
83231             this._reference = state.reference;
83232             this._alpha = state.alpha;
83233             this._stateTransitionAlpha = 0;
83234             this._camera = state.camera.clone();
83235             this._zoom = state.zoom;
83236             this._currentIndex = state.currentIndex;
83237             this._trajectory = state.trajectory.slice();
83238             this._trajectoryTransforms = [];
83239             this._trajectoryCameras = [];
83240             for (let image of this._trajectory) {
83241                 let translation = this._imageToTranslation(image, this._reference);
83242                 let transform = new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, image.image, undefined, image.cameraParameters, image.cameraType);
83243                 this._trajectoryTransforms.push(transform);
83244                 this._trajectoryCameras.push(new Camera(transform));
83245             }
83246             this._currentImage = this._trajectory.length > 0 ?
83247                 this._trajectory[this._currentIndex] :
83248                 null;
83249             this._previousImage = this._trajectory.length > 1 && this.currentIndex > 0 ?
83250                 this._trajectory[this._currentIndex - 1] :
83251                 null;
83252             this._currentCamera = this._trajectoryCameras.length > 0 ?
83253                 this._trajectoryCameras[this._currentIndex].clone() :
83254                 new Camera();
83255             this._previousCamera = this._trajectoryCameras.length > 1 && this.currentIndex > 0 ?
83256                 this._trajectoryCameras[this._currentIndex - 1].clone() :
83257                 this._currentCamera.clone();
83258         }
83259         get reference() {
83260             return this._reference;
83261         }
83262         get alpha() {
83263             return this._getAlpha();
83264         }
83265         get stateTransitionAlpha() {
83266             return this._getStateTransitionAlpha();
83267         }
83268         get camera() {
83269             return this._camera;
83270         }
83271         get zoom() {
83272             return this._zoom;
83273         }
83274         get trajectory() {
83275             return this._trajectory;
83276         }
83277         get currentIndex() {
83278             return this._currentIndex;
83279         }
83280         get currentImage() {
83281             return this._currentImage;
83282         }
83283         get previousImage() {
83284             return this._previousImage;
83285         }
83286         get currentCamera() {
83287             return this._currentCamera;
83288         }
83289         get currentTransform() {
83290             return this._trajectoryTransforms.length > 0 ?
83291                 this._trajectoryTransforms[this.currentIndex] : null;
83292         }
83293         get previousTransform() {
83294             return this._trajectoryTransforms.length > 1 && this.currentIndex > 0 ?
83295                 this._trajectoryTransforms[this.currentIndex - 1] : null;
83296         }
83297         get motionless() {
83298             return this._motionless;
83299         }
83300         get transitionMode() {
83301             return this._transitionMode;
83302         }
83303         move(delta) { }
83304         moveTo(position) { }
83305         rotate(delta) { }
83306         rotateUnbounded(delta) { }
83307         rotateWithoutInertia(delta) { }
83308         rotateBasic(basicRotation) { }
83309         rotateBasicUnbounded(basicRotation) { }
83310         rotateBasicWithoutInertia(basicRotation) { }
83311         rotateToBasic(basic) { }
83312         setSpeed(speed) { }
83313         zoomIn(delta, reference) { }
83314         update(delta) { }
83315         setCenter(center) { }
83316         setZoom(zoom) { }
83317         dolly(delta) { }
83318         orbit(rotation) { }
83319         setViewMatrix(matrix) { }
83320         truck(direction) { }
83321         append(images) {
83322             if (images.length < 1) {
83323                 throw Error("Trajectory can not be empty");
83324             }
83325             if (this._currentIndex < 0) {
83326                 this.set(images);
83327             }
83328             else {
83329                 this._trajectory = this._trajectory.concat(images);
83330                 this._appendToTrajectories(images);
83331             }
83332         }
83333         prepend(images) {
83334             if (images.length < 1) {
83335                 throw Error("Trajectory can not be empty");
83336             }
83337             this._trajectory = images.slice().concat(this._trajectory);
83338             this._currentIndex += images.length;
83339             this._setCurrentImage();
83340             let referenceReset = this._setReference(this._currentImage);
83341             if (referenceReset) {
83342                 this._setTrajectories();
83343             }
83344             else {
83345                 this._prependToTrajectories(images);
83346             }
83347             this._setCurrentCamera();
83348         }
83349         remove(n) {
83350             if (n < 0) {
83351                 throw Error("n must be a positive integer");
83352             }
83353             if (this._currentIndex - 1 < n) {
83354                 throw Error("Current and previous images can not be removed");
83355             }
83356             for (let i = 0; i < n; i++) {
83357                 this._trajectory.shift();
83358                 this._trajectoryTransforms.shift();
83359                 this._trajectoryCameras.shift();
83360                 this._currentIndex--;
83361             }
83362             this._setCurrentImage();
83363         }
83364         clearPrior() {
83365             if (this._currentIndex > 0) {
83366                 this.remove(this._currentIndex - 1);
83367             }
83368         }
83369         clear() {
83370             this.cut();
83371             if (this._currentIndex > 0) {
83372                 this.remove(this._currentIndex - 1);
83373             }
83374         }
83375         cut() {
83376             while (this._trajectory.length - 1 > this._currentIndex) {
83377                 this._trajectory.pop();
83378                 this._trajectoryTransforms.pop();
83379                 this._trajectoryCameras.pop();
83380             }
83381         }
83382         set(images) {
83383             this._setTrajectory(images);
83384             this._setCurrentImage();
83385             this._setReference(this._currentImage);
83386             this._setTrajectories();
83387             this._setCurrentCamera();
83388         }
83389         getCenter() {
83390             return this._currentImage != null ?
83391                 this.currentTransform.projectBasic(this._camera.lookat.toArray()) :
83392                 [0.5, 0.5];
83393         }
83394         setTransitionMode(mode) {
83395             this._transitionMode = mode;
83396         }
83397         _getAlpha() { return 1; }
83398         _getStateTransitionAlpha() { return 1; }
83399         _setCurrent() {
83400             this._setCurrentImage();
83401             let referenceReset = this._setReference(this._currentImage);
83402             if (referenceReset) {
83403                 this._setTrajectories();
83404             }
83405             this._setCurrentCamera();
83406         }
83407         _setCurrentCamera() {
83408             this._currentCamera = this._trajectoryCameras[this._currentIndex].clone();
83409             this._previousCamera = this._currentIndex > 0 ?
83410                 this._trajectoryCameras[this._currentIndex - 1].clone() :
83411                 this._currentCamera.clone();
83412         }
83413         _motionlessTransition() {
83414             let imagesSet = this._currentImage != null && this._previousImage != null;
83415             return imagesSet && (this._transitionMode === exports.TransitionMode.Instantaneous || !(this._currentImage.merged &&
83416                 this._previousImage.merged &&
83417                 this._withinOriginalDistance() &&
83418                 this._sameConnectedComponent()));
83419         }
83420         _setReference(image) {
83421             // do not reset reference if image is within threshold distance
83422             if (Math.abs(image.lngLat.lat - this.reference.lat) < this._referenceThreshold &&
83423                 Math.abs(image.lngLat.lng - this.reference.lng) < this._referenceThreshold) {
83424                 return false;
83425             }
83426             // do not reset reference if previous image exist and transition is with motion
83427             if (this._previousImage != null && !this._motionlessTransition()) {
83428                 return false;
83429             }
83430             this._reference.lat = image.lngLat.lat;
83431             this._reference.lng = image.lngLat.lng;
83432             this._reference.alt = image.computedAltitude;
83433             return true;
83434         }
83435         _setCurrentImage() {
83436             this._currentImage = this._trajectory.length > 0 ?
83437                 this._trajectory[this._currentIndex] :
83438                 null;
83439             this._previousImage = this._currentIndex > 0 ?
83440                 this._trajectory[this._currentIndex - 1] :
83441                 null;
83442         }
83443         _setTrajectory(images) {
83444             if (images.length < 1) {
83445                 throw new ArgumentMapillaryError("Trajectory can not be empty");
83446             }
83447             if (this._currentImage != null) {
83448                 this._trajectory = [this._currentImage].concat(images);
83449                 this._currentIndex = 1;
83450             }
83451             else {
83452                 this._trajectory = images.slice();
83453                 this._currentIndex = 0;
83454             }
83455         }
83456         _setTrajectories() {
83457             this._trajectoryTransforms.length = 0;
83458             this._trajectoryCameras.length = 0;
83459             this._appendToTrajectories(this._trajectory);
83460         }
83461         _appendToTrajectories(images) {
83462             for (let image of images) {
83463                 if (!image.assetsCached) {
83464                     throw new ArgumentMapillaryError("Assets must be cached when image is added to trajectory");
83465                 }
83466                 let translation = this._imageToTranslation(image, this.reference);
83467                 let transform = new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, image.image, undefined, image.cameraParameters, image.cameraType);
83468                 this._trajectoryTransforms.push(transform);
83469                 this._trajectoryCameras.push(new Camera(transform));
83470             }
83471         }
83472         _prependToTrajectories(images) {
83473             for (let image of images.reverse()) {
83474                 if (!image.assetsCached) {
83475                     throw new ArgumentMapillaryError("Assets must be cached when added to trajectory");
83476                 }
83477                 let translation = this._imageToTranslation(image, this.reference);
83478                 let transform = new Transform(image.exifOrientation, image.width, image.height, image.scale, image.rotation, translation, image.image, undefined, image.cameraParameters, image.cameraType);
83479                 this._trajectoryTransforms.unshift(transform);
83480                 this._trajectoryCameras.unshift(new Camera(transform));
83481             }
83482         }
83483         _imageToTranslation(image, reference) {
83484             return computeTranslation({ alt: image.computedAltitude, lat: image.lngLat.lat, lng: image.lngLat.lng }, image.rotation, reference);
83485         }
83486         _sameConnectedComponent() {
83487             let current = this._currentImage;
83488             let previous = this._previousImage;
83489             return !!current && !!previous &&
83490                 current.mergeId === previous.mergeId;
83491         }
83492         _withinOriginalDistance() {
83493             let current = this._currentImage;
83494             let previous = this._previousImage;
83495             if (!current || !previous) {
83496                 return true;
83497             }
83498             // 50 km/h moves 28m in 2s
83499             let distance = this._spatial.distanceFromLngLat(current.originalLngLat.lng, current.originalLngLat.lat, previous.originalLngLat.lng, previous.originalLngLat.lat);
83500             return distance < 25;
83501         }
83502     }
83503
83504     class CustomState extends StateBase {
83505         constructor(state) {
83506             super(state);
83507         }
83508         setViewMatrix(viewMatrix) {
83509             const viewMatrixInverse = new Matrix4()
83510                 .fromArray(viewMatrix)
83511                 .invert();
83512             const me = viewMatrixInverse.elements;
83513             const eye = new Vector3(me[12], me[13], me[14]);
83514             const forward = new Vector3(-me[8], -me[9], -me[10]);
83515             const up = new Vector3(me[4], me[5], me[6]);
83516             const camera = this._camera;
83517             camera.position.copy(eye);
83518             camera.lookat.copy(eye
83519                 .clone()
83520                 .add(forward));
83521             camera.up.copy(up);
83522             const focal = 0.5 / Math.tan(Math.PI / 3);
83523             camera.focal = focal;
83524         }
83525     }
83526
83527     class EarthState extends StateBase {
83528         constructor(state) {
83529             super(state);
83530             this._transition = 0;
83531             const eye = this._camera.position.clone();
83532             const forward = this._camera.lookat
83533                 .clone()
83534                 .sub(eye)
83535                 .normalize();
83536             const xy = Math.sqrt(forward.x * forward.x + forward.y * forward.y);
83537             const angle = Math.atan2(forward.z, xy);
83538             const lookat = new Vector3();
83539             if (angle > -Math.PI / 45) {
83540                 lookat.copy(eye);
83541                 eye.add(new Vector3(forward.x, forward.y, 0)
83542                     .multiplyScalar(-50));
83543                 eye.z = 30;
83544             }
83545             else {
83546                 // Target a point on invented ground and keep forward direction
83547                 const l0 = eye.clone();
83548                 const n = new Vector3(0, 0, 1);
83549                 const p0 = new Vector3(0, 0, -2);
83550                 const d = new Vector3().subVectors(p0, l0).dot(n) / forward.dot(n);
83551                 const maxDistance = 10000;
83552                 const intersection = l0
83553                     .clone()
83554                     .add(forward.
83555                     clone()
83556                     .multiplyScalar(Math.min(maxDistance, d)));
83557                 lookat.copy(intersection);
83558                 const t = eye
83559                     .clone()
83560                     .sub(intersection)
83561                     .normalize();
83562                 eye.copy(intersection.add(t.multiplyScalar(Math.max(50, t.length()))));
83563             }
83564             const eye1 = this._camera.position.clone();
83565             const lookat1 = eye1.clone().add(forward.clone().normalize().multiplyScalar(10));
83566             const up1 = this._camera.up.clone();
83567             const eye0 = lookat1.clone();
83568             const lookat0 = eye0.clone().add(forward.clone().normalize().multiplyScalar(10));
83569             const up0 = up1.clone();
83570             const eye2 = eye.clone();
83571             const lookat2 = lookat.clone();
83572             const up2 = new Vector3(0, 0, 1);
83573             const eye3 = eye.clone().add(lookat2.clone().sub(eye2).normalize().multiplyScalar(-10));
83574             const lookat3 = lookat2.clone();
83575             const up3 = up2.clone();
83576             this._curveE = new CatmullRomCurve3([eye0, eye1, eye2, eye3]);
83577             this._curveL = new CatmullRomCurve3([lookat0, lookat1, lookat2, lookat3]);
83578             this._curveU = new CatmullRomCurve3([up0, up1, up2, up3]);
83579             this._zoom0 = this._zoom;
83580             this._zoom1 = 0;
83581             this._camera.focal = 0.5 / Math.tan(Math.PI / 4);
83582         }
83583         get _isTransitioning() {
83584             return this._transition < 1;
83585         }
83586         dolly(delta) {
83587             if (this._isTransitioning) {
83588                 return;
83589             }
83590             const camera = this._camera;
83591             const offset = camera.position
83592                 .clone()
83593                 .sub(camera.lookat);
83594             const length = offset.length();
83595             const scaled = length * Math.pow(2, -delta);
83596             const clipped = Math.max(1, Math.min(scaled, 4000));
83597             offset.normalize();
83598             offset.multiplyScalar(clipped);
83599             camera.position
83600                 .copy(camera.lookat)
83601                 .add(offset);
83602         }
83603         orbit(rotation) {
83604             if (this._isTransitioning) {
83605                 return;
83606             }
83607             const camera = this._camera;
83608             const q = new Quaternion()
83609                 .setFromUnitVectors(camera.up, new Vector3(0, 0, 1));
83610             const qInverse = q
83611                 .clone()
83612                 .invert();
83613             const offset = camera.position
83614                 .clone()
83615                 .sub(camera.lookat);
83616             offset.applyQuaternion(q);
83617             const length = offset.length();
83618             let phi = Math.atan2(offset.y, offset.x);
83619             phi += rotation.phi;
83620             let theta = Math.atan2(Math.sqrt(offset.x * offset.x + offset.y * offset.y), offset.z);
83621             theta += rotation.theta;
83622             const threshold = Math.PI / 36;
83623             theta = Math.max(threshold, Math.min(Math.PI / 2 - threshold, theta));
83624             offset.x = Math.sin(theta) * Math.cos(phi);
83625             offset.y = Math.sin(theta) * Math.sin(phi);
83626             offset.z = Math.cos(theta);
83627             offset.applyQuaternion(qInverse);
83628             camera.position
83629                 .copy(camera.lookat)
83630                 .add(offset.multiplyScalar(length));
83631         }
83632         truck(direction) {
83633             if (this._isTransitioning) {
83634                 return;
83635             }
83636             const camera = this._camera;
83637             camera.position
83638                 .add(new Vector3().fromArray(direction));
83639             camera.lookat
83640                 .add(new Vector3().fromArray(direction));
83641         }
83642         update(delta) {
83643             if (!this._isTransitioning) {
83644                 return;
83645             }
83646             this._transition = Math.min(this._transition + 2 * delta / 3, 1);
83647             const sta = MathUtils.smootherstep(this._transition, 0, 1);
83648             const t = (sta + 1) / 3;
83649             const eye = this._curveE.getPoint(t);
83650             const lookat = this._curveL.getPoint(t);
83651             const up = this._curveU.getPoint(t);
83652             this._camera.position.copy(eye);
83653             this._camera.lookat.copy(lookat);
83654             this._camera.up.copy(up);
83655             this._zoom = MathUtils.lerp(this._zoom0, this._zoom1, sta);
83656             this._stateTransitionAlpha = sta;
83657         }
83658         _getStateTransitionAlpha() {
83659             return this._stateTransitionAlpha;
83660         }
83661     }
83662
83663     class EulerRotationDelta {
83664         constructor(phi, theta) {
83665             this._phi = phi;
83666             this._theta = theta;
83667         }
83668         get phi() {
83669             return this._phi;
83670         }
83671         set phi(value) {
83672             this._phi = value;
83673         }
83674         get theta() {
83675             return this._theta;
83676         }
83677         set theta(value) {
83678             this._theta = value;
83679         }
83680         get isZero() {
83681             return this._phi === 0 && this._theta === 0;
83682         }
83683         copy(delta) {
83684             this._phi = delta.phi;
83685             this._theta = delta.theta;
83686         }
83687         lerp(other, alpha) {
83688             this._phi = (1 - alpha) * this._phi + alpha * other.phi;
83689             this._theta = (1 - alpha) * this._theta + alpha * other.theta;
83690         }
83691         multiply(value) {
83692             this._phi *= value;
83693             this._theta *= value;
83694         }
83695         threshold(value) {
83696             this._phi = Math.abs(this._phi) > value ? this._phi : 0;
83697             this._theta = Math.abs(this._theta) > value ? this._theta : 0;
83698         }
83699         lengthSquared() {
83700             return this._phi * this._phi + this._theta * this._theta;
83701         }
83702         reset() {
83703             this._phi = 0;
83704             this._theta = 0;
83705         }
83706     }
83707
83708     class InteractiveStateBase extends StateBase {
83709         constructor(state) {
83710             super(state);
83711             this._animationSpeed = 1 / 40;
83712             this._rotationDelta = new EulerRotationDelta(0, 0);
83713             this._requestedRotationDelta = null;
83714             this._basicRotation = [0, 0];
83715             this._requestedBasicRotation = null;
83716             this._requestedBasicRotationUnbounded = null;
83717             this._rotationAcceleration = 0.86;
83718             this._rotationIncreaseAlpha = 0.97;
83719             this._rotationDecreaseAlpha = 0.9;
83720             this._rotationThreshold = 1e-3;
83721             this._unboundedRotationAlpha = 0.8;
83722             this._desiredZoom = state.zoom;
83723             this._minZoom = 0;
83724             this._maxZoom = 3;
83725             this._lookatDepth = 10;
83726             this._desiredLookat = null;
83727             this._desiredCenter = null;
83728         }
83729         rotate(rotationDelta) {
83730             if (this._currentImage == null) {
83731                 return;
83732             }
83733             if (rotationDelta.phi === 0 && rotationDelta.theta === 0) {
83734                 return;
83735             }
83736             this._desiredZoom = this._zoom;
83737             this._desiredLookat = null;
83738             this._requestedBasicRotation = null;
83739             if (this._requestedRotationDelta != null) {
83740                 this._requestedRotationDelta.phi = this._requestedRotationDelta.phi + rotationDelta.phi;
83741                 this._requestedRotationDelta.theta = this._requestedRotationDelta.theta + rotationDelta.theta;
83742             }
83743             else {
83744                 this._requestedRotationDelta = new EulerRotationDelta(rotationDelta.phi, rotationDelta.theta);
83745             }
83746         }
83747         rotateUnbounded(delta) {
83748             if (this._currentImage == null) {
83749                 return;
83750             }
83751             this._requestedBasicRotation = null;
83752             this._requestedRotationDelta = null;
83753             this._applyRotation(delta, this._currentCamera);
83754             this._applyRotation(delta, this._previousCamera);
83755             if (!this._desiredLookat) {
83756                 return;
83757             }
83758             const q = new Quaternion().setFromUnitVectors(this._currentCamera.up, new Vector3(0, 0, 1));
83759             const qInverse = q.clone().invert();
83760             const offset = new Vector3()
83761                 .copy(this._desiredLookat)
83762                 .sub(this._camera.position)
83763                 .applyQuaternion(q);
83764             const length = offset.length();
83765             let phi = Math.atan2(offset.y, offset.x);
83766             phi += delta.phi;
83767             let theta = Math.atan2(Math.sqrt(offset.x * offset.x + offset.y * offset.y), offset.z);
83768             theta += delta.theta;
83769             theta = Math.max(0.1, Math.min(Math.PI - 0.1, theta));
83770             offset.x = Math.sin(theta) * Math.cos(phi);
83771             offset.y = Math.sin(theta) * Math.sin(phi);
83772             offset.z = Math.cos(theta);
83773             offset.applyQuaternion(qInverse);
83774             this._desiredLookat
83775                 .copy(this._camera.position)
83776                 .add(offset.multiplyScalar(length));
83777         }
83778         rotateWithoutInertia(rotationDelta) {
83779             if (this._currentImage == null) {
83780                 return;
83781             }
83782             this._desiredZoom = this._zoom;
83783             this._desiredLookat = null;
83784             this._requestedBasicRotation = null;
83785             this._requestedRotationDelta = null;
83786             const threshold = Math.PI / (10 * Math.pow(2, this._zoom));
83787             const delta = {
83788                 phi: this._spatial.clamp(rotationDelta.phi, -threshold, threshold),
83789                 theta: this._spatial.clamp(rotationDelta.theta, -threshold, threshold),
83790             };
83791             this._applyRotation(delta, this._currentCamera);
83792             this._applyRotation(delta, this._previousCamera);
83793         }
83794         rotateBasic(basicRotation) {
83795             if (this._currentImage == null) {
83796                 return;
83797             }
83798             this._desiredZoom = this._zoom;
83799             this._desiredLookat = null;
83800             this._requestedRotationDelta = null;
83801             if (this._requestedBasicRotation != null) {
83802                 this._requestedBasicRotation[0] += basicRotation[0];
83803                 this._requestedBasicRotation[1] += basicRotation[1];
83804                 let threshold = 0.05 / Math.pow(2, this._zoom);
83805                 this._requestedBasicRotation[0] =
83806                     this._spatial.clamp(this._requestedBasicRotation[0], -threshold, threshold);
83807                 this._requestedBasicRotation[1] =
83808                     this._spatial.clamp(this._requestedBasicRotation[1], -threshold, threshold);
83809             }
83810             else {
83811                 this._requestedBasicRotation = basicRotation.slice();
83812             }
83813         }
83814         rotateBasicUnbounded(basicRotation) {
83815             if (this._currentImage == null) {
83816                 return;
83817             }
83818             if (this._requestedBasicRotationUnbounded != null) {
83819                 this._requestedBasicRotationUnbounded[0] += basicRotation[0];
83820                 this._requestedBasicRotationUnbounded[1] += basicRotation[1];
83821             }
83822             else {
83823                 this._requestedBasicRotationUnbounded = basicRotation.slice();
83824             }
83825         }
83826         rotateBasicWithoutInertia(basic) {
83827             if (this._currentImage == null) {
83828                 return;
83829             }
83830             this._desiredZoom = this._zoom;
83831             this._desiredLookat = null;
83832             this._requestedRotationDelta = null;
83833             this._requestedBasicRotation = null;
83834             const threshold = 0.05 / Math.pow(2, this._zoom);
83835             const basicRotation = basic.slice();
83836             basicRotation[0] = this._spatial.clamp(basicRotation[0], -threshold, threshold);
83837             basicRotation[1] = this._spatial.clamp(basicRotation[1], -threshold, threshold);
83838             this._applyRotationBasic(basicRotation);
83839         }
83840         rotateToBasic(basic) {
83841             if (this._currentImage == null) {
83842                 return;
83843             }
83844             this._desiredZoom = this._zoom;
83845             this._desiredLookat = null;
83846             basic[0] = this._spatial.clamp(basic[0], 0, 1);
83847             basic[1] = this._spatial.clamp(basic[1], 0, 1);
83848             let lookat = this.currentTransform.unprojectBasic(basic, this._lookatDepth);
83849             this._currentCamera.lookat.fromArray(lookat);
83850         }
83851         zoomIn(delta, reference) {
83852             if (this._currentImage == null) {
83853                 return;
83854             }
83855             this._desiredZoom = Math.max(this._minZoom, Math.min(this._maxZoom, this._desiredZoom + delta));
83856             let currentCenter = this.currentTransform.projectBasic(this._currentCamera.lookat.toArray());
83857             let currentCenterX = currentCenter[0];
83858             let currentCenterY = currentCenter[1];
83859             let zoom0 = Math.pow(2, this._zoom);
83860             let zoom1 = Math.pow(2, this._desiredZoom);
83861             let refX = reference[0];
83862             let refY = reference[1];
83863             if (isSpherical(this.currentTransform.cameraType)) {
83864                 if (refX - currentCenterX > 0.5) {
83865                     refX = refX - 1;
83866                 }
83867                 else if (currentCenterX - refX > 0.5) {
83868                     refX = 1 + refX;
83869                 }
83870             }
83871             let newCenterX = refX - zoom0 / zoom1 * (refX - currentCenterX);
83872             let newCenterY = refY - zoom0 / zoom1 * (refY - currentCenterY);
83873             if (isSpherical(this._currentImage.cameraType)) {
83874                 newCenterX = this._spatial
83875                     .wrap(newCenterX + this._basicRotation[0], 0, 1);
83876                 newCenterY = this._spatial
83877                     .clamp(newCenterY + this._basicRotation[1], 0.05, 0.95);
83878             }
83879             else {
83880                 newCenterX = this._spatial.clamp(newCenterX, 0, 1);
83881                 newCenterY = this._spatial.clamp(newCenterY, 0, 1);
83882             }
83883             this._desiredLookat = new Vector3()
83884                 .fromArray(this.currentTransform.unprojectBasic([newCenterX, newCenterY], this._lookatDepth));
83885         }
83886         setCenter(center) {
83887             this._desiredLookat = null;
83888             this._requestedRotationDelta = null;
83889             this._requestedBasicRotation = null;
83890             this._desiredZoom = this._zoom;
83891             let clamped = [
83892                 this._spatial.clamp(center[0], 0, 1),
83893                 this._spatial.clamp(center[1], 0, 1),
83894             ];
83895             if (this._currentImage == null) {
83896                 this._desiredCenter = clamped;
83897                 return;
83898             }
83899             this._desiredCenter = null;
83900             let currentLookat = new Vector3()
83901                 .fromArray(this.currentTransform.unprojectBasic(clamped, this._lookatDepth));
83902             let previousTransform = this.previousTransform != null ?
83903                 this.previousTransform :
83904                 this.currentTransform;
83905             let previousLookat = new Vector3()
83906                 .fromArray(previousTransform.unprojectBasic(clamped, this._lookatDepth));
83907             this._currentCamera.lookat.copy(currentLookat);
83908             this._previousCamera.lookat.copy(previousLookat);
83909         }
83910         setZoom(zoom) {
83911             this._desiredLookat = null;
83912             this._requestedRotationDelta = null;
83913             this._requestedBasicRotation = null;
83914             this._zoom = this._spatial.clamp(zoom, this._minZoom, this._maxZoom);
83915             this._desiredZoom = this._zoom;
83916         }
83917         _applyRotation(delta, camera) {
83918             if (camera == null) {
83919                 return;
83920             }
83921             let q = new Quaternion().setFromUnitVectors(camera.up, new Vector3(0, 0, 1));
83922             let qInverse = q.clone().invert();
83923             let offset = new Vector3();
83924             offset.copy(camera.lookat).sub(camera.position);
83925             offset.applyQuaternion(q);
83926             let length = offset.length();
83927             let phi = Math.atan2(offset.y, offset.x);
83928             phi += delta.phi;
83929             let theta = Math.atan2(Math.sqrt(offset.x * offset.x + offset.y * offset.y), offset.z);
83930             theta += delta.theta;
83931             theta = Math.max(0.1, Math.min(Math.PI - 0.1, theta));
83932             offset.x = Math.sin(theta) * Math.cos(phi);
83933             offset.y = Math.sin(theta) * Math.sin(phi);
83934             offset.z = Math.cos(theta);
83935             offset.applyQuaternion(qInverse);
83936             camera.lookat.copy(camera.position).add(offset.multiplyScalar(length));
83937         }
83938         _applyRotationBasic(basicRotation) {
83939             let currentImage = this._currentImage;
83940             let previousImage = this._previousImage != null ?
83941                 this.previousImage :
83942                 this.currentImage;
83943             let currentCamera = this._currentCamera;
83944             let previousCamera = this._previousCamera;
83945             let currentTransform = this.currentTransform;
83946             let previousTransform = this.previousTransform != null ?
83947                 this.previousTransform :
83948                 this.currentTransform;
83949             let currentBasic = currentTransform.projectBasic(currentCamera.lookat.toArray());
83950             let previousBasic = previousTransform.projectBasic(previousCamera.lookat.toArray());
83951             if (isSpherical(currentImage.cameraType)) {
83952                 currentBasic[0] = this._spatial.wrap(currentBasic[0] + basicRotation[0], 0, 1);
83953                 currentBasic[1] = this._spatial.clamp(currentBasic[1] + basicRotation[1], 0.05, 0.95);
83954             }
83955             else {
83956                 currentBasic[0] = this._spatial.clamp(currentBasic[0] + basicRotation[0], 0, 1);
83957                 currentBasic[1] = this._spatial.clamp(currentBasic[1] + basicRotation[1], 0, 1);
83958             }
83959             if (isSpherical(previousImage.cameraType)) {
83960                 previousBasic[0] = this._spatial.wrap(previousBasic[0] + basicRotation[0], 0, 1);
83961                 previousBasic[1] = this._spatial.clamp(previousBasic[1] + basicRotation[1], 0.05, 0.95);
83962             }
83963             else {
83964                 previousBasic[0] = this._spatial.clamp(previousBasic[0] + basicRotation[0], 0, 1);
83965                 previousBasic[1] = this._spatial.clamp(currentBasic[1] + basicRotation[1], 0, 1);
83966             }
83967             let currentLookat = currentTransform.unprojectBasic(currentBasic, this._lookatDepth);
83968             currentCamera.lookat.fromArray(currentLookat);
83969             let previousLookat = previousTransform.unprojectBasic(previousBasic, this._lookatDepth);
83970             previousCamera.lookat.fromArray(previousLookat);
83971         }
83972         _updateZoom(animationSpeed) {
83973             let diff = this._desiredZoom - this._zoom;
83974             let sign = diff > 0 ? 1 : diff < 0 ? -1 : 0;
83975             if (diff === 0) {
83976                 return;
83977             }
83978             else if (Math.abs(diff) < 2e-3) {
83979                 this._zoom = this._desiredZoom;
83980                 if (this._desiredLookat != null) {
83981                     this._desiredLookat = null;
83982                 }
83983             }
83984             else {
83985                 this._zoom += sign * Math.max(Math.abs(5 * animationSpeed * diff), 2e-3);
83986             }
83987         }
83988         _updateLookat(animationSpeed) {
83989             if (this._desiredLookat === null) {
83990                 return;
83991             }
83992             let diff = this._desiredLookat.distanceToSquared(this._currentCamera.lookat);
83993             if (Math.abs(diff) < 1e-6) {
83994                 this._currentCamera.lookat.copy(this._desiredLookat);
83995                 this._desiredLookat = null;
83996             }
83997             else {
83998                 this._currentCamera.lookat.lerp(this._desiredLookat, 5 * animationSpeed);
83999             }
84000         }
84001         _updateRotation() {
84002             if (this._requestedRotationDelta != null) {
84003                 let length = this._rotationDelta.lengthSquared();
84004                 let requestedLength = this._requestedRotationDelta.lengthSquared();
84005                 if (requestedLength > length) {
84006                     this._rotationDelta.lerp(this._requestedRotationDelta, this._rotationIncreaseAlpha);
84007                 }
84008                 else {
84009                     this._rotationDelta.lerp(this._requestedRotationDelta, this._rotationDecreaseAlpha);
84010                 }
84011                 this._requestedRotationDelta = null;
84012                 return;
84013             }
84014             if (this._rotationDelta.isZero) {
84015                 return;
84016             }
84017             const alpha = isSpherical(this.currentImage.cameraType) ?
84018                 1 : this._alpha;
84019             this._rotationDelta.multiply(this._rotationAcceleration * alpha);
84020             this._rotationDelta.threshold(this._rotationThreshold);
84021         }
84022         _updateRotationBasic() {
84023             if (this._requestedBasicRotation != null) {
84024                 let x = this._basicRotation[0];
84025                 let y = this._basicRotation[1];
84026                 let reqX = this._requestedBasicRotation[0];
84027                 let reqY = this._requestedBasicRotation[1];
84028                 if (Math.abs(reqX) > Math.abs(x)) {
84029                     this._basicRotation[0] = (1 - this._rotationIncreaseAlpha) * x + this._rotationIncreaseAlpha * reqX;
84030                 }
84031                 else {
84032                     this._basicRotation[0] = (1 - this._rotationDecreaseAlpha) * x + this._rotationDecreaseAlpha * reqX;
84033                 }
84034                 if (Math.abs(reqY) > Math.abs(y)) {
84035                     this._basicRotation[1] = (1 - this._rotationIncreaseAlpha) * y + this._rotationIncreaseAlpha * reqY;
84036                 }
84037                 else {
84038                     this._basicRotation[1] = (1 - this._rotationDecreaseAlpha) * y + this._rotationDecreaseAlpha * reqY;
84039                 }
84040                 this._requestedBasicRotation = null;
84041                 return;
84042             }
84043             if (this._requestedBasicRotationUnbounded != null) {
84044                 let reqX = this._requestedBasicRotationUnbounded[0];
84045                 let reqY = this._requestedBasicRotationUnbounded[1];
84046                 if (Math.abs(reqX) > 0) {
84047                     this._basicRotation[0] = (1 - this._unboundedRotationAlpha) * this._basicRotation[0] + this._unboundedRotationAlpha * reqX;
84048                 }
84049                 if (Math.abs(reqY) > 0) {
84050                     this._basicRotation[1] = (1 - this._unboundedRotationAlpha) * this._basicRotation[1] + this._unboundedRotationAlpha * reqY;
84051                 }
84052                 if (this._desiredLookat != null) {
84053                     let desiredBasicLookat = this.currentTransform.projectBasic(this._desiredLookat.toArray());
84054                     desiredBasicLookat[0] += reqX;
84055                     desiredBasicLookat[1] += reqY;
84056                     this._desiredLookat = new Vector3()
84057                         .fromArray(this.currentTransform.unprojectBasic(desiredBasicLookat, this._lookatDepth));
84058                 }
84059                 this._requestedBasicRotationUnbounded = null;
84060             }
84061             if (this._basicRotation[0] === 0 && this._basicRotation[1] === 0) {
84062                 return;
84063             }
84064             this._basicRotation[0] = this._rotationAcceleration * this._basicRotation[0];
84065             this._basicRotation[1] = this._rotationAcceleration * this._basicRotation[1];
84066             if (Math.abs(this._basicRotation[0]) < this._rotationThreshold / Math.pow(2, this._zoom) &&
84067                 Math.abs(this._basicRotation[1]) < this._rotationThreshold / Math.pow(2, this._zoom)) {
84068                 this._basicRotation = [0, 0];
84069             }
84070         }
84071         _clearRotation() {
84072             if (isSpherical(this._currentImage.cameraType)) {
84073                 return;
84074             }
84075             if (this._requestedRotationDelta != null) {
84076                 this._requestedRotationDelta = null;
84077             }
84078             if (!this._rotationDelta.isZero) {
84079                 this._rotationDelta.reset();
84080             }
84081             if (this._requestedBasicRotation != null) {
84082                 this._requestedBasicRotation = null;
84083             }
84084             if (this._basicRotation[0] > 0 || this._basicRotation[1] > 0) {
84085                 this._basicRotation = [0, 0];
84086             }
84087         }
84088         _setDesiredCenter() {
84089             if (this._desiredCenter == null) {
84090                 return;
84091             }
84092             let lookatDirection = new Vector3()
84093                 .fromArray(this.currentTransform.unprojectBasic(this._desiredCenter, this._lookatDepth))
84094                 .sub(this._currentCamera.position);
84095             this._currentCamera.lookat.copy(this._currentCamera.position.clone().add(lookatDirection));
84096             this._previousCamera.lookat.copy(this._previousCamera.position.clone().add(lookatDirection));
84097             this._desiredCenter = null;
84098         }
84099         _setDesiredZoom() {
84100             this._desiredZoom =
84101                 isSpherical(this._currentImage.cameraType) ||
84102                     this._previousImage == null ?
84103                     this._zoom : 0;
84104         }
84105     }
84106
84107     class InteractiveWaitingState extends InteractiveStateBase {
84108         constructor(state) {
84109             super(state);
84110             this._adjustCameras();
84111             this._motionless = this._motionlessTransition();
84112         }
84113         prepend(images) {
84114             super.prepend(images);
84115             this._motionless = this._motionlessTransition();
84116         }
84117         set(images) {
84118             super.set(images);
84119             this._motionless = this._motionlessTransition();
84120         }
84121         move(delta) {
84122             this._alpha = Math.max(0, Math.min(1, this._alpha + delta));
84123         }
84124         moveTo(position) {
84125             this._alpha = Math.max(0, Math.min(1, position));
84126         }
84127         update(delta) {
84128             this._updateRotation();
84129             if (!this._rotationDelta.isZero) {
84130                 this._applyRotation(this._rotationDelta, this._previousCamera);
84131                 this._applyRotation(this._rotationDelta, this._currentCamera);
84132             }
84133             this._updateRotationBasic();
84134             if (this._basicRotation[0] !== 0 || this._basicRotation[1] !== 0) {
84135                 this._applyRotationBasic(this._basicRotation);
84136             }
84137             let animationSpeed = this._animationSpeed * delta / 1e-1 * 6;
84138             this._updateZoom(animationSpeed);
84139             this._updateLookat(animationSpeed);
84140             this._camera.lerpCameras(this._previousCamera, this._currentCamera, this.alpha);
84141         }
84142         _getAlpha() {
84143             return this._motionless ? Math.round(this._alpha) : this._alpha;
84144         }
84145         _setCurrentCamera() {
84146             super._setCurrentCamera();
84147             this._adjustCameras();
84148         }
84149         _adjustCameras() {
84150             if (this._previousImage == null) {
84151                 return;
84152             }
84153             if (isSpherical(this._currentImage.cameraType)) {
84154                 let lookat = this._camera.lookat.clone().sub(this._camera.position);
84155                 this._currentCamera.lookat.copy(lookat.clone().add(this._currentCamera.position));
84156             }
84157             if (isSpherical(this._previousImage.cameraType)) {
84158                 let lookat = this._currentCamera.lookat.clone().sub(this._currentCamera.position);
84159                 this._previousCamera.lookat.copy(lookat.clone().add(this._previousCamera.position));
84160             }
84161         }
84162     }
84163
84164     class TraversingState extends InteractiveStateBase {
84165         constructor(state) {
84166             super(state);
84167             this._adjustCameras();
84168             this._motionless = this._motionlessTransition();
84169             this._baseAlpha = this._alpha;
84170             this._speedCoefficient = 1;
84171             this._smoothing = false;
84172         }
84173         append(images) {
84174             let emptyTrajectory = this._trajectory.length === 0;
84175             if (emptyTrajectory) {
84176                 this._resetTransition();
84177             }
84178             super.append(images);
84179             if (emptyTrajectory) {
84180                 this._setDesiredCenter();
84181                 this._setDesiredZoom();
84182             }
84183         }
84184         prepend(images) {
84185             let emptyTrajectory = this._trajectory.length === 0;
84186             if (emptyTrajectory) {
84187                 this._resetTransition();
84188             }
84189             super.prepend(images);
84190             if (emptyTrajectory) {
84191                 this._setDesiredCenter();
84192                 this._setDesiredZoom();
84193             }
84194         }
84195         set(images) {
84196             super.set(images);
84197             this._desiredLookat = null;
84198             this._resetTransition();
84199             this._clearRotation();
84200             this._setDesiredCenter();
84201             this._setDesiredZoom();
84202             if (this._trajectory.length < 3) {
84203                 this._smoothing = true;
84204             }
84205         }
84206         setSpeed(speed) {
84207             this._speedCoefficient = this._spatial.clamp(speed, 0, 10);
84208         }
84209         update(delta) {
84210             if (this._alpha === 1 && this._currentIndex + this._alpha < this._trajectory.length) {
84211                 this._currentIndex += 1;
84212                 this._smoothing = this._trajectory.length < 3 &&
84213                     this._currentIndex + 1 === this._trajectory.length;
84214                 this._setCurrent();
84215                 this._resetTransition();
84216                 this._clearRotation();
84217                 this._desiredZoom =
84218                     isSpherical(this._currentImage.cameraType) ?
84219                         this._zoom : 0;
84220                 this._desiredLookat = null;
84221             }
84222             let animationSpeed = this._animationSpeed * delta / 1e-1 * 6;
84223             this._baseAlpha = Math.min(1, this._baseAlpha + this._speedCoefficient * animationSpeed);
84224             if (this._smoothing) {
84225                 this._alpha = MathUtils.smootherstep(this._baseAlpha, 0, 1);
84226             }
84227             else {
84228                 this._alpha = this._baseAlpha;
84229             }
84230             this._updateRotation();
84231             if (!this._rotationDelta.isZero) {
84232                 this._applyRotation(this._rotationDelta, this._previousCamera);
84233                 this._applyRotation(this._rotationDelta, this._currentCamera);
84234             }
84235             this._updateRotationBasic();
84236             if (this._basicRotation[0] !== 0 || this._basicRotation[1] !== 0) {
84237                 this._applyRotationBasic(this._basicRotation);
84238             }
84239             this._updateZoom(animationSpeed);
84240             this._updateLookat(animationSpeed);
84241             this._camera.lerpCameras(this._previousCamera, this._currentCamera, this.alpha);
84242         }
84243         _getAlpha() {
84244             return this._motionless ? Math.ceil(this._alpha) : this._alpha;
84245         }
84246         _setCurrentCamera() {
84247             super._setCurrentCamera();
84248             this._adjustCameras();
84249         }
84250         _adjustCameras() {
84251             if (this._previousImage == null) {
84252                 return;
84253             }
84254             let lookat = this._camera.lookat.clone().sub(this._camera.position);
84255             this._previousCamera.lookat.copy(lookat.clone().add(this._previousCamera.position));
84256             if (isSpherical(this._currentImage.cameraType)) {
84257                 this._currentCamera.lookat.copy(lookat.clone().add(this._currentCamera.position));
84258             }
84259         }
84260         _resetTransition() {
84261             this._alpha = 0;
84262             this._baseAlpha = 0;
84263             this._motionless = this._motionlessTransition();
84264         }
84265     }
84266
84267     class WaitingState extends StateBase {
84268         constructor(state) {
84269             super(state);
84270             this._zoom = 0;
84271             this._adjustCameras();
84272             this._motionless = this._motionlessTransition();
84273         }
84274         prepend(images) {
84275             super.prepend(images);
84276             this._motionless = this._motionlessTransition();
84277         }
84278         set(images) {
84279             super.set(images);
84280             this._motionless = this._motionlessTransition();
84281         }
84282         move(delta) {
84283             this._alpha = Math.max(0, Math.min(1, this._alpha + delta));
84284         }
84285         moveTo(position) {
84286             this._alpha = Math.max(0, Math.min(1, position));
84287         }
84288         update() {
84289             this._camera.lerpCameras(this._previousCamera, this._currentCamera, this.alpha);
84290         }
84291         _getAlpha() {
84292             return this._motionless ? Math.round(this._alpha) : this._alpha;
84293         }
84294         _setCurrentCamera() {
84295             super._setCurrentCamera();
84296             this._adjustCameras();
84297         }
84298         _adjustCameras() {
84299             if (this._previousImage == null) {
84300                 return;
84301             }
84302             if (isSpherical(this._currentImage.cameraType)) {
84303                 let lookat = this._camera.lookat.clone().sub(this._camera.position);
84304                 this._currentCamera.lookat.copy(lookat.clone().add(this._currentCamera.position));
84305             }
84306             if (isSpherical(this._previousImage.cameraType)) {
84307                 let lookat = this._currentCamera.lookat.clone().sub(this._currentCamera.position);
84308                 this._previousCamera.lookat.copy(lookat.clone().add(this._previousCamera.position));
84309             }
84310         }
84311     }
84312
84313     class StateTransitionMatrix {
84314         constructor() {
84315             const custom = State[State.Custom];
84316             const earth = State[State.Earth];
84317             const traverse = State[State.Traversing];
84318             const wait = State[State.Waiting];
84319             const waitInteractively = State[State.WaitingInteractively];
84320             this._creators = new Map();
84321             const creator = this._creators;
84322             creator.set(custom, CustomState);
84323             creator.set(earth, EarthState);
84324             creator.set(traverse, TraversingState);
84325             creator.set(wait, WaitingState);
84326             creator.set(waitInteractively, InteractiveWaitingState);
84327             this._transitions = new Map();
84328             const transitions = this._transitions;
84329             transitions.set(custom, [earth, traverse]);
84330             transitions.set(earth, [custom, traverse]);
84331             transitions.set(traverse, [custom, earth, wait, waitInteractively]);
84332             transitions.set(wait, [traverse, waitInteractively]);
84333             transitions.set(waitInteractively, [traverse, wait]);
84334         }
84335         getState(state) {
84336             if (state instanceof CustomState) {
84337                 return State.Custom;
84338             }
84339             else if (state instanceof EarthState) {
84340                 return State.Earth;
84341             }
84342             else if (state instanceof TraversingState) {
84343                 return State.Traversing;
84344             }
84345             else if (state instanceof WaitingState) {
84346                 return State.Waiting;
84347             }
84348             else if (state instanceof InteractiveWaitingState) {
84349                 return State.WaitingInteractively;
84350             }
84351             throw new Error("Invalid state instance");
84352         }
84353         generate(state, options) {
84354             const concreteState = this._creators.get(State[state]);
84355             return new concreteState(options);
84356         }
84357         transition(state, to) {
84358             if (!this.validate(state, to)) {
84359                 throw new Error("Invalid transition");
84360             }
84361             return this.generate(to, state);
84362         }
84363         validate(state, to) {
84364             const source = State[this.getState(state)];
84365             const target = State[to];
84366             const transitions = this._transitions;
84367             return transitions.has(source) &&
84368                 transitions.get(source).includes(target);
84369         }
84370     }
84371
84372     class StateContext {
84373         constructor(state, transitionMode) {
84374             this._transitions = new StateTransitionMatrix();
84375             this._state = this._transitions.generate(state, {
84376                 alpha: 1,
84377                 camera: new Camera(),
84378                 currentIndex: -1,
84379                 reference: { alt: 0, lat: 0, lng: 0 },
84380                 trajectory: [],
84381                 transitionMode: transitionMode == null ? exports.TransitionMode.Default : transitionMode,
84382                 zoom: 0,
84383             });
84384         }
84385         get state() {
84386             return this._transitions.getState(this._state);
84387         }
84388         get reference() {
84389             return this._state.reference;
84390         }
84391         get alpha() {
84392             return this._state.alpha;
84393         }
84394         get stateTransitionAlpha() {
84395             return this._state.stateTransitionAlpha;
84396         }
84397         get camera() {
84398             return this._state.camera;
84399         }
84400         get zoom() {
84401             return this._state.zoom;
84402         }
84403         get currentImage() {
84404             return this._state.currentImage;
84405         }
84406         get previousImage() {
84407             return this._state.previousImage;
84408         }
84409         get currentCamera() {
84410             return this._state.currentCamera;
84411         }
84412         get currentTransform() {
84413             return this._state.currentTransform;
84414         }
84415         get previousTransform() {
84416             return this._state.previousTransform;
84417         }
84418         get trajectory() {
84419             return this._state.trajectory;
84420         }
84421         get currentIndex() {
84422             return this._state.currentIndex;
84423         }
84424         get lastImage() {
84425             return this._state.trajectory[this._state.trajectory.length - 1];
84426         }
84427         get imagesAhead() {
84428             return this._state.trajectory.length - 1 - this._state.currentIndex;
84429         }
84430         get motionless() {
84431             return this._state.motionless;
84432         }
84433         custom() {
84434             this._transition(State.Custom);
84435         }
84436         earth() {
84437             this._transition(State.Earth);
84438         }
84439         traverse() {
84440             this._transition(State.Traversing);
84441         }
84442         wait() {
84443             this._transition(State.Waiting);
84444         }
84445         waitInteractively() {
84446             this._transition(State.WaitingInteractively);
84447         }
84448         getCenter() {
84449             return this._state.getCenter();
84450         }
84451         setCenter(center) {
84452             this._state.setCenter(center);
84453         }
84454         setZoom(zoom) {
84455             this._state.setZoom(zoom);
84456         }
84457         update(delta) {
84458             this._state.update(delta);
84459         }
84460         append(images) {
84461             this._state.append(images);
84462         }
84463         prepend(images) {
84464             this._state.prepend(images);
84465         }
84466         remove(n) {
84467             this._state.remove(n);
84468         }
84469         clear() {
84470             this._state.clear();
84471         }
84472         clearPrior() {
84473             this._state.clearPrior();
84474         }
84475         cut() {
84476             this._state.cut();
84477         }
84478         set(images) {
84479             this._state.set(images);
84480         }
84481         setViewMatrix(matrix) {
84482             this._state.setViewMatrix(matrix);
84483         }
84484         rotate(delta) {
84485             this._state.rotate(delta);
84486         }
84487         rotateUnbounded(delta) {
84488             this._state.rotateUnbounded(delta);
84489         }
84490         rotateWithoutInertia(delta) {
84491             this._state.rotateWithoutInertia(delta);
84492         }
84493         rotateBasic(basicRotation) {
84494             this._state.rotateBasic(basicRotation);
84495         }
84496         rotateBasicUnbounded(basicRotation) {
84497             this._state.rotateBasicUnbounded(basicRotation);
84498         }
84499         rotateBasicWithoutInertia(basicRotation) {
84500             this._state.rotateBasicWithoutInertia(basicRotation);
84501         }
84502         rotateToBasic(basic) {
84503             this._state.rotateToBasic(basic);
84504         }
84505         move(delta) {
84506             this._state.move(delta);
84507         }
84508         moveTo(delta) {
84509             this._state.moveTo(delta);
84510         }
84511         zoomIn(delta, reference) {
84512             this._state.zoomIn(delta, reference);
84513         }
84514         setSpeed(speed) {
84515             this._state.setSpeed(speed);
84516         }
84517         setTransitionMode(mode) {
84518             this._state.setTransitionMode(mode);
84519         }
84520         dolly(delta) {
84521             this._state.dolly(delta);
84522         }
84523         orbit(rotation) {
84524             this._state.orbit(rotation);
84525         }
84526         truck(direction) {
84527             this._state.truck(direction);
84528         }
84529         _transition(to) {
84530             if (!this._transitions.validate(this._state, to)) {
84531                 const from = this._transitions.getState(this._state);
84532                 console.warn(`Transition not valid (${State[from]} - ${State[to]})`);
84533                 return;
84534             }
84535             const state = this._transitions.transition(this._state, to);
84536             this._state = state;
84537         }
84538     }
84539
84540     class StateService {
84541         constructor(initialState, transitionMode) {
84542             this._appendImage$ = new Subject();
84543             this._clock = new Clock();
84544             this._subscriptions = new SubscriptionHolder();
84545             const subs = this._subscriptions;
84546             this._start$ = new Subject();
84547             this._frame$ = new Subject();
84548             this._contextOperation$ = new BehaviorSubject((context) => {
84549                 return context;
84550             });
84551             this._context$ = this._contextOperation$.pipe(scan((context, operation) => {
84552                 return operation(context);
84553             }, new StateContext(initialState, transitionMode)), publishReplay(1), refCount());
84554             this._state$ = this._context$.pipe(map((context) => {
84555                 return context.state;
84556             }), distinctUntilChanged(), publishReplay(1), refCount());
84557             this._currentState$ = this._frame$.pipe(withLatestFrom(this._context$, (frameId, context) => {
84558                 return [frameId, context];
84559             }), filter((fc) => {
84560                 return fc[1].currentImage != null;
84561             }), tap((fc) => {
84562                 fc[1].update(this._clock.getDelta());
84563             }), map((fc) => {
84564                 return { fps: 60, id: fc[0], state: fc[1] };
84565             }), share());
84566             this._lastState$ = this._currentState$.pipe(publishReplay(1), refCount());
84567             let imageChanged$ = this._currentState$.pipe(distinctUntilChanged(undefined, (f) => {
84568                 return f.state.currentImage.id;
84569             }), publishReplay(1), refCount());
84570             let imageChangedSubject$ = new Subject();
84571             subs.push(imageChanged$
84572                 .subscribe(imageChangedSubject$));
84573             this._currentId$ = new BehaviorSubject(null);
84574             subs.push(imageChangedSubject$.pipe(map((f) => {
84575                 return f.state.currentImage.id;
84576             }))
84577                 .subscribe(this._currentId$));
84578             this._currentImage$ = imageChangedSubject$.pipe(map((f) => {
84579                 return f.state.currentImage;
84580             }), publishReplay(1), refCount());
84581             this._currentCamera$ = imageChangedSubject$.pipe(map((f) => {
84582                 return f.state.currentCamera;
84583             }), publishReplay(1), refCount());
84584             this._currentTransform$ = imageChangedSubject$.pipe(map((f) => {
84585                 return f.state.currentTransform;
84586             }), publishReplay(1), refCount());
84587             this._reference$ = imageChangedSubject$.pipe(map((f) => {
84588                 return f.state.reference;
84589             }), distinctUntilChanged((r1, r2) => {
84590                 return r1.lat === r2.lat && r1.lng === r2.lng;
84591             }, (reference) => {
84592                 return { lat: reference.lat, lng: reference.lng };
84593             }), publishReplay(1), refCount());
84594             this._currentImageExternal$ = imageChanged$.pipe(map((f) => {
84595                 return f.state.currentImage;
84596             }), publishReplay(1), refCount());
84597             subs.push(this._appendImage$.pipe(map((image) => {
84598                 return (context) => {
84599                     context.append([image]);
84600                     return context;
84601                 };
84602             }))
84603                 .subscribe(this._contextOperation$));
84604             this._inMotionOperation$ = new Subject();
84605             subs.push(imageChanged$.pipe(map(() => {
84606                 return true;
84607             }))
84608                 .subscribe(this._inMotionOperation$));
84609             subs.push(this._inMotionOperation$.pipe(distinctUntilChanged(), filter((moving) => {
84610                 return moving;
84611             }), switchMap(() => {
84612                 return this._currentState$.pipe(filter((frame) => {
84613                     return frame.state.imagesAhead === 0;
84614                 }), map((frame) => {
84615                     return [frame.state.camera.clone(), frame.state.zoom];
84616                 }), pairwise(), map((pair) => {
84617                     let c1 = pair[0][0];
84618                     let c2 = pair[1][0];
84619                     let z1 = pair[0][1];
84620                     let z2 = pair[1][1];
84621                     return c1.diff(c2) > 1e-5 || Math.abs(z1 - z2) > 1e-5;
84622                 }), first((changed) => {
84623                     return !changed;
84624                 }));
84625             }))
84626                 .subscribe(this._inMotionOperation$));
84627             this._inMotion$ = this._inMotionOperation$.pipe(distinctUntilChanged(), publishReplay(1), refCount());
84628             this._inTranslationOperation$ = new Subject();
84629             subs.push(imageChanged$.pipe(map(() => {
84630                 return true;
84631             }))
84632                 .subscribe(this._inTranslationOperation$));
84633             subs.push(this._inTranslationOperation$.pipe(distinctUntilChanged(), filter((inTranslation) => {
84634                 return inTranslation;
84635             }), switchMap(() => {
84636                 return this._currentState$.pipe(filter((frame) => {
84637                     return frame.state.imagesAhead === 0;
84638                 }), map((frame) => {
84639                     return frame.state.camera.position.clone();
84640                 }), pairwise(), map((pair) => {
84641                     return pair[0].distanceToSquared(pair[1]) !== 0;
84642                 }), first((changed) => {
84643                     return !changed;
84644                 }));
84645             }))
84646                 .subscribe(this._inTranslationOperation$));
84647             this._inTranslation$ = this._inTranslationOperation$.pipe(distinctUntilChanged(), publishReplay(1), refCount());
84648             subs.push(this._state$.subscribe(() => { }));
84649             subs.push(this._currentImage$.subscribe(() => { }));
84650             subs.push(this._currentCamera$.subscribe(() => { }));
84651             subs.push(this._currentTransform$.subscribe(() => { }));
84652             subs.push(this._reference$.subscribe(() => { }));
84653             subs.push(this._currentImageExternal$.subscribe(() => { }));
84654             subs.push(this._lastState$.subscribe(() => { }));
84655             subs.push(this._inMotion$.subscribe(() => { }));
84656             subs.push(this._inTranslation$.subscribe(() => { }));
84657             this._frameId = null;
84658             this._frameGenerator = new FrameGenerator(window);
84659         }
84660         get currentState$() {
84661             return this._currentState$;
84662         }
84663         get currentImage$() {
84664             return this._currentImage$;
84665         }
84666         get currentId$() {
84667             return this._currentId$;
84668         }
84669         get currentImageExternal$() {
84670             return this._currentImageExternal$;
84671         }
84672         get currentCamera$() {
84673             return this._currentCamera$;
84674         }
84675         get currentTransform$() {
84676             return this._currentTransform$;
84677         }
84678         get state$() {
84679             return this._state$;
84680         }
84681         get reference$() {
84682             return this._reference$;
84683         }
84684         get inMotion$() {
84685             return this._inMotion$;
84686         }
84687         get inTranslation$() {
84688             return this._inTranslation$;
84689         }
84690         get appendImage$() {
84691             return this._appendImage$;
84692         }
84693         dispose() {
84694             this.stop();
84695             this._subscriptions.unsubscribe();
84696         }
84697         custom() {
84698             this._inMotionOperation$.next(true);
84699             this._invokeContextOperation((context) => {
84700                 context.custom();
84701             });
84702         }
84703         earth() {
84704             this._inMotionOperation$.next(true);
84705             this._invokeContextOperation((context) => { context.earth(); });
84706         }
84707         traverse() {
84708             this._inMotionOperation$.next(true);
84709             this._invokeContextOperation((context) => { context.traverse(); });
84710         }
84711         wait() {
84712             this._invokeContextOperation((context) => { context.wait(); });
84713         }
84714         waitInteractively() {
84715             this._invokeContextOperation((context) => { context.waitInteractively(); });
84716         }
84717         appendImagess(images) {
84718             this._invokeContextOperation((context) => { context.append(images); });
84719         }
84720         prependImages(images) {
84721             this._invokeContextOperation((context) => { context.prepend(images); });
84722         }
84723         removeImages(n) {
84724             this._invokeContextOperation((context) => { context.remove(n); });
84725         }
84726         clearImages() {
84727             this._invokeContextOperation((context) => { context.clear(); });
84728         }
84729         clearPriorImages() {
84730             this._invokeContextOperation((context) => { context.clearPrior(); });
84731         }
84732         cutImages() {
84733             this._invokeContextOperation((context) => { context.cut(); });
84734         }
84735         setImages(images) {
84736             this._invokeContextOperation((context) => { context.set(images); });
84737         }
84738         setViewMatrix(matrix) {
84739             this._inMotionOperation$.next(true);
84740             this._invokeContextOperation((context) => { context.setViewMatrix(matrix); });
84741         }
84742         rotate(delta) {
84743             this._inMotionOperation$.next(true);
84744             this._invokeContextOperation((context) => { context.rotate(delta); });
84745         }
84746         rotateUnbounded(delta) {
84747             this._inMotionOperation$.next(true);
84748             this._invokeContextOperation((context) => { context.rotateUnbounded(delta); });
84749         }
84750         rotateWithoutInertia(delta) {
84751             this._inMotionOperation$.next(true);
84752             this._invokeContextOperation((context) => { context.rotateWithoutInertia(delta); });
84753         }
84754         rotateBasic(basicRotation) {
84755             this._inMotionOperation$.next(true);
84756             this._invokeContextOperation((context) => { context.rotateBasic(basicRotation); });
84757         }
84758         rotateBasicUnbounded(basicRotation) {
84759             this._inMotionOperation$.next(true);
84760             this._invokeContextOperation((context) => { context.rotateBasicUnbounded(basicRotation); });
84761         }
84762         rotateBasicWithoutInertia(basicRotation) {
84763             this._inMotionOperation$.next(true);
84764             this._invokeContextOperation((context) => { context.rotateBasicWithoutInertia(basicRotation); });
84765         }
84766         rotateToBasic(basic) {
84767             this._inMotionOperation$.next(true);
84768             this._invokeContextOperation((context) => { context.rotateToBasic(basic); });
84769         }
84770         move(delta) {
84771             this._inMotionOperation$.next(true);
84772             this._invokeContextOperation((context) => { context.move(delta); });
84773         }
84774         moveTo(position) {
84775             this._inMotionOperation$.next(true);
84776             this._invokeContextOperation((context) => { context.moveTo(position); });
84777         }
84778         dolly(delta) {
84779             this._inMotionOperation$.next(true);
84780             this._invokeContextOperation((context) => { context.dolly(delta); });
84781         }
84782         orbit(rotation) {
84783             this._inMotionOperation$.next(true);
84784             this._invokeContextOperation((context) => { context.orbit(rotation); });
84785         }
84786         truck(direction) {
84787             this._inMotionOperation$.next(true);
84788             this._invokeContextOperation((context) => { context.truck(direction); });
84789         }
84790         /**
84791          * Change zoom level while keeping the reference point position approximately static.
84792          *
84793          * @parameter {number} delta - Change in zoom level.
84794          * @parameter {Array<number>} reference - Reference point in basic coordinates.
84795          */
84796         zoomIn(delta, reference) {
84797             this._inMotionOperation$.next(true);
84798             this._invokeContextOperation((context) => { context.zoomIn(delta, reference); });
84799         }
84800         getCenter() {
84801             return this._lastState$.pipe(first(), map((frame) => {
84802                 return frame.state.getCenter();
84803             }));
84804         }
84805         getZoom() {
84806             return this._lastState$.pipe(first(), map((frame) => {
84807                 return frame.state.zoom;
84808             }));
84809         }
84810         setCenter(center) {
84811             this._inMotionOperation$.next(true);
84812             this._invokeContextOperation((context) => { context.setCenter(center); });
84813         }
84814         setSpeed(speed) {
84815             this._invokeContextOperation((context) => { context.setSpeed(speed); });
84816         }
84817         setTransitionMode(mode) {
84818             this._invokeContextOperation((context) => { context.setTransitionMode(mode); });
84819         }
84820         setZoom(zoom) {
84821             this._inMotionOperation$.next(true);
84822             this._invokeContextOperation((context) => { context.setZoom(zoom); });
84823         }
84824         start() {
84825             this._clock.start();
84826             if (this._frameId == null) {
84827                 this._start$.next(null);
84828                 this._frameId = this._frameGenerator.requestAnimationFrame(this._frame.bind(this));
84829                 this._frame$.next(this._frameId);
84830             }
84831         }
84832         stop() {
84833             this._clock.stop();
84834             if (this._frameId != null) {
84835                 this._frameGenerator.cancelAnimationFrame(this._frameId);
84836                 this._frameId = null;
84837             }
84838         }
84839         _invokeContextOperation(action) {
84840             this._contextOperation$
84841                 .next((context) => {
84842                 action(context);
84843                 return context;
84844             });
84845         }
84846         _frame() {
84847             this._frameId = this._frameGenerator.requestAnimationFrame(this._frame.bind(this));
84848             this._frame$.next(this._frameId);
84849         }
84850     }
84851
84852     function cameraControlsToState(cameraControls) {
84853         switch (cameraControls) {
84854             case exports.CameraControls.Custom:
84855                 return State.Custom;
84856             case exports.CameraControls.Earth:
84857                 return State.Earth;
84858             case exports.CameraControls.Street:
84859                 return State.Traversing;
84860             default:
84861                 return null;
84862         }
84863     }
84864
84865     class Navigator {
84866         constructor(options, api, graphService, loadingService, stateService, cacheService, playService, panService) {
84867             var _a;
84868             if (api) {
84869                 this._api = api;
84870             }
84871             else if (options.dataProvider) {
84872                 this._api = new APIWrapper(options.dataProvider);
84873             }
84874             else {
84875                 this._api = new APIWrapper(new GraphDataProvider({
84876                     accessToken: options.accessToken,
84877                 }));
84878             }
84879             this._graphService = graphService !== null && graphService !== void 0 ? graphService : new GraphService(new Graph(this.api));
84880             this._loadingName = "navigator";
84881             this._loadingService = loadingService !== null && loadingService !== void 0 ? loadingService : new LoadingService();
84882             const cameraControls = (_a = options.cameraControls) !== null && _a !== void 0 ? _a : exports.CameraControls.Street;
84883             this._stateService = stateService !== null && stateService !== void 0 ? stateService : new StateService(cameraControlsToState(cameraControls), options.transitionMode);
84884             this._cacheService = cacheService !== null && cacheService !== void 0 ? cacheService : new CacheService(this._graphService, this._stateService, this._api);
84885             this._playService = playService !== null && playService !== void 0 ? playService : new PlayService(this._graphService, this._stateService);
84886             this._panService = panService !== null && panService !== void 0 ? panService : new PanService(this._graphService, this._stateService, options.combinedPanning);
84887             this._idRequested$ = new BehaviorSubject(null);
84888             this._movedToId$ = new BehaviorSubject(null);
84889             this._request$ = null;
84890             this._requestSubscription = null;
84891             this._imageRequestSubscription = null;
84892         }
84893         get api() {
84894             return this._api;
84895         }
84896         get cacheService() {
84897             return this._cacheService;
84898         }
84899         get graphService() {
84900             return this._graphService;
84901         }
84902         get loadingService() {
84903             return this._loadingService;
84904         }
84905         get movedToId$() {
84906             return this._movedToId$;
84907         }
84908         get panService() {
84909             return this._panService;
84910         }
84911         get playService() {
84912             return this._playService;
84913         }
84914         get stateService() {
84915             return this._stateService;
84916         }
84917         dispose() {
84918             this._abortRequest("viewer removed");
84919             this._cacheService.stop();
84920             this._graphService.dispose();
84921             this._panService.dispose();
84922             this._playService.dispose();
84923             this._stateService.dispose();
84924         }
84925         moveTo$(id) {
84926             this._abortRequest(`to id ${id}`);
84927             this._loadingService.startLoading(this._loadingName);
84928             const image$ = this._moveTo$(id);
84929             return this._makeRequest$(image$);
84930         }
84931         moveDir$(direction) {
84932             this._abortRequest(`in dir ${exports.NavigationDirection[direction]}`);
84933             this._loadingService.startLoading(this._loadingName);
84934             const image$ = this.stateService.currentImage$.pipe(first(), mergeMap((image) => {
84935                 return ([exports.NavigationDirection.Next, exports.NavigationDirection.Prev].indexOf(direction) > -1 ?
84936                     image.sequenceEdges$ :
84937                     image.spatialEdges$).pipe(first(), map((status) => {
84938                     for (let edge of status.edges) {
84939                         if (edge.data.direction === direction) {
84940                             return edge.target;
84941                         }
84942                     }
84943                     return null;
84944                 }));
84945             }), mergeMap((directionId) => {
84946                 if (directionId == null) {
84947                     this._loadingService.stopLoading(this._loadingName);
84948                     return throwError(new Error(`Direction (${direction}) does not exist for current image.`));
84949                 }
84950                 return this._moveTo$(directionId);
84951             }));
84952             return this._makeRequest$(image$);
84953         }
84954         setFilter$(filter) {
84955             this._stateService.clearImages();
84956             return this._movedToId$.pipe(first(), mergeMap((id) => {
84957                 if (id != null) {
84958                     return this._trajectoryIds$().pipe(mergeMap((ids) => {
84959                         return this._graphService.setFilter$(filter).pipe(mergeMap(() => {
84960                             return this._cacheIds$(ids);
84961                         }));
84962                     }), last());
84963                 }
84964                 return this._idRequested$.pipe(first(), mergeMap((requestedId) => {
84965                     if (requestedId != null) {
84966                         return this._graphService.setFilter$(filter).pipe(mergeMap(() => {
84967                             return this._graphService.cacheImage$(requestedId);
84968                         }));
84969                     }
84970                     return this._graphService.setFilter$(filter).pipe(map(() => {
84971                         return undefined;
84972                     }));
84973                 }));
84974             }), map(() => {
84975                 return undefined;
84976             }));
84977         }
84978         setAccessToken$(accessToken) {
84979             this._abortRequest("to set user token");
84980             this._stateService.clearImages();
84981             return this._movedToId$.pipe(first(), tap(() => {
84982                 this._api.setAccessToken(accessToken);
84983             }), mergeMap((id) => {
84984                 return id == null ?
84985                     this._graphService.reset$([]) :
84986                     this._trajectoryIds$().pipe(mergeMap((ids) => {
84987                         return this._graphService.reset$(ids).pipe(mergeMap(() => {
84988                             return this._cacheIds$(ids);
84989                         }));
84990                     }), last(), map(() => {
84991                         return undefined;
84992                     }));
84993             }));
84994         }
84995         _cacheIds$(ids) {
84996             const cacheImages$ = ids
84997                 .map((id) => {
84998                 return this._graphService.cacheImage$(id);
84999             });
85000             return from(cacheImages$).pipe(mergeAll());
85001         }
85002         _abortRequest(reason) {
85003             if (this._requestSubscription != null) {
85004                 this._requestSubscription.unsubscribe();
85005                 this._requestSubscription = null;
85006             }
85007             if (this._imageRequestSubscription != null) {
85008                 this._imageRequestSubscription.unsubscribe();
85009                 this._imageRequestSubscription = null;
85010             }
85011             if (this._request$ != null) {
85012                 if (!(this._request$.isStopped || this._request$.hasError)) {
85013                     this._request$.error(new CancelMapillaryError(`Request aborted by a subsequent request ${reason}.`));
85014                 }
85015                 this._request$ = null;
85016             }
85017         }
85018         _makeRequest$(image$) {
85019             const request$ = new ReplaySubject(1);
85020             this._requestSubscription = request$
85021                 .subscribe(undefined, () => { });
85022             this._request$ = request$;
85023             this._imageRequestSubscription = image$
85024                 .subscribe((image) => {
85025                 this._request$ = null;
85026                 request$.next(image);
85027                 request$.complete();
85028             }, (error) => {
85029                 this._request$ = null;
85030                 request$.error(error);
85031             });
85032             return request$;
85033         }
85034         _moveTo$(id) {
85035             this._idRequested$.next(id);
85036             return this._graphService.cacheImage$(id).pipe(tap((image) => {
85037                 this._stateService.setImages([image]);
85038                 this._movedToId$.next(image.id);
85039             }), finalize(() => {
85040                 this._loadingService.stopLoading(this._loadingName);
85041             }));
85042         }
85043         _trajectoryIds$() {
85044             return this._stateService.currentState$.pipe(first(), map((frame) => {
85045                 return frame.state.trajectory
85046                     .map((image) => {
85047                     return image.id;
85048                 });
85049             }));
85050         }
85051     }
85052
85053     class Projection {
85054         constructor(viewportCoords, spatial) {
85055             this._spatial = spatial !== null && spatial !== void 0 ? spatial : new Spatial();
85056             this._viewportCoords = viewportCoords !== null && viewportCoords !== void 0 ? viewportCoords : new ViewportCoords();
85057         }
85058         basicToCanvas(basicPoint, container, render, transform) {
85059             return this._viewportCoords
85060                 .basicToCanvasSafe(basicPoint[0], basicPoint[1], container, transform, render.perspective);
85061         }
85062         canvasToBasic(canvasPoint, container, render, transform) {
85063             let basicPoint = this._viewportCoords
85064                 .canvasToBasic(canvasPoint[0], canvasPoint[1], container, transform, render.perspective);
85065             if (basicPoint[0] < 0 ||
85066                 basicPoint[0] > 1 ||
85067                 basicPoint[1] < 0 ||
85068                 basicPoint[1] > 1) {
85069                 basicPoint = null;
85070             }
85071             return basicPoint;
85072         }
85073         eventToUnprojection(event, container, render, reference, transform) {
85074             const pixelPoint = this._viewportCoords
85075                 .canvasPosition(event, container);
85076             return this.canvasToUnprojection(pixelPoint, container, render, reference, transform);
85077         }
85078         canvasToUnprojection(canvasPoint, container, render, reference, transform) {
85079             const canvasX = canvasPoint[0];
85080             const canvasY = canvasPoint[1];
85081             const [viewportX, viewportY] = this._viewportCoords
85082                 .canvasToViewport(canvasX, canvasY, container);
85083             const point3d = new Vector3(viewportX, viewportY, 1)
85084                 .unproject(render.perspective);
85085             let basicPoint = transform
85086                 .projectBasic(point3d.toArray());
85087             if (basicPoint[0] < 0 ||
85088                 basicPoint[0] > 1 ||
85089                 basicPoint[1] < 0 ||
85090                 basicPoint[1] > 1) {
85091                 basicPoint = null;
85092             }
85093             const direction3d = point3d
85094                 .clone()
85095                 .sub(render.camera.position)
85096                 .normalize();
85097             const dist = -2 / direction3d.z;
85098             let lngLat = null;
85099             if (dist > 0 && dist < 100 && !!basicPoint) {
85100                 const point = direction3d
85101                     .clone()
85102                     .multiplyScalar(dist)
85103                     .add(render.camera.position);
85104                 const [lng, lat] = enuToGeodetic(point.x, point.y, point.z, reference.lng, reference.lat, reference.alt);
85105                 lngLat = { lat, lng };
85106             }
85107             const unprojection = {
85108                 basicPoint: basicPoint,
85109                 lngLat: lngLat,
85110                 pixelPoint: [canvasX, canvasY],
85111             };
85112             return unprojection;
85113         }
85114         cameraToLngLat(render, reference) {
85115             const position = render.camera.position;
85116             const [lng, lat] = enuToGeodetic(position.x, position.y, position.z, reference.lng, reference.lat, reference.alt);
85117             return { lat, lng };
85118         }
85119         lngLatToCanvas(lngLat, container, render, reference) {
85120             const point3d = geodeticToEnu(lngLat.lng, lngLat.lat, 0, reference.lng, reference.lat, reference.alt);
85121             const canvas = this._viewportCoords
85122                 .projectToCanvasSafe(point3d, container, render.perspective);
85123             return canvas;
85124         }
85125         distanceBetweenLngLats(lngLat1, lngLat2) {
85126             return this._spatial
85127                 .distanceFromLngLat(lngLat1.lng, lngLat1.lat, lngLat2.lng, lngLat2.lat);
85128         }
85129     }
85130
85131     class Observer {
85132         constructor(viewer, navigator, container) {
85133             this._subscriptions = new SubscriptionHolder();
85134             this._emitSubscriptions = new SubscriptionHolder();
85135             this._container = container;
85136             this._viewer = viewer;
85137             this._navigator = navigator;
85138             this._projection = new Projection();
85139             this._started = false;
85140             this._navigable$ = new Subject();
85141             const subs = this._subscriptions;
85142             // load, navigable, dataloading should always emit,
85143             // also when cover is activated.
85144             subs.push(this._navigable$
85145                 .subscribe((navigable) => {
85146                 const type = "navigable";
85147                 const event = {
85148                     navigable,
85149                     target: this._viewer,
85150                     type,
85151                 };
85152                 this._viewer.fire(type, event);
85153             }));
85154             subs.push(this._navigator.loadingService.loading$
85155                 .subscribe((loading) => {
85156                 const type = "dataloading";
85157                 const event = {
85158                     loading,
85159                     target: this._viewer,
85160                     type,
85161                 };
85162                 this._viewer.fire(type, event);
85163             }));
85164             subs.push(this._container.glRenderer.opaqueRender$
85165                 .pipe(first())
85166                 .subscribe(() => {
85167                 const type = "load";
85168                 const event = {
85169                     target: this._viewer,
85170                     type,
85171                 };
85172                 this._viewer.fire(type, event);
85173             }));
85174         }
85175         get started() {
85176             return this._started;
85177         }
85178         get navigable$() {
85179             return this._navigable$;
85180         }
85181         get projection() {
85182             return this._projection;
85183         }
85184         dispose() {
85185             this.stopEmit();
85186             this._subscriptions.unsubscribe();
85187         }
85188         project$(lngLat) {
85189             return combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentImage$, this._navigator.stateService.reference$).pipe(first(), map(([render, image, reference]) => {
85190                 if (this._projection
85191                     .distanceBetweenLngLats(lngLat, image.lngLat) > 1000) {
85192                     return null;
85193                 }
85194                 const canvasPoint = this._projection.lngLatToCanvas(lngLat, this._container.container, render, reference);
85195                 return !!canvasPoint ?
85196                     [Math.round(canvasPoint[0]), Math.round(canvasPoint[1])] :
85197                     null;
85198             }));
85199         }
85200         projectBasic$(basicPoint) {
85201             return combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$).pipe(first(), map(([render, transform]) => {
85202                 const canvasPoint = this._projection.basicToCanvas(basicPoint, this._container.container, render, transform);
85203                 return !!canvasPoint ?
85204                     [Math.round(canvasPoint[0]), Math.round(canvasPoint[1])] :
85205                     null;
85206             }));
85207         }
85208         startEmit() {
85209             if (this._started) {
85210                 return;
85211             }
85212             this._started = true;
85213             const subs = this._emitSubscriptions;
85214             subs.push(this._navigator.stateService.currentImageExternal$
85215                 .subscribe((image) => {
85216                 const type = "image";
85217                 const event = {
85218                     image,
85219                     target: this._viewer,
85220                     type,
85221                 };
85222                 this._viewer.fire(type, event);
85223             }));
85224             subs.push(this._navigator.stateService.currentImageExternal$.pipe(switchMap((image) => {
85225                 return image.sequenceEdges$;
85226             }))
85227                 .subscribe((status) => {
85228                 const type = "sequenceedges";
85229                 const event = {
85230                     status,
85231                     target: this._viewer,
85232                     type,
85233                 };
85234                 this._viewer.fire(type, event);
85235             }));
85236             subs.push(this._navigator.stateService.currentImageExternal$.pipe(switchMap((image) => {
85237                 return image.spatialEdges$;
85238             }))
85239                 .subscribe((status) => {
85240                 const type = "spatialedges";
85241                 const event = {
85242                     status,
85243                     target: this._viewer,
85244                     type,
85245                 };
85246                 this._viewer.fire(type, event);
85247             }));
85248             subs.push(this._navigator.stateService.reference$
85249                 .subscribe((reference) => {
85250                 const type = "reference";
85251                 const event = {
85252                     reference,
85253                     target: this._viewer,
85254                     type,
85255                 };
85256                 this._viewer.fire(type, event);
85257             }));
85258             subs.push(combineLatest(this._navigator.stateService.inMotion$, this._container.mouseService.active$, this._container.touchService.active$).pipe(map((values) => {
85259                 return values[0] || values[1] || values[2];
85260             }), distinctUntilChanged())
85261                 .subscribe((started) => {
85262                 const type = started ? "movestart" : "moveend";
85263                 const event = {
85264                     target: this._viewer,
85265                     type,
85266                 };
85267                 this._viewer.fire(type, event);
85268             }));
85269             subs.push(this._container.renderService.bearing$.pipe(auditTime(100), distinctUntilChanged((b1, b2) => {
85270                 return Math.abs(b2 - b1) < 1;
85271             }))
85272                 .subscribe((bearing) => {
85273                 const type = "bearing";
85274                 const event = {
85275                     bearing,
85276                     target: this._viewer,
85277                     type,
85278                 };
85279                 this._viewer.fire(type, event);
85280             }));
85281             const mouseMove$ = this._container.mouseService.active$.pipe(switchMap((active) => {
85282                 return active ?
85283                     empty() :
85284                     this._container.mouseService.mouseMove$;
85285             }));
85286             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$))
85287                 .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]) => {
85288                 const unprojection = this._projection.eventToUnprojection(event, this._container.container, render, reference, transform);
85289                 const basicPoint = state === State.Traversing ?
85290                     unprojection.basicPoint : null;
85291                 return {
85292                     basicPoint,
85293                     lngLat: unprojection.lngLat,
85294                     originalEvent: event,
85295                     pixelPoint: unprojection.pixelPoint,
85296                     target: this._viewer,
85297                     type: type,
85298                 };
85299             }))
85300                 .subscribe((event) => {
85301                 this._viewer.fire(event.type, event);
85302             }));
85303             subs.push(this._container.renderService.renderCamera$.pipe(distinctUntilChanged(([x1, y1], [x2, y2]) => {
85304                 return this._closeTo(x1, x2, 1e-2) &&
85305                     this._closeTo(y1, y2, 1e-2);
85306             }, (rc) => {
85307                 return rc.camera.position.toArray();
85308             }))
85309                 .subscribe(() => {
85310                 const type = "position";
85311                 const event = {
85312                     target: this._viewer,
85313                     type,
85314                 };
85315                 this._viewer.fire(type, event);
85316             }));
85317             subs.push(this._container.renderService.renderCamera$.pipe(distinctUntilChanged(([phi1, theta1], [phi2, theta2]) => {
85318                 return this._closeTo(phi1, phi2, 1e-3) &&
85319                     this._closeTo(theta1, theta2, 1e-3);
85320             }, (rc) => {
85321                 return [rc.rotation.phi, rc.rotation.theta];
85322             }))
85323                 .subscribe(() => {
85324                 const type = "pov";
85325                 const event = {
85326                     target: this._viewer,
85327                     type,
85328                 };
85329                 this._viewer.fire(type, event);
85330             }));
85331             subs.push(this._container.renderService.renderCamera$.pipe(distinctUntilChanged((fov1, fov2) => {
85332                 return this._closeTo(fov1, fov2, 1e-2);
85333             }, (rc) => {
85334                 return rc.perspective.fov;
85335             }))
85336                 .subscribe(() => {
85337                 const type = "fov";
85338                 const event = {
85339                     target: this._viewer,
85340                     type,
85341                 };
85342                 this._viewer.fire(type, event);
85343             }));
85344         }
85345         stopEmit() {
85346             if (!this.started) {
85347                 return;
85348             }
85349             this._emitSubscriptions.unsubscribe();
85350             this._started = false;
85351         }
85352         unproject$(canvasPoint) {
85353             return combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.reference$, this._navigator.stateService.currentTransform$).pipe(first(), map(([render, reference, transform]) => {
85354                 const unprojection = this._projection.canvasToUnprojection(canvasPoint, this._container.container, render, reference, transform);
85355                 return unprojection.lngLat;
85356             }));
85357         }
85358         unprojectBasic$(canvasPoint) {
85359             return combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$).pipe(first(), map(([render, transform]) => {
85360                 return this._projection.canvasToBasic(canvasPoint, this._container.container, render, transform);
85361             }));
85362         }
85363         _closeTo(v1, v2, absoluteTolerance) {
85364             return Math.abs(v1 - v2) <= absoluteTolerance;
85365         }
85366         _mapMouseEvent$(type, mouseEvent$) {
85367             return mouseEvent$.pipe(map((event) => {
85368                 return [type, event];
85369             }));
85370         }
85371     }
85372
85373     class CustomRenderer {
85374         constructor(_container, _navigator) {
85375             this._container = _container;
85376             this._navigator = _navigator;
85377             this._renderers = {};
85378         }
85379         add(renderer, viewer) {
85380             const subs = new SubscriptionHolder();
85381             this._renderers[renderer.id] = { subs, renderer };
85382             subs.push(combineLatest([
85383                 this._container.glRenderer.webGLRenderer$,
85384                 this._navigator.stateService.reference$,
85385             ])
85386                 .pipe(take(1))
85387                 .subscribe(([gl, reference]) => {
85388                 renderer.onAdd(viewer, reference, gl.getContext());
85389             }));
85390             subs.push(this._container.glRenderer.opaqueRender$
85391                 .pipe(withLatestFrom(this._container.renderService.renderCamera$, this._container.glRenderer.webGLRenderer$))
85392                 .subscribe(([, renderCamera, glRenderer]) => {
85393                 const context = glRenderer.getContext();
85394                 const viewMatrix = renderCamera.perspective.matrixWorldInverse;
85395                 const projectionMatrix = renderCamera.perspective.projectionMatrix;
85396                 renderer.render(context, viewMatrix.toArray(), projectionMatrix.toArray());
85397             }));
85398             subs.push(this._navigator.stateService.reference$
85399                 .pipe(skip(1))
85400                 .subscribe((reference) => {
85401                 renderer.onReference(viewer, reference);
85402             }));
85403         }
85404         dispose(viewer) {
85405             for (const id of Object.keys(this._renderers)) {
85406                 this.remove(id, viewer);
85407             }
85408         }
85409         has(id) {
85410             return id in this._renderers;
85411         }
85412         remove(id, viewer) {
85413             this._renderers[id].subs.unsubscribe();
85414             const renderer = this._renderers[id].renderer;
85415             delete this._renderers[id];
85416             this._container.glRenderer.webGLRenderer$
85417                 .subscribe((gl) => {
85418                 renderer.onRemove(viewer, gl.getContext());
85419             });
85420         }
85421     }
85422
85423     class CustomCameraControls {
85424         constructor(_container, _navigator) {
85425             this._container = _container;
85426             this._navigator = _navigator;
85427             this._controls = null;
85428             this._subscriptions = new SubscriptionHolder();
85429         }
85430         attach(controls, viewer) {
85431             if (this._controls) {
85432                 throw new MapillaryError('Custom camera controls already attached');
85433             }
85434             this._controls = controls;
85435             const attach$ = new Subject();
85436             const active$ = attach$
85437                 .pipe(switchMap(() => {
85438                 return this._navigator.stateService.state$;
85439             }), map((state) => {
85440                 return state === State.Custom;
85441             }), distinctUntilChanged());
85442             const subs = this._subscriptions;
85443             subs.push(active$
85444                 .pipe(startWith(false), pairwise(), withLatestFrom(this._navigator.stateService.reference$, this._container.renderService.renderCamera$))
85445                 .subscribe(([[deactivate, activate], ref, cam]) => {
85446                 if (activate) {
85447                     controls.onActivate(viewer, cam.perspective.matrixWorldInverse.toArray(), cam.perspective.projectionMatrix.toArray(), ref);
85448                 }
85449                 else if (deactivate) {
85450                     controls.onDeactivate(viewer);
85451                 }
85452             }));
85453             subs.push(active$
85454                 .pipe(switchMap(active => {
85455                 return active ?
85456                     this._navigator.stateService.currentState$
85457                         .pipe(skip(1)) :
85458                     empty();
85459             }))
85460                 .subscribe(frame => {
85461                 controls.onAnimationFrame(viewer, frame.id);
85462             }));
85463             subs.push(active$
85464                 .pipe(switchMap(active => {
85465                 return active ?
85466                     this._navigator.stateService.reference$
85467                         .pipe(skip(1)) :
85468                     empty();
85469             }))
85470                 .subscribe(ref => controls.onReference(viewer, ref)));
85471             subs.push(active$
85472                 .pipe(switchMap(active => {
85473                 return active ?
85474                     this._container.renderService.size$
85475                         .pipe(skip(1)) :
85476                     empty();
85477             }))
85478                 .subscribe(() => controls.onResize(viewer)));
85479             subs.push(combineLatest([
85480                 // Include to ensure GL renderer has been initialized
85481                 this._container.glRenderer.webGLRenderer$,
85482                 this._container.renderService.renderCamera$,
85483                 this._navigator.stateService.reference$,
85484                 this._navigator.stateService.state$,
85485             ])
85486                 .pipe(first())
85487                 .subscribe(() => {
85488                 const projectionMatrixCallback = (projectionMatrix) => {
85489                     if (!this._controls ||
85490                         controls !== this._controls) {
85491                         return;
85492                     }
85493                     this._updateProjectionMatrix(projectionMatrix);
85494                 };
85495                 const viewMatrixCallback = (viewMatrix) => {
85496                     if (!this._controls ||
85497                         controls !== this._controls) {
85498                         return;
85499                     }
85500                     this._updateViewMatrix(viewMatrix);
85501                 };
85502                 controls.onAttach(viewer, viewMatrixCallback, projectionMatrixCallback);
85503                 attach$.next();
85504                 attach$.complete();
85505             }));
85506         }
85507         detach(viewer) {
85508             const controls = this._controls;
85509             this._controls = null;
85510             this._subscriptions.unsubscribe();
85511             return new Promise(resolve => {
85512                 this._navigator.stateService.state$
85513                     .pipe(take(1))
85514                     .subscribe(state => {
85515                     if (!controls) {
85516                         resolve(null);
85517                         return;
85518                     }
85519                     if (state === State.Custom) {
85520                         controls.onDeactivate(viewer);
85521                     }
85522                     controls.onDetach(viewer);
85523                     resolve(controls);
85524                 });
85525             });
85526         }
85527         dispose(viewer) {
85528             this.detach(viewer);
85529         }
85530         has(controls) {
85531             return !!this._controls && controls === this._controls;
85532         }
85533         _updateProjectionMatrix(projectionMatrix) {
85534             this._navigator.stateService.state$
85535                 .pipe(first())
85536                 .subscribe(state => {
85537                 if (state !== State.Custom) {
85538                     const message = "Incorrect camera control mode for " +
85539                         "projection matrix update";
85540                     console.warn(message);
85541                     return;
85542                 }
85543                 this._container.renderService.projectionMatrix$
85544                     .next(projectionMatrix);
85545             });
85546         }
85547         _updateViewMatrix(viewMatrix) {
85548             this._navigator.stateService.state$
85549                 .pipe(first())
85550                 .subscribe(state => {
85551                 if (state !== State.Custom) {
85552                     const message = "Incorrect camera control mode for " +
85553                         "view matrix update";
85554                     console.warn(message);
85555                     return;
85556                 }
85557                 this._navigator.stateService.setViewMatrix(viewMatrix);
85558             });
85559         }
85560     }
85561
85562     /**
85563      * @class Viewer
85564      *
85565      * @classdesc The Viewer object represents the navigable image viewer.
85566      * Create a Viewer by specifying a container, client ID, image ID and
85567      * other options. The viewer exposes methods and events for programmatic
85568      * interaction.
85569      *
85570      * In the case of asynchronous methods, MapillaryJS returns promises to
85571      * the results. Notifications are always emitted through JavaScript events.
85572      */
85573     class Viewer extends EventEmitter {
85574         /**
85575          * Create a new viewer instance.
85576          *
85577          * @description The `Viewer` object represents the street imagery
85578          * viewer on your web page. It exposes methods and properties that
85579          * you can use to programatically change the view, and fires
85580          * events as users interact with it.
85581          *
85582          * It is possible to initialize the viewer with or
85583          * without a ID.
85584          *
85585          * When you want to show a specific image in the viewer from
85586          * the start you should initialize it with a ID.
85587          *
85588          * When you do not know the first image ID at implementation
85589          * time, e.g. in a map-viewer application you should initialize
85590          * the viewer without a ID and call `moveTo` instead.
85591          *
85592          * When initializing with an ID the viewer is bound to that ID
85593          * until the image for that ID has been successfully loaded.
85594          * Also, a cover with the image of the ID will be shown.
85595          * If the data for that ID can not be loaded because the ID is
85596          * faulty or other errors occur it is not possible to navigate
85597          * to another ID because the viewer is not navigable. The viewer
85598          * becomes navigable when the data for the ID has been loaded and
85599          * the image is shown in the viewer. This way of initializing
85600          * the viewer is mostly for embedding in blog posts and similar
85601          * where one wants to show a specific image initially.
85602          *
85603          * If the viewer is initialized without a ID (with null or
85604          * undefined) it is not bound to any particular ID and it is
85605          * possible to move to any ID with `viewer.moveTo("<my-image-id>")`.
85606          * If the first move to a ID fails it is possible to move to another
85607          * ID. The viewer will show a black background until a move
85608          * succeeds. This way of intitializing is suited for a map-viewer
85609          * application when the initial ID is not known at implementation
85610          * time.
85611          *
85612          * @param {ViewerOptions} options - Optional configuration object
85613          * specifying Viewer's and the components' initial setup.
85614          *
85615          * @example
85616          * ```js
85617          * var viewer = new Viewer({
85618          *     accessToken: "<my-access-token>",
85619          *     container: "<my-container-id>",
85620          * });
85621          * ```
85622          */
85623         constructor(options) {
85624             super();
85625             this._navigator =
85626                 new Navigator(options);
85627             this._container =
85628                 new Container(options, this._navigator.stateService);
85629             this._observer =
85630                 new Observer(this, this._navigator, this._container);
85631             this._componentController =
85632                 new ComponentController(this._container, this._navigator, this._observer, options.imageId, options.component);
85633             this._customRenderer =
85634                 new CustomRenderer(this._container, this._navigator);
85635             this._customCameraControls =
85636                 new CustomCameraControls(this._container, this._navigator);
85637         }
85638         /**
85639          * Returns the data provider used by the viewer to fetch
85640          * all contracts, ents, and buffers.
85641          *
85642          * @description The viewer's data provider can be set
85643          * upon initialization through the {@link ViewerOptions.dataProvider}
85644          * property.
85645          *
85646          * @returns {IDataProvider} The viewer's data provider.
85647          */
85648         get dataProvider() {
85649             return this._navigator.api.data;
85650         }
85651         /**
85652          * Return a boolean indicating if the viewer is in a navigable state.
85653          *
85654          * @description The navigable state indicates if the viewer supports
85655          * moving, i.e. calling the {@link moveTo} and {@link moveDir}
85656          * methods or changing the authentication state,
85657          * i.e. calling {@link setAccessToken}. The viewer will not be in a navigable
85658          * state if the cover is activated and the viewer has been supplied a ID.
85659          * When the cover is deactivated or the viewer is activated without being
85660          * supplied a ID it will be navigable.
85661          *
85662          * @returns {boolean} Boolean indicating whether the viewer is navigable.
85663          */
85664         get isNavigable() {
85665             return this._componentController.navigable;
85666         }
85667         /**
85668          * Activate the combined panning functionality.
85669          *
85670          * @description The combined panning functionality is active by default.
85671          */
85672         activateCombinedPanning() {
85673             this._navigator.panService.enable();
85674         }
85675         /**
85676          * Activate a component.
85677          *
85678          * @param {ComponentName | FallbackComponentName} name - Name of
85679          * the component which will become active.
85680          *
85681          * @example
85682          * ```js
85683          * viewer.activateComponent("marker");
85684          * ```
85685          */
85686         activateComponent(name) {
85687             this._componentController.activate(name);
85688         }
85689         /**
85690          * Activate the cover (deactivates all other components).
85691          */
85692         activateCover() {
85693             this._componentController.activateCover();
85694         }
85695         /**
85696          * Add a custom renderer to the viewer's rendering pipeline.
85697          *
85698          * @description During a render pass, custom renderers
85699          * are called in the order they were added.
85700          *
85701          * @param renderer - The custom renderer implementation.
85702          */
85703         addCustomRenderer(renderer) {
85704             this._customRenderer.add(renderer, this);
85705         }
85706         /**
85707          * Attach custom camera controls to control the viewer's
85708          * camera pose and projection.
85709          *
85710          * @description Custom camera controls allow the API user
85711          * to move the viewer's camera freely and define the camera
85712          * projection. These camera properties are used
85713          * to render the viewer 3D scene directly into the
85714          * viewer's GL context.
85715          *
85716          * Only a single custom camera control instance can be
85717          * attached to the viewer. A new custom camera control
85718          * instance can be attached after detaching a previous
85719          * one.
85720          *
85721          * Set the viewer's camera controls to
85722          * {@link CameraControls.Custom} to activate attached
85723          * camera controls. If {@link CameraControls.Custom}
85724          * has already been set when a custom camera control
85725          * instance is attached, it will be activated immediately.
85726          *
85727          * Set the viewer's camera controls to any other
85728          * {@link CameraControls} mode to deactivate the
85729          * custom camera controls.
85730          *
85731          * @param controls - The custom camera controls implementation.
85732          *
85733          * @throws {MapillaryError} When camera controls attached
85734          * are already attached to the viewer.
85735          */
85736         attachCustomCameraControls(controls) {
85737             this._customCameraControls.attach(controls, this);
85738         }
85739         /**
85740          * Deactivate the combined panning functionality.
85741          *
85742          * @description Deactivating the combined panning functionality
85743          * could be needed in scenarios involving sequence only navigation.
85744          */
85745         deactivateCombinedPanning() {
85746             this._navigator.panService.disable();
85747         }
85748         /**
85749          * Deactivate a component.
85750          *
85751          * @param {ComponentName | FallbackComponentName} name - Name
85752          * of component which become inactive.
85753          *
85754          * @example
85755          * ```js
85756          * viewer.deactivateComponent("pointer");
85757          * ```
85758          */
85759         deactivateComponent(name) {
85760             this._componentController.deactivate(name);
85761         }
85762         /**
85763          * Deactivate the cover (activates all components marked as active).
85764          */
85765         deactivateCover() {
85766             this._componentController.deactivateCover();
85767         }
85768         /**
85769          * Detach a previously attached custom camera control
85770          * instance from the viewer.
85771          *
85772          * @description If no custom camera control instance
85773          * has previously been attached, calling this method
85774          * has no effect.
85775          *
85776          * Already attached custom camera controls need to
85777          * be detached before attaching another custom camera
85778          * control instance.
85779          */
85780         detachCustomCameraControls() {
85781             return this._customCameraControls.detach(this);
85782         }
85783         fire(type, event) {
85784             super.fire(type, event);
85785         }
85786         /**
85787          * Get the bearing of the current viewer camera.
85788          *
85789          * @description The bearing depends on how the camera
85790          * is currently rotated and does not correspond
85791          * to the compass angle of the current image if the view
85792          * has been panned.
85793          *
85794          * Bearing is measured in degrees clockwise with respect to
85795          * north.
85796          *
85797          * @returns {Promise<number>} Promise to the bearing
85798          * of the current viewer camera.
85799          *
85800          * @example
85801          * ```js
85802          * viewer.getBearing().then(b => { console.log(b); });
85803          * ```
85804          */
85805         getBearing() {
85806             return new Promise((resolve, reject) => {
85807                 this._container.renderService.bearing$.pipe(first())
85808                     .subscribe((bearing) => {
85809                     resolve(bearing);
85810                 }, (error) => {
85811                     reject(error);
85812                 });
85813             });
85814         }
85815         /**
85816          * Get the viewer's camera control mode.
85817          *
85818          * @description The camera control mode determines
85819          * how the camera is controlled when the viewer
85820          * receives pointer and keyboard input.
85821          *
85822          * @returns {CameraControls} controls - Camera control mode.
85823          *
85824          * @example
85825          * ```js
85826          * viewer.getCameraControls().then(c => { console.log(c); });
85827          * ```
85828          */
85829         getCameraControls() {
85830             return new Promise((resolve, reject) => {
85831                 this._navigator.stateService.state$.pipe(first())
85832                     .subscribe((state) => {
85833                     switch (state) {
85834                         case State.Custom:
85835                             resolve(exports.CameraControls.Custom);
85836                             break;
85837                         case State.Earth:
85838                             resolve(exports.CameraControls.Earth);
85839                             break;
85840                         default:
85841                             resolve(exports.CameraControls.Street);
85842                             break;
85843                     }
85844                 }, (error) => {
85845                     reject(error);
85846                 });
85847             });
85848         }
85849         /**
85850          * Returns the viewer's canvas element.
85851          *
85852          * @description This is the element onto which the viewer renders
85853          * the WebGL content.
85854          *
85855          * @returns {HTMLCanvasElement} The viewer's canvas element, or
85856          * null or not initialized.
85857          */
85858         getCanvas() {
85859             return this._container.canvas;
85860         }
85861         /**
85862          * Returns the HTML element containing the viewer's canvas element.
85863          *
85864          * @description This is the element to which event bindings for viewer
85865          * interactivity (such as panning and zooming) are attached.
85866          *
85867          * @returns {HTMLDivElement} The container for the viewer's
85868          * canvas element.
85869          */
85870         getCanvasContainer() {
85871             return this._container.canvasContainer;
85872         }
85873         /**
85874          * Get the basic coordinates of the current image that is
85875          * at the center of the viewport.
85876          *
85877          * @description Basic coordinates are 2D coordinates on the [0, 1] interval
85878          * and have the origin point, (0, 0), at the top left corner and the
85879          * maximum value, (1, 1), at the bottom right corner of the original
85880          * image.
85881          *
85882          * @returns {Promise<number[]>} Promise to the basic coordinates
85883          * of the current image at the center for the viewport.
85884          *
85885          * @example
85886          * ```js
85887          * viewer.getCenter().then(c => { console.log(c); });
85888          * ```
85889          */
85890         getCenter() {
85891             return new Promise((resolve, reject) => {
85892                 this._navigator.stateService.getCenter()
85893                     .subscribe((center) => {
85894                     resolve(center);
85895                 }, (error) => {
85896                     reject(error);
85897                 });
85898             });
85899         }
85900         /**
85901          * Get a component.
85902          *
85903          * @param {string} name - Name of component.
85904          * @returns {Component} The requested component.
85905          *
85906          * @example
85907          * ```js
85908          * var pointerComponent = viewer.getComponent("pointer");
85909          * ```
85910          */
85911         getComponent(name) {
85912             return this._componentController.get(name);
85913         }
85914         /**
85915          * Returns the viewer's containing HTML element.
85916          *
85917          * @returns {HTMLElement} The viewer's container.
85918          */
85919         getContainer() {
85920             return this._container.container;
85921         }
85922         /**
85923          * Get the viewer's current vertical field of view.
85924          *
85925          * @description The vertical field of view rendered on the viewer canvas
85926          * measured in degrees.
85927          *
85928          * @returns {Promise<number>} Promise to the current field of view
85929          * of the viewer camera.
85930          *
85931          * @example
85932          * ```js
85933          * viewer.getFieldOfView().then(fov => { console.log(fov); });
85934          * ```
85935          */
85936         getFieldOfView() {
85937             return new Promise((resolve, reject) => {
85938                 this._container.renderService.renderCamera$.pipe(first())
85939                     .subscribe((rc) => {
85940                     resolve(rc.perspective.fov);
85941                 }, (error) => {
85942                     reject(error);
85943                 });
85944             });
85945         }
85946         /**
85947          * Get the viewer's current image.
85948          *
85949          * @returns {Promise<Image>} Promise to the current image.
85950          *
85951          * @example
85952          * ```js
85953          * viewer.getImage().then(image => { console.log(image.id); });
85954          * ```
85955          */
85956         getImage() {
85957             return new Promise((resolve, reject) => {
85958                 this._navigator.stateService.currentImage$.pipe(first())
85959                     .subscribe((image) => { resolve(image); }, (error) => { reject(error); });
85960             });
85961         }
85962         /**
85963          * Get the viewer's current point of view.
85964          *
85965          * @returns {Promise<PointOfView>} Promise to the current point of view
85966          * of the viewer camera.
85967          *
85968          * @example
85969          * ```js
85970          * viewer.getPointOfView().then(pov => { console.log(pov); });
85971          * ```
85972          */
85973         getPointOfView() {
85974             return new Promise((resolve, reject) => {
85975                 combineLatest(this._container.renderService.renderCamera$, this._container.renderService.bearing$).pipe(first())
85976                     .subscribe(([rc, bearing]) => {
85977                     resolve({
85978                         bearing: bearing,
85979                         tilt: rc.getTilt(),
85980                     });
85981                 }, (error) => {
85982                     reject(error);
85983                 });
85984             });
85985         }
85986         /**
85987          * Get the viewer's current position
85988          *
85989          * @returns {Promise<LngLat>} Promise to the viewers's current
85990          * position.
85991          *
85992          * @example
85993          * ```js
85994          * viewer.getPosition().then(pos => { console.log(pos); });
85995          * ```
85996          */
85997         getPosition() {
85998             return new Promise((resolve, reject) => {
85999                 combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.reference$).pipe(first())
86000                     .subscribe(([render, reference]) => {
86001                     resolve(this._observer.projection.cameraToLngLat(render, reference));
86002                 }, (error) => {
86003                     reject(error);
86004                 });
86005             });
86006         }
86007         /**
86008          * Get the viewer's current reference position.
86009          *
86010          * @description The reference position specifies the origin in
86011          * the viewer's topocentric coordinate system.
86012          *
86013          * @returns {Promise<LngLatAlt>} Promise to the reference position.
86014          *
86015          * @example
86016          * ```js
86017          * viewer.getReference().then(reference => { console.log(reference); });
86018          * ```
86019          */
86020         getReference() {
86021             return new Promise((resolve, reject) => {
86022                 this._navigator.stateService.reference$.pipe(first())
86023                     .subscribe((reference) => { resolve(reference); }, (error) => { reject(error); });
86024             });
86025         }
86026         /**
86027          * Get the image's current zoom level.
86028          *
86029          * @returns {Promise<number>} Promise to the viewers's current
86030          * zoom level.
86031          *
86032          * @example
86033          * ```js
86034          * viewer.getZoom().then(z => { console.log(z); });
86035          * ```
86036          */
86037         getZoom() {
86038             return new Promise((resolve, reject) => {
86039                 this._navigator.stateService.getZoom()
86040                     .subscribe((zoom) => {
86041                     resolve(zoom);
86042                 }, (error) => {
86043                     reject(error);
86044                 });
86045             });
86046         }
86047         /**
86048          * Check if a controls instance is the camera controls that are
86049          * currently attached to the viewer.
86050          *
86051          * @param {ICustomCameraControls} controls - Camera controls instance.
86052          * @returns {boolean} Value indicating whether the controls instance
86053          * is currently attached.
86054          */
86055         hasCustomCameraControls(controls) {
86056             return this._customCameraControls.has(controls);
86057         }
86058         /**
86059          * Check if a custom renderer has been added to the viewer's
86060          * rendering pipeline.
86061          *
86062          * @param {string} id - Unique ID of the custom renderer.
86063          * @returns {boolean} Value indicating whether the customer
86064          * renderer has been added.
86065          */
86066         hasCustomRenderer(rendererId) {
86067             return this._customRenderer.has(rendererId);
86068         }
86069         /**
86070          * Navigate in a given direction.
86071          *
86072          * @param {NavigationDirection} direction - Direction in which which to move.
86073          * @returns {Promise<Image>} Promise to the image that was navigated to.
86074          * @throws If the current image does not have the edge direction
86075          * or the edges has not yet been cached.
86076          * @throws Propagates any IO errors to the caller.
86077          * @throws When viewer is not navigable.
86078          * @throws {@link CancelMapillaryError} When a subsequent move request
86079          * is made before the move dir call has completed.
86080          *
86081          * @example
86082          * ```js
86083          * viewer.moveDir(NavigationDirection.Next).then(
86084          *     image => { console.log(image); },
86085          *     error => { console.error(error); });
86086          * ```
86087          */
86088         moveDir(direction) {
86089             const moveDir$ = this.isNavigable ?
86090                 this._navigator.moveDir$(direction) :
86091                 throwError(new Error("Calling moveDir is not supported when viewer is not navigable."));
86092             return new Promise((resolve, reject) => {
86093                 moveDir$.subscribe((image) => {
86094                     resolve(image);
86095                 }, (error) => {
86096                     reject(error);
86097                 });
86098             });
86099         }
86100         /**
86101          * Navigate to a given image ID.
86102          *
86103          * @param {string} imageId - Id of the image to move to.
86104          * @returns {Promise<Image>} Promise to the image that was navigated to.
86105          * @throws Propagates any IO errors to the caller.
86106          * @throws When viewer is not navigable.
86107          * @throws {@link CancelMapillaryError} When a subsequent
86108          * move request is made before the move to ID call has completed.
86109          *
86110          * @example
86111          * ```js
86112          * viewer.moveTo("<my-image-id>").then(
86113          *     image => { console.log(image); },
86114          *     error => { console.error(error); });
86115          * ```
86116          */
86117         moveTo(imageId) {
86118             const moveTo$ = this.isNavigable ?
86119                 this._navigator.moveTo$(imageId) :
86120                 throwError(new Error("Calling moveTo is not supported when viewer is not navigable."));
86121             return new Promise((resolve, reject) => {
86122                 moveTo$.subscribe((image) => {
86123                     resolve(image);
86124                 }, (error) => {
86125                     reject(error);
86126                 });
86127             });
86128         }
86129         off(type, handler) {
86130             super.off(type, handler);
86131         }
86132         on(type, handler) {
86133             super.on(type, handler);
86134         }
86135         /**
86136          * Project geodetic coordinates to canvas pixel coordinates.
86137          *
86138          * @description The geodetic coordinates may not always correspond to pixel
86139          * coordinates, e.g. if the geodetic coordinates have a position behind the
86140          * viewer camera. In the case of no correspondence the returned value will
86141          * be `null`.
86142          *
86143          * If the distance from the viewer camera position to the provided
86144          * longitude-latitude is more than 1000 meters `null` will be returned.
86145          *
86146          * The projection is performed from the ground plane, i.e.
86147          * the altitude with respect to the ground plane for the geodetic
86148          * point is zero.
86149          *
86150          * Note that whenever the camera moves, the result of the method will be
86151          * different.
86152          *
86153          * @param {LngLat} lngLat - Geographical coordinates to project.
86154          * @returns {Promise<Array<number>>} Promise to the pixel coordinates corresponding
86155          * to the lngLat.
86156          *
86157          * @example
86158          * ```js
86159          * viewer.project({ lat: 0, lng: 0 })
86160          *     .then(pixelPoint => {
86161          *          if (!pixelPoint) {
86162          *              console.log("no correspondence");
86163          *          }
86164          *
86165          *          console.log(pixelPoint);
86166          *     });
86167          * ```
86168          */
86169         project(lngLat) {
86170             return new Promise((resolve, reject) => {
86171                 this._observer.project$(lngLat)
86172                     .subscribe((pixelPoint) => {
86173                     resolve(pixelPoint);
86174                 }, (error) => {
86175                     reject(error);
86176                 });
86177             });
86178         }
86179         /**
86180          * Project basic image coordinates for the current image to canvas pixel
86181          * coordinates.
86182          *
86183          * @description The basic image coordinates may not always correspond to a
86184          * pixel point that lies in the visible area of the viewer container. In the
86185          * case of no correspondence the returned value can be `null`.
86186          *
86187          *
86188          * @param {Array<number>} basicPoint - Basic images coordinates to project.
86189          * @returns {Promise<Array<number>>} Promise to the pixel coordinates corresponding
86190          * to the basic image point.
86191          *
86192          * @example
86193          * ```js
86194          * viewer.projectFromBasic([0.3, 0.7])
86195          *     .then(pixelPoint => { console.log(pixelPoint); });
86196          * ```
86197          */
86198         projectFromBasic(basicPoint) {
86199             return new Promise((resolve, reject) => {
86200                 this._observer.projectBasic$(basicPoint)
86201                     .subscribe((pixelPoint) => {
86202                     resolve(pixelPoint);
86203                 }, (error) => {
86204                     reject(error);
86205                 });
86206             });
86207         }
86208         /**
86209          * Clean up and release all internal resources associated with
86210          * this viewer.
86211          *
86212          * @description This includes DOM elements, event bindings, and
86213          * WebGL resources.
86214          *
86215          * Use this method when you are done using the viewer and wish to
86216          * ensure that it no longer consumes browser resources. Afterwards,
86217          * you must not call any other methods on the viewer.
86218          *
86219          * @fires remove
86220          *
86221          * @example
86222          * ```js
86223          * viewer.remove();
86224          * ```
86225          */
86226         remove() {
86227             this._customRenderer.dispose(this);
86228             this._customCameraControls.dispose(this);
86229             this._observer.dispose();
86230             this._componentController.remove();
86231             this._navigator.dispose();
86232             this._container.remove();
86233             const type = "remove";
86234             const event = {
86235                 target: this,
86236                 type,
86237             };
86238             this.fire(type, event);
86239         }
86240         /**
86241          * Remove a custom renderer from the viewer's rendering pipeline.
86242          *
86243          * @param id - Unique ID of the custom renderer.
86244          */
86245         removeCustomRenderer(rendererId) {
86246             this._customRenderer.remove(rendererId, this);
86247         }
86248         /**
86249          * Detect the viewer's new width and height and resize it
86250          * manually.
86251          *
86252          * @description The components will also detect the viewer's
86253          * new size and resize their rendered elements if needed.
86254          *
86255          * When the {@link ViewerOptions.trackResize} option is
86256          * set to true, the viewer will automatically resize
86257          * when the browser window is resized. If any other
86258          * custom behavior is preferred, the option should be set
86259          * to false and the {@link Viewer.resize} method should
86260          * be called on demand.
86261          *
86262          * @example
86263          * ```js
86264          * viewer.resize();
86265          * ```
86266          */
86267         resize() {
86268             this._container.renderService.resize$.next();
86269         }
86270         /**
86271          * Set the viewer's camera control mode.
86272          *
86273          * @description The camera control mode determines
86274          * how the camera is controlled when the viewer
86275          * receives pointer and keyboard input.
86276          *
86277          * Changing the camera control mode is not possible
86278          * when the slider component is active and attempts
86279          * to do so will be ignored.
86280          *
86281          * @param {CameraControls} controls - Camera control mode.
86282          *
86283          * @example
86284          * ```js
86285          * viewer.setCameraControls(CameraControls.Street);
86286          * ```
86287          */
86288         setCameraControls(controls) {
86289             const state = cameraControlsToState(controls);
86290             if (state === State.Traversing) {
86291                 this._navigator.stateService.traverse();
86292             }
86293             else if (state === State.Earth) {
86294                 this._navigator.stateService.earth();
86295             }
86296             else if (state === State.Custom) {
86297                 this._navigator.stateService.custom();
86298             }
86299             else {
86300                 console.warn(`Unsupported camera control transition (${controls})`);
86301             }
86302         }
86303         /**
86304          * Set the basic coordinates of the current image to be in the
86305          * center of the viewport.
86306          *
86307          * @description Basic coordinates are 2D coordinates on the [0, 1] interval
86308          * and has the origin point, (0, 0), at the top left corner and the
86309          * maximum value, (1, 1), at the bottom right corner of the original
86310          * image.
86311          *
86312          * @param {number[]} The basic coordinates of the current
86313          * image to be at the center for the viewport.
86314          *
86315          * @example
86316          * ```js
86317          * viewer.setCenter([0.5, 0.5]);
86318          * ```
86319          */
86320         setCenter(center) {
86321             this._navigator.stateService.setCenter(center);
86322         }
86323         /**
86324          * Set the viewer's current vertical field of view.
86325          *
86326          * @description Sets the vertical field of view rendered
86327          * on the viewer canvas measured in degrees. The value
86328          * will be clamped to be able to set a valid zoom level
86329          * based on the projection model of the current image and
86330          * the viewer's current render mode.
86331          *
86332          * @param {number} fov - Vertical field of view in degrees.
86333          *
86334          * @example
86335          * ```js
86336          * viewer.setFieldOfView(45);
86337          * ```
86338          */
86339         setFieldOfView(fov) {
86340             this._container.renderService.renderCamera$.pipe(first())
86341                 .subscribe((rc) => {
86342                 const zoom = rc.fovToZoom(fov);
86343                 this._navigator.stateService.setZoom(zoom);
86344             });
86345         }
86346         /**
86347          * Set the filter selecting images to use when calculating
86348          * the spatial edges.
86349          *
86350          * @description The following filter types are supported:
86351          *
86352          * Comparison
86353          *
86354          * `["==", key, value]` equality: `image[key] = value`
86355          *
86356          * `["!=", key, value]` inequality: `image[key] â‰  value`
86357          *
86358          * `["<", key, value]` less than: `image[key] < value`
86359          *
86360          * `["<=", key, value]` less than or equal: `image[key] â‰¤ value`
86361          *
86362          * `[">", key, value]` greater than: `image[key] > value`
86363          *
86364          * `[">=", key, value]` greater than or equal: `image[key] â‰¥ value`
86365          *
86366          * Set membership
86367          *
86368          * `["in", key, v0, ..., vn]` set inclusion: `image[key] âˆˆ {v0, ..., vn}`
86369          *
86370          * `["!in", key, v0, ..., vn]` set exclusion: `image[key] âˆ‰ {v0, ..., vn}`
86371          *
86372          * Combining
86373          *
86374          * `["all", f0, ..., fn]` logical `AND`: `f0 âˆ§ ... âˆ§ fn`
86375          *
86376          * A key must be a string that identifies a property name of a
86377          * simple {@link Image} property, i.e. a key of the {@link FilterKey}
86378          * type. A value must be a string, number, or
86379          * boolean. Strictly-typed comparisons are used. The values
86380          * `f0, ..., fn` of the combining filter must be filter expressions.
86381          *
86382          * Clear the filter by setting it to null or empty array.
86383          *
86384          * Commonly used filter properties (see the {@link Image} class
86385          * documentation for a full list of properties that can be used
86386          * in a filter) are shown the the example code.
86387          *
86388          * @param {FilterExpression} [filter] - The filter expression.
86389          * Applied filter is cleared if omitted.
86390          * @returns {Promise<void>} Promise that resolves after filter is applied.
86391          *
86392          * @example
86393          * ```js
86394          * // Examples
86395          * viewer.setFilter(["==", "cameraType", "spherical"]);
86396          * viewer.setFilter([">=", "capturedAt", <my-time-stamp>]);
86397          * viewer.setFilter(["in", "sequenceId", "<sequence-id-1>", "<sequence-id-2>"]);
86398          * ```
86399          */
86400         setFilter(filter) {
86401             return new Promise((resolve, reject) => {
86402                 this._navigator.setFilter$(filter)
86403                     .subscribe(() => {
86404                     resolve(undefined);
86405                 }, (error) => {
86406                     reject(error);
86407                 });
86408             });
86409         }
86410         /**
86411          * Set the viewer's render mode.
86412          *
86413          * @param {RenderMode} renderMode - Render mode.
86414          *
86415          * @example
86416          * ```js
86417          * viewer.setRenderMode(RenderMode.Letterbox);
86418          * ```
86419          */
86420         setRenderMode(renderMode) {
86421             this._container.renderService.renderMode$.next(renderMode);
86422         }
86423         /**
86424          * Set the viewer's transition mode.
86425          *
86426          * @param {TransitionMode} transitionMode - Transition mode.
86427          *
86428          * @example
86429          * ```js
86430          * viewer.setTransitionMode(TransitionMode.Instantaneous);
86431          * ```
86432          */
86433         setTransitionMode(transitionMode) {
86434             this._navigator.stateService.setTransitionMode(transitionMode);
86435         }
86436         /**
86437          * Set an access token for authenticated API requests of protected
86438          * resources.
86439          *
86440          * The token may be a user access token or a client access token.
86441          *
86442          * @description When the supplied user token is null or undefined,
86443          * any previously set user bearer token will be cleared and the
86444          * viewer will make unauthenticated requests.
86445          *
86446          * Calling setAccessToken aborts all outstanding move requests.
86447          * The promises of those move requests will be rejected with a
86448          * {@link CancelMapillaryError} the rejections need to be caught.
86449          *
86450          * Calling setAccessToken also resets the complete viewer cache
86451          * so it should not be called repeatedly.
86452          *
86453          * @param {string} [accessToken] accessToken - Optional user
86454          * access token or client access token.
86455          * @returns {Promise<void>} Promise that resolves after token
86456          * is set.
86457          *
86458          * @throws When viewer is not navigable.
86459          *
86460          * @example
86461          * ```js
86462          * viewer.setAccessToken("<my access token>")
86463          *     .then(() => { console.log("user token set"); });
86464          * ```
86465          */
86466         setAccessToken(accessToken) {
86467             const setAccessToken$ = this.isNavigable ?
86468                 this._navigator.setAccessToken$(accessToken) :
86469                 throwError(new Error("Calling setAccessToken is not supported when viewer is not navigable."));
86470             return new Promise((resolve, reject) => {
86471                 setAccessToken$
86472                     .subscribe(() => {
86473                     resolve(undefined);
86474                 }, (error) => {
86475                     reject(error);
86476                 });
86477             });
86478         }
86479         /**
86480          * Set the image's current zoom level.
86481          *
86482          * @description Possible zoom level values are on the [0, 3] interval.
86483          * Zero means zooming out to fit the image to the view whereas three
86484          * shows the highest level of detail.
86485          *
86486          * @param {number} The image's current zoom level.
86487          *
86488          * @example
86489          * ```js
86490          * viewer.setZoom(2);
86491          * ```
86492          */
86493         setZoom(zoom) {
86494             this._navigator.stateService.setZoom(zoom);
86495         }
86496         /**
86497          * Trigger the rendering of a single frame.
86498          *
86499          * @description Use this method with custom renderers to
86500          * force the viewer to rerender when the custom content
86501          * changes. Calling this multiple times before the next
86502          * frame is rendered will still result in only a single
86503          * frame being rendered.
86504          */
86505         triggerRerender() {
86506             this._container.glRenderer.triggerRerender();
86507         }
86508         /**
86509          * Unproject canvas pixel coordinates to geodetic
86510          * coordinates.
86511          *
86512          * @description The pixel point may not always correspond to geodetic
86513          * coordinates. In the case of no correspondence the returned value will
86514          * be `null`.
86515          *
86516          * The unprojection to a lngLat will be performed towards the ground plane, i.e.
86517          * the altitude with respect to the ground plane for the returned lngLat is zero.
86518          *
86519          * @param {Array<number>} pixelPoint - Pixel coordinates to unproject.
86520          * @returns {Promise<LngLat>} Promise to the lngLat corresponding to the pixel point.
86521          *
86522          * @example
86523          * ```js
86524          * viewer.unproject([100, 100])
86525          *     .then(lngLat => { console.log(lngLat); });
86526          * ```
86527          */
86528         unproject(pixelPoint) {
86529             return new Promise((resolve, reject) => {
86530                 this._observer.unproject$(pixelPoint)
86531                     .subscribe((lngLat) => {
86532                     resolve(lngLat);
86533                 }, (error) => {
86534                     reject(error);
86535                 });
86536             });
86537         }
86538         /**
86539          * Unproject canvas pixel coordinates to basic image coordinates for the
86540          * current image.
86541          *
86542          * @description The pixel point may not always correspond to basic image
86543          * coordinates. In the case of no correspondence the returned value will
86544          * be `null`.
86545          *
86546          * @param {Array<number>} pixelPoint - Pixel coordinates to unproject.
86547          * @returns {Promise<LngLat>} Promise to the basic coordinates corresponding
86548          * to the pixel point.
86549          *
86550          * @example
86551          * ```js
86552          * viewer.unprojectToBasic([100, 100])
86553          *     .then(basicPoint => { console.log(basicPoint); });
86554          * ```
86555          */
86556         unprojectToBasic(pixelPoint) {
86557             return new Promise((resolve, reject) => {
86558                 this._observer.unprojectBasic$(pixelPoint)
86559                     .subscribe((basicPoint) => {
86560                     resolve(basicPoint);
86561                 }, (error) => {
86562                     reject(error);
86563                 });
86564             });
86565         }
86566     }
86567
86568     /**
86569      * Internal bootstrap
86570      *
86571      * This is a workaround to make the CommonJS unit testing
86572      * work with Jest. Once Jest/Node supports ES6 modules
86573      * fully this should be removed. GeoRBush is registered
86574      * here only to avoid loading it during
86575      * unit tests.
86576      */
86577     Graph.register(GeoRBush);
86578     MarkerSet.register(GeoRBush);
86579     ComponentService.registerCover(CoverComponent);
86580     ComponentService.register(AttributionComponent);
86581     ComponentService.register(BearingComponent);
86582     ComponentService.register(CacheComponent);
86583     ComponentService.register(DirectionComponent);
86584     ComponentService.register(ImageComponent);
86585     ComponentService.register(KeyboardComponent);
86586     ComponentService.register(MarkerComponent);
86587     ComponentService.register(PointerComponent);
86588     ComponentService.register(PopupComponent);
86589     ComponentService.register(SequenceComponent);
86590     ComponentService.register(SliderComponent);
86591     ComponentService.register(SpatialComponent);
86592     ComponentService.register(TagComponent);
86593     ComponentService.register(ZoomComponent);
86594     ComponentService.register(ImageFallbackComponent);
86595     ComponentService.register(NavigationFallbackComponent);
86596
86597     exports.ArgumentMapillaryError = ArgumentMapillaryError;
86598     exports.BearingComponent = BearingComponent;
86599     exports.CacheComponent = CacheComponent;
86600     exports.CancelMapillaryError = CancelMapillaryError;
86601     exports.CircleMarker = CircleMarker;
86602     exports.Component = Component;
86603     exports.DataProviderBase = DataProviderBase;
86604     exports.DirectionComponent = DirectionComponent;
86605     exports.DragPanHandler = DragPanHandler;
86606     exports.EventEmitter = EventEmitter;
86607     exports.ExtremePointTag = ExtremePointTag;
86608     exports.Geometry = Geometry;
86609     exports.GeometryProviderBase = GeometryProviderBase;
86610     exports.GeometryTagError = GeometryTagError;
86611     exports.GraphDataProvider = GraphDataProvider;
86612     exports.GraphMapillaryError = GraphMapillaryError;
86613     exports.Image = Image$1;
86614     exports.KeyPlayHandler = KeyPlayHandler;
86615     exports.KeySequenceNavigationHandler = KeySequenceNavigationHandler;
86616     exports.KeySpatialNavigationHandler = KeySpatialNavigationHandler;
86617     exports.KeyZoomHandler = KeyZoomHandler;
86618     exports.KeyboardComponent = KeyboardComponent;
86619     exports.MapillaryError = MapillaryError;
86620     exports.Marker = Marker;
86621     exports.MarkerComponent = MarkerComponent;
86622     exports.OutlineTag = OutlineTag;
86623     exports.PointGeometry = PointGeometry;
86624     exports.PointerComponent = PointerComponent;
86625     exports.PointsGeometry = PointsGeometry;
86626     exports.PolygonGeometry = PolygonGeometry;
86627     exports.Popup = Popup;
86628     exports.PopupComponent = PopupComponent;
86629     exports.RectGeometry = RectGeometry;
86630     exports.S2GeometryProvider = S2GeometryProvider;
86631     exports.ScrollZoomHandler = ScrollZoomHandler;
86632     exports.SequenceComponent = SequenceComponent;
86633     exports.SimpleMarker = SimpleMarker;
86634     exports.SliderComponent = SliderComponent;
86635     exports.SpatialComponent = SpatialComponent;
86636     exports.SpotTag = SpotTag;
86637     exports.Tag = Tag;
86638     exports.TagComponent = TagComponent;
86639     exports.TouchZoomHandler = TouchZoomHandler;
86640     exports.VertexGeometry = VertexGeometry;
86641     exports.Viewer = Viewer;
86642     exports.ZoomComponent = ZoomComponent;
86643     exports.decompress = decompress;
86644     exports.ecefToEnu = ecefToEnu;
86645     exports.ecefToGeodetic = ecefToGeodetic;
86646     exports.enuToEcef = enuToEcef;
86647     exports.enuToGeodetic = enuToGeodetic;
86648     exports.fetchArrayBuffer = fetchArrayBuffer;
86649     exports.geodeticToEcef = geodeticToEcef;
86650     exports.geodeticToEnu = geodeticToEnu;
86651     exports.isFallbackSupported = isFallbackSupported;
86652     exports.isSupported = isSupported;
86653     exports.readMeshPbf = readMeshPbf;
86654
86655     Object.defineProperty(exports, '__esModule', { value: true });
86656
86657 }));
86658 //# sourceMappingURL=mapillary.unminified.js.map