]> gitweb.ps.run Git - cloth_sim/blob - Scripts/three.module.js
tweaking parameters
[cloth_sim] / Scripts / three.module.js
1 // threejs.org/license
2 const REVISION = '125';
3 const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
4 const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
5 const CullFaceNone = 0;
6 const CullFaceBack = 1;
7 const CullFaceFront = 2;
8 const CullFaceFrontBack = 3;
9 const BasicShadowMap = 0;
10 const PCFShadowMap = 1;
11 const PCFSoftShadowMap = 2;
12 const VSMShadowMap = 3;
13 const FrontSide = 0;
14 const BackSide = 1;
15 const DoubleSide = 2;
16 const FlatShading = 1;
17 const SmoothShading = 2;
18 const NoBlending = 0;
19 const NormalBlending = 1;
20 const AdditiveBlending = 2;
21 const SubtractiveBlending = 3;
22 const MultiplyBlending = 4;
23 const CustomBlending = 5;
24 const AddEquation = 100;
25 const SubtractEquation = 101;
26 const ReverseSubtractEquation = 102;
27 const MinEquation = 103;
28 const MaxEquation = 104;
29 const ZeroFactor = 200;
30 const OneFactor = 201;
31 const SrcColorFactor = 202;
32 const OneMinusSrcColorFactor = 203;
33 const SrcAlphaFactor = 204;
34 const OneMinusSrcAlphaFactor = 205;
35 const DstAlphaFactor = 206;
36 const OneMinusDstAlphaFactor = 207;
37 const DstColorFactor = 208;
38 const OneMinusDstColorFactor = 209;
39 const SrcAlphaSaturateFactor = 210;
40 const NeverDepth = 0;
41 const AlwaysDepth = 1;
42 const LessDepth = 2;
43 const LessEqualDepth = 3;
44 const EqualDepth = 4;
45 const GreaterEqualDepth = 5;
46 const GreaterDepth = 6;
47 const NotEqualDepth = 7;
48 const MultiplyOperation = 0;
49 const MixOperation = 1;
50 const AddOperation = 2;
51 const NoToneMapping = 0;
52 const LinearToneMapping = 1;
53 const ReinhardToneMapping = 2;
54 const CineonToneMapping = 3;
55 const ACESFilmicToneMapping = 4;
56 const CustomToneMapping = 5;
57
58 const UVMapping = 300;
59 const CubeReflectionMapping = 301;
60 const CubeRefractionMapping = 302;
61 const EquirectangularReflectionMapping = 303;
62 const EquirectangularRefractionMapping = 304;
63 const CubeUVReflectionMapping = 306;
64 const CubeUVRefractionMapping = 307;
65 const RepeatWrapping = 1000;
66 const ClampToEdgeWrapping = 1001;
67 const MirroredRepeatWrapping = 1002;
68 const NearestFilter = 1003;
69 const NearestMipmapNearestFilter = 1004;
70 const NearestMipMapNearestFilter = 1004;
71 const NearestMipmapLinearFilter = 1005;
72 const NearestMipMapLinearFilter = 1005;
73 const LinearFilter = 1006;
74 const LinearMipmapNearestFilter = 1007;
75 const LinearMipMapNearestFilter = 1007;
76 const LinearMipmapLinearFilter = 1008;
77 const LinearMipMapLinearFilter = 1008;
78 const UnsignedByteType = 1009;
79 const ByteType = 1010;
80 const ShortType = 1011;
81 const UnsignedShortType = 1012;
82 const IntType = 1013;
83 const UnsignedIntType = 1014;
84 const FloatType = 1015;
85 const HalfFloatType = 1016;
86 const UnsignedShort4444Type = 1017;
87 const UnsignedShort5551Type = 1018;
88 const UnsignedShort565Type = 1019;
89 const UnsignedInt248Type = 1020;
90 const AlphaFormat = 1021;
91 const RGBFormat = 1022;
92 const RGBAFormat = 1023;
93 const LuminanceFormat = 1024;
94 const LuminanceAlphaFormat = 1025;
95 const RGBEFormat = RGBAFormat;
96 const DepthFormat = 1026;
97 const DepthStencilFormat = 1027;
98 const RedFormat = 1028;
99 const RedIntegerFormat = 1029;
100 const RGFormat = 1030;
101 const RGIntegerFormat = 1031;
102 const RGBIntegerFormat = 1032;
103 const RGBAIntegerFormat = 1033;
104
105 const RGB_S3TC_DXT1_Format = 33776;
106 const RGBA_S3TC_DXT1_Format = 33777;
107 const RGBA_S3TC_DXT3_Format = 33778;
108 const RGBA_S3TC_DXT5_Format = 33779;
109 const RGB_PVRTC_4BPPV1_Format = 35840;
110 const RGB_PVRTC_2BPPV1_Format = 35841;
111 const RGBA_PVRTC_4BPPV1_Format = 35842;
112 const RGBA_PVRTC_2BPPV1_Format = 35843;
113 const RGB_ETC1_Format = 36196;
114 const RGB_ETC2_Format = 37492;
115 const RGBA_ETC2_EAC_Format = 37496;
116 const RGBA_ASTC_4x4_Format = 37808;
117 const RGBA_ASTC_5x4_Format = 37809;
118 const RGBA_ASTC_5x5_Format = 37810;
119 const RGBA_ASTC_6x5_Format = 37811;
120 const RGBA_ASTC_6x6_Format = 37812;
121 const RGBA_ASTC_8x5_Format = 37813;
122 const RGBA_ASTC_8x6_Format = 37814;
123 const RGBA_ASTC_8x8_Format = 37815;
124 const RGBA_ASTC_10x5_Format = 37816;
125 const RGBA_ASTC_10x6_Format = 37817;
126 const RGBA_ASTC_10x8_Format = 37818;
127 const RGBA_ASTC_10x10_Format = 37819;
128 const RGBA_ASTC_12x10_Format = 37820;
129 const RGBA_ASTC_12x12_Format = 37821;
130 const RGBA_BPTC_Format = 36492;
131 const SRGB8_ALPHA8_ASTC_4x4_Format = 37840;
132 const SRGB8_ALPHA8_ASTC_5x4_Format = 37841;
133 const SRGB8_ALPHA8_ASTC_5x5_Format = 37842;
134 const SRGB8_ALPHA8_ASTC_6x5_Format = 37843;
135 const SRGB8_ALPHA8_ASTC_6x6_Format = 37844;
136 const SRGB8_ALPHA8_ASTC_8x5_Format = 37845;
137 const SRGB8_ALPHA8_ASTC_8x6_Format = 37846;
138 const SRGB8_ALPHA8_ASTC_8x8_Format = 37847;
139 const SRGB8_ALPHA8_ASTC_10x5_Format = 37848;
140 const SRGB8_ALPHA8_ASTC_10x6_Format = 37849;
141 const SRGB8_ALPHA8_ASTC_10x8_Format = 37850;
142 const SRGB8_ALPHA8_ASTC_10x10_Format = 37851;
143 const SRGB8_ALPHA8_ASTC_12x10_Format = 37852;
144 const SRGB8_ALPHA8_ASTC_12x12_Format = 37853;
145 const LoopOnce = 2200;
146 const LoopRepeat = 2201;
147 const LoopPingPong = 2202;
148 const InterpolateDiscrete = 2300;
149 const InterpolateLinear = 2301;
150 const InterpolateSmooth = 2302;
151 const ZeroCurvatureEnding = 2400;
152 const ZeroSlopeEnding = 2401;
153 const WrapAroundEnding = 2402;
154 const NormalAnimationBlendMode = 2500;
155 const AdditiveAnimationBlendMode = 2501;
156 const TrianglesDrawMode = 0;
157 const TriangleStripDrawMode = 1;
158 const TriangleFanDrawMode = 2;
159 const LinearEncoding = 3000;
160 const sRGBEncoding = 3001;
161 const GammaEncoding = 3007;
162 const RGBEEncoding = 3002;
163 const LogLuvEncoding = 3003;
164 const RGBM7Encoding = 3004;
165 const RGBM16Encoding = 3005;
166 const RGBDEncoding = 3006;
167 const BasicDepthPacking = 3200;
168 const RGBADepthPacking = 3201;
169 const TangentSpaceNormalMap = 0;
170 const ObjectSpaceNormalMap = 1;
171
172 const ZeroStencilOp = 0;
173 const KeepStencilOp = 7680;
174 const ReplaceStencilOp = 7681;
175 const IncrementStencilOp = 7682;
176 const DecrementStencilOp = 7683;
177 const IncrementWrapStencilOp = 34055;
178 const DecrementWrapStencilOp = 34056;
179 const InvertStencilOp = 5386;
180
181 const NeverStencilFunc = 512;
182 const LessStencilFunc = 513;
183 const EqualStencilFunc = 514;
184 const LessEqualStencilFunc = 515;
185 const GreaterStencilFunc = 516;
186 const NotEqualStencilFunc = 517;
187 const GreaterEqualStencilFunc = 518;
188 const AlwaysStencilFunc = 519;
189
190 const StaticDrawUsage = 35044;
191 const DynamicDrawUsage = 35048;
192 const StreamDrawUsage = 35040;
193 const StaticReadUsage = 35045;
194 const DynamicReadUsage = 35049;
195 const StreamReadUsage = 35041;
196 const StaticCopyUsage = 35046;
197 const DynamicCopyUsage = 35050;
198 const StreamCopyUsage = 35042;
199
200 const GLSL1 = '100';
201 const GLSL3 = '300 es';
202
203 /**
204  * https://github.com/mrdoob/eventdispatcher.js/
205  */
206
207 function EventDispatcher() {}
208
209 Object.assign( EventDispatcher.prototype, {
210
211         addEventListener: function ( type, listener ) {
212
213                 if ( this._listeners === undefined ) this._listeners = {};
214
215                 const listeners = this._listeners;
216
217                 if ( listeners[ type ] === undefined ) {
218
219                         listeners[ type ] = [];
220
221                 }
222
223                 if ( listeners[ type ].indexOf( listener ) === - 1 ) {
224
225                         listeners[ type ].push( listener );
226
227                 }
228
229         },
230
231         hasEventListener: function ( type, listener ) {
232
233                 if ( this._listeners === undefined ) return false;
234
235                 const listeners = this._listeners;
236
237                 return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
238
239         },
240
241         removeEventListener: function ( type, listener ) {
242
243                 if ( this._listeners === undefined ) return;
244
245                 const listeners = this._listeners;
246                 const listenerArray = listeners[ type ];
247
248                 if ( listenerArray !== undefined ) {
249
250                         const index = listenerArray.indexOf( listener );
251
252                         if ( index !== - 1 ) {
253
254                                 listenerArray.splice( index, 1 );
255
256                         }
257
258                 }
259
260         },
261
262         dispatchEvent: function ( event ) {
263
264                 if ( this._listeners === undefined ) return;
265
266                 const listeners = this._listeners;
267                 const listenerArray = listeners[ event.type ];
268
269                 if ( listenerArray !== undefined ) {
270
271                         event.target = this;
272
273                         // Make a copy, in case listeners are removed while iterating.
274                         const array = listenerArray.slice( 0 );
275
276                         for ( let i = 0, l = array.length; i < l; i ++ ) {
277
278                                 array[ i ].call( this, event );
279
280                         }
281
282                 }
283
284         }
285
286 } );
287
288 const _lut = [];
289
290 for ( let i = 0; i < 256; i ++ ) {
291
292         _lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
293
294 }
295
296 let _seed = 1234567;
297
298 const MathUtils = {
299
300         DEG2RAD: Math.PI / 180,
301         RAD2DEG: 180 / Math.PI,
302
303         generateUUID: function () {
304
305                 // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
306
307                 const d0 = Math.random() * 0xffffffff | 0;
308                 const d1 = Math.random() * 0xffffffff | 0;
309                 const d2 = Math.random() * 0xffffffff | 0;
310                 const d3 = Math.random() * 0xffffffff | 0;
311                 const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
312                         _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
313                         _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
314                         _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
315
316                 // .toUpperCase() here flattens concatenated strings to save heap memory space.
317                 return uuid.toUpperCase();
318
319         },
320
321         clamp: function ( value, min, max ) {
322
323                 return Math.max( min, Math.min( max, value ) );
324
325         },
326
327         // compute euclidian modulo of m % n
328         // https://en.wikipedia.org/wiki/Modulo_operation
329
330         euclideanModulo: function ( n, m ) {
331
332                 return ( ( n % m ) + m ) % m;
333
334         },
335
336         // Linear mapping from range <a1, a2> to range <b1, b2>
337
338         mapLinear: function ( x, a1, a2, b1, b2 ) {
339
340                 return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
341
342         },
343
344         // https://en.wikipedia.org/wiki/Linear_interpolation
345
346         lerp: function ( x, y, t ) {
347
348                 return ( 1 - t ) * x + t * y;
349
350         },
351
352         // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
353
354         damp: function ( x, y, lambda, dt ) {
355
356                 return MathUtils.lerp( x, y, 1 - Math.exp( - lambda * dt ) );
357
358         },
359
360         // https://www.desmos.com/calculator/vcsjnyz7x4
361
362         pingpong: function ( x, length = 1 ) {
363
364                 return length - Math.abs( MathUtils.euclideanModulo( x, length * 2 ) - length );
365
366         },
367
368         // http://en.wikipedia.org/wiki/Smoothstep
369
370         smoothstep: function ( x, min, max ) {
371
372                 if ( x <= min ) return 0;
373                 if ( x >= max ) return 1;
374
375                 x = ( x - min ) / ( max - min );
376
377                 return x * x * ( 3 - 2 * x );
378
379         },
380
381         smootherstep: function ( x, min, max ) {
382
383                 if ( x <= min ) return 0;
384                 if ( x >= max ) return 1;
385
386                 x = ( x - min ) / ( max - min );
387
388                 return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
389
390         },
391
392         // Random integer from <low, high> interval
393
394         randInt: function ( low, high ) {
395
396                 return low + Math.floor( Math.random() * ( high - low + 1 ) );
397
398         },
399
400         // Random float from <low, high> interval
401
402         randFloat: function ( low, high ) {
403
404                 return low + Math.random() * ( high - low );
405
406         },
407
408         // Random float from <-range/2, range/2> interval
409
410         randFloatSpread: function ( range ) {
411
412                 return range * ( 0.5 - Math.random() );
413
414         },
415
416         // Deterministic pseudo-random float in the interval [ 0, 1 ]
417
418         seededRandom: function ( s ) {
419
420                 if ( s !== undefined ) _seed = s % 2147483647;
421
422                 // Park-Miller algorithm
423
424                 _seed = _seed * 16807 % 2147483647;
425
426                 return ( _seed - 1 ) / 2147483646;
427
428         },
429
430         degToRad: function ( degrees ) {
431
432                 return degrees * MathUtils.DEG2RAD;
433
434         },
435
436         radToDeg: function ( radians ) {
437
438                 return radians * MathUtils.RAD2DEG;
439
440         },
441
442         isPowerOfTwo: function ( value ) {
443
444                 return ( value & ( value - 1 ) ) === 0 && value !== 0;
445
446         },
447
448         ceilPowerOfTwo: function ( value ) {
449
450                 return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
451
452         },
453
454         floorPowerOfTwo: function ( value ) {
455
456                 return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
457
458         },
459
460         setQuaternionFromProperEuler: function ( q, a, b, c, order ) {
461
462                 // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
463
464                 // rotations are applied to the axes in the order specified by 'order'
465                 // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
466                 // angles are in radians
467
468                 const cos = Math.cos;
469                 const sin = Math.sin;
470
471                 const c2 = cos( b / 2 );
472                 const s2 = sin( b / 2 );
473
474                 const c13 = cos( ( a + c ) / 2 );
475                 const s13 = sin( ( a + c ) / 2 );
476
477                 const c1_3 = cos( ( a - c ) / 2 );
478                 const s1_3 = sin( ( a - c ) / 2 );
479
480                 const c3_1 = cos( ( c - a ) / 2 );
481                 const s3_1 = sin( ( c - a ) / 2 );
482
483                 switch ( order ) {
484
485                         case 'XYX':
486                                 q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
487                                 break;
488
489                         case 'YZY':
490                                 q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
491                                 break;
492
493                         case 'ZXZ':
494                                 q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
495                                 break;
496
497                         case 'XZX':
498                                 q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
499                                 break;
500
501                         case 'YXY':
502                                 q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
503                                 break;
504
505                         case 'ZYZ':
506                                 q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
507                                 break;
508
509                         default:
510                                 console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
511
512                 }
513
514         }
515
516 };
517
518 class Vector2 {
519
520         constructor( x = 0, y = 0 ) {
521
522                 Object.defineProperty( this, 'isVector2', { value: true } );
523
524                 this.x = x;
525                 this.y = y;
526
527         }
528
529         get width() {
530
531                 return this.x;
532
533         }
534
535         set width( value ) {
536
537                 this.x = value;
538
539         }
540
541         get height() {
542
543                 return this.y;
544
545         }
546
547         set height( value ) {
548
549                 this.y = value;
550
551         }
552
553         set( x, y ) {
554
555                 this.x = x;
556                 this.y = y;
557
558                 return this;
559
560         }
561
562         setScalar( scalar ) {
563
564                 this.x = scalar;
565                 this.y = scalar;
566
567                 return this;
568
569         }
570
571         setX( x ) {
572
573                 this.x = x;
574
575                 return this;
576
577         }
578
579         setY( y ) {
580
581                 this.y = y;
582
583                 return this;
584
585         }
586
587         setComponent( index, value ) {
588
589                 switch ( index ) {
590
591                         case 0: this.x = value; break;
592                         case 1: this.y = value; break;
593                         default: throw new Error( 'index is out of range: ' + index );
594
595                 }
596
597                 return this;
598
599         }
600
601         getComponent( index ) {
602
603                 switch ( index ) {
604
605                         case 0: return this.x;
606                         case 1: return this.y;
607                         default: throw new Error( 'index is out of range: ' + index );
608
609                 }
610
611         }
612
613         clone() {
614
615                 return new this.constructor( this.x, this.y );
616
617         }
618
619         copy( v ) {
620
621                 this.x = v.x;
622                 this.y = v.y;
623
624                 return this;
625
626         }
627
628         add( v, w ) {
629
630                 if ( w !== undefined ) {
631
632                         console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
633                         return this.addVectors( v, w );
634
635                 }
636
637                 this.x += v.x;
638                 this.y += v.y;
639
640                 return this;
641
642         }
643
644         addScalar( s ) {
645
646                 this.x += s;
647                 this.y += s;
648
649                 return this;
650
651         }
652
653         addVectors( a, b ) {
654
655                 this.x = a.x + b.x;
656                 this.y = a.y + b.y;
657
658                 return this;
659
660         }
661
662         addScaledVector( v, s ) {
663
664                 this.x += v.x * s;
665                 this.y += v.y * s;
666
667                 return this;
668
669         }
670
671         sub( v, w ) {
672
673                 if ( w !== undefined ) {
674
675                         console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
676                         return this.subVectors( v, w );
677
678                 }
679
680                 this.x -= v.x;
681                 this.y -= v.y;
682
683                 return this;
684
685         }
686
687         subScalar( s ) {
688
689                 this.x -= s;
690                 this.y -= s;
691
692                 return this;
693
694         }
695
696         subVectors( a, b ) {
697
698                 this.x = a.x - b.x;
699                 this.y = a.y - b.y;
700
701                 return this;
702
703         }
704
705         multiply( v ) {
706
707                 this.x *= v.x;
708                 this.y *= v.y;
709
710                 return this;
711
712         }
713
714         multiplyScalar( scalar ) {
715
716                 this.x *= scalar;
717                 this.y *= scalar;
718
719                 return this;
720
721         }
722
723         divide( v ) {
724
725                 this.x /= v.x;
726                 this.y /= v.y;
727
728                 return this;
729
730         }
731
732         divideScalar( scalar ) {
733
734                 return this.multiplyScalar( 1 / scalar );
735
736         }
737
738         applyMatrix3( m ) {
739
740                 const x = this.x, y = this.y;
741                 const e = m.elements;
742
743                 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
744                 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
745
746                 return this;
747
748         }
749
750         min( v ) {
751
752                 this.x = Math.min( this.x, v.x );
753                 this.y = Math.min( this.y, v.y );
754
755                 return this;
756
757         }
758
759         max( v ) {
760
761                 this.x = Math.max( this.x, v.x );
762                 this.y = Math.max( this.y, v.y );
763
764                 return this;
765
766         }
767
768         clamp( min, max ) {
769
770                 // assumes min < max, componentwise
771
772                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
773                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
774
775                 return this;
776
777         }
778
779         clampScalar( minVal, maxVal ) {
780
781                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
782                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
783
784                 return this;
785
786         }
787
788         clampLength( min, max ) {
789
790                 const length = this.length();
791
792                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
793
794         }
795
796         floor() {
797
798                 this.x = Math.floor( this.x );
799                 this.y = Math.floor( this.y );
800
801                 return this;
802
803         }
804
805         ceil() {
806
807                 this.x = Math.ceil( this.x );
808                 this.y = Math.ceil( this.y );
809
810                 return this;
811
812         }
813
814         round() {
815
816                 this.x = Math.round( this.x );
817                 this.y = Math.round( this.y );
818
819                 return this;
820
821         }
822
823         roundToZero() {
824
825                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
826                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
827
828                 return this;
829
830         }
831
832         negate() {
833
834                 this.x = - this.x;
835                 this.y = - this.y;
836
837                 return this;
838
839         }
840
841         dot( v ) {
842
843                 return this.x * v.x + this.y * v.y;
844
845         }
846
847         cross( v ) {
848
849                 return this.x * v.y - this.y * v.x;
850
851         }
852
853         lengthSq() {
854
855                 return this.x * this.x + this.y * this.y;
856
857         }
858
859         length() {
860
861                 return Math.sqrt( this.x * this.x + this.y * this.y );
862
863         }
864
865         manhattanLength() {
866
867                 return Math.abs( this.x ) + Math.abs( this.y );
868
869         }
870
871         normalize() {
872
873                 return this.divideScalar( this.length() || 1 );
874
875         }
876
877         angle() {
878
879                 // computes the angle in radians with respect to the positive x-axis
880
881                 const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
882
883                 return angle;
884
885         }
886
887         distanceTo( v ) {
888
889                 return Math.sqrt( this.distanceToSquared( v ) );
890
891         }
892
893         distanceToSquared( v ) {
894
895                 const dx = this.x - v.x, dy = this.y - v.y;
896                 return dx * dx + dy * dy;
897
898         }
899
900         manhattanDistanceTo( v ) {
901
902                 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
903
904         }
905
906         setLength( length ) {
907
908                 return this.normalize().multiplyScalar( length );
909
910         }
911
912         lerp( v, alpha ) {
913
914                 this.x += ( v.x - this.x ) * alpha;
915                 this.y += ( v.y - this.y ) * alpha;
916
917                 return this;
918
919         }
920
921         lerpVectors( v1, v2, alpha ) {
922
923                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
924                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
925
926                 return this;
927
928         }
929
930         equals( v ) {
931
932                 return ( ( v.x === this.x ) && ( v.y === this.y ) );
933
934         }
935
936         fromArray( array, offset = 0 ) {
937
938                 this.x = array[ offset ];
939                 this.y = array[ offset + 1 ];
940
941                 return this;
942
943         }
944
945         toArray( array = [], offset = 0 ) {
946
947                 array[ offset ] = this.x;
948                 array[ offset + 1 ] = this.y;
949
950                 return array;
951
952         }
953
954         fromBufferAttribute( attribute, index, offset ) {
955
956                 if ( offset !== undefined ) {
957
958                         console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
959
960                 }
961
962                 this.x = attribute.getX( index );
963                 this.y = attribute.getY( index );
964
965                 return this;
966
967         }
968
969         rotateAround( center, angle ) {
970
971                 const c = Math.cos( angle ), s = Math.sin( angle );
972
973                 const x = this.x - center.x;
974                 const y = this.y - center.y;
975
976                 this.x = x * c - y * s + center.x;
977                 this.y = x * s + y * c + center.y;
978
979                 return this;
980
981         }
982
983         random() {
984
985                 this.x = Math.random();
986                 this.y = Math.random();
987
988                 return this;
989
990         }
991
992 }
993
994 class Matrix3 {
995
996         constructor() {
997
998                 Object.defineProperty( this, 'isMatrix3', { value: true } );
999
1000                 this.elements = [
1001
1002                         1, 0, 0,
1003                         0, 1, 0,
1004                         0, 0, 1
1005
1006                 ];
1007
1008                 if ( arguments.length > 0 ) {
1009
1010                         console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
1011
1012                 }
1013
1014         }
1015
1016         set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
1017
1018                 const te = this.elements;
1019
1020                 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
1021                 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
1022                 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
1023
1024                 return this;
1025
1026         }
1027
1028         identity() {
1029
1030                 this.set(
1031
1032                         1, 0, 0,
1033                         0, 1, 0,
1034                         0, 0, 1
1035
1036                 );
1037
1038                 return this;
1039
1040         }
1041
1042         clone() {
1043
1044                 return new this.constructor().fromArray( this.elements );
1045
1046         }
1047
1048         copy( m ) {
1049
1050                 const te = this.elements;
1051                 const me = m.elements;
1052
1053                 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
1054                 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
1055                 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
1056
1057                 return this;
1058
1059         }
1060
1061         extractBasis( xAxis, yAxis, zAxis ) {
1062
1063                 xAxis.setFromMatrix3Column( this, 0 );
1064                 yAxis.setFromMatrix3Column( this, 1 );
1065                 zAxis.setFromMatrix3Column( this, 2 );
1066
1067                 return this;
1068
1069         }
1070
1071         setFromMatrix4( m ) {
1072
1073                 const me = m.elements;
1074
1075                 this.set(
1076
1077                         me[ 0 ], me[ 4 ], me[ 8 ],
1078                         me[ 1 ], me[ 5 ], me[ 9 ],
1079                         me[ 2 ], me[ 6 ], me[ 10 ]
1080
1081                 );
1082
1083                 return this;
1084
1085         }
1086
1087         multiply( m ) {
1088
1089                 return this.multiplyMatrices( this, m );
1090
1091         }
1092
1093         premultiply( m ) {
1094
1095                 return this.multiplyMatrices( m, this );
1096
1097         }
1098
1099         multiplyMatrices( a, b ) {
1100
1101                 const ae = a.elements;
1102                 const be = b.elements;
1103                 const te = this.elements;
1104
1105                 const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
1106                 const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
1107                 const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
1108
1109                 const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
1110                 const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
1111                 const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
1112
1113                 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
1114                 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
1115                 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
1116
1117                 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
1118                 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
1119                 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
1120
1121                 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
1122                 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
1123                 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
1124
1125                 return this;
1126
1127         }
1128
1129         multiplyScalar( s ) {
1130
1131                 const te = this.elements;
1132
1133                 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
1134                 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
1135                 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
1136
1137                 return this;
1138
1139         }
1140
1141         determinant() {
1142
1143                 const te = this.elements;
1144
1145                 const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
1146                         d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
1147                         g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
1148
1149                 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
1150
1151         }
1152
1153         invert() {
1154
1155                 const te = this.elements,
1156
1157                         n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
1158                         n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
1159                         n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
1160
1161                         t11 = n33 * n22 - n32 * n23,
1162                         t12 = n32 * n13 - n33 * n12,
1163                         t13 = n23 * n12 - n22 * n13,
1164
1165                         det = n11 * t11 + n21 * t12 + n31 * t13;
1166
1167                 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
1168
1169                 const detInv = 1 / det;
1170
1171                 te[ 0 ] = t11 * detInv;
1172                 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
1173                 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
1174
1175                 te[ 3 ] = t12 * detInv;
1176                 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
1177                 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
1178
1179                 te[ 6 ] = t13 * detInv;
1180                 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
1181                 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
1182
1183                 return this;
1184
1185         }
1186
1187         transpose() {
1188
1189                 let tmp;
1190                 const m = this.elements;
1191
1192                 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
1193                 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
1194                 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
1195
1196                 return this;
1197
1198         }
1199
1200         getNormalMatrix( matrix4 ) {
1201
1202                 return this.setFromMatrix4( matrix4 ).copy( this ).invert().transpose();
1203
1204         }
1205
1206         transposeIntoArray( r ) {
1207
1208                 const m = this.elements;
1209
1210                 r[ 0 ] = m[ 0 ];
1211                 r[ 1 ] = m[ 3 ];
1212                 r[ 2 ] = m[ 6 ];
1213                 r[ 3 ] = m[ 1 ];
1214                 r[ 4 ] = m[ 4 ];
1215                 r[ 5 ] = m[ 7 ];
1216                 r[ 6 ] = m[ 2 ];
1217                 r[ 7 ] = m[ 5 ];
1218                 r[ 8 ] = m[ 8 ];
1219
1220                 return this;
1221
1222         }
1223
1224         setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
1225
1226                 const c = Math.cos( rotation );
1227                 const s = Math.sin( rotation );
1228
1229                 this.set(
1230                         sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
1231                         - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
1232                         0, 0, 1
1233                 );
1234
1235                 return this;
1236
1237         }
1238
1239         scale( sx, sy ) {
1240
1241                 const te = this.elements;
1242
1243                 te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
1244                 te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
1245
1246                 return this;
1247
1248         }
1249
1250         rotate( theta ) {
1251
1252                 const c = Math.cos( theta );
1253                 const s = Math.sin( theta );
1254
1255                 const te = this.elements;
1256
1257                 const a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
1258                 const a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
1259
1260                 te[ 0 ] = c * a11 + s * a21;
1261                 te[ 3 ] = c * a12 + s * a22;
1262                 te[ 6 ] = c * a13 + s * a23;
1263
1264                 te[ 1 ] = - s * a11 + c * a21;
1265                 te[ 4 ] = - s * a12 + c * a22;
1266                 te[ 7 ] = - s * a13 + c * a23;
1267
1268                 return this;
1269
1270         }
1271
1272         translate( tx, ty ) {
1273
1274                 const te = this.elements;
1275
1276                 te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
1277                 te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
1278
1279                 return this;
1280
1281         }
1282
1283         equals( matrix ) {
1284
1285                 const te = this.elements;
1286                 const me = matrix.elements;
1287
1288                 for ( let i = 0; i < 9; i ++ ) {
1289
1290                         if ( te[ i ] !== me[ i ] ) return false;
1291
1292                 }
1293
1294                 return true;
1295
1296         }
1297
1298         fromArray( array, offset = 0 ) {
1299
1300                 for ( let i = 0; i < 9; i ++ ) {
1301
1302                         this.elements[ i ] = array[ i + offset ];
1303
1304                 }
1305
1306                 return this;
1307
1308         }
1309
1310         toArray( array = [], offset = 0 ) {
1311
1312                 const te = this.elements;
1313
1314                 array[ offset ] = te[ 0 ];
1315                 array[ offset + 1 ] = te[ 1 ];
1316                 array[ offset + 2 ] = te[ 2 ];
1317
1318                 array[ offset + 3 ] = te[ 3 ];
1319                 array[ offset + 4 ] = te[ 4 ];
1320                 array[ offset + 5 ] = te[ 5 ];
1321
1322                 array[ offset + 6 ] = te[ 6 ];
1323                 array[ offset + 7 ] = te[ 7 ];
1324                 array[ offset + 8 ] = te[ 8 ];
1325
1326                 return array;
1327
1328         }
1329
1330 }
1331
1332 let _canvas;
1333
1334 const ImageUtils = {
1335
1336         getDataURL: function ( image ) {
1337
1338                 if ( /^data:/i.test( image.src ) ) {
1339
1340                         return image.src;
1341
1342                 }
1343
1344                 if ( typeof HTMLCanvasElement == 'undefined' ) {
1345
1346                         return image.src;
1347
1348                 }
1349
1350                 let canvas;
1351
1352                 if ( image instanceof HTMLCanvasElement ) {
1353
1354                         canvas = image;
1355
1356                 } else {
1357
1358                         if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
1359
1360                         _canvas.width = image.width;
1361                         _canvas.height = image.height;
1362
1363                         const context = _canvas.getContext( '2d' );
1364
1365                         if ( image instanceof ImageData ) {
1366
1367                                 context.putImageData( image, 0, 0 );
1368
1369                         } else {
1370
1371                                 context.drawImage( image, 0, 0, image.width, image.height );
1372
1373                         }
1374
1375                         canvas = _canvas;
1376
1377                 }
1378
1379                 if ( canvas.width > 2048 || canvas.height > 2048 ) {
1380
1381                         return canvas.toDataURL( 'image/jpeg', 0.6 );
1382
1383                 } else {
1384
1385                         return canvas.toDataURL( 'image/png' );
1386
1387                 }
1388
1389         }
1390
1391 };
1392
1393 let textureId = 0;
1394
1395 function Texture( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding ) {
1396
1397         Object.defineProperty( this, 'id', { value: textureId ++ } );
1398
1399         this.uuid = MathUtils.generateUUID();
1400
1401         this.name = '';
1402
1403         this.image = image;
1404         this.mipmaps = [];
1405
1406         this.mapping = mapping;
1407
1408         this.wrapS = wrapS;
1409         this.wrapT = wrapT;
1410
1411         this.magFilter = magFilter;
1412         this.minFilter = minFilter;
1413
1414         this.anisotropy = anisotropy;
1415
1416         this.format = format;
1417         this.internalFormat = null;
1418         this.type = type;
1419
1420         this.offset = new Vector2( 0, 0 );
1421         this.repeat = new Vector2( 1, 1 );
1422         this.center = new Vector2( 0, 0 );
1423         this.rotation = 0;
1424
1425         this.matrixAutoUpdate = true;
1426         this.matrix = new Matrix3();
1427
1428         this.generateMipmaps = true;
1429         this.premultiplyAlpha = false;
1430         this.flipY = true;
1431         this.unpackAlignment = 4;       // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
1432
1433         // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
1434         //
1435         // Also changing the encoding after already used by a Material will not automatically make the Material
1436         // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
1437         this.encoding = encoding;
1438
1439         this.version = 0;
1440         this.onUpdate = null;
1441
1442 }
1443
1444 Texture.DEFAULT_IMAGE = undefined;
1445 Texture.DEFAULT_MAPPING = UVMapping;
1446
1447 Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
1448
1449         constructor: Texture,
1450
1451         isTexture: true,
1452
1453         updateMatrix: function () {
1454
1455                 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
1456
1457         },
1458
1459         clone: function () {
1460
1461                 return new this.constructor().copy( this );
1462
1463         },
1464
1465         copy: function ( source ) {
1466
1467                 this.name = source.name;
1468
1469                 this.image = source.image;
1470                 this.mipmaps = source.mipmaps.slice( 0 );
1471
1472                 this.mapping = source.mapping;
1473
1474                 this.wrapS = source.wrapS;
1475                 this.wrapT = source.wrapT;
1476
1477                 this.magFilter = source.magFilter;
1478                 this.minFilter = source.minFilter;
1479
1480                 this.anisotropy = source.anisotropy;
1481
1482                 this.format = source.format;
1483                 this.internalFormat = source.internalFormat;
1484                 this.type = source.type;
1485
1486                 this.offset.copy( source.offset );
1487                 this.repeat.copy( source.repeat );
1488                 this.center.copy( source.center );
1489                 this.rotation = source.rotation;
1490
1491                 this.matrixAutoUpdate = source.matrixAutoUpdate;
1492                 this.matrix.copy( source.matrix );
1493
1494                 this.generateMipmaps = source.generateMipmaps;
1495                 this.premultiplyAlpha = source.premultiplyAlpha;
1496                 this.flipY = source.flipY;
1497                 this.unpackAlignment = source.unpackAlignment;
1498                 this.encoding = source.encoding;
1499
1500                 return this;
1501
1502         },
1503
1504         toJSON: function ( meta ) {
1505
1506                 const isRootObject = ( meta === undefined || typeof meta === 'string' );
1507
1508                 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
1509
1510                         return meta.textures[ this.uuid ];
1511
1512                 }
1513
1514                 const output = {
1515
1516                         metadata: {
1517                                 version: 4.5,
1518                                 type: 'Texture',
1519                                 generator: 'Texture.toJSON'
1520                         },
1521
1522                         uuid: this.uuid,
1523                         name: this.name,
1524
1525                         mapping: this.mapping,
1526
1527                         repeat: [ this.repeat.x, this.repeat.y ],
1528                         offset: [ this.offset.x, this.offset.y ],
1529                         center: [ this.center.x, this.center.y ],
1530                         rotation: this.rotation,
1531
1532                         wrap: [ this.wrapS, this.wrapT ],
1533
1534                         format: this.format,
1535                         type: this.type,
1536                         encoding: this.encoding,
1537
1538                         minFilter: this.minFilter,
1539                         magFilter: this.magFilter,
1540                         anisotropy: this.anisotropy,
1541
1542                         flipY: this.flipY,
1543
1544                         premultiplyAlpha: this.premultiplyAlpha,
1545                         unpackAlignment: this.unpackAlignment
1546
1547                 };
1548
1549                 if ( this.image !== undefined ) {
1550
1551                         // TODO: Move to THREE.Image
1552
1553                         const image = this.image;
1554
1555                         if ( image.uuid === undefined ) {
1556
1557                                 image.uuid = MathUtils.generateUUID(); // UGH
1558
1559                         }
1560
1561                         if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
1562
1563                                 let url;
1564
1565                                 if ( Array.isArray( image ) ) {
1566
1567                                         // process array of images e.g. CubeTexture
1568
1569                                         url = [];
1570
1571                                         for ( let i = 0, l = image.length; i < l; i ++ ) {
1572
1573                                                 // check cube texture with data textures
1574
1575                                                 if ( image[ i ].isDataTexture ) {
1576
1577                                                         url.push( serializeImage( image[ i ].image ) );
1578
1579                                                 } else {
1580
1581                                                         url.push( serializeImage( image[ i ] ) );
1582
1583                                                 }
1584
1585                                         }
1586
1587                                 } else {
1588
1589                                         // process single image
1590
1591                                         url = serializeImage( image );
1592
1593                                 }
1594
1595                                 meta.images[ image.uuid ] = {
1596                                         uuid: image.uuid,
1597                                         url: url
1598                                 };
1599
1600                         }
1601
1602                         output.image = image.uuid;
1603
1604                 }
1605
1606                 if ( ! isRootObject ) {
1607
1608                         meta.textures[ this.uuid ] = output;
1609
1610                 }
1611
1612                 return output;
1613
1614         },
1615
1616         dispose: function () {
1617
1618                 this.dispatchEvent( { type: 'dispose' } );
1619
1620         },
1621
1622         transformUv: function ( uv ) {
1623
1624                 if ( this.mapping !== UVMapping ) return uv;
1625
1626                 uv.applyMatrix3( this.matrix );
1627
1628                 if ( uv.x < 0 || uv.x > 1 ) {
1629
1630                         switch ( this.wrapS ) {
1631
1632                                 case RepeatWrapping:
1633
1634                                         uv.x = uv.x - Math.floor( uv.x );
1635                                         break;
1636
1637                                 case ClampToEdgeWrapping:
1638
1639                                         uv.x = uv.x < 0 ? 0 : 1;
1640                                         break;
1641
1642                                 case MirroredRepeatWrapping:
1643
1644                                         if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
1645
1646                                                 uv.x = Math.ceil( uv.x ) - uv.x;
1647
1648                                         } else {
1649
1650                                                 uv.x = uv.x - Math.floor( uv.x );
1651
1652                                         }
1653
1654                                         break;
1655
1656                         }
1657
1658                 }
1659
1660                 if ( uv.y < 0 || uv.y > 1 ) {
1661
1662                         switch ( this.wrapT ) {
1663
1664                                 case RepeatWrapping:
1665
1666                                         uv.y = uv.y - Math.floor( uv.y );
1667                                         break;
1668
1669                                 case ClampToEdgeWrapping:
1670
1671                                         uv.y = uv.y < 0 ? 0 : 1;
1672                                         break;
1673
1674                                 case MirroredRepeatWrapping:
1675
1676                                         if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
1677
1678                                                 uv.y = Math.ceil( uv.y ) - uv.y;
1679
1680                                         } else {
1681
1682                                                 uv.y = uv.y - Math.floor( uv.y );
1683
1684                                         }
1685
1686                                         break;
1687
1688                         }
1689
1690                 }
1691
1692                 if ( this.flipY ) {
1693
1694                         uv.y = 1 - uv.y;
1695
1696                 }
1697
1698                 return uv;
1699
1700         }
1701
1702 } );
1703
1704 Object.defineProperty( Texture.prototype, 'needsUpdate', {
1705
1706         set: function ( value ) {
1707
1708                 if ( value === true ) this.version ++;
1709
1710         }
1711
1712 } );
1713
1714 function serializeImage( image ) {
1715
1716         if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
1717                 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
1718                 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
1719
1720                 // default images
1721
1722                 return ImageUtils.getDataURL( image );
1723
1724         } else {
1725
1726                 if ( image.data ) {
1727
1728                         // images of DataTexture
1729
1730                         return {
1731                                 data: Array.prototype.slice.call( image.data ),
1732                                 width: image.width,
1733                                 height: image.height,
1734                                 type: image.data.constructor.name
1735                         };
1736
1737                 } else {
1738
1739                         console.warn( 'THREE.Texture: Unable to serialize Texture.' );
1740                         return {};
1741
1742                 }
1743
1744         }
1745
1746 }
1747
1748 class Vector4 {
1749
1750         constructor( x = 0, y = 0, z = 0, w = 1 ) {
1751
1752                 Object.defineProperty( this, 'isVector4', { value: true } );
1753
1754                 this.x = x;
1755                 this.y = y;
1756                 this.z = z;
1757                 this.w = w;
1758
1759         }
1760
1761         get width() {
1762
1763                 return this.z;
1764
1765         }
1766
1767         set width( value ) {
1768
1769                 this.z = value;
1770
1771         }
1772
1773         get height() {
1774
1775                 return this.w;
1776
1777         }
1778
1779         set height( value ) {
1780
1781                 this.w = value;
1782
1783         }
1784
1785         set( x, y, z, w ) {
1786
1787                 this.x = x;
1788                 this.y = y;
1789                 this.z = z;
1790                 this.w = w;
1791
1792                 return this;
1793
1794         }
1795
1796         setScalar( scalar ) {
1797
1798                 this.x = scalar;
1799                 this.y = scalar;
1800                 this.z = scalar;
1801                 this.w = scalar;
1802
1803                 return this;
1804
1805         }
1806
1807         setX( x ) {
1808
1809                 this.x = x;
1810
1811                 return this;
1812
1813         }
1814
1815         setY( y ) {
1816
1817                 this.y = y;
1818
1819                 return this;
1820
1821         }
1822
1823         setZ( z ) {
1824
1825                 this.z = z;
1826
1827                 return this;
1828
1829         }
1830
1831         setW( w ) {
1832
1833                 this.w = w;
1834
1835                 return this;
1836
1837         }
1838
1839         setComponent( index, value ) {
1840
1841                 switch ( index ) {
1842
1843                         case 0: this.x = value; break;
1844                         case 1: this.y = value; break;
1845                         case 2: this.z = value; break;
1846                         case 3: this.w = value; break;
1847                         default: throw new Error( 'index is out of range: ' + index );
1848
1849                 }
1850
1851                 return this;
1852
1853         }
1854
1855         getComponent( index ) {
1856
1857                 switch ( index ) {
1858
1859                         case 0: return this.x;
1860                         case 1: return this.y;
1861                         case 2: return this.z;
1862                         case 3: return this.w;
1863                         default: throw new Error( 'index is out of range: ' + index );
1864
1865                 }
1866
1867         }
1868
1869         clone() {
1870
1871                 return new this.constructor( this.x, this.y, this.z, this.w );
1872
1873         }
1874
1875         copy( v ) {
1876
1877                 this.x = v.x;
1878                 this.y = v.y;
1879                 this.z = v.z;
1880                 this.w = ( v.w !== undefined ) ? v.w : 1;
1881
1882                 return this;
1883
1884         }
1885
1886         add( v, w ) {
1887
1888                 if ( w !== undefined ) {
1889
1890                         console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
1891                         return this.addVectors( v, w );
1892
1893                 }
1894
1895                 this.x += v.x;
1896                 this.y += v.y;
1897                 this.z += v.z;
1898                 this.w += v.w;
1899
1900                 return this;
1901
1902         }
1903
1904         addScalar( s ) {
1905
1906                 this.x += s;
1907                 this.y += s;
1908                 this.z += s;
1909                 this.w += s;
1910
1911                 return this;
1912
1913         }
1914
1915         addVectors( a, b ) {
1916
1917                 this.x = a.x + b.x;
1918                 this.y = a.y + b.y;
1919                 this.z = a.z + b.z;
1920                 this.w = a.w + b.w;
1921
1922                 return this;
1923
1924         }
1925
1926         addScaledVector( v, s ) {
1927
1928                 this.x += v.x * s;
1929                 this.y += v.y * s;
1930                 this.z += v.z * s;
1931                 this.w += v.w * s;
1932
1933                 return this;
1934
1935         }
1936
1937         sub( v, w ) {
1938
1939                 if ( w !== undefined ) {
1940
1941                         console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
1942                         return this.subVectors( v, w );
1943
1944                 }
1945
1946                 this.x -= v.x;
1947                 this.y -= v.y;
1948                 this.z -= v.z;
1949                 this.w -= v.w;
1950
1951                 return this;
1952
1953         }
1954
1955         subScalar( s ) {
1956
1957                 this.x -= s;
1958                 this.y -= s;
1959                 this.z -= s;
1960                 this.w -= s;
1961
1962                 return this;
1963
1964         }
1965
1966         subVectors( a, b ) {
1967
1968                 this.x = a.x - b.x;
1969                 this.y = a.y - b.y;
1970                 this.z = a.z - b.z;
1971                 this.w = a.w - b.w;
1972
1973                 return this;
1974
1975         }
1976
1977         multiply( v ) {
1978
1979                 this.x *= v.x;
1980                 this.y *= v.y;
1981                 this.z *= v.z;
1982                 this.w *= v.w;
1983
1984                 return this;
1985
1986         }
1987
1988         multiplyScalar( scalar ) {
1989
1990                 this.x *= scalar;
1991                 this.y *= scalar;
1992                 this.z *= scalar;
1993                 this.w *= scalar;
1994
1995                 return this;
1996
1997         }
1998
1999         applyMatrix4( m ) {
2000
2001                 const x = this.x, y = this.y, z = this.z, w = this.w;
2002                 const e = m.elements;
2003
2004                 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
2005                 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
2006                 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
2007                 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
2008
2009                 return this;
2010
2011         }
2012
2013         divideScalar( scalar ) {
2014
2015                 return this.multiplyScalar( 1 / scalar );
2016
2017         }
2018
2019         setAxisAngleFromQuaternion( q ) {
2020
2021                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
2022
2023                 // q is assumed to be normalized
2024
2025                 this.w = 2 * Math.acos( q.w );
2026
2027                 const s = Math.sqrt( 1 - q.w * q.w );
2028
2029                 if ( s < 0.0001 ) {
2030
2031                         this.x = 1;
2032                         this.y = 0;
2033                         this.z = 0;
2034
2035                 } else {
2036
2037                         this.x = q.x / s;
2038                         this.y = q.y / s;
2039                         this.z = q.z / s;
2040
2041                 }
2042
2043                 return this;
2044
2045         }
2046
2047         setAxisAngleFromRotationMatrix( m ) {
2048
2049                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
2050
2051                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2052
2053                 let angle, x, y, z; // variables for result
2054                 const epsilon = 0.01,           // margin to allow for rounding errors
2055                         epsilon2 = 0.1,         // margin to distinguish between 0 and 180 degrees
2056
2057                         te = m.elements,
2058
2059                         m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2060                         m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2061                         m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
2062
2063                 if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
2064                      ( Math.abs( m13 - m31 ) < epsilon ) &&
2065                      ( Math.abs( m23 - m32 ) < epsilon ) ) {
2066
2067                         // singularity found
2068                         // first check for identity matrix which must have +1 for all terms
2069                         // in leading diagonal and zero in other terms
2070
2071                         if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
2072                              ( Math.abs( m13 + m31 ) < epsilon2 ) &&
2073                              ( Math.abs( m23 + m32 ) < epsilon2 ) &&
2074                              ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
2075
2076                                 // this singularity is identity matrix so angle = 0
2077
2078                                 this.set( 1, 0, 0, 0 );
2079
2080                                 return this; // zero angle, arbitrary axis
2081
2082                         }
2083
2084                         // otherwise this singularity is angle = 180
2085
2086                         angle = Math.PI;
2087
2088                         const xx = ( m11 + 1 ) / 2;
2089                         const yy = ( m22 + 1 ) / 2;
2090                         const zz = ( m33 + 1 ) / 2;
2091                         const xy = ( m12 + m21 ) / 4;
2092                         const xz = ( m13 + m31 ) / 4;
2093                         const yz = ( m23 + m32 ) / 4;
2094
2095                         if ( ( xx > yy ) && ( xx > zz ) ) {
2096
2097                                 // m11 is the largest diagonal term
2098
2099                                 if ( xx < epsilon ) {
2100
2101                                         x = 0;
2102                                         y = 0.707106781;
2103                                         z = 0.707106781;
2104
2105                                 } else {
2106
2107                                         x = Math.sqrt( xx );
2108                                         y = xy / x;
2109                                         z = xz / x;
2110
2111                                 }
2112
2113                         } else if ( yy > zz ) {
2114
2115                                 // m22 is the largest diagonal term
2116
2117                                 if ( yy < epsilon ) {
2118
2119                                         x = 0.707106781;
2120                                         y = 0;
2121                                         z = 0.707106781;
2122
2123                                 } else {
2124
2125                                         y = Math.sqrt( yy );
2126                                         x = xy / y;
2127                                         z = yz / y;
2128
2129                                 }
2130
2131                         } else {
2132
2133                                 // m33 is the largest diagonal term so base result on this
2134
2135                                 if ( zz < epsilon ) {
2136
2137                                         x = 0.707106781;
2138                                         y = 0.707106781;
2139                                         z = 0;
2140
2141                                 } else {
2142
2143                                         z = Math.sqrt( zz );
2144                                         x = xz / z;
2145                                         y = yz / z;
2146
2147                                 }
2148
2149                         }
2150
2151                         this.set( x, y, z, angle );
2152
2153                         return this; // return 180 deg rotation
2154
2155                 }
2156
2157                 // as we have reached here there are no singularities so we can handle normally
2158
2159                 let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
2160                         ( m13 - m31 ) * ( m13 - m31 ) +
2161                         ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
2162
2163                 if ( Math.abs( s ) < 0.001 ) s = 1;
2164
2165                 // prevent divide by zero, should not happen if matrix is orthogonal and should be
2166                 // caught by singularity test above, but I've left it in just in case
2167
2168                 this.x = ( m32 - m23 ) / s;
2169                 this.y = ( m13 - m31 ) / s;
2170                 this.z = ( m21 - m12 ) / s;
2171                 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
2172
2173                 return this;
2174
2175         }
2176
2177         min( v ) {
2178
2179                 this.x = Math.min( this.x, v.x );
2180                 this.y = Math.min( this.y, v.y );
2181                 this.z = Math.min( this.z, v.z );
2182                 this.w = Math.min( this.w, v.w );
2183
2184                 return this;
2185
2186         }
2187
2188         max( v ) {
2189
2190                 this.x = Math.max( this.x, v.x );
2191                 this.y = Math.max( this.y, v.y );
2192                 this.z = Math.max( this.z, v.z );
2193                 this.w = Math.max( this.w, v.w );
2194
2195                 return this;
2196
2197         }
2198
2199         clamp( min, max ) {
2200
2201                 // assumes min < max, componentwise
2202
2203                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2204                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2205                 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2206                 this.w = Math.max( min.w, Math.min( max.w, this.w ) );
2207
2208                 return this;
2209
2210         }
2211
2212         clampScalar( minVal, maxVal ) {
2213
2214                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
2215                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
2216                 this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
2217                 this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
2218
2219                 return this;
2220
2221         }
2222
2223         clampLength( min, max ) {
2224
2225                 const length = this.length();
2226
2227                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
2228
2229         }
2230
2231         floor() {
2232
2233                 this.x = Math.floor( this.x );
2234                 this.y = Math.floor( this.y );
2235                 this.z = Math.floor( this.z );
2236                 this.w = Math.floor( this.w );
2237
2238                 return this;
2239
2240         }
2241
2242         ceil() {
2243
2244                 this.x = Math.ceil( this.x );
2245                 this.y = Math.ceil( this.y );
2246                 this.z = Math.ceil( this.z );
2247                 this.w = Math.ceil( this.w );
2248
2249                 return this;
2250
2251         }
2252
2253         round() {
2254
2255                 this.x = Math.round( this.x );
2256                 this.y = Math.round( this.y );
2257                 this.z = Math.round( this.z );
2258                 this.w = Math.round( this.w );
2259
2260                 return this;
2261
2262         }
2263
2264         roundToZero() {
2265
2266                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
2267                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
2268                 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
2269                 this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
2270
2271                 return this;
2272
2273         }
2274
2275         negate() {
2276
2277                 this.x = - this.x;
2278                 this.y = - this.y;
2279                 this.z = - this.z;
2280                 this.w = - this.w;
2281
2282                 return this;
2283
2284         }
2285
2286         dot( v ) {
2287
2288                 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
2289
2290         }
2291
2292         lengthSq() {
2293
2294                 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
2295
2296         }
2297
2298         length() {
2299
2300                 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
2301
2302         }
2303
2304         manhattanLength() {
2305
2306                 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
2307
2308         }
2309
2310         normalize() {
2311
2312                 return this.divideScalar( this.length() || 1 );
2313
2314         }
2315
2316         setLength( length ) {
2317
2318                 return this.normalize().multiplyScalar( length );
2319
2320         }
2321
2322         lerp( v, alpha ) {
2323
2324                 this.x += ( v.x - this.x ) * alpha;
2325                 this.y += ( v.y - this.y ) * alpha;
2326                 this.z += ( v.z - this.z ) * alpha;
2327                 this.w += ( v.w - this.w ) * alpha;
2328
2329                 return this;
2330
2331         }
2332
2333         lerpVectors( v1, v2, alpha ) {
2334
2335                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
2336                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
2337                 this.z = v1.z + ( v2.z - v1.z ) * alpha;
2338                 this.w = v1.w + ( v2.w - v1.w ) * alpha;
2339
2340                 return this;
2341
2342         }
2343
2344         equals( v ) {
2345
2346                 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
2347
2348         }
2349
2350         fromArray( array, offset = 0 ) {
2351
2352                 this.x = array[ offset ];
2353                 this.y = array[ offset + 1 ];
2354                 this.z = array[ offset + 2 ];
2355                 this.w = array[ offset + 3 ];
2356
2357                 return this;
2358
2359         }
2360
2361         toArray( array = [], offset = 0 ) {
2362
2363                 array[ offset ] = this.x;
2364                 array[ offset + 1 ] = this.y;
2365                 array[ offset + 2 ] = this.z;
2366                 array[ offset + 3 ] = this.w;
2367
2368                 return array;
2369
2370         }
2371
2372         fromBufferAttribute( attribute, index, offset ) {
2373
2374                 if ( offset !== undefined ) {
2375
2376                         console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
2377
2378                 }
2379
2380                 this.x = attribute.getX( index );
2381                 this.y = attribute.getY( index );
2382                 this.z = attribute.getZ( index );
2383                 this.w = attribute.getW( index );
2384
2385                 return this;
2386
2387         }
2388
2389         random() {
2390
2391                 this.x = Math.random();
2392                 this.y = Math.random();
2393                 this.z = Math.random();
2394                 this.w = Math.random();
2395
2396                 return this;
2397
2398         }
2399
2400 }
2401
2402 /*
2403  In options, we can specify:
2404  * Texture parameters for an auto-generated target texture
2405  * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
2406 */
2407 class WebGLRenderTarget extends EventDispatcher {
2408
2409         constructor( width, height, options ) {
2410
2411                 super();
2412
2413                 Object.defineProperty( this, 'isWebGLRenderTarget', { value: true } );
2414
2415                 this.width = width;
2416                 this.height = height;
2417
2418                 this.scissor = new Vector4( 0, 0, width, height );
2419                 this.scissorTest = false;
2420
2421                 this.viewport = new Vector4( 0, 0, width, height );
2422
2423                 options = options || {};
2424
2425                 this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
2426
2427                 this.texture.image = {};
2428                 this.texture.image.width = width;
2429                 this.texture.image.height = height;
2430
2431                 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
2432                 this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
2433
2434                 this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
2435                 this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
2436                 this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
2437
2438         }
2439
2440         setSize( width, height ) {
2441
2442                 if ( this.width !== width || this.height !== height ) {
2443
2444                         this.width = width;
2445                         this.height = height;
2446
2447                         this.texture.image.width = width;
2448                         this.texture.image.height = height;
2449
2450                         this.dispose();
2451
2452                 }
2453
2454                 this.viewport.set( 0, 0, width, height );
2455                 this.scissor.set( 0, 0, width, height );
2456
2457         }
2458
2459         clone() {
2460
2461                 return new this.constructor().copy( this );
2462
2463         }
2464
2465         copy( source ) {
2466
2467                 this.width = source.width;
2468                 this.height = source.height;
2469
2470                 this.viewport.copy( source.viewport );
2471
2472                 this.texture = source.texture.clone();
2473
2474                 this.depthBuffer = source.depthBuffer;
2475                 this.stencilBuffer = source.stencilBuffer;
2476                 this.depthTexture = source.depthTexture;
2477
2478                 return this;
2479
2480         }
2481
2482         dispose() {
2483
2484                 this.dispatchEvent( { type: 'dispose' } );
2485
2486         }
2487
2488 }
2489
2490 class WebGLMultisampleRenderTarget extends WebGLRenderTarget {
2491
2492         constructor( width, height, options ) {
2493
2494                 super( width, height, options );
2495
2496                 Object.defineProperty( this, 'isWebGLMultisampleRenderTarget', { value: true } );
2497
2498                 this.samples = 4;
2499
2500         }
2501
2502         copy( source ) {
2503
2504                 super.copy.call( this, source );
2505
2506                 this.samples = source.samples;
2507
2508                 return this;
2509
2510         }
2511
2512 }
2513
2514 class Quaternion {
2515
2516         constructor( x = 0, y = 0, z = 0, w = 1 ) {
2517
2518                 Object.defineProperty( this, 'isQuaternion', { value: true } );
2519
2520                 this._x = x;
2521                 this._y = y;
2522                 this._z = z;
2523                 this._w = w;
2524
2525         }
2526
2527         static slerp( qa, qb, qm, t ) {
2528
2529                 return qm.copy( qa ).slerp( qb, t );
2530
2531         }
2532
2533         static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
2534
2535                 // fuzz-free, array-based Quaternion SLERP operation
2536
2537                 let x0 = src0[ srcOffset0 + 0 ],
2538                         y0 = src0[ srcOffset0 + 1 ],
2539                         z0 = src0[ srcOffset0 + 2 ],
2540                         w0 = src0[ srcOffset0 + 3 ];
2541
2542                 const x1 = src1[ srcOffset1 + 0 ],
2543                         y1 = src1[ srcOffset1 + 1 ],
2544                         z1 = src1[ srcOffset1 + 2 ],
2545                         w1 = src1[ srcOffset1 + 3 ];
2546
2547                 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
2548
2549                         let s = 1 - t;
2550                         const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
2551                                 dir = ( cos >= 0 ? 1 : - 1 ),
2552                                 sqrSin = 1 - cos * cos;
2553
2554                         // Skip the Slerp for tiny steps to avoid numeric problems:
2555                         if ( sqrSin > Number.EPSILON ) {
2556
2557                                 const sin = Math.sqrt( sqrSin ),
2558                                         len = Math.atan2( sin, cos * dir );
2559
2560                                 s = Math.sin( s * len ) / sin;
2561                                 t = Math.sin( t * len ) / sin;
2562
2563                         }
2564
2565                         const tDir = t * dir;
2566
2567                         x0 = x0 * s + x1 * tDir;
2568                         y0 = y0 * s + y1 * tDir;
2569                         z0 = z0 * s + z1 * tDir;
2570                         w0 = w0 * s + w1 * tDir;
2571
2572                         // Normalize in case we just did a lerp:
2573                         if ( s === 1 - t ) {
2574
2575                                 const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
2576
2577                                 x0 *= f;
2578                                 y0 *= f;
2579                                 z0 *= f;
2580                                 w0 *= f;
2581
2582                         }
2583
2584                 }
2585
2586                 dst[ dstOffset ] = x0;
2587                 dst[ dstOffset + 1 ] = y0;
2588                 dst[ dstOffset + 2 ] = z0;
2589                 dst[ dstOffset + 3 ] = w0;
2590
2591         }
2592
2593         static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
2594
2595                 const x0 = src0[ srcOffset0 ];
2596                 const y0 = src0[ srcOffset0 + 1 ];
2597                 const z0 = src0[ srcOffset0 + 2 ];
2598                 const w0 = src0[ srcOffset0 + 3 ];
2599
2600                 const x1 = src1[ srcOffset1 ];
2601                 const y1 = src1[ srcOffset1 + 1 ];
2602                 const z1 = src1[ srcOffset1 + 2 ];
2603                 const w1 = src1[ srcOffset1 + 3 ];
2604
2605                 dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
2606                 dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
2607                 dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
2608                 dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
2609
2610                 return dst;
2611
2612         }
2613
2614         get x() {
2615
2616                 return this._x;
2617
2618         }
2619
2620         set x( value ) {
2621
2622                 this._x = value;
2623                 this._onChangeCallback();
2624
2625         }
2626
2627         get y() {
2628
2629                 return this._y;
2630
2631         }
2632
2633         set y( value ) {
2634
2635                 this._y = value;
2636                 this._onChangeCallback();
2637
2638         }
2639
2640         get z() {
2641
2642                 return this._z;
2643
2644         }
2645
2646         set z( value ) {
2647
2648                 this._z = value;
2649                 this._onChangeCallback();
2650
2651         }
2652
2653         get w() {
2654
2655                 return this._w;
2656
2657         }
2658
2659         set w( value ) {
2660
2661                 this._w = value;
2662                 this._onChangeCallback();
2663
2664         }
2665
2666         set( x, y, z, w ) {
2667
2668                 this._x = x;
2669                 this._y = y;
2670                 this._z = z;
2671                 this._w = w;
2672
2673                 this._onChangeCallback();
2674
2675                 return this;
2676
2677         }
2678
2679         clone() {
2680
2681                 return new this.constructor( this._x, this._y, this._z, this._w );
2682
2683         }
2684
2685         copy( quaternion ) {
2686
2687                 this._x = quaternion.x;
2688                 this._y = quaternion.y;
2689                 this._z = quaternion.z;
2690                 this._w = quaternion.w;
2691
2692                 this._onChangeCallback();
2693
2694                 return this;
2695
2696         }
2697
2698         setFromEuler( euler, update ) {
2699
2700                 if ( ! ( euler && euler.isEuler ) ) {
2701
2702                         throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2703
2704                 }
2705
2706                 const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
2707
2708                 // http://www.mathworks.com/matlabcentral/fileexchange/
2709                 //      20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
2710                 //      content/SpinCalc.m
2711
2712                 const cos = Math.cos;
2713                 const sin = Math.sin;
2714
2715                 const c1 = cos( x / 2 );
2716                 const c2 = cos( y / 2 );
2717                 const c3 = cos( z / 2 );
2718
2719                 const s1 = sin( x / 2 );
2720                 const s2 = sin( y / 2 );
2721                 const s3 = sin( z / 2 );
2722
2723                 switch ( order ) {
2724
2725                         case 'XYZ':
2726                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2727                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2728                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2729                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2730                                 break;
2731
2732                         case 'YXZ':
2733                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2734                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2735                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2736                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2737                                 break;
2738
2739                         case 'ZXY':
2740                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2741                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2742                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2743                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2744                                 break;
2745
2746                         case 'ZYX':
2747                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2748                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2749                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2750                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2751                                 break;
2752
2753                         case 'YZX':
2754                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2755                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2756                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2757                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2758                                 break;
2759
2760                         case 'XZY':
2761                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2762                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2763                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2764                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2765                                 break;
2766
2767                         default:
2768                                 console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
2769
2770                 }
2771
2772                 if ( update !== false ) this._onChangeCallback();
2773
2774                 return this;
2775
2776         }
2777
2778         setFromAxisAngle( axis, angle ) {
2779
2780                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
2781
2782                 // assumes axis is normalized
2783
2784                 const halfAngle = angle / 2, s = Math.sin( halfAngle );
2785
2786                 this._x = axis.x * s;
2787                 this._y = axis.y * s;
2788                 this._z = axis.z * s;
2789                 this._w = Math.cos( halfAngle );
2790
2791                 this._onChangeCallback();
2792
2793                 return this;
2794
2795         }
2796
2797         setFromRotationMatrix( m ) {
2798
2799                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
2800
2801                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2802
2803                 const te = m.elements,
2804
2805                         m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2806                         m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2807                         m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
2808
2809                         trace = m11 + m22 + m33;
2810
2811                 if ( trace > 0 ) {
2812
2813                         const s = 0.5 / Math.sqrt( trace + 1.0 );
2814
2815                         this._w = 0.25 / s;
2816                         this._x = ( m32 - m23 ) * s;
2817                         this._y = ( m13 - m31 ) * s;
2818                         this._z = ( m21 - m12 ) * s;
2819
2820                 } else if ( m11 > m22 && m11 > m33 ) {
2821
2822                         const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
2823
2824                         this._w = ( m32 - m23 ) / s;
2825                         this._x = 0.25 * s;
2826                         this._y = ( m12 + m21 ) / s;
2827                         this._z = ( m13 + m31 ) / s;
2828
2829                 } else if ( m22 > m33 ) {
2830
2831                         const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
2832
2833                         this._w = ( m13 - m31 ) / s;
2834                         this._x = ( m12 + m21 ) / s;
2835                         this._y = 0.25 * s;
2836                         this._z = ( m23 + m32 ) / s;
2837
2838                 } else {
2839
2840                         const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
2841
2842                         this._w = ( m21 - m12 ) / s;
2843                         this._x = ( m13 + m31 ) / s;
2844                         this._y = ( m23 + m32 ) / s;
2845                         this._z = 0.25 * s;
2846
2847                 }
2848
2849                 this._onChangeCallback();
2850
2851                 return this;
2852
2853         }
2854
2855         setFromUnitVectors( vFrom, vTo ) {
2856
2857                 // assumes direction vectors vFrom and vTo are normalized
2858
2859                 const EPS = 0.000001;
2860
2861                 let r = vFrom.dot( vTo ) + 1;
2862
2863                 if ( r < EPS ) {
2864
2865                         r = 0;
2866
2867                         if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
2868
2869                                 this._x = - vFrom.y;
2870                                 this._y = vFrom.x;
2871                                 this._z = 0;
2872                                 this._w = r;
2873
2874                         } else {
2875
2876                                 this._x = 0;
2877                                 this._y = - vFrom.z;
2878                                 this._z = vFrom.y;
2879                                 this._w = r;
2880
2881                         }
2882
2883                 } else {
2884
2885                         // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
2886
2887                         this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
2888                         this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
2889                         this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
2890                         this._w = r;
2891
2892                 }
2893
2894                 return this.normalize();
2895
2896         }
2897
2898         angleTo( q ) {
2899
2900                 return 2 * Math.acos( Math.abs( MathUtils.clamp( this.dot( q ), - 1, 1 ) ) );
2901
2902         }
2903
2904         rotateTowards( q, step ) {
2905
2906                 const angle = this.angleTo( q );
2907
2908                 if ( angle === 0 ) return this;
2909
2910                 const t = Math.min( 1, step / angle );
2911
2912                 this.slerp( q, t );
2913
2914                 return this;
2915
2916         }
2917
2918         identity() {
2919
2920                 return this.set( 0, 0, 0, 1 );
2921
2922         }
2923
2924         invert() {
2925
2926                 // quaternion is assumed to have unit length
2927
2928                 return this.conjugate();
2929
2930         }
2931
2932         conjugate() {
2933
2934                 this._x *= - 1;
2935                 this._y *= - 1;
2936                 this._z *= - 1;
2937
2938                 this._onChangeCallback();
2939
2940                 return this;
2941
2942         }
2943
2944         dot( v ) {
2945
2946                 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
2947
2948         }
2949
2950         lengthSq() {
2951
2952                 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
2953
2954         }
2955
2956         length() {
2957
2958                 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
2959
2960         }
2961
2962         normalize() {
2963
2964                 let l = this.length();
2965
2966                 if ( l === 0 ) {
2967
2968                         this._x = 0;
2969                         this._y = 0;
2970                         this._z = 0;
2971                         this._w = 1;
2972
2973                 } else {
2974
2975                         l = 1 / l;
2976
2977                         this._x = this._x * l;
2978                         this._y = this._y * l;
2979                         this._z = this._z * l;
2980                         this._w = this._w * l;
2981
2982                 }
2983
2984                 this._onChangeCallback();
2985
2986                 return this;
2987
2988         }
2989
2990         multiply( q, p ) {
2991
2992                 if ( p !== undefined ) {
2993
2994                         console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
2995                         return this.multiplyQuaternions( q, p );
2996
2997                 }
2998
2999                 return this.multiplyQuaternions( this, q );
3000
3001         }
3002
3003         premultiply( q ) {
3004
3005                 return this.multiplyQuaternions( q, this );
3006
3007         }
3008
3009         multiplyQuaternions( a, b ) {
3010
3011                 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
3012
3013                 const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
3014                 const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
3015
3016                 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
3017                 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
3018                 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
3019                 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
3020
3021                 this._onChangeCallback();
3022
3023                 return this;
3024
3025         }
3026
3027         slerp( qb, t ) {
3028
3029                 if ( t === 0 ) return this;
3030                 if ( t === 1 ) return this.copy( qb );
3031
3032                 const x = this._x, y = this._y, z = this._z, w = this._w;
3033
3034                 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
3035
3036                 let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
3037
3038                 if ( cosHalfTheta < 0 ) {
3039
3040                         this._w = - qb._w;
3041                         this._x = - qb._x;
3042                         this._y = - qb._y;
3043                         this._z = - qb._z;
3044
3045                         cosHalfTheta = - cosHalfTheta;
3046
3047                 } else {
3048
3049                         this.copy( qb );
3050
3051                 }
3052
3053                 if ( cosHalfTheta >= 1.0 ) {
3054
3055                         this._w = w;
3056                         this._x = x;
3057                         this._y = y;
3058                         this._z = z;
3059
3060                         return this;
3061
3062                 }
3063
3064                 const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
3065
3066                 if ( sqrSinHalfTheta <= Number.EPSILON ) {
3067
3068                         const s = 1 - t;
3069                         this._w = s * w + t * this._w;
3070                         this._x = s * x + t * this._x;
3071                         this._y = s * y + t * this._y;
3072                         this._z = s * z + t * this._z;
3073
3074                         this.normalize();
3075                         this._onChangeCallback();
3076
3077                         return this;
3078
3079                 }
3080
3081                 const sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
3082                 const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
3083                 const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
3084                         ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
3085
3086                 this._w = ( w * ratioA + this._w * ratioB );
3087                 this._x = ( x * ratioA + this._x * ratioB );
3088                 this._y = ( y * ratioA + this._y * ratioB );
3089                 this._z = ( z * ratioA + this._z * ratioB );
3090
3091                 this._onChangeCallback();
3092
3093                 return this;
3094
3095         }
3096
3097         equals( quaternion ) {
3098
3099                 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
3100
3101         }
3102
3103         fromArray( array, offset = 0 ) {
3104
3105                 this._x = array[ offset ];
3106                 this._y = array[ offset + 1 ];
3107                 this._z = array[ offset + 2 ];
3108                 this._w = array[ offset + 3 ];
3109
3110                 this._onChangeCallback();
3111
3112                 return this;
3113
3114         }
3115
3116         toArray( array = [], offset = 0 ) {
3117
3118                 array[ offset ] = this._x;
3119                 array[ offset + 1 ] = this._y;
3120                 array[ offset + 2 ] = this._z;
3121                 array[ offset + 3 ] = this._w;
3122
3123                 return array;
3124
3125         }
3126
3127         fromBufferAttribute( attribute, index ) {
3128
3129                 this._x = attribute.getX( index );
3130                 this._y = attribute.getY( index );
3131                 this._z = attribute.getZ( index );
3132                 this._w = attribute.getW( index );
3133
3134                 return this;
3135
3136         }
3137
3138         _onChange( callback ) {
3139
3140                 this._onChangeCallback = callback;
3141
3142                 return this;
3143
3144         }
3145
3146         _onChangeCallback() {}
3147
3148 }
3149
3150 class Vector3 {
3151
3152         constructor( x = 0, y = 0, z = 0 ) {
3153
3154                 Object.defineProperty( this, 'isVector3', { value: true } );
3155
3156                 this.x = x;
3157                 this.y = y;
3158                 this.z = z;
3159
3160         }
3161
3162         set( x, y, z ) {
3163
3164                 if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
3165
3166                 this.x = x;
3167                 this.y = y;
3168                 this.z = z;
3169
3170                 return this;
3171
3172         }
3173
3174         setScalar( scalar ) {
3175
3176                 this.x = scalar;
3177                 this.y = scalar;
3178                 this.z = scalar;
3179
3180                 return this;
3181
3182         }
3183
3184         setX( x ) {
3185
3186                 this.x = x;
3187
3188                 return this;
3189
3190         }
3191
3192         setY( y ) {
3193
3194                 this.y = y;
3195
3196                 return this;
3197
3198         }
3199
3200         setZ( z ) {
3201
3202                 this.z = z;
3203
3204                 return this;
3205
3206         }
3207
3208         setComponent( index, value ) {
3209
3210                 switch ( index ) {
3211
3212                         case 0: this.x = value; break;
3213                         case 1: this.y = value; break;
3214                         case 2: this.z = value; break;
3215                         default: throw new Error( 'index is out of range: ' + index );
3216
3217                 }
3218
3219                 return this;
3220
3221         }
3222
3223         getComponent( index ) {
3224
3225                 switch ( index ) {
3226
3227                         case 0: return this.x;
3228                         case 1: return this.y;
3229                         case 2: return this.z;
3230                         default: throw new Error( 'index is out of range: ' + index );
3231
3232                 }
3233
3234         }
3235
3236         clone() {
3237
3238                 return new this.constructor( this.x, this.y, this.z );
3239
3240         }
3241
3242         copy( v ) {
3243
3244                 this.x = v.x;
3245                 this.y = v.y;
3246                 this.z = v.z;
3247
3248                 return this;
3249
3250         }
3251
3252         add( v, w ) {
3253
3254                 if ( w !== undefined ) {
3255
3256                         console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
3257                         return this.addVectors( v, w );
3258
3259                 }
3260
3261                 this.x += v.x;
3262                 this.y += v.y;
3263                 this.z += v.z;
3264
3265                 return this;
3266
3267         }
3268
3269         addScalar( s ) {
3270
3271                 this.x += s;
3272                 this.y += s;
3273                 this.z += s;
3274
3275                 return this;
3276
3277         }
3278
3279         addVectors( a, b ) {
3280
3281                 this.x = a.x + b.x;
3282                 this.y = a.y + b.y;
3283                 this.z = a.z + b.z;
3284
3285                 return this;
3286
3287         }
3288
3289         addScaledVector( v, s ) {
3290
3291                 this.x += v.x * s;
3292                 this.y += v.y * s;
3293                 this.z += v.z * s;
3294
3295                 return this;
3296
3297         }
3298
3299         sub( v, w ) {
3300
3301                 if ( w !== undefined ) {
3302
3303                         console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
3304                         return this.subVectors( v, w );
3305
3306                 }
3307
3308                 this.x -= v.x;
3309                 this.y -= v.y;
3310                 this.z -= v.z;
3311
3312                 return this;
3313
3314         }
3315
3316         subScalar( s ) {
3317
3318                 this.x -= s;
3319                 this.y -= s;
3320                 this.z -= s;
3321
3322                 return this;
3323
3324         }
3325
3326         subVectors( a, b ) {
3327
3328                 this.x = a.x - b.x;
3329                 this.y = a.y - b.y;
3330                 this.z = a.z - b.z;
3331
3332                 return this;
3333
3334         }
3335
3336         multiply( v, w ) {
3337
3338                 if ( w !== undefined ) {
3339
3340                         console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
3341                         return this.multiplyVectors( v, w );
3342
3343                 }
3344
3345                 this.x *= v.x;
3346                 this.y *= v.y;
3347                 this.z *= v.z;
3348
3349                 return this;
3350
3351         }
3352
3353         multiplyScalar( scalar ) {
3354
3355                 this.x *= scalar;
3356                 this.y *= scalar;
3357                 this.z *= scalar;
3358
3359                 return this;
3360
3361         }
3362
3363         multiplyVectors( a, b ) {
3364
3365                 this.x = a.x * b.x;
3366                 this.y = a.y * b.y;
3367                 this.z = a.z * b.z;
3368
3369                 return this;
3370
3371         }
3372
3373         applyEuler( euler ) {
3374
3375                 if ( ! ( euler && euler.isEuler ) ) {
3376
3377                         console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
3378
3379                 }
3380
3381                 return this.applyQuaternion( _quaternion.setFromEuler( euler ) );
3382
3383         }
3384
3385         applyAxisAngle( axis, angle ) {
3386
3387                 return this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );
3388
3389         }
3390
3391         applyMatrix3( m ) {
3392
3393                 const x = this.x, y = this.y, z = this.z;
3394                 const e = m.elements;
3395
3396                 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
3397                 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
3398                 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
3399
3400                 return this;
3401
3402         }
3403
3404         applyNormalMatrix( m ) {
3405
3406                 return this.applyMatrix3( m ).normalize();
3407
3408         }
3409
3410         applyMatrix4( m ) {
3411
3412                 const x = this.x, y = this.y, z = this.z;
3413                 const e = m.elements;
3414
3415                 const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
3416
3417                 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
3418                 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
3419                 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
3420
3421                 return this;
3422
3423         }
3424
3425         applyQuaternion( q ) {
3426
3427                 const x = this.x, y = this.y, z = this.z;
3428                 const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
3429
3430                 // calculate quat * vector
3431
3432                 const ix = qw * x + qy * z - qz * y;
3433                 const iy = qw * y + qz * x - qx * z;
3434                 const iz = qw * z + qx * y - qy * x;
3435                 const iw = - qx * x - qy * y - qz * z;
3436
3437                 // calculate result * inverse quat
3438
3439                 this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
3440                 this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
3441                 this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
3442
3443                 return this;
3444
3445         }
3446
3447         project( camera ) {
3448
3449                 return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
3450
3451         }
3452
3453         unproject( camera ) {
3454
3455                 return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
3456
3457         }
3458
3459         transformDirection( m ) {
3460
3461                 // input: THREE.Matrix4 affine matrix
3462                 // vector interpreted as a direction
3463
3464                 const x = this.x, y = this.y, z = this.z;
3465                 const e = m.elements;
3466
3467                 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
3468                 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
3469                 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
3470
3471                 return this.normalize();
3472
3473         }
3474
3475         divide( v ) {
3476
3477                 this.x /= v.x;
3478                 this.y /= v.y;
3479                 this.z /= v.z;
3480
3481                 return this;
3482
3483         }
3484
3485         divideScalar( scalar ) {
3486
3487                 return this.multiplyScalar( 1 / scalar );
3488
3489         }
3490
3491         min( v ) {
3492
3493                 this.x = Math.min( this.x, v.x );
3494                 this.y = Math.min( this.y, v.y );
3495                 this.z = Math.min( this.z, v.z );
3496
3497                 return this;
3498
3499         }
3500
3501         max( v ) {
3502
3503                 this.x = Math.max( this.x, v.x );
3504                 this.y = Math.max( this.y, v.y );
3505                 this.z = Math.max( this.z, v.z );
3506
3507                 return this;
3508
3509         }
3510
3511         clamp( min, max ) {
3512
3513                 // assumes min < max, componentwise
3514
3515                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
3516                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
3517                 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
3518
3519                 return this;
3520
3521         }
3522
3523         clampScalar( minVal, maxVal ) {
3524
3525                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
3526                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
3527                 this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
3528
3529                 return this;
3530
3531         }
3532
3533         clampLength( min, max ) {
3534
3535                 const length = this.length();
3536
3537                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
3538
3539         }
3540
3541         floor() {
3542
3543                 this.x = Math.floor( this.x );
3544                 this.y = Math.floor( this.y );
3545                 this.z = Math.floor( this.z );
3546
3547                 return this;
3548
3549         }
3550
3551         ceil() {
3552
3553                 this.x = Math.ceil( this.x );
3554                 this.y = Math.ceil( this.y );
3555                 this.z = Math.ceil( this.z );
3556
3557                 return this;
3558
3559         }
3560
3561         round() {
3562
3563                 this.x = Math.round( this.x );
3564                 this.y = Math.round( this.y );
3565                 this.z = Math.round( this.z );
3566
3567                 return this;
3568
3569         }
3570
3571         roundToZero() {
3572
3573                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
3574                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
3575                 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
3576
3577                 return this;
3578
3579         }
3580
3581         negate() {
3582
3583                 this.x = - this.x;
3584                 this.y = - this.y;
3585                 this.z = - this.z;
3586
3587                 return this;
3588
3589         }
3590
3591         dot( v ) {
3592
3593                 return this.x * v.x + this.y * v.y + this.z * v.z;
3594
3595         }
3596
3597         // TODO lengthSquared?
3598
3599         lengthSq() {
3600
3601                 return this.x * this.x + this.y * this.y + this.z * this.z;
3602
3603         }
3604
3605         length() {
3606
3607                 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
3608
3609         }
3610
3611         manhattanLength() {
3612
3613                 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
3614
3615         }
3616
3617         normalize() {
3618
3619                 return this.divideScalar( this.length() || 1 );
3620
3621         }
3622
3623         setLength( length ) {
3624
3625                 return this.normalize().multiplyScalar( length );
3626
3627         }
3628
3629         lerp( v, alpha ) {
3630
3631                 this.x += ( v.x - this.x ) * alpha;
3632                 this.y += ( v.y - this.y ) * alpha;
3633                 this.z += ( v.z - this.z ) * alpha;
3634
3635                 return this;
3636
3637         }
3638
3639         lerpVectors( v1, v2, alpha ) {
3640
3641                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
3642                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
3643                 this.z = v1.z + ( v2.z - v1.z ) * alpha;
3644
3645                 return this;
3646
3647         }
3648
3649         cross( v, w ) {
3650
3651                 if ( w !== undefined ) {
3652
3653                         console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
3654                         return this.crossVectors( v, w );
3655
3656                 }
3657
3658                 return this.crossVectors( this, v );
3659
3660         }
3661
3662         crossVectors( a, b ) {
3663
3664                 const ax = a.x, ay = a.y, az = a.z;
3665                 const bx = b.x, by = b.y, bz = b.z;
3666
3667                 this.x = ay * bz - az * by;
3668                 this.y = az * bx - ax * bz;
3669                 this.z = ax * by - ay * bx;
3670
3671                 return this;
3672
3673         }
3674
3675         projectOnVector( v ) {
3676
3677                 const denominator = v.lengthSq();
3678
3679                 if ( denominator === 0 ) return this.set( 0, 0, 0 );
3680
3681                 const scalar = v.dot( this ) / denominator;
3682
3683                 return this.copy( v ).multiplyScalar( scalar );
3684
3685         }
3686
3687         projectOnPlane( planeNormal ) {
3688
3689                 _vector.copy( this ).projectOnVector( planeNormal );
3690
3691                 return this.sub( _vector );
3692
3693         }
3694
3695         reflect( normal ) {
3696
3697                 // reflect incident vector off plane orthogonal to normal
3698                 // normal is assumed to have unit length
3699
3700                 return this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
3701
3702         }
3703
3704         angleTo( v ) {
3705
3706                 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
3707
3708                 if ( denominator === 0 ) return Math.PI / 2;
3709
3710                 const theta = this.dot( v ) / denominator;
3711
3712                 // clamp, to handle numerical problems
3713
3714                 return Math.acos( MathUtils.clamp( theta, - 1, 1 ) );
3715
3716         }
3717
3718         distanceTo( v ) {
3719
3720                 return Math.sqrt( this.distanceToSquared( v ) );
3721
3722         }
3723
3724         distanceToSquared( v ) {
3725
3726                 const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
3727
3728                 return dx * dx + dy * dy + dz * dz;
3729
3730         }
3731
3732         manhattanDistanceTo( v ) {
3733
3734                 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
3735
3736         }
3737
3738         setFromSpherical( s ) {
3739
3740                 return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
3741
3742         }
3743
3744         setFromSphericalCoords( radius, phi, theta ) {
3745
3746                 const sinPhiRadius = Math.sin( phi ) * radius;
3747
3748                 this.x = sinPhiRadius * Math.sin( theta );
3749                 this.y = Math.cos( phi ) * radius;
3750                 this.z = sinPhiRadius * Math.cos( theta );
3751
3752                 return this;
3753
3754         }
3755
3756         setFromCylindrical( c ) {
3757
3758                 return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
3759
3760         }
3761
3762         setFromCylindricalCoords( radius, theta, y ) {
3763
3764                 this.x = radius * Math.sin( theta );
3765                 this.y = y;
3766                 this.z = radius * Math.cos( theta );
3767
3768                 return this;
3769
3770         }
3771
3772         setFromMatrixPosition( m ) {
3773
3774                 const e = m.elements;
3775
3776                 this.x = e[ 12 ];
3777                 this.y = e[ 13 ];
3778                 this.z = e[ 14 ];
3779
3780                 return this;
3781
3782         }
3783
3784         setFromMatrixScale( m ) {
3785
3786                 const sx = this.setFromMatrixColumn( m, 0 ).length();
3787                 const sy = this.setFromMatrixColumn( m, 1 ).length();
3788                 const sz = this.setFromMatrixColumn( m, 2 ).length();
3789
3790                 this.x = sx;
3791                 this.y = sy;
3792                 this.z = sz;
3793
3794                 return this;
3795
3796         }
3797
3798         setFromMatrixColumn( m, index ) {
3799
3800                 return this.fromArray( m.elements, index * 4 );
3801
3802         }
3803
3804         setFromMatrix3Column( m, index ) {
3805
3806                 return this.fromArray( m.elements, index * 3 );
3807
3808         }
3809
3810         equals( v ) {
3811
3812                 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
3813
3814         }
3815
3816         fromArray( array, offset = 0 ) {
3817
3818                 this.x = array[ offset ];
3819                 this.y = array[ offset + 1 ];
3820                 this.z = array[ offset + 2 ];
3821
3822                 return this;
3823
3824         }
3825
3826         toArray( array = [], offset = 0 ) {
3827
3828                 array[ offset ] = this.x;
3829                 array[ offset + 1 ] = this.y;
3830                 array[ offset + 2 ] = this.z;
3831
3832                 return array;
3833
3834         }
3835
3836         fromBufferAttribute( attribute, index, offset ) {
3837
3838                 if ( offset !== undefined ) {
3839
3840                         console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
3841
3842                 }
3843
3844                 this.x = attribute.getX( index );
3845                 this.y = attribute.getY( index );
3846                 this.z = attribute.getZ( index );
3847
3848                 return this;
3849
3850         }
3851
3852         random() {
3853
3854                 this.x = Math.random();
3855                 this.y = Math.random();
3856                 this.z = Math.random();
3857
3858                 return this;
3859
3860         }
3861
3862 }
3863
3864 const _vector = /*@__PURE__*/ new Vector3();
3865 const _quaternion = /*@__PURE__*/ new Quaternion();
3866
3867 class Box3 {
3868
3869         constructor( min, max ) {
3870
3871                 Object.defineProperty( this, 'isBox3', { value: true } );
3872
3873                 this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
3874                 this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
3875
3876         }
3877
3878         set( min, max ) {
3879
3880                 this.min.copy( min );
3881                 this.max.copy( max );
3882
3883                 return this;
3884
3885         }
3886
3887         setFromArray( array ) {
3888
3889                 let minX = + Infinity;
3890                 let minY = + Infinity;
3891                 let minZ = + Infinity;
3892
3893                 let maxX = - Infinity;
3894                 let maxY = - Infinity;
3895                 let maxZ = - Infinity;
3896
3897                 for ( let i = 0, l = array.length; i < l; i += 3 ) {
3898
3899                         const x = array[ i ];
3900                         const y = array[ i + 1 ];
3901                         const z = array[ i + 2 ];
3902
3903                         if ( x < minX ) minX = x;
3904                         if ( y < minY ) minY = y;
3905                         if ( z < minZ ) minZ = z;
3906
3907                         if ( x > maxX ) maxX = x;
3908                         if ( y > maxY ) maxY = y;
3909                         if ( z > maxZ ) maxZ = z;
3910
3911                 }
3912
3913                 this.min.set( minX, minY, minZ );
3914                 this.max.set( maxX, maxY, maxZ );
3915
3916                 return this;
3917
3918         }
3919
3920         setFromBufferAttribute( attribute ) {
3921
3922                 let minX = + Infinity;
3923                 let minY = + Infinity;
3924                 let minZ = + Infinity;
3925
3926                 let maxX = - Infinity;
3927                 let maxY = - Infinity;
3928                 let maxZ = - Infinity;
3929
3930                 for ( let i = 0, l = attribute.count; i < l; i ++ ) {
3931
3932                         const x = attribute.getX( i );
3933                         const y = attribute.getY( i );
3934                         const z = attribute.getZ( i );
3935
3936                         if ( x < minX ) minX = x;
3937                         if ( y < minY ) minY = y;
3938                         if ( z < minZ ) minZ = z;
3939
3940                         if ( x > maxX ) maxX = x;
3941                         if ( y > maxY ) maxY = y;
3942                         if ( z > maxZ ) maxZ = z;
3943
3944                 }
3945
3946                 this.min.set( minX, minY, minZ );
3947                 this.max.set( maxX, maxY, maxZ );
3948
3949                 return this;
3950
3951         }
3952
3953         setFromPoints( points ) {
3954
3955                 this.makeEmpty();
3956
3957                 for ( let i = 0, il = points.length; i < il; i ++ ) {
3958
3959                         this.expandByPoint( points[ i ] );
3960
3961                 }
3962
3963                 return this;
3964
3965         }
3966
3967         setFromCenterAndSize( center, size ) {
3968
3969                 const halfSize = _vector$1.copy( size ).multiplyScalar( 0.5 );
3970
3971                 this.min.copy( center ).sub( halfSize );
3972                 this.max.copy( center ).add( halfSize );
3973
3974                 return this;
3975
3976         }
3977
3978         setFromObject( object ) {
3979
3980                 this.makeEmpty();
3981
3982                 return this.expandByObject( object );
3983
3984         }
3985
3986         clone() {
3987
3988                 return new this.constructor().copy( this );
3989
3990         }
3991
3992         copy( box ) {
3993
3994                 this.min.copy( box.min );
3995                 this.max.copy( box.max );
3996
3997                 return this;
3998
3999         }
4000
4001         makeEmpty() {
4002
4003                 this.min.x = this.min.y = this.min.z = + Infinity;
4004                 this.max.x = this.max.y = this.max.z = - Infinity;
4005
4006                 return this;
4007
4008         }
4009
4010         isEmpty() {
4011
4012                 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4013
4014                 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
4015
4016         }
4017
4018         getCenter( target ) {
4019
4020                 if ( target === undefined ) {
4021
4022                         console.warn( 'THREE.Box3: .getCenter() target is now required' );
4023                         target = new Vector3();
4024
4025                 }
4026
4027                 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4028
4029         }
4030
4031         getSize( target ) {
4032
4033                 if ( target === undefined ) {
4034
4035                         console.warn( 'THREE.Box3: .getSize() target is now required' );
4036                         target = new Vector3();
4037
4038                 }
4039
4040                 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
4041
4042         }
4043
4044         expandByPoint( point ) {
4045
4046                 this.min.min( point );
4047                 this.max.max( point );
4048
4049                 return this;
4050
4051         }
4052
4053         expandByVector( vector ) {
4054
4055                 this.min.sub( vector );
4056                 this.max.add( vector );
4057
4058                 return this;
4059
4060         }
4061
4062         expandByScalar( scalar ) {
4063
4064                 this.min.addScalar( - scalar );
4065                 this.max.addScalar( scalar );
4066
4067                 return this;
4068
4069         }
4070
4071         expandByObject( object ) {
4072
4073                 // Computes the world-axis-aligned bounding box of an object (including its children),
4074                 // accounting for both the object's, and children's, world transforms
4075
4076                 object.updateWorldMatrix( false, false );
4077
4078                 const geometry = object.geometry;
4079
4080                 if ( geometry !== undefined ) {
4081
4082                         if ( geometry.boundingBox === null ) {
4083
4084                                 geometry.computeBoundingBox();
4085
4086                         }
4087
4088                         _box.copy( geometry.boundingBox );
4089                         _box.applyMatrix4( object.matrixWorld );
4090
4091                         this.union( _box );
4092
4093                 }
4094
4095                 const children = object.children;
4096
4097                 for ( let i = 0, l = children.length; i < l; i ++ ) {
4098
4099                         this.expandByObject( children[ i ] );
4100
4101                 }
4102
4103                 return this;
4104
4105         }
4106
4107         containsPoint( point ) {
4108
4109                 return point.x < this.min.x || point.x > this.max.x ||
4110                         point.y < this.min.y || point.y > this.max.y ||
4111                         point.z < this.min.z || point.z > this.max.z ? false : true;
4112
4113         }
4114
4115         containsBox( box ) {
4116
4117                 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
4118                         this.min.y <= box.min.y && box.max.y <= this.max.y &&
4119                         this.min.z <= box.min.z && box.max.z <= this.max.z;
4120
4121         }
4122
4123         getParameter( point, target ) {
4124
4125                 // This can potentially have a divide by zero if the box
4126                 // has a size dimension of 0.
4127
4128                 if ( target === undefined ) {
4129
4130                         console.warn( 'THREE.Box3: .getParameter() target is now required' );
4131                         target = new Vector3();
4132
4133                 }
4134
4135                 return target.set(
4136                         ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
4137                         ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
4138                         ( point.z - this.min.z ) / ( this.max.z - this.min.z )
4139                 );
4140
4141         }
4142
4143         intersectsBox( box ) {
4144
4145                 // using 6 splitting planes to rule out intersections.
4146                 return box.max.x < this.min.x || box.min.x > this.max.x ||
4147                         box.max.y < this.min.y || box.min.y > this.max.y ||
4148                         box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
4149
4150         }
4151
4152         intersectsSphere( sphere ) {
4153
4154                 // Find the point on the AABB closest to the sphere center.
4155                 this.clampPoint( sphere.center, _vector$1 );
4156
4157                 // If that point is inside the sphere, the AABB and sphere intersect.
4158                 return _vector$1.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
4159
4160         }
4161
4162         intersectsPlane( plane ) {
4163
4164                 // We compute the minimum and maximum dot product values. If those values
4165                 // are on the same side (back or front) of the plane, then there is no intersection.
4166
4167                 let min, max;
4168
4169                 if ( plane.normal.x > 0 ) {
4170
4171                         min = plane.normal.x * this.min.x;
4172                         max = plane.normal.x * this.max.x;
4173
4174                 } else {
4175
4176                         min = plane.normal.x * this.max.x;
4177                         max = plane.normal.x * this.min.x;
4178
4179                 }
4180
4181                 if ( plane.normal.y > 0 ) {
4182
4183                         min += plane.normal.y * this.min.y;
4184                         max += plane.normal.y * this.max.y;
4185
4186                 } else {
4187
4188                         min += plane.normal.y * this.max.y;
4189                         max += plane.normal.y * this.min.y;
4190
4191                 }
4192
4193                 if ( plane.normal.z > 0 ) {
4194
4195                         min += plane.normal.z * this.min.z;
4196                         max += plane.normal.z * this.max.z;
4197
4198                 } else {
4199
4200                         min += plane.normal.z * this.max.z;
4201                         max += plane.normal.z * this.min.z;
4202
4203                 }
4204
4205                 return ( min <= - plane.constant && max >= - plane.constant );
4206
4207         }
4208
4209         intersectsTriangle( triangle ) {
4210
4211                 if ( this.isEmpty() ) {
4212
4213                         return false;
4214
4215                 }
4216
4217                 // compute box center and extents
4218                 this.getCenter( _center );
4219                 _extents.subVectors( this.max, _center );
4220
4221                 // translate triangle to aabb origin
4222                 _v0.subVectors( triangle.a, _center );
4223                 _v1.subVectors( triangle.b, _center );
4224                 _v2.subVectors( triangle.c, _center );
4225
4226                 // compute edge vectors for triangle
4227                 _f0.subVectors( _v1, _v0 );
4228                 _f1.subVectors( _v2, _v1 );
4229                 _f2.subVectors( _v0, _v2 );
4230
4231                 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
4232                 // 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
4233                 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
4234                 let axes = [
4235                         0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
4236                         _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
4237                         - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
4238                 ];
4239                 if ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {
4240
4241                         return false;
4242
4243                 }
4244
4245                 // test 3 face normals from the aabb
4246                 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
4247                 if ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {
4248
4249                         return false;
4250
4251                 }
4252
4253                 // finally testing the face normal of the triangle
4254                 // use already existing triangle edge vectors here
4255                 _triangleNormal.crossVectors( _f0, _f1 );
4256                 axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
4257
4258                 return satForAxes( axes, _v0, _v1, _v2, _extents );
4259
4260         }
4261
4262         clampPoint( point, target ) {
4263
4264                 if ( target === undefined ) {
4265
4266                         console.warn( 'THREE.Box3: .clampPoint() target is now required' );
4267                         target = new Vector3();
4268
4269                 }
4270
4271                 return target.copy( point ).clamp( this.min, this.max );
4272
4273         }
4274
4275         distanceToPoint( point ) {
4276
4277                 const clampedPoint = _vector$1.copy( point ).clamp( this.min, this.max );
4278
4279                 return clampedPoint.sub( point ).length();
4280
4281         }
4282
4283         getBoundingSphere( target ) {
4284
4285                 if ( target === undefined ) {
4286
4287                         console.error( 'THREE.Box3: .getBoundingSphere() target is now required' );
4288                         //target = new Sphere(); // removed to avoid cyclic dependency
4289
4290                 }
4291
4292                 this.getCenter( target.center );
4293
4294                 target.radius = this.getSize( _vector$1 ).length() * 0.5;
4295
4296                 return target;
4297
4298         }
4299
4300         intersect( box ) {
4301
4302                 this.min.max( box.min );
4303                 this.max.min( box.max );
4304
4305                 // 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.
4306                 if ( this.isEmpty() ) this.makeEmpty();
4307
4308                 return this;
4309
4310         }
4311
4312         union( box ) {
4313
4314                 this.min.min( box.min );
4315                 this.max.max( box.max );
4316
4317                 return this;
4318
4319         }
4320
4321         applyMatrix4( matrix ) {
4322
4323                 // transform of empty box is an empty box.
4324                 if ( this.isEmpty() ) return this;
4325
4326                 // NOTE: I am using a binary pattern to specify all 2^3 combinations below
4327                 _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
4328                 _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
4329                 _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
4330                 _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
4331                 _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
4332                 _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
4333                 _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
4334                 _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
4335
4336                 this.setFromPoints( _points );
4337
4338                 return this;
4339
4340         }
4341
4342         translate( offset ) {
4343
4344                 this.min.add( offset );
4345                 this.max.add( offset );
4346
4347                 return this;
4348
4349         }
4350
4351         equals( box ) {
4352
4353                 return box.min.equals( this.min ) && box.max.equals( this.max );
4354
4355         }
4356
4357 }
4358
4359 function satForAxes( axes, v0, v1, v2, extents ) {
4360
4361         for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
4362
4363                 _testAxis.fromArray( axes, i );
4364                 // project the aabb onto the seperating axis
4365                 const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
4366                 // project all 3 vertices of the triangle onto the seperating axis
4367                 const p0 = v0.dot( _testAxis );
4368                 const p1 = v1.dot( _testAxis );
4369                 const p2 = v2.dot( _testAxis );
4370                 // actual test, basically see if either of the most extreme of the triangle points intersects r
4371                 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
4372
4373                         // points of the projected triangle are outside the projected half-length of the aabb
4374                         // the axis is seperating and we can exit
4375                         return false;
4376
4377                 }
4378
4379         }
4380
4381         return true;
4382
4383 }
4384
4385 const _points = [
4386         /*@__PURE__*/ new Vector3(),
4387         /*@__PURE__*/ new Vector3(),
4388         /*@__PURE__*/ new Vector3(),
4389         /*@__PURE__*/ new Vector3(),
4390         /*@__PURE__*/ new Vector3(),
4391         /*@__PURE__*/ new Vector3(),
4392         /*@__PURE__*/ new Vector3(),
4393         /*@__PURE__*/ new Vector3()
4394 ];
4395
4396 const _vector$1 = /*@__PURE__*/ new Vector3();
4397
4398 const _box = /*@__PURE__*/ new Box3();
4399
4400 // triangle centered vertices
4401
4402 const _v0 = /*@__PURE__*/ new Vector3();
4403 const _v1 = /*@__PURE__*/ new Vector3();
4404 const _v2 = /*@__PURE__*/ new Vector3();
4405
4406 // triangle edge vectors
4407
4408 const _f0 = /*@__PURE__*/ new Vector3();
4409 const _f1 = /*@__PURE__*/ new Vector3();
4410 const _f2 = /*@__PURE__*/ new Vector3();
4411
4412 const _center = /*@__PURE__*/ new Vector3();
4413 const _extents = /*@__PURE__*/ new Vector3();
4414 const _triangleNormal = /*@__PURE__*/ new Vector3();
4415 const _testAxis = /*@__PURE__*/ new Vector3();
4416
4417 const _box$1 = /*@__PURE__*/ new Box3();
4418
4419 class Sphere {
4420
4421         constructor( center, radius ) {
4422
4423                 this.center = ( center !== undefined ) ? center : new Vector3();
4424                 this.radius = ( radius !== undefined ) ? radius : - 1;
4425
4426         }
4427
4428         set( center, radius ) {
4429
4430                 this.center.copy( center );
4431                 this.radius = radius;
4432
4433                 return this;
4434
4435         }
4436
4437         setFromPoints( points, optionalCenter ) {
4438
4439                 const center = this.center;
4440
4441                 if ( optionalCenter !== undefined ) {
4442
4443                         center.copy( optionalCenter );
4444
4445                 } else {
4446
4447                         _box$1.setFromPoints( points ).getCenter( center );
4448
4449                 }
4450
4451                 let maxRadiusSq = 0;
4452
4453                 for ( let i = 0, il = points.length; i < il; i ++ ) {
4454
4455                         maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
4456
4457                 }
4458
4459                 this.radius = Math.sqrt( maxRadiusSq );
4460
4461                 return this;
4462
4463         }
4464
4465         clone() {
4466
4467                 return new this.constructor().copy( this );
4468
4469         }
4470
4471         copy( sphere ) {
4472
4473                 this.center.copy( sphere.center );
4474                 this.radius = sphere.radius;
4475
4476                 return this;
4477
4478         }
4479
4480         isEmpty() {
4481
4482                 return ( this.radius < 0 );
4483
4484         }
4485
4486         makeEmpty() {
4487
4488                 this.center.set( 0, 0, 0 );
4489                 this.radius = - 1;
4490
4491                 return this;
4492
4493         }
4494
4495         containsPoint( point ) {
4496
4497                 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
4498
4499         }
4500
4501         distanceToPoint( point ) {
4502
4503                 return ( point.distanceTo( this.center ) - this.radius );
4504
4505         }
4506
4507         intersectsSphere( sphere ) {
4508
4509                 const radiusSum = this.radius + sphere.radius;
4510
4511                 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
4512
4513         }
4514
4515         intersectsBox( box ) {
4516
4517                 return box.intersectsSphere( this );
4518
4519         }
4520
4521         intersectsPlane( plane ) {
4522
4523                 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
4524
4525         }
4526
4527         clampPoint( point, target ) {
4528
4529                 const deltaLengthSq = this.center.distanceToSquared( point );
4530
4531                 if ( target === undefined ) {
4532
4533                         console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
4534                         target = new Vector3();
4535
4536                 }
4537
4538                 target.copy( point );
4539
4540                 if ( deltaLengthSq > ( this.radius * this.radius ) ) {
4541
4542                         target.sub( this.center ).normalize();
4543                         target.multiplyScalar( this.radius ).add( this.center );
4544
4545                 }
4546
4547                 return target;
4548
4549         }
4550
4551         getBoundingBox( target ) {
4552
4553                 if ( target === undefined ) {
4554
4555                         console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
4556                         target = new Box3();
4557
4558                 }
4559
4560                 if ( this.isEmpty() ) {
4561
4562                         // Empty sphere produces empty bounding box
4563                         target.makeEmpty();
4564                         return target;
4565
4566                 }
4567
4568                 target.set( this.center, this.center );
4569                 target.expandByScalar( this.radius );
4570
4571                 return target;
4572
4573         }
4574
4575         applyMatrix4( matrix ) {
4576
4577                 this.center.applyMatrix4( matrix );
4578                 this.radius = this.radius * matrix.getMaxScaleOnAxis();
4579
4580                 return this;
4581
4582         }
4583
4584         translate( offset ) {
4585
4586                 this.center.add( offset );
4587
4588                 return this;
4589
4590         }
4591
4592         equals( sphere ) {
4593
4594                 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
4595
4596         }
4597
4598 }
4599
4600 const _vector$2 = /*@__PURE__*/ new Vector3();
4601 const _segCenter = /*@__PURE__*/ new Vector3();
4602 const _segDir = /*@__PURE__*/ new Vector3();
4603 const _diff = /*@__PURE__*/ new Vector3();
4604
4605 const _edge1 = /*@__PURE__*/ new Vector3();
4606 const _edge2 = /*@__PURE__*/ new Vector3();
4607 const _normal = /*@__PURE__*/ new Vector3();
4608
4609 class Ray {
4610
4611         constructor( origin, direction ) {
4612
4613                 this.origin = ( origin !== undefined ) ? origin : new Vector3();
4614                 this.direction = ( direction !== undefined ) ? direction : new Vector3( 0, 0, - 1 );
4615
4616         }
4617
4618         set( origin, direction ) {
4619
4620                 this.origin.copy( origin );
4621                 this.direction.copy( direction );
4622
4623                 return this;
4624
4625         }
4626
4627         clone() {
4628
4629                 return new this.constructor().copy( this );
4630
4631         }
4632
4633         copy( ray ) {
4634
4635                 this.origin.copy( ray.origin );
4636                 this.direction.copy( ray.direction );
4637
4638                 return this;
4639
4640         }
4641
4642         at( t, target ) {
4643
4644                 if ( target === undefined ) {
4645
4646                         console.warn( 'THREE.Ray: .at() target is now required' );
4647                         target = new Vector3();
4648
4649                 }
4650
4651                 return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
4652
4653         }
4654
4655         lookAt( v ) {
4656
4657                 this.direction.copy( v ).sub( this.origin ).normalize();
4658
4659                 return this;
4660
4661         }
4662
4663         recast( t ) {
4664
4665                 this.origin.copy( this.at( t, _vector$2 ) );
4666
4667                 return this;
4668
4669         }
4670
4671         closestPointToPoint( point, target ) {
4672
4673                 if ( target === undefined ) {
4674
4675                         console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
4676                         target = new Vector3();
4677
4678                 }
4679
4680                 target.subVectors( point, this.origin );
4681
4682                 const directionDistance = target.dot( this.direction );
4683
4684                 if ( directionDistance < 0 ) {
4685
4686                         return target.copy( this.origin );
4687
4688                 }
4689
4690                 return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
4691
4692         }
4693
4694         distanceToPoint( point ) {
4695
4696                 return Math.sqrt( this.distanceSqToPoint( point ) );
4697
4698         }
4699
4700         distanceSqToPoint( point ) {
4701
4702                 const directionDistance = _vector$2.subVectors( point, this.origin ).dot( this.direction );
4703
4704                 // point behind the ray
4705
4706                 if ( directionDistance < 0 ) {
4707
4708                         return this.origin.distanceToSquared( point );
4709
4710                 }
4711
4712                 _vector$2.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
4713
4714                 return _vector$2.distanceToSquared( point );
4715
4716         }
4717
4718         distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
4719
4720                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
4721                 // It returns the min distance between the ray and the segment
4722                 // defined by v0 and v1
4723                 // It can also set two optional targets :
4724                 // - The closest point on the ray
4725                 // - The closest point on the segment
4726
4727                 _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
4728                 _segDir.copy( v1 ).sub( v0 ).normalize();
4729                 _diff.copy( this.origin ).sub( _segCenter );
4730
4731                 const segExtent = v0.distanceTo( v1 ) * 0.5;
4732                 const a01 = - this.direction.dot( _segDir );
4733                 const b0 = _diff.dot( this.direction );
4734                 const b1 = - _diff.dot( _segDir );
4735                 const c = _diff.lengthSq();
4736                 const det = Math.abs( 1 - a01 * a01 );
4737                 let s0, s1, sqrDist, extDet;
4738
4739                 if ( det > 0 ) {
4740
4741                         // The ray and segment are not parallel.
4742
4743                         s0 = a01 * b1 - b0;
4744                         s1 = a01 * b0 - b1;
4745                         extDet = segExtent * det;
4746
4747                         if ( s0 >= 0 ) {
4748
4749                                 if ( s1 >= - extDet ) {
4750
4751                                         if ( s1 <= extDet ) {
4752
4753                                                 // region 0
4754                                                 // Minimum at interior points of ray and segment.
4755
4756                                                 const invDet = 1 / det;
4757                                                 s0 *= invDet;
4758                                                 s1 *= invDet;
4759                                                 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
4760
4761                                         } else {
4762
4763                                                 // region 1
4764
4765                                                 s1 = segExtent;
4766                                                 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
4767                                                 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4768
4769                                         }
4770
4771                                 } else {
4772
4773                                         // region 5
4774
4775                                         s1 = - segExtent;
4776                                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
4777                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4778
4779                                 }
4780
4781                         } else {
4782
4783                                 if ( s1 <= - extDet ) {
4784
4785                                         // region 4
4786
4787                                         s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
4788                                         s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
4789                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4790
4791                                 } else if ( s1 <= extDet ) {
4792
4793                                         // region 3
4794
4795                                         s0 = 0;
4796                                         s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
4797                                         sqrDist = s1 * ( s1 + 2 * b1 ) + c;
4798
4799                                 } else {
4800
4801                                         // region 2
4802
4803                                         s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
4804                                         s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
4805                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4806
4807                                 }
4808
4809                         }
4810
4811                 } else {
4812
4813                         // Ray and segment are parallel.
4814
4815                         s1 = ( a01 > 0 ) ? - segExtent : segExtent;
4816                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
4817                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4818
4819                 }
4820
4821                 if ( optionalPointOnRay ) {
4822
4823                         optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
4824
4825                 }
4826
4827                 if ( optionalPointOnSegment ) {
4828
4829                         optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );
4830
4831                 }
4832
4833                 return sqrDist;
4834
4835         }
4836
4837         intersectSphere( sphere, target ) {
4838
4839                 _vector$2.subVectors( sphere.center, this.origin );
4840                 const tca = _vector$2.dot( this.direction );
4841                 const d2 = _vector$2.dot( _vector$2 ) - tca * tca;
4842                 const radius2 = sphere.radius * sphere.radius;
4843
4844                 if ( d2 > radius2 ) return null;
4845
4846                 const thc = Math.sqrt( radius2 - d2 );
4847
4848                 // t0 = first intersect point - entrance on front of sphere
4849                 const t0 = tca - thc;
4850
4851                 // t1 = second intersect point - exit point on back of sphere
4852                 const t1 = tca + thc;
4853
4854                 // test to see if both t0 and t1 are behind the ray - if so, return null
4855                 if ( t0 < 0 && t1 < 0 ) return null;
4856
4857                 // test to see if t0 is behind the ray:
4858                 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
4859                 // in order to always return an intersect point that is in front of the ray.
4860                 if ( t0 < 0 ) return this.at( t1, target );
4861
4862                 // else t0 is in front of the ray, so return the first collision point scaled by t0
4863                 return this.at( t0, target );
4864
4865         }
4866
4867         intersectsSphere( sphere ) {
4868
4869                 return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
4870
4871         }
4872
4873         distanceToPlane( plane ) {
4874
4875                 const denominator = plane.normal.dot( this.direction );
4876
4877                 if ( denominator === 0 ) {
4878
4879                         // line is coplanar, return origin
4880                         if ( plane.distanceToPoint( this.origin ) === 0 ) {
4881
4882                                 return 0;
4883
4884                         }
4885
4886                         // Null is preferable to undefined since undefined means.... it is undefined
4887
4888                         return null;
4889
4890                 }
4891
4892                 const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
4893
4894                 // Return if the ray never intersects the plane
4895
4896                 return t >= 0 ? t : null;
4897
4898         }
4899
4900         intersectPlane( plane, target ) {
4901
4902                 const t = this.distanceToPlane( plane );
4903
4904                 if ( t === null ) {
4905
4906                         return null;
4907
4908                 }
4909
4910                 return this.at( t, target );
4911
4912         }
4913
4914         intersectsPlane( plane ) {
4915
4916                 // check if the ray lies on the plane first
4917
4918                 const distToPoint = plane.distanceToPoint( this.origin );
4919
4920                 if ( distToPoint === 0 ) {
4921
4922                         return true;
4923
4924                 }
4925
4926                 const denominator = plane.normal.dot( this.direction );
4927
4928                 if ( denominator * distToPoint < 0 ) {
4929
4930                         return true;
4931
4932                 }
4933
4934                 // ray origin is behind the plane (and is pointing behind it)
4935
4936                 return false;
4937
4938         }
4939
4940         intersectBox( box, target ) {
4941
4942                 let tmin, tmax, tymin, tymax, tzmin, tzmax;
4943
4944                 const invdirx = 1 / this.direction.x,
4945                         invdiry = 1 / this.direction.y,
4946                         invdirz = 1 / this.direction.z;
4947
4948                 const origin = this.origin;
4949
4950                 if ( invdirx >= 0 ) {
4951
4952                         tmin = ( box.min.x - origin.x ) * invdirx;
4953                         tmax = ( box.max.x - origin.x ) * invdirx;
4954
4955                 } else {
4956
4957                         tmin = ( box.max.x - origin.x ) * invdirx;
4958                         tmax = ( box.min.x - origin.x ) * invdirx;
4959
4960                 }
4961
4962                 if ( invdiry >= 0 ) {
4963
4964                         tymin = ( box.min.y - origin.y ) * invdiry;
4965                         tymax = ( box.max.y - origin.y ) * invdiry;
4966
4967                 } else {
4968
4969                         tymin = ( box.max.y - origin.y ) * invdiry;
4970                         tymax = ( box.min.y - origin.y ) * invdiry;
4971
4972                 }
4973
4974                 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
4975
4976                 // These lines also handle the case where tmin or tmax is NaN
4977                 // (result of 0 * Infinity). x !== x returns true if x is NaN
4978
4979                 if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
4980
4981                 if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
4982
4983                 if ( invdirz >= 0 ) {
4984
4985                         tzmin = ( box.min.z - origin.z ) * invdirz;
4986                         tzmax = ( box.max.z - origin.z ) * invdirz;
4987
4988                 } else {
4989
4990                         tzmin = ( box.max.z - origin.z ) * invdirz;
4991                         tzmax = ( box.min.z - origin.z ) * invdirz;
4992
4993                 }
4994
4995                 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
4996
4997                 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
4998
4999                 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
5000
5001                 //return point closest to the ray (positive side)
5002
5003                 if ( tmax < 0 ) return null;
5004
5005                 return this.at( tmin >= 0 ? tmin : tmax, target );
5006
5007         }
5008
5009         intersectsBox( box ) {
5010
5011                 return this.intersectBox( box, _vector$2 ) !== null;
5012
5013         }
5014
5015         intersectTriangle( a, b, c, backfaceCulling, target ) {
5016
5017                 // Compute the offset origin, edges, and normal.
5018
5019                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
5020
5021                 _edge1.subVectors( b, a );
5022                 _edge2.subVectors( c, a );
5023                 _normal.crossVectors( _edge1, _edge2 );
5024
5025                 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
5026                 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
5027                 //   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
5028                 //   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
5029                 //   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
5030                 let DdN = this.direction.dot( _normal );
5031                 let sign;
5032
5033                 if ( DdN > 0 ) {
5034
5035                         if ( backfaceCulling ) return null;
5036                         sign = 1;
5037
5038                 } else if ( DdN < 0 ) {
5039
5040                         sign = - 1;
5041                         DdN = - DdN;
5042
5043                 } else {
5044
5045                         return null;
5046
5047                 }
5048
5049                 _diff.subVectors( this.origin, a );
5050                 const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
5051
5052                 // b1 < 0, no intersection
5053                 if ( DdQxE2 < 0 ) {
5054
5055                         return null;
5056
5057                 }
5058
5059                 const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
5060
5061                 // b2 < 0, no intersection
5062                 if ( DdE1xQ < 0 ) {
5063
5064                         return null;
5065
5066                 }
5067
5068                 // b1+b2 > 1, no intersection
5069                 if ( DdQxE2 + DdE1xQ > DdN ) {
5070
5071                         return null;
5072
5073                 }
5074
5075                 // Line intersects triangle, check if ray does.
5076                 const QdN = - sign * _diff.dot( _normal );
5077
5078                 // t < 0, no intersection
5079                 if ( QdN < 0 ) {
5080
5081                         return null;
5082
5083                 }
5084
5085                 // Ray intersects triangle.
5086                 return this.at( QdN / DdN, target );
5087
5088         }
5089
5090         applyMatrix4( matrix4 ) {
5091
5092                 this.origin.applyMatrix4( matrix4 );
5093                 this.direction.transformDirection( matrix4 );
5094
5095                 return this;
5096
5097         }
5098
5099         equals( ray ) {
5100
5101                 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
5102
5103         }
5104
5105 }
5106
5107 class Matrix4 {
5108
5109         constructor() {
5110
5111                 Object.defineProperty( this, 'isMatrix4', { value: true } );
5112
5113                 this.elements = [
5114
5115                         1, 0, 0, 0,
5116                         0, 1, 0, 0,
5117                         0, 0, 1, 0,
5118                         0, 0, 0, 1
5119
5120                 ];
5121
5122                 if ( arguments.length > 0 ) {
5123
5124                         console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
5125
5126                 }
5127
5128         }
5129
5130         set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
5131
5132                 const te = this.elements;
5133
5134                 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
5135                 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
5136                 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
5137                 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
5138
5139                 return this;
5140
5141         }
5142
5143         identity() {
5144
5145                 this.set(
5146
5147                         1, 0, 0, 0,
5148                         0, 1, 0, 0,
5149                         0, 0, 1, 0,
5150                         0, 0, 0, 1
5151
5152                 );
5153
5154                 return this;
5155
5156         }
5157
5158         clone() {
5159
5160                 return new Matrix4().fromArray( this.elements );
5161
5162         }
5163
5164         copy( m ) {
5165
5166                 const te = this.elements;
5167                 const me = m.elements;
5168
5169                 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
5170                 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
5171                 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
5172                 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
5173
5174                 return this;
5175
5176         }
5177
5178         copyPosition( m ) {
5179
5180                 const te = this.elements, me = m.elements;
5181
5182                 te[ 12 ] = me[ 12 ];
5183                 te[ 13 ] = me[ 13 ];
5184                 te[ 14 ] = me[ 14 ];
5185
5186                 return this;
5187
5188         }
5189
5190         setFromMatrix3( m ) {
5191
5192                 const me = m.elements;
5193
5194                 this.set(
5195
5196                         me[ 0 ], me[ 3 ], me[ 6 ], 0,
5197                         me[ 1 ], me[ 4 ], me[ 7 ], 0,
5198                         me[ 2 ], me[ 5 ], me[ 8 ], 0,
5199                         0, 0, 0, 1
5200
5201                 );
5202
5203                 return this;
5204
5205         }
5206
5207         extractBasis( xAxis, yAxis, zAxis ) {
5208
5209                 xAxis.setFromMatrixColumn( this, 0 );
5210                 yAxis.setFromMatrixColumn( this, 1 );
5211                 zAxis.setFromMatrixColumn( this, 2 );
5212
5213                 return this;
5214
5215         }
5216
5217         makeBasis( xAxis, yAxis, zAxis ) {
5218
5219                 this.set(
5220                         xAxis.x, yAxis.x, zAxis.x, 0,
5221                         xAxis.y, yAxis.y, zAxis.y, 0,
5222                         xAxis.z, yAxis.z, zAxis.z, 0,
5223                         0, 0, 0, 1
5224                 );
5225
5226                 return this;
5227
5228         }
5229
5230         extractRotation( m ) {
5231
5232                 // this method does not support reflection matrices
5233
5234                 const te = this.elements;
5235                 const me = m.elements;
5236
5237                 const scaleX = 1 / _v1$1.setFromMatrixColumn( m, 0 ).length();
5238                 const scaleY = 1 / _v1$1.setFromMatrixColumn( m, 1 ).length();
5239                 const scaleZ = 1 / _v1$1.setFromMatrixColumn( m, 2 ).length();
5240
5241                 te[ 0 ] = me[ 0 ] * scaleX;
5242                 te[ 1 ] = me[ 1 ] * scaleX;
5243                 te[ 2 ] = me[ 2 ] * scaleX;
5244                 te[ 3 ] = 0;
5245
5246                 te[ 4 ] = me[ 4 ] * scaleY;
5247                 te[ 5 ] = me[ 5 ] * scaleY;
5248                 te[ 6 ] = me[ 6 ] * scaleY;
5249                 te[ 7 ] = 0;
5250
5251                 te[ 8 ] = me[ 8 ] * scaleZ;
5252                 te[ 9 ] = me[ 9 ] * scaleZ;
5253                 te[ 10 ] = me[ 10 ] * scaleZ;
5254                 te[ 11 ] = 0;
5255
5256                 te[ 12 ] = 0;
5257                 te[ 13 ] = 0;
5258                 te[ 14 ] = 0;
5259                 te[ 15 ] = 1;
5260
5261                 return this;
5262
5263         }
5264
5265         makeRotationFromEuler( euler ) {
5266
5267                 if ( ! ( euler && euler.isEuler ) ) {
5268
5269                         console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
5270
5271                 }
5272
5273                 const te = this.elements;
5274
5275                 const x = euler.x, y = euler.y, z = euler.z;
5276                 const a = Math.cos( x ), b = Math.sin( x );
5277                 const c = Math.cos( y ), d = Math.sin( y );
5278                 const e = Math.cos( z ), f = Math.sin( z );
5279
5280                 if ( euler.order === 'XYZ' ) {
5281
5282                         const ae = a * e, af = a * f, be = b * e, bf = b * f;
5283
5284                         te[ 0 ] = c * e;
5285                         te[ 4 ] = - c * f;
5286                         te[ 8 ] = d;
5287
5288                         te[ 1 ] = af + be * d;
5289                         te[ 5 ] = ae - bf * d;
5290                         te[ 9 ] = - b * c;
5291
5292                         te[ 2 ] = bf - ae * d;
5293                         te[ 6 ] = be + af * d;
5294                         te[ 10 ] = a * c;
5295
5296                 } else if ( euler.order === 'YXZ' ) {
5297
5298                         const ce = c * e, cf = c * f, de = d * e, df = d * f;
5299
5300                         te[ 0 ] = ce + df * b;
5301                         te[ 4 ] = de * b - cf;
5302                         te[ 8 ] = a * d;
5303
5304                         te[ 1 ] = a * f;
5305                         te[ 5 ] = a * e;
5306                         te[ 9 ] = - b;
5307
5308                         te[ 2 ] = cf * b - de;
5309                         te[ 6 ] = df + ce * b;
5310                         te[ 10 ] = a * c;
5311
5312                 } else if ( euler.order === 'ZXY' ) {
5313
5314                         const ce = c * e, cf = c * f, de = d * e, df = d * f;
5315
5316                         te[ 0 ] = ce - df * b;
5317                         te[ 4 ] = - a * f;
5318                         te[ 8 ] = de + cf * b;
5319
5320                         te[ 1 ] = cf + de * b;
5321                         te[ 5 ] = a * e;
5322                         te[ 9 ] = df - ce * b;
5323
5324                         te[ 2 ] = - a * d;
5325                         te[ 6 ] = b;
5326                         te[ 10 ] = a * c;
5327
5328                 } else if ( euler.order === 'ZYX' ) {
5329
5330                         const ae = a * e, af = a * f, be = b * e, bf = b * f;
5331
5332                         te[ 0 ] = c * e;
5333                         te[ 4 ] = be * d - af;
5334                         te[ 8 ] = ae * d + bf;
5335
5336                         te[ 1 ] = c * f;
5337                         te[ 5 ] = bf * d + ae;
5338                         te[ 9 ] = af * d - be;
5339
5340                         te[ 2 ] = - d;
5341                         te[ 6 ] = b * c;
5342                         te[ 10 ] = a * c;
5343
5344                 } else if ( euler.order === 'YZX' ) {
5345
5346                         const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
5347
5348                         te[ 0 ] = c * e;
5349                         te[ 4 ] = bd - ac * f;
5350                         te[ 8 ] = bc * f + ad;
5351
5352                         te[ 1 ] = f;
5353                         te[ 5 ] = a * e;
5354                         te[ 9 ] = - b * e;
5355
5356                         te[ 2 ] = - d * e;
5357                         te[ 6 ] = ad * f + bc;
5358                         te[ 10 ] = ac - bd * f;
5359
5360                 } else if ( euler.order === 'XZY' ) {
5361
5362                         const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
5363
5364                         te[ 0 ] = c * e;
5365                         te[ 4 ] = - f;
5366                         te[ 8 ] = d * e;
5367
5368                         te[ 1 ] = ac * f + bd;
5369                         te[ 5 ] = a * e;
5370                         te[ 9 ] = ad * f - bc;
5371
5372                         te[ 2 ] = bc * f - ad;
5373                         te[ 6 ] = b * e;
5374                         te[ 10 ] = bd * f + ac;
5375
5376                 }
5377
5378                 // bottom row
5379                 te[ 3 ] = 0;
5380                 te[ 7 ] = 0;
5381                 te[ 11 ] = 0;
5382
5383                 // last column
5384                 te[ 12 ] = 0;
5385                 te[ 13 ] = 0;
5386                 te[ 14 ] = 0;
5387                 te[ 15 ] = 1;
5388
5389                 return this;
5390
5391         }
5392
5393         makeRotationFromQuaternion( q ) {
5394
5395                 return this.compose( _zero, q, _one );
5396
5397         }
5398
5399         lookAt( eye, target, up ) {
5400
5401                 const te = this.elements;
5402
5403                 _z.subVectors( eye, target );
5404
5405                 if ( _z.lengthSq() === 0 ) {
5406
5407                         // eye and target are in the same position
5408
5409                         _z.z = 1;
5410
5411                 }
5412
5413                 _z.normalize();
5414                 _x.crossVectors( up, _z );
5415
5416                 if ( _x.lengthSq() === 0 ) {
5417
5418                         // up and z are parallel
5419
5420                         if ( Math.abs( up.z ) === 1 ) {
5421
5422                                 _z.x += 0.0001;
5423
5424                         } else {
5425
5426                                 _z.z += 0.0001;
5427
5428                         }
5429
5430                         _z.normalize();
5431                         _x.crossVectors( up, _z );
5432
5433                 }
5434
5435                 _x.normalize();
5436                 _y.crossVectors( _z, _x );
5437
5438                 te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
5439                 te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
5440                 te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
5441
5442                 return this;
5443
5444         }
5445
5446         multiply( m, n ) {
5447
5448                 if ( n !== undefined ) {
5449
5450                         console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
5451                         return this.multiplyMatrices( m, n );
5452
5453                 }
5454
5455                 return this.multiplyMatrices( this, m );
5456
5457         }
5458
5459         premultiply( m ) {
5460
5461                 return this.multiplyMatrices( m, this );
5462
5463         }
5464
5465         multiplyMatrices( a, b ) {
5466
5467                 const ae = a.elements;
5468                 const be = b.elements;
5469                 const te = this.elements;
5470
5471                 const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
5472                 const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
5473                 const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
5474                 const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
5475
5476                 const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
5477                 const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
5478                 const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
5479                 const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
5480
5481                 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
5482                 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
5483                 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
5484                 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
5485
5486                 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
5487                 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
5488                 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
5489                 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
5490
5491                 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
5492                 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
5493                 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
5494                 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
5495
5496                 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
5497                 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
5498                 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
5499                 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
5500
5501                 return this;
5502
5503         }
5504
5505         multiplyScalar( s ) {
5506
5507                 const te = this.elements;
5508
5509                 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
5510                 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
5511                 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
5512                 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
5513
5514                 return this;
5515
5516         }
5517
5518         determinant() {
5519
5520                 const te = this.elements;
5521
5522                 const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
5523                 const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
5524                 const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
5525                 const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
5526
5527                 //TODO: make this more efficient
5528                 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
5529
5530                 return (
5531                         n41 * (
5532                                 + n14 * n23 * n32
5533                                  - n13 * n24 * n32
5534                                  - n14 * n22 * n33
5535                                  + n12 * n24 * n33
5536                                  + n13 * n22 * n34
5537                                  - n12 * n23 * n34
5538                         ) +
5539                         n42 * (
5540                                 + n11 * n23 * n34
5541                                  - n11 * n24 * n33
5542                                  + n14 * n21 * n33
5543                                  - n13 * n21 * n34
5544                                  + n13 * n24 * n31
5545                                  - n14 * n23 * n31
5546                         ) +
5547                         n43 * (
5548                                 + n11 * n24 * n32
5549                                  - n11 * n22 * n34
5550                                  - n14 * n21 * n32
5551                                  + n12 * n21 * n34
5552                                  + n14 * n22 * n31
5553                                  - n12 * n24 * n31
5554                         ) +
5555                         n44 * (
5556                                 - n13 * n22 * n31
5557                                  - n11 * n23 * n32
5558                                  + n11 * n22 * n33
5559                                  + n13 * n21 * n32
5560                                  - n12 * n21 * n33
5561                                  + n12 * n23 * n31
5562                         )
5563
5564                 );
5565
5566         }
5567
5568         transpose() {
5569
5570                 const te = this.elements;
5571                 let tmp;
5572
5573                 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
5574                 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
5575                 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
5576
5577                 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
5578                 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
5579                 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
5580
5581                 return this;
5582
5583         }
5584
5585         setPosition( x, y, z ) {
5586
5587                 const te = this.elements;
5588
5589                 if ( x.isVector3 ) {
5590
5591                         te[ 12 ] = x.x;
5592                         te[ 13 ] = x.y;
5593                         te[ 14 ] = x.z;
5594
5595                 } else {
5596
5597                         te[ 12 ] = x;
5598                         te[ 13 ] = y;
5599                         te[ 14 ] = z;
5600
5601                 }
5602
5603                 return this;
5604
5605         }
5606
5607         invert() {
5608
5609                 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
5610                 const te = this.elements,
5611
5612                         n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
5613                         n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
5614                         n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
5615                         n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
5616
5617                         t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
5618                         t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
5619                         t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
5620                         t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
5621
5622                 const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
5623
5624                 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
5625
5626                 const detInv = 1 / det;
5627
5628                 te[ 0 ] = t11 * detInv;
5629                 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
5630                 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
5631                 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
5632
5633                 te[ 4 ] = t12 * detInv;
5634                 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
5635                 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
5636                 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
5637
5638                 te[ 8 ] = t13 * detInv;
5639                 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
5640                 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
5641                 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
5642
5643                 te[ 12 ] = t14 * detInv;
5644                 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
5645                 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
5646                 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
5647
5648                 return this;
5649
5650         }
5651
5652         scale( v ) {
5653
5654                 const te = this.elements;
5655                 const x = v.x, y = v.y, z = v.z;
5656
5657                 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
5658                 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
5659                 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
5660                 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
5661
5662                 return this;
5663
5664         }
5665
5666         getMaxScaleOnAxis() {
5667
5668                 const te = this.elements;
5669
5670                 const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
5671                 const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
5672                 const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
5673
5674                 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
5675
5676         }
5677
5678         makeTranslation( x, y, z ) {
5679
5680                 this.set(
5681
5682                         1, 0, 0, x,
5683                         0, 1, 0, y,
5684                         0, 0, 1, z,
5685                         0, 0, 0, 1
5686
5687                 );
5688
5689                 return this;
5690
5691         }
5692
5693         makeRotationX( theta ) {
5694
5695                 const c = Math.cos( theta ), s = Math.sin( theta );
5696
5697                 this.set(
5698
5699                         1, 0, 0, 0,
5700                         0, c, - s, 0,
5701                         0, s, c, 0,
5702                         0, 0, 0, 1
5703
5704                 );
5705
5706                 return this;
5707
5708         }
5709
5710         makeRotationY( theta ) {
5711
5712                 const c = Math.cos( theta ), s = Math.sin( theta );
5713
5714                 this.set(
5715
5716                          c, 0, s, 0,
5717                          0, 1, 0, 0,
5718                         - s, 0, c, 0,
5719                          0, 0, 0, 1
5720
5721                 );
5722
5723                 return this;
5724
5725         }
5726
5727         makeRotationZ( theta ) {
5728
5729                 const c = Math.cos( theta ), s = Math.sin( theta );
5730
5731                 this.set(
5732
5733                         c, - s, 0, 0,
5734                         s, c, 0, 0,
5735                         0, 0, 1, 0,
5736                         0, 0, 0, 1
5737
5738                 );
5739
5740                 return this;
5741
5742         }
5743
5744         makeRotationAxis( axis, angle ) {
5745
5746                 // Based on http://www.gamedev.net/reference/articles/article1199.asp
5747
5748                 const c = Math.cos( angle );
5749                 const s = Math.sin( angle );
5750                 const t = 1 - c;
5751                 const x = axis.x, y = axis.y, z = axis.z;
5752                 const tx = t * x, ty = t * y;
5753
5754                 this.set(
5755
5756                         tx * x + c, tx * y - s * z, tx * z + s * y, 0,
5757                         tx * y + s * z, ty * y + c, ty * z - s * x, 0,
5758                         tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
5759                         0, 0, 0, 1
5760
5761                 );
5762
5763                 return this;
5764
5765         }
5766
5767         makeScale( x, y, z ) {
5768
5769                 this.set(
5770
5771                         x, 0, 0, 0,
5772                         0, y, 0, 0,
5773                         0, 0, z, 0,
5774                         0, 0, 0, 1
5775
5776                 );
5777
5778                 return this;
5779
5780         }
5781
5782         makeShear( x, y, z ) {
5783
5784                 this.set(
5785
5786                         1, y, z, 0,
5787                         x, 1, z, 0,
5788                         x, y, 1, 0,
5789                         0, 0, 0, 1
5790
5791                 );
5792
5793                 return this;
5794
5795         }
5796
5797         compose( position, quaternion, scale ) {
5798
5799                 const te = this.elements;
5800
5801                 const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
5802                 const x2 = x + x,       y2 = y + y, z2 = z + z;
5803                 const xx = x * x2, xy = x * y2, xz = x * z2;
5804                 const yy = y * y2, yz = y * z2, zz = z * z2;
5805                 const wx = w * x2, wy = w * y2, wz = w * z2;
5806
5807                 const sx = scale.x, sy = scale.y, sz = scale.z;
5808
5809                 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
5810                 te[ 1 ] = ( xy + wz ) * sx;
5811                 te[ 2 ] = ( xz - wy ) * sx;
5812                 te[ 3 ] = 0;
5813
5814                 te[ 4 ] = ( xy - wz ) * sy;
5815                 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
5816                 te[ 6 ] = ( yz + wx ) * sy;
5817                 te[ 7 ] = 0;
5818
5819                 te[ 8 ] = ( xz + wy ) * sz;
5820                 te[ 9 ] = ( yz - wx ) * sz;
5821                 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
5822                 te[ 11 ] = 0;
5823
5824                 te[ 12 ] = position.x;
5825                 te[ 13 ] = position.y;
5826                 te[ 14 ] = position.z;
5827                 te[ 15 ] = 1;
5828
5829                 return this;
5830
5831         }
5832
5833         decompose( position, quaternion, scale ) {
5834
5835                 const te = this.elements;
5836
5837                 let sx = _v1$1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
5838                 const sy = _v1$1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
5839                 const sz = _v1$1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
5840
5841                 // if determine is negative, we need to invert one scale
5842                 const det = this.determinant();
5843                 if ( det < 0 ) sx = - sx;
5844
5845                 position.x = te[ 12 ];
5846                 position.y = te[ 13 ];
5847                 position.z = te[ 14 ];
5848
5849                 // scale the rotation part
5850                 _m1.copy( this );
5851
5852                 const invSX = 1 / sx;
5853                 const invSY = 1 / sy;
5854                 const invSZ = 1 / sz;
5855
5856                 _m1.elements[ 0 ] *= invSX;
5857                 _m1.elements[ 1 ] *= invSX;
5858                 _m1.elements[ 2 ] *= invSX;
5859
5860                 _m1.elements[ 4 ] *= invSY;
5861                 _m1.elements[ 5 ] *= invSY;
5862                 _m1.elements[ 6 ] *= invSY;
5863
5864                 _m1.elements[ 8 ] *= invSZ;
5865                 _m1.elements[ 9 ] *= invSZ;
5866                 _m1.elements[ 10 ] *= invSZ;
5867
5868                 quaternion.setFromRotationMatrix( _m1 );
5869
5870                 scale.x = sx;
5871                 scale.y = sy;
5872                 scale.z = sz;
5873
5874                 return this;
5875
5876         }
5877
5878         makePerspective( left, right, top, bottom, near, far ) {
5879
5880                 if ( far === undefined ) {
5881
5882                         console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
5883
5884                 }
5885
5886                 const te = this.elements;
5887                 const x = 2 * near / ( right - left );
5888                 const y = 2 * near / ( top - bottom );
5889
5890                 const a = ( right + left ) / ( right - left );
5891                 const b = ( top + bottom ) / ( top - bottom );
5892                 const c = - ( far + near ) / ( far - near );
5893                 const d = - 2 * far * near / ( far - near );
5894
5895                 te[ 0 ] = x;    te[ 4 ] = 0;    te[ 8 ] = a;    te[ 12 ] = 0;
5896                 te[ 1 ] = 0;    te[ 5 ] = y;    te[ 9 ] = b;    te[ 13 ] = 0;
5897                 te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = c;   te[ 14 ] = d;
5898                 te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = - 1; te[ 15 ] = 0;
5899
5900                 return this;
5901
5902         }
5903
5904         makeOrthographic( left, right, top, bottom, near, far ) {
5905
5906                 const te = this.elements;
5907                 const w = 1.0 / ( right - left );
5908                 const h = 1.0 / ( top - bottom );
5909                 const p = 1.0 / ( far - near );
5910
5911                 const x = ( right + left ) * w;
5912                 const y = ( top + bottom ) * h;
5913                 const z = ( far + near ) * p;
5914
5915                 te[ 0 ] = 2 * w;        te[ 4 ] = 0;    te[ 8 ] = 0;    te[ 12 ] = - x;
5916                 te[ 1 ] = 0;    te[ 5 ] = 2 * h;        te[ 9 ] = 0;    te[ 13 ] = - y;
5917                 te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = - 2 * p;     te[ 14 ] = - z;
5918                 te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = 0;   te[ 15 ] = 1;
5919
5920                 return this;
5921
5922         }
5923
5924         equals( matrix ) {
5925
5926                 const te = this.elements;
5927                 const me = matrix.elements;
5928
5929                 for ( let i = 0; i < 16; i ++ ) {
5930
5931                         if ( te[ i ] !== me[ i ] ) return false;
5932
5933                 }
5934
5935                 return true;
5936
5937         }
5938
5939         fromArray( array, offset = 0 ) {
5940
5941                 for ( let i = 0; i < 16; i ++ ) {
5942
5943                         this.elements[ i ] = array[ i + offset ];
5944
5945                 }
5946
5947                 return this;
5948
5949         }
5950
5951         toArray( array = [], offset = 0 ) {
5952
5953                 const te = this.elements;
5954
5955                 array[ offset ] = te[ 0 ];
5956                 array[ offset + 1 ] = te[ 1 ];
5957                 array[ offset + 2 ] = te[ 2 ];
5958                 array[ offset + 3 ] = te[ 3 ];
5959
5960                 array[ offset + 4 ] = te[ 4 ];
5961                 array[ offset + 5 ] = te[ 5 ];
5962                 array[ offset + 6 ] = te[ 6 ];
5963                 array[ offset + 7 ] = te[ 7 ];
5964
5965                 array[ offset + 8 ] = te[ 8 ];
5966                 array[ offset + 9 ] = te[ 9 ];
5967                 array[ offset + 10 ] = te[ 10 ];
5968                 array[ offset + 11 ] = te[ 11 ];
5969
5970                 array[ offset + 12 ] = te[ 12 ];
5971                 array[ offset + 13 ] = te[ 13 ];
5972                 array[ offset + 14 ] = te[ 14 ];
5973                 array[ offset + 15 ] = te[ 15 ];
5974
5975                 return array;
5976
5977         }
5978
5979 }
5980
5981 const _v1$1 = /*@__PURE__*/ new Vector3();
5982 const _m1 = /*@__PURE__*/ new Matrix4();
5983 const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
5984 const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
5985 const _x = /*@__PURE__*/ new Vector3();
5986 const _y = /*@__PURE__*/ new Vector3();
5987 const _z = /*@__PURE__*/ new Vector3();
5988
5989 class Euler {
5990
5991         constructor( x = 0, y = 0, z = 0, order = Euler.DefaultOrder ) {
5992
5993                 Object.defineProperty( this, 'isEuler', { value: true } );
5994
5995                 this._x = x;
5996                 this._y = y;
5997                 this._z = z;
5998                 this._order = order;
5999
6000         }
6001
6002         get x() {
6003
6004                 return this._x;
6005
6006         }
6007
6008         set x( value ) {
6009
6010                 this._x = value;
6011                 this._onChangeCallback();
6012
6013         }
6014
6015         get y() {
6016
6017                 return this._y;
6018
6019         }
6020
6021         set y( value ) {
6022
6023                 this._y = value;
6024                 this._onChangeCallback();
6025
6026         }
6027
6028         get z() {
6029
6030                 return this._z;
6031
6032         }
6033
6034         set z( value ) {
6035
6036                 this._z = value;
6037                 this._onChangeCallback();
6038
6039         }
6040
6041         get order() {
6042
6043                 return this._order;
6044
6045         }
6046
6047         set order( value ) {
6048
6049                 this._order = value;
6050                 this._onChangeCallback();
6051
6052         }
6053
6054         set( x, y, z, order ) {
6055
6056                 this._x = x;
6057                 this._y = y;
6058                 this._z = z;
6059                 this._order = order || this._order;
6060
6061                 this._onChangeCallback();
6062
6063                 return this;
6064
6065         }
6066
6067         clone() {
6068
6069                 return new this.constructor( this._x, this._y, this._z, this._order );
6070
6071         }
6072
6073         copy( euler ) {
6074
6075                 this._x = euler._x;
6076                 this._y = euler._y;
6077                 this._z = euler._z;
6078                 this._order = euler._order;
6079
6080                 this._onChangeCallback();
6081
6082                 return this;
6083
6084         }
6085
6086         setFromRotationMatrix( m, order, update ) {
6087
6088                 const clamp = MathUtils.clamp;
6089
6090                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6091
6092                 const te = m.elements;
6093                 const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
6094                 const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
6095                 const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
6096
6097                 order = order || this._order;
6098
6099                 switch ( order ) {
6100
6101                         case 'XYZ':
6102
6103                                 this._y = Math.asin( clamp( m13, - 1, 1 ) );
6104
6105                                 if ( Math.abs( m13 ) < 0.9999999 ) {
6106
6107                                         this._x = Math.atan2( - m23, m33 );
6108                                         this._z = Math.atan2( - m12, m11 );
6109
6110                                 } else {
6111
6112                                         this._x = Math.atan2( m32, m22 );
6113                                         this._z = 0;
6114
6115                                 }
6116
6117                                 break;
6118
6119                         case 'YXZ':
6120
6121                                 this._x = Math.asin( - clamp( m23, - 1, 1 ) );
6122
6123                                 if ( Math.abs( m23 ) < 0.9999999 ) {
6124
6125                                         this._y = Math.atan2( m13, m33 );
6126                                         this._z = Math.atan2( m21, m22 );
6127
6128                                 } else {
6129
6130                                         this._y = Math.atan2( - m31, m11 );
6131                                         this._z = 0;
6132
6133                                 }
6134
6135                                 break;
6136
6137                         case 'ZXY':
6138
6139                                 this._x = Math.asin( clamp( m32, - 1, 1 ) );
6140
6141                                 if ( Math.abs( m32 ) < 0.9999999 ) {
6142
6143                                         this._y = Math.atan2( - m31, m33 );
6144                                         this._z = Math.atan2( - m12, m22 );
6145
6146                                 } else {
6147
6148                                         this._y = 0;
6149                                         this._z = Math.atan2( m21, m11 );
6150
6151                                 }
6152
6153                                 break;
6154
6155                         case 'ZYX':
6156
6157                                 this._y = Math.asin( - clamp( m31, - 1, 1 ) );
6158
6159                                 if ( Math.abs( m31 ) < 0.9999999 ) {
6160
6161                                         this._x = Math.atan2( m32, m33 );
6162                                         this._z = Math.atan2( m21, m11 );
6163
6164                                 } else {
6165
6166                                         this._x = 0;
6167                                         this._z = Math.atan2( - m12, m22 );
6168
6169                                 }
6170
6171                                 break;
6172
6173                         case 'YZX':
6174
6175                                 this._z = Math.asin( clamp( m21, - 1, 1 ) );
6176
6177                                 if ( Math.abs( m21 ) < 0.9999999 ) {
6178
6179                                         this._x = Math.atan2( - m23, m22 );
6180                                         this._y = Math.atan2( - m31, m11 );
6181
6182                                 } else {
6183
6184                                         this._x = 0;
6185                                         this._y = Math.atan2( m13, m33 );
6186
6187                                 }
6188
6189                                 break;
6190
6191                         case 'XZY':
6192
6193                                 this._z = Math.asin( - clamp( m12, - 1, 1 ) );
6194
6195                                 if ( Math.abs( m12 ) < 0.9999999 ) {
6196
6197                                         this._x = Math.atan2( m32, m22 );
6198                                         this._y = Math.atan2( m13, m11 );
6199
6200                                 } else {
6201
6202                                         this._x = Math.atan2( - m23, m33 );
6203                                         this._y = 0;
6204
6205                                 }
6206
6207                                 break;
6208
6209                         default:
6210
6211                                 console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
6212
6213                 }
6214
6215                 this._order = order;
6216
6217                 if ( update !== false ) this._onChangeCallback();
6218
6219                 return this;
6220
6221         }
6222
6223         setFromQuaternion( q, order, update ) {
6224
6225                 _matrix.makeRotationFromQuaternion( q );
6226
6227                 return this.setFromRotationMatrix( _matrix, order, update );
6228
6229         }
6230
6231         setFromVector3( v, order ) {
6232
6233                 return this.set( v.x, v.y, v.z, order || this._order );
6234
6235         }
6236
6237         reorder( newOrder ) {
6238
6239                 // WARNING: this discards revolution information -bhouston
6240
6241                 _quaternion$1.setFromEuler( this );
6242
6243                 return this.setFromQuaternion( _quaternion$1, newOrder );
6244
6245         }
6246
6247         equals( euler ) {
6248
6249                 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
6250
6251         }
6252
6253         fromArray( array ) {
6254
6255                 this._x = array[ 0 ];
6256                 this._y = array[ 1 ];
6257                 this._z = array[ 2 ];
6258                 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
6259
6260                 this._onChangeCallback();
6261
6262                 return this;
6263
6264         }
6265
6266         toArray( array = [], offset = 0 ) {
6267
6268                 array[ offset ] = this._x;
6269                 array[ offset + 1 ] = this._y;
6270                 array[ offset + 2 ] = this._z;
6271                 array[ offset + 3 ] = this._order;
6272
6273                 return array;
6274
6275         }
6276
6277         toVector3( optionalResult ) {
6278
6279                 if ( optionalResult ) {
6280
6281                         return optionalResult.set( this._x, this._y, this._z );
6282
6283                 } else {
6284
6285                         return new Vector3( this._x, this._y, this._z );
6286
6287                 }
6288
6289         }
6290
6291         _onChange( callback ) {
6292
6293                 this._onChangeCallback = callback;
6294
6295                 return this;
6296
6297         }
6298
6299         _onChangeCallback() {}
6300
6301 }
6302
6303 Euler.DefaultOrder = 'XYZ';
6304 Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
6305
6306 const _matrix = /*@__PURE__*/ new Matrix4();
6307 const _quaternion$1 = /*@__PURE__*/ new Quaternion();
6308
6309 class Layers {
6310
6311         constructor() {
6312
6313                 this.mask = 1 | 0;
6314
6315         }
6316
6317         set( channel ) {
6318
6319                 this.mask = 1 << channel | 0;
6320
6321         }
6322
6323         enable( channel ) {
6324
6325                 this.mask |= 1 << channel | 0;
6326
6327         }
6328
6329         enableAll() {
6330
6331                 this.mask = 0xffffffff | 0;
6332
6333         }
6334
6335         toggle( channel ) {
6336
6337                 this.mask ^= 1 << channel | 0;
6338
6339         }
6340
6341         disable( channel ) {
6342
6343                 this.mask &= ~ ( 1 << channel | 0 );
6344
6345         }
6346
6347         disableAll() {
6348
6349                 this.mask = 0;
6350
6351         }
6352
6353         test( layers ) {
6354
6355                 return ( this.mask & layers.mask ) !== 0;
6356
6357         }
6358
6359 }
6360
6361 let _object3DId = 0;
6362
6363 const _v1$2 = new Vector3();
6364 const _q1 = new Quaternion();
6365 const _m1$1 = new Matrix4();
6366 const _target = new Vector3();
6367
6368 const _position = new Vector3();
6369 const _scale = new Vector3();
6370 const _quaternion$2 = new Quaternion();
6371
6372 const _xAxis = new Vector3( 1, 0, 0 );
6373 const _yAxis = new Vector3( 0, 1, 0 );
6374 const _zAxis = new Vector3( 0, 0, 1 );
6375
6376 const _addedEvent = { type: 'added' };
6377 const _removedEvent = { type: 'removed' };
6378
6379 function Object3D() {
6380
6381         Object.defineProperty( this, 'id', { value: _object3DId ++ } );
6382
6383         this.uuid = MathUtils.generateUUID();
6384
6385         this.name = '';
6386         this.type = 'Object3D';
6387
6388         this.parent = null;
6389         this.children = [];
6390
6391         this.up = Object3D.DefaultUp.clone();
6392
6393         const position = new Vector3();
6394         const rotation = new Euler();
6395         const quaternion = new Quaternion();
6396         const scale = new Vector3( 1, 1, 1 );
6397
6398         function onRotationChange() {
6399
6400                 quaternion.setFromEuler( rotation, false );
6401
6402         }
6403
6404         function onQuaternionChange() {
6405
6406                 rotation.setFromQuaternion( quaternion, undefined, false );
6407
6408         }
6409
6410         rotation._onChange( onRotationChange );
6411         quaternion._onChange( onQuaternionChange );
6412
6413         Object.defineProperties( this, {
6414                 position: {
6415                         configurable: true,
6416                         enumerable: true,
6417                         value: position
6418                 },
6419                 rotation: {
6420                         configurable: true,
6421                         enumerable: true,
6422                         value: rotation
6423                 },
6424                 quaternion: {
6425                         configurable: true,
6426                         enumerable: true,
6427                         value: quaternion
6428                 },
6429                 scale: {
6430                         configurable: true,
6431                         enumerable: true,
6432                         value: scale
6433                 },
6434                 modelViewMatrix: {
6435                         value: new Matrix4()
6436                 },
6437                 normalMatrix: {
6438                         value: new Matrix3()
6439                 }
6440         } );
6441
6442         this.matrix = new Matrix4();
6443         this.matrixWorld = new Matrix4();
6444
6445         this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
6446         this.matrixWorldNeedsUpdate = false;
6447
6448         this.layers = new Layers();
6449         this.visible = true;
6450
6451         this.castShadow = false;
6452         this.receiveShadow = false;
6453
6454         this.frustumCulled = true;
6455         this.renderOrder = 0;
6456
6457         this.animations = [];
6458
6459         this.userData = {};
6460
6461 }
6462
6463 Object3D.DefaultUp = new Vector3( 0, 1, 0 );
6464 Object3D.DefaultMatrixAutoUpdate = true;
6465
6466 Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
6467
6468         constructor: Object3D,
6469
6470         isObject3D: true,
6471
6472         onBeforeRender: function () {},
6473         onAfterRender: function () {},
6474
6475         applyMatrix4: function ( matrix ) {
6476
6477                 if ( this.matrixAutoUpdate ) this.updateMatrix();
6478
6479                 this.matrix.premultiply( matrix );
6480
6481                 this.matrix.decompose( this.position, this.quaternion, this.scale );
6482
6483         },
6484
6485         applyQuaternion: function ( q ) {
6486
6487                 this.quaternion.premultiply( q );
6488
6489                 return this;
6490
6491         },
6492
6493         setRotationFromAxisAngle: function ( axis, angle ) {
6494
6495                 // assumes axis is normalized
6496
6497                 this.quaternion.setFromAxisAngle( axis, angle );
6498
6499         },
6500
6501         setRotationFromEuler: function ( euler ) {
6502
6503                 this.quaternion.setFromEuler( euler, true );
6504
6505         },
6506
6507         setRotationFromMatrix: function ( m ) {
6508
6509                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6510
6511                 this.quaternion.setFromRotationMatrix( m );
6512
6513         },
6514
6515         setRotationFromQuaternion: function ( q ) {
6516
6517                 // assumes q is normalized
6518
6519                 this.quaternion.copy( q );
6520
6521         },
6522
6523         rotateOnAxis: function ( axis, angle ) {
6524
6525                 // rotate object on axis in object space
6526                 // axis is assumed to be normalized
6527
6528                 _q1.setFromAxisAngle( axis, angle );
6529
6530                 this.quaternion.multiply( _q1 );
6531
6532                 return this;
6533
6534         },
6535
6536         rotateOnWorldAxis: function ( axis, angle ) {
6537
6538                 // rotate object on axis in world space
6539                 // axis is assumed to be normalized
6540                 // method assumes no rotated parent
6541
6542                 _q1.setFromAxisAngle( axis, angle );
6543
6544                 this.quaternion.premultiply( _q1 );
6545
6546                 return this;
6547
6548         },
6549
6550         rotateX: function ( angle ) {
6551
6552                 return this.rotateOnAxis( _xAxis, angle );
6553
6554         },
6555
6556         rotateY: function ( angle ) {
6557
6558                 return this.rotateOnAxis( _yAxis, angle );
6559
6560         },
6561
6562         rotateZ: function ( angle ) {
6563
6564                 return this.rotateOnAxis( _zAxis, angle );
6565
6566         },
6567
6568         translateOnAxis: function ( axis, distance ) {
6569
6570                 // translate object by distance along axis in object space
6571                 // axis is assumed to be normalized
6572
6573                 _v1$2.copy( axis ).applyQuaternion( this.quaternion );
6574
6575                 this.position.add( _v1$2.multiplyScalar( distance ) );
6576
6577                 return this;
6578
6579         },
6580
6581         translateX: function ( distance ) {
6582
6583                 return this.translateOnAxis( _xAxis, distance );
6584
6585         },
6586
6587         translateY: function ( distance ) {
6588
6589                 return this.translateOnAxis( _yAxis, distance );
6590
6591         },
6592
6593         translateZ: function ( distance ) {
6594
6595                 return this.translateOnAxis( _zAxis, distance );
6596
6597         },
6598
6599         localToWorld: function ( vector ) {
6600
6601                 return vector.applyMatrix4( this.matrixWorld );
6602
6603         },
6604
6605         worldToLocal: function ( vector ) {
6606
6607                 return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
6608
6609         },
6610
6611         lookAt: function ( x, y, z ) {
6612
6613                 // This method does not support objects having non-uniformly-scaled parent(s)
6614
6615                 if ( x.isVector3 ) {
6616
6617                         _target.copy( x );
6618
6619                 } else {
6620
6621                         _target.set( x, y, z );
6622
6623                 }
6624
6625                 const parent = this.parent;
6626
6627                 this.updateWorldMatrix( true, false );
6628
6629                 _position.setFromMatrixPosition( this.matrixWorld );
6630
6631                 if ( this.isCamera || this.isLight ) {
6632
6633                         _m1$1.lookAt( _position, _target, this.up );
6634
6635                 } else {
6636
6637                         _m1$1.lookAt( _target, _position, this.up );
6638
6639                 }
6640
6641                 this.quaternion.setFromRotationMatrix( _m1$1 );
6642
6643                 if ( parent ) {
6644
6645                         _m1$1.extractRotation( parent.matrixWorld );
6646                         _q1.setFromRotationMatrix( _m1$1 );
6647                         this.quaternion.premultiply( _q1.invert() );
6648
6649                 }
6650
6651         },
6652
6653         add: function ( object ) {
6654
6655                 if ( arguments.length > 1 ) {
6656
6657                         for ( let i = 0; i < arguments.length; i ++ ) {
6658
6659                                 this.add( arguments[ i ] );
6660
6661                         }
6662
6663                         return this;
6664
6665                 }
6666
6667                 if ( object === this ) {
6668
6669                         console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object );
6670                         return this;
6671
6672                 }
6673
6674                 if ( object && object.isObject3D ) {
6675
6676                         if ( object.parent !== null ) {
6677
6678                                 object.parent.remove( object );
6679
6680                         }
6681
6682                         object.parent = this;
6683                         this.children.push( object );
6684
6685                         object.dispatchEvent( _addedEvent );
6686
6687                 } else {
6688
6689                         console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object );
6690
6691                 }
6692
6693                 return this;
6694
6695         },
6696
6697         remove: function ( object ) {
6698
6699                 if ( arguments.length > 1 ) {
6700
6701                         for ( let i = 0; i < arguments.length; i ++ ) {
6702
6703                                 this.remove( arguments[ i ] );
6704
6705                         }
6706
6707                         return this;
6708
6709                 }
6710
6711                 const index = this.children.indexOf( object );
6712
6713                 if ( index !== - 1 ) {
6714
6715                         object.parent = null;
6716                         this.children.splice( index, 1 );
6717
6718                         object.dispatchEvent( _removedEvent );
6719
6720                 }
6721
6722                 return this;
6723
6724         },
6725
6726         clear: function () {
6727
6728                 for ( let i = 0; i < this.children.length; i ++ ) {
6729
6730                         const object = this.children[ i ];
6731
6732                         object.parent = null;
6733
6734                         object.dispatchEvent( _removedEvent );
6735
6736                 }
6737
6738                 this.children.length = 0;
6739
6740                 return this;
6741
6742
6743         },
6744
6745         attach: function ( object ) {
6746
6747                 // adds object as a child of this, while maintaining the object's world transform
6748
6749                 this.updateWorldMatrix( true, false );
6750
6751                 _m1$1.copy( this.matrixWorld ).invert();
6752
6753                 if ( object.parent !== null ) {
6754
6755                         object.parent.updateWorldMatrix( true, false );
6756
6757                         _m1$1.multiply( object.parent.matrixWorld );
6758
6759                 }
6760
6761                 object.applyMatrix4( _m1$1 );
6762
6763                 object.updateWorldMatrix( false, false );
6764
6765                 this.add( object );
6766
6767                 return this;
6768
6769         },
6770
6771         getObjectById: function ( id ) {
6772
6773                 return this.getObjectByProperty( 'id', id );
6774
6775         },
6776
6777         getObjectByName: function ( name ) {
6778
6779                 return this.getObjectByProperty( 'name', name );
6780
6781         },
6782
6783         getObjectByProperty: function ( name, value ) {
6784
6785                 if ( this[ name ] === value ) return this;
6786
6787                 for ( let i = 0, l = this.children.length; i < l; i ++ ) {
6788
6789                         const child = this.children[ i ];
6790                         const object = child.getObjectByProperty( name, value );
6791
6792                         if ( object !== undefined ) {
6793
6794                                 return object;
6795
6796                         }
6797
6798                 }
6799
6800                 return undefined;
6801
6802         },
6803
6804         getWorldPosition: function ( target ) {
6805
6806                 if ( target === undefined ) {
6807
6808                         console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
6809                         target = new Vector3();
6810
6811                 }
6812
6813                 this.updateWorldMatrix( true, false );
6814
6815                 return target.setFromMatrixPosition( this.matrixWorld );
6816
6817         },
6818
6819         getWorldQuaternion: function ( target ) {
6820
6821                 if ( target === undefined ) {
6822
6823                         console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
6824                         target = new Quaternion();
6825
6826                 }
6827
6828                 this.updateWorldMatrix( true, false );
6829
6830                 this.matrixWorld.decompose( _position, target, _scale );
6831
6832                 return target;
6833
6834         },
6835
6836         getWorldScale: function ( target ) {
6837
6838                 if ( target === undefined ) {
6839
6840                         console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
6841                         target = new Vector3();
6842
6843                 }
6844
6845                 this.updateWorldMatrix( true, false );
6846
6847                 this.matrixWorld.decompose( _position, _quaternion$2, target );
6848
6849                 return target;
6850
6851         },
6852
6853         getWorldDirection: function ( target ) {
6854
6855                 if ( target === undefined ) {
6856
6857                         console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
6858                         target = new Vector3();
6859
6860                 }
6861
6862                 this.updateWorldMatrix( true, false );
6863
6864                 const e = this.matrixWorld.elements;
6865
6866                 return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
6867
6868         },
6869
6870         raycast: function () {},
6871
6872         traverse: function ( callback ) {
6873
6874                 callback( this );
6875
6876                 const children = this.children;
6877
6878                 for ( let i = 0, l = children.length; i < l; i ++ ) {
6879
6880                         children[ i ].traverse( callback );
6881
6882                 }
6883
6884         },
6885
6886         traverseVisible: function ( callback ) {
6887
6888                 if ( this.visible === false ) return;
6889
6890                 callback( this );
6891
6892                 const children = this.children;
6893
6894                 for ( let i = 0, l = children.length; i < l; i ++ ) {
6895
6896                         children[ i ].traverseVisible( callback );
6897
6898                 }
6899
6900         },
6901
6902         traverseAncestors: function ( callback ) {
6903
6904                 const parent = this.parent;
6905
6906                 if ( parent !== null ) {
6907
6908                         callback( parent );
6909
6910                         parent.traverseAncestors( callback );
6911
6912                 }
6913
6914         },
6915
6916         updateMatrix: function () {
6917
6918                 this.matrix.compose( this.position, this.quaternion, this.scale );
6919
6920                 this.matrixWorldNeedsUpdate = true;
6921
6922         },
6923
6924         updateMatrixWorld: function ( force ) {
6925
6926                 if ( this.matrixAutoUpdate ) this.updateMatrix();
6927
6928                 if ( this.matrixWorldNeedsUpdate || force ) {
6929
6930                         if ( this.parent === null ) {
6931
6932                                 this.matrixWorld.copy( this.matrix );
6933
6934                         } else {
6935
6936                                 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
6937
6938                         }
6939
6940                         this.matrixWorldNeedsUpdate = false;
6941
6942                         force = true;
6943
6944                 }
6945
6946                 // update children
6947
6948                 const children = this.children;
6949
6950                 for ( let i = 0, l = children.length; i < l; i ++ ) {
6951
6952                         children[ i ].updateMatrixWorld( force );
6953
6954                 }
6955
6956         },
6957
6958         updateWorldMatrix: function ( updateParents, updateChildren ) {
6959
6960                 const parent = this.parent;
6961
6962                 if ( updateParents === true && parent !== null ) {
6963
6964                         parent.updateWorldMatrix( true, false );
6965
6966                 }
6967
6968                 if ( this.matrixAutoUpdate ) this.updateMatrix();
6969
6970                 if ( this.parent === null ) {
6971
6972                         this.matrixWorld.copy( this.matrix );
6973
6974                 } else {
6975
6976                         this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
6977
6978                 }
6979
6980                 // update children
6981
6982                 if ( updateChildren === true ) {
6983
6984                         const children = this.children;
6985
6986                         for ( let i = 0, l = children.length; i < l; i ++ ) {
6987
6988                                 children[ i ].updateWorldMatrix( false, true );
6989
6990                         }
6991
6992                 }
6993
6994         },
6995
6996         toJSON: function ( meta ) {
6997
6998                 // meta is a string when called from JSON.stringify
6999                 const isRootObject = ( meta === undefined || typeof meta === 'string' );
7000
7001                 const output = {};
7002
7003                 // meta is a hash used to collect geometries, materials.
7004                 // not providing it implies that this is the root object
7005                 // being serialized.
7006                 if ( isRootObject ) {
7007
7008                         // initialize meta obj
7009                         meta = {
7010                                 geometries: {},
7011                                 materials: {},
7012                                 textures: {},
7013                                 images: {},
7014                                 shapes: {},
7015                                 skeletons: {},
7016                                 animations: {}
7017                         };
7018
7019                         output.metadata = {
7020                                 version: 4.5,
7021                                 type: 'Object',
7022                                 generator: 'Object3D.toJSON'
7023                         };
7024
7025                 }
7026
7027                 // standard Object3D serialization
7028
7029                 const object = {};
7030
7031                 object.uuid = this.uuid;
7032                 object.type = this.type;
7033
7034                 if ( this.name !== '' ) object.name = this.name;
7035                 if ( this.castShadow === true ) object.castShadow = true;
7036                 if ( this.receiveShadow === true ) object.receiveShadow = true;
7037                 if ( this.visible === false ) object.visible = false;
7038                 if ( this.frustumCulled === false ) object.frustumCulled = false;
7039                 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
7040                 if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
7041
7042                 object.layers = this.layers.mask;
7043                 object.matrix = this.matrix.toArray();
7044
7045                 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
7046
7047                 // object specific properties
7048
7049                 if ( this.isInstancedMesh ) {
7050
7051                         object.type = 'InstancedMesh';
7052                         object.count = this.count;
7053                         object.instanceMatrix = this.instanceMatrix.toJSON();
7054
7055                 }
7056
7057                 //
7058
7059                 function serialize( library, element ) {
7060
7061                         if ( library[ element.uuid ] === undefined ) {
7062
7063                                 library[ element.uuid ] = element.toJSON( meta );
7064
7065                         }
7066
7067                         return element.uuid;
7068
7069                 }
7070
7071                 if ( this.isMesh || this.isLine || this.isPoints ) {
7072
7073                         object.geometry = serialize( meta.geometries, this.geometry );
7074
7075                         const parameters = this.geometry.parameters;
7076
7077                         if ( parameters !== undefined && parameters.shapes !== undefined ) {
7078
7079                                 const shapes = parameters.shapes;
7080
7081                                 if ( Array.isArray( shapes ) ) {
7082
7083                                         for ( let i = 0, l = shapes.length; i < l; i ++ ) {
7084
7085                                                 const shape = shapes[ i ];
7086
7087                                                 serialize( meta.shapes, shape );
7088
7089                                         }
7090
7091                                 } else {
7092
7093                                         serialize( meta.shapes, shapes );
7094
7095                                 }
7096
7097                         }
7098
7099                 }
7100
7101                 if ( this.isSkinnedMesh ) {
7102
7103                         object.bindMode = this.bindMode;
7104                         object.bindMatrix = this.bindMatrix.toArray();
7105
7106                         if ( this.skeleton !== undefined ) {
7107
7108                                 serialize( meta.skeletons, this.skeleton );
7109
7110                                 object.skeleton = this.skeleton.uuid;
7111
7112                         }
7113
7114                 }
7115
7116                 if ( this.material !== undefined ) {
7117
7118                         if ( Array.isArray( this.material ) ) {
7119
7120                                 const uuids = [];
7121
7122                                 for ( let i = 0, l = this.material.length; i < l; i ++ ) {
7123
7124                                         uuids.push( serialize( meta.materials, this.material[ i ] ) );
7125
7126                                 }
7127
7128                                 object.material = uuids;
7129
7130                         } else {
7131
7132                                 object.material = serialize( meta.materials, this.material );
7133
7134                         }
7135
7136                 }
7137
7138                 //
7139
7140                 if ( this.children.length > 0 ) {
7141
7142                         object.children = [];
7143
7144                         for ( let i = 0; i < this.children.length; i ++ ) {
7145
7146                                 object.children.push( this.children[ i ].toJSON( meta ).object );
7147
7148                         }
7149
7150                 }
7151
7152                 //
7153
7154                 if ( this.animations.length > 0 ) {
7155
7156                         object.animations = [];
7157
7158                         for ( let i = 0; i < this.animations.length; i ++ ) {
7159
7160                                 const animation = this.animations[ i ];
7161
7162                                 object.animations.push( serialize( meta.animations, animation ) );
7163
7164                         }
7165
7166                 }
7167
7168                 if ( isRootObject ) {
7169
7170                         const geometries = extractFromCache( meta.geometries );
7171                         const materials = extractFromCache( meta.materials );
7172                         const textures = extractFromCache( meta.textures );
7173                         const images = extractFromCache( meta.images );
7174                         const shapes = extractFromCache( meta.shapes );
7175                         const skeletons = extractFromCache( meta.skeletons );
7176                         const animations = extractFromCache( meta.animations );
7177
7178                         if ( geometries.length > 0 ) output.geometries = geometries;
7179                         if ( materials.length > 0 ) output.materials = materials;
7180                         if ( textures.length > 0 ) output.textures = textures;
7181                         if ( images.length > 0 ) output.images = images;
7182                         if ( shapes.length > 0 ) output.shapes = shapes;
7183                         if ( skeletons.length > 0 ) output.skeletons = skeletons;
7184                         if ( animations.length > 0 ) output.animations = animations;
7185
7186                 }
7187
7188                 output.object = object;
7189
7190                 return output;
7191
7192                 // extract data from the cache hash
7193                 // remove metadata on each item
7194                 // and return as array
7195                 function extractFromCache( cache ) {
7196
7197                         const values = [];
7198                         for ( const key in cache ) {
7199
7200                                 const data = cache[ key ];
7201                                 delete data.metadata;
7202                                 values.push( data );
7203
7204                         }
7205
7206                         return values;
7207
7208                 }
7209
7210         },
7211
7212         clone: function ( recursive ) {
7213
7214                 return new this.constructor().copy( this, recursive );
7215
7216         },
7217
7218         copy: function ( source, recursive = true ) {
7219
7220                 this.name = source.name;
7221
7222                 this.up.copy( source.up );
7223
7224                 this.position.copy( source.position );
7225                 this.rotation.order = source.rotation.order;
7226                 this.quaternion.copy( source.quaternion );
7227                 this.scale.copy( source.scale );
7228
7229                 this.matrix.copy( source.matrix );
7230                 this.matrixWorld.copy( source.matrixWorld );
7231
7232                 this.matrixAutoUpdate = source.matrixAutoUpdate;
7233                 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
7234
7235                 this.layers.mask = source.layers.mask;
7236                 this.visible = source.visible;
7237
7238                 this.castShadow = source.castShadow;
7239                 this.receiveShadow = source.receiveShadow;
7240
7241                 this.frustumCulled = source.frustumCulled;
7242                 this.renderOrder = source.renderOrder;
7243
7244                 this.userData = JSON.parse( JSON.stringify( source.userData ) );
7245
7246                 if ( recursive === true ) {
7247
7248                         for ( let i = 0; i < source.children.length; i ++ ) {
7249
7250                                 const child = source.children[ i ];
7251                                 this.add( child.clone() );
7252
7253                         }
7254
7255                 }
7256
7257                 return this;
7258
7259         }
7260
7261 } );
7262
7263 const _vector1 = /*@__PURE__*/ new Vector3();
7264 const _vector2 = /*@__PURE__*/ new Vector3();
7265 const _normalMatrix = /*@__PURE__*/ new Matrix3();
7266
7267 class Plane {
7268
7269         constructor( normal, constant ) {
7270
7271                 Object.defineProperty( this, 'isPlane', { value: true } );
7272
7273                 // normal is assumed to be normalized
7274
7275                 this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
7276                 this.constant = ( constant !== undefined ) ? constant : 0;
7277
7278         }
7279
7280         set( normal, constant ) {
7281
7282                 this.normal.copy( normal );
7283                 this.constant = constant;
7284
7285                 return this;
7286
7287         }
7288
7289         setComponents( x, y, z, w ) {
7290
7291                 this.normal.set( x, y, z );
7292                 this.constant = w;
7293
7294                 return this;
7295
7296         }
7297
7298         setFromNormalAndCoplanarPoint( normal, point ) {
7299
7300                 this.normal.copy( normal );
7301                 this.constant = - point.dot( this.normal );
7302
7303                 return this;
7304
7305         }
7306
7307         setFromCoplanarPoints( a, b, c ) {
7308
7309                 const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
7310
7311                 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
7312
7313                 this.setFromNormalAndCoplanarPoint( normal, a );
7314
7315                 return this;
7316
7317         }
7318
7319         clone() {
7320
7321                 return new this.constructor().copy( this );
7322
7323         }
7324
7325         copy( plane ) {
7326
7327                 this.normal.copy( plane.normal );
7328                 this.constant = plane.constant;
7329
7330                 return this;
7331
7332         }
7333
7334         normalize() {
7335
7336                 // Note: will lead to a divide by zero if the plane is invalid.
7337
7338                 const inverseNormalLength = 1.0 / this.normal.length();
7339                 this.normal.multiplyScalar( inverseNormalLength );
7340                 this.constant *= inverseNormalLength;
7341
7342                 return this;
7343
7344         }
7345
7346         negate() {
7347
7348                 this.constant *= - 1;
7349                 this.normal.negate();
7350
7351                 return this;
7352
7353         }
7354
7355         distanceToPoint( point ) {
7356
7357                 return this.normal.dot( point ) + this.constant;
7358
7359         }
7360
7361         distanceToSphere( sphere ) {
7362
7363                 return this.distanceToPoint( sphere.center ) - sphere.radius;
7364
7365         }
7366
7367         projectPoint( point, target ) {
7368
7369                 if ( target === undefined ) {
7370
7371                         console.warn( 'THREE.Plane: .projectPoint() target is now required' );
7372                         target = new Vector3();
7373
7374                 }
7375
7376                 return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
7377
7378         }
7379
7380         intersectLine( line, target ) {
7381
7382                 if ( target === undefined ) {
7383
7384                         console.warn( 'THREE.Plane: .intersectLine() target is now required' );
7385                         target = new Vector3();
7386
7387                 }
7388
7389                 const direction = line.delta( _vector1 );
7390
7391                 const denominator = this.normal.dot( direction );
7392
7393                 if ( denominator === 0 ) {
7394
7395                         // line is coplanar, return origin
7396                         if ( this.distanceToPoint( line.start ) === 0 ) {
7397
7398                                 return target.copy( line.start );
7399
7400                         }
7401
7402                         // Unsure if this is the correct method to handle this case.
7403                         return undefined;
7404
7405                 }
7406
7407                 const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
7408
7409                 if ( t < 0 || t > 1 ) {
7410
7411                         return undefined;
7412
7413                 }
7414
7415                 return target.copy( direction ).multiplyScalar( t ).add( line.start );
7416
7417         }
7418
7419         intersectsLine( line ) {
7420
7421                 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
7422
7423                 const startSign = this.distanceToPoint( line.start );
7424                 const endSign = this.distanceToPoint( line.end );
7425
7426                 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
7427
7428         }
7429
7430         intersectsBox( box ) {
7431
7432                 return box.intersectsPlane( this );
7433
7434         }
7435
7436         intersectsSphere( sphere ) {
7437
7438                 return sphere.intersectsPlane( this );
7439
7440         }
7441
7442         coplanarPoint( target ) {
7443
7444                 if ( target === undefined ) {
7445
7446                         console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
7447                         target = new Vector3();
7448
7449                 }
7450
7451                 return target.copy( this.normal ).multiplyScalar( - this.constant );
7452
7453         }
7454
7455         applyMatrix4( matrix, optionalNormalMatrix ) {
7456
7457                 const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
7458
7459                 const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
7460
7461                 const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
7462
7463                 this.constant = - referencePoint.dot( normal );
7464
7465                 return this;
7466
7467         }
7468
7469         translate( offset ) {
7470
7471                 this.constant -= offset.dot( this.normal );
7472
7473                 return this;
7474
7475         }
7476
7477         equals( plane ) {
7478
7479                 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
7480
7481         }
7482
7483 }
7484
7485 const _v0$1 = /*@__PURE__*/ new Vector3();
7486 const _v1$3 = /*@__PURE__*/ new Vector3();
7487 const _v2$1 = /*@__PURE__*/ new Vector3();
7488 const _v3 = /*@__PURE__*/ new Vector3();
7489
7490 const _vab = /*@__PURE__*/ new Vector3();
7491 const _vac = /*@__PURE__*/ new Vector3();
7492 const _vbc = /*@__PURE__*/ new Vector3();
7493 const _vap = /*@__PURE__*/ new Vector3();
7494 const _vbp = /*@__PURE__*/ new Vector3();
7495 const _vcp = /*@__PURE__*/ new Vector3();
7496
7497 class Triangle {
7498
7499         constructor( a, b, c ) {
7500
7501                 this.a = ( a !== undefined ) ? a : new Vector3();
7502                 this.b = ( b !== undefined ) ? b : new Vector3();
7503                 this.c = ( c !== undefined ) ? c : new Vector3();
7504
7505         }
7506
7507         static getNormal( a, b, c, target ) {
7508
7509                 if ( target === undefined ) {
7510
7511                         console.warn( 'THREE.Triangle: .getNormal() target is now required' );
7512                         target = new Vector3();
7513
7514                 }
7515
7516                 target.subVectors( c, b );
7517                 _v0$1.subVectors( a, b );
7518                 target.cross( _v0$1 );
7519
7520                 const targetLengthSq = target.lengthSq();
7521                 if ( targetLengthSq > 0 ) {
7522
7523                         return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
7524
7525                 }
7526
7527                 return target.set( 0, 0, 0 );
7528
7529         }
7530
7531         // static/instance method to calculate barycentric coordinates
7532         // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
7533         static getBarycoord( point, a, b, c, target ) {
7534
7535                 _v0$1.subVectors( c, a );
7536                 _v1$3.subVectors( b, a );
7537                 _v2$1.subVectors( point, a );
7538
7539                 const dot00 = _v0$1.dot( _v0$1 );
7540                 const dot01 = _v0$1.dot( _v1$3 );
7541                 const dot02 = _v0$1.dot( _v2$1 );
7542                 const dot11 = _v1$3.dot( _v1$3 );
7543                 const dot12 = _v1$3.dot( _v2$1 );
7544
7545                 const denom = ( dot00 * dot11 - dot01 * dot01 );
7546
7547                 if ( target === undefined ) {
7548
7549                         console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
7550                         target = new Vector3();
7551
7552                 }
7553
7554                 // collinear or singular triangle
7555                 if ( denom === 0 ) {
7556
7557                         // arbitrary location outside of triangle?
7558                         // not sure if this is the best idea, maybe should be returning undefined
7559                         return target.set( - 2, - 1, - 1 );
7560
7561                 }
7562
7563                 const invDenom = 1 / denom;
7564                 const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
7565                 const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
7566
7567                 // barycentric coordinates must always sum to 1
7568                 return target.set( 1 - u - v, v, u );
7569
7570         }
7571
7572         static containsPoint( point, a, b, c ) {
7573
7574                 this.getBarycoord( point, a, b, c, _v3 );
7575
7576                 return ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );
7577
7578         }
7579
7580         static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) {
7581
7582                 this.getBarycoord( point, p1, p2, p3, _v3 );
7583
7584                 target.set( 0, 0 );
7585                 target.addScaledVector( uv1, _v3.x );
7586                 target.addScaledVector( uv2, _v3.y );
7587                 target.addScaledVector( uv3, _v3.z );
7588
7589                 return target;
7590
7591         }
7592
7593         static isFrontFacing( a, b, c, direction ) {
7594
7595                 _v0$1.subVectors( c, b );
7596                 _v1$3.subVectors( a, b );
7597
7598                 // strictly front facing
7599                 return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
7600
7601         }
7602
7603         set( a, b, c ) {
7604
7605                 this.a.copy( a );
7606                 this.b.copy( b );
7607                 this.c.copy( c );
7608
7609                 return this;
7610
7611         }
7612
7613         setFromPointsAndIndices( points, i0, i1, i2 ) {
7614
7615                 this.a.copy( points[ i0 ] );
7616                 this.b.copy( points[ i1 ] );
7617                 this.c.copy( points[ i2 ] );
7618
7619                 return this;
7620
7621         }
7622
7623         clone() {
7624
7625                 return new this.constructor().copy( this );
7626
7627         }
7628
7629         copy( triangle ) {
7630
7631                 this.a.copy( triangle.a );
7632                 this.b.copy( triangle.b );
7633                 this.c.copy( triangle.c );
7634
7635                 return this;
7636
7637         }
7638
7639         getArea() {
7640
7641                 _v0$1.subVectors( this.c, this.b );
7642                 _v1$3.subVectors( this.a, this.b );
7643
7644                 return _v0$1.cross( _v1$3 ).length() * 0.5;
7645
7646         }
7647
7648         getMidpoint( target ) {
7649
7650                 if ( target === undefined ) {
7651
7652                         console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
7653                         target = new Vector3();
7654
7655                 }
7656
7657                 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
7658
7659         }
7660
7661         getNormal( target ) {
7662
7663                 return Triangle.getNormal( this.a, this.b, this.c, target );
7664
7665         }
7666
7667         getPlane( target ) {
7668
7669                 if ( target === undefined ) {
7670
7671                         console.warn( 'THREE.Triangle: .getPlane() target is now required' );
7672                         target = new Plane();
7673
7674                 }
7675
7676                 return target.setFromCoplanarPoints( this.a, this.b, this.c );
7677
7678         }
7679
7680         getBarycoord( point, target ) {
7681
7682                 return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
7683
7684         }
7685
7686         getUV( point, uv1, uv2, uv3, target ) {
7687
7688                 return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
7689
7690         }
7691
7692         containsPoint( point ) {
7693
7694                 return Triangle.containsPoint( point, this.a, this.b, this.c );
7695
7696         }
7697
7698         isFrontFacing( direction ) {
7699
7700                 return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
7701
7702         }
7703
7704         intersectsBox( box ) {
7705
7706                 return box.intersectsTriangle( this );
7707
7708         }
7709
7710         closestPointToPoint( p, target ) {
7711
7712                 if ( target === undefined ) {
7713
7714                         console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
7715                         target = new Vector3();
7716
7717                 }
7718
7719                 const a = this.a, b = this.b, c = this.c;
7720                 let v, w;
7721
7722                 // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
7723                 // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
7724                 // under the accompanying license; see chapter 5.1.5 for detailed explanation.
7725                 // basically, we're distinguishing which of the voronoi regions of the triangle
7726                 // the point lies in with the minimum amount of redundant computation.
7727
7728                 _vab.subVectors( b, a );
7729                 _vac.subVectors( c, a );
7730                 _vap.subVectors( p, a );
7731                 const d1 = _vab.dot( _vap );
7732                 const d2 = _vac.dot( _vap );
7733                 if ( d1 <= 0 && d2 <= 0 ) {
7734
7735                         // vertex region of A; barycentric coords (1, 0, 0)
7736                         return target.copy( a );
7737
7738                 }
7739
7740                 _vbp.subVectors( p, b );
7741                 const d3 = _vab.dot( _vbp );
7742                 const d4 = _vac.dot( _vbp );
7743                 if ( d3 >= 0 && d4 <= d3 ) {
7744
7745                         // vertex region of B; barycentric coords (0, 1, 0)
7746                         return target.copy( b );
7747
7748                 }
7749
7750                 const vc = d1 * d4 - d3 * d2;
7751                 if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
7752
7753                         v = d1 / ( d1 - d3 );
7754                         // edge region of AB; barycentric coords (1-v, v, 0)
7755                         return target.copy( a ).addScaledVector( _vab, v );
7756
7757                 }
7758
7759                 _vcp.subVectors( p, c );
7760                 const d5 = _vab.dot( _vcp );
7761                 const d6 = _vac.dot( _vcp );
7762                 if ( d6 >= 0 && d5 <= d6 ) {
7763
7764                         // vertex region of C; barycentric coords (0, 0, 1)
7765                         return target.copy( c );
7766
7767                 }
7768
7769                 const vb = d5 * d2 - d1 * d6;
7770                 if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
7771
7772                         w = d2 / ( d2 - d6 );
7773                         // edge region of AC; barycentric coords (1-w, 0, w)
7774                         return target.copy( a ).addScaledVector( _vac, w );
7775
7776                 }
7777
7778                 const va = d3 * d6 - d5 * d4;
7779                 if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
7780
7781                         _vbc.subVectors( c, b );
7782                         w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
7783                         // edge region of BC; barycentric coords (0, 1-w, w)
7784                         return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
7785
7786                 }
7787
7788                 // face region
7789                 const denom = 1 / ( va + vb + vc );
7790                 // u = va * denom
7791                 v = vb * denom;
7792                 w = vc * denom;
7793
7794                 return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
7795
7796         }
7797
7798         equals( triangle ) {
7799
7800                 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
7801
7802         }
7803
7804 }
7805
7806 const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
7807         'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
7808         'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
7809         'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
7810         'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
7811         'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
7812         'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
7813         'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
7814         'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
7815         'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
7816         'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
7817         'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
7818         'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
7819         'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
7820         'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
7821         'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
7822         'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
7823         'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
7824         'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
7825         'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
7826         'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
7827         'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
7828         'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
7829         'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
7830
7831 const _hslA = { h: 0, s: 0, l: 0 };
7832 const _hslB = { h: 0, s: 0, l: 0 };
7833
7834 function hue2rgb( p, q, t ) {
7835
7836         if ( t < 0 ) t += 1;
7837         if ( t > 1 ) t -= 1;
7838         if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
7839         if ( t < 1 / 2 ) return q;
7840         if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
7841         return p;
7842
7843 }
7844
7845 function SRGBToLinear( c ) {
7846
7847         return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
7848
7849 }
7850
7851 function LinearToSRGB( c ) {
7852
7853         return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
7854
7855 }
7856
7857 class Color {
7858
7859         constructor( r, g, b ) {
7860
7861                 Object.defineProperty( this, 'isColor', { value: true } );
7862
7863                 if ( g === undefined && b === undefined ) {
7864
7865                         // r is THREE.Color, hex or string
7866                         return this.set( r );
7867
7868                 }
7869
7870                 return this.setRGB( r, g, b );
7871
7872         }
7873
7874         set( value ) {
7875
7876                 if ( value && value.isColor ) {
7877
7878                         this.copy( value );
7879
7880                 } else if ( typeof value === 'number' ) {
7881
7882                         this.setHex( value );
7883
7884                 } else if ( typeof value === 'string' ) {
7885
7886                         this.setStyle( value );
7887
7888                 }
7889
7890                 return this;
7891
7892         }
7893
7894         setScalar( scalar ) {
7895
7896                 this.r = scalar;
7897                 this.g = scalar;
7898                 this.b = scalar;
7899
7900                 return this;
7901
7902         }
7903
7904         setHex( hex ) {
7905
7906                 hex = Math.floor( hex );
7907
7908                 this.r = ( hex >> 16 & 255 ) / 255;
7909                 this.g = ( hex >> 8 & 255 ) / 255;
7910                 this.b = ( hex & 255 ) / 255;
7911
7912                 return this;
7913
7914         }
7915
7916         setRGB( r, g, b ) {
7917
7918                 this.r = r;
7919                 this.g = g;
7920                 this.b = b;
7921
7922                 return this;
7923
7924         }
7925
7926         setHSL( h, s, l ) {
7927
7928                 // h,s,l ranges are in 0.0 - 1.0
7929                 h = MathUtils.euclideanModulo( h, 1 );
7930                 s = MathUtils.clamp( s, 0, 1 );
7931                 l = MathUtils.clamp( l, 0, 1 );
7932
7933                 if ( s === 0 ) {
7934
7935                         this.r = this.g = this.b = l;
7936
7937                 } else {
7938
7939                         const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
7940                         const q = ( 2 * l ) - p;
7941
7942                         this.r = hue2rgb( q, p, h + 1 / 3 );
7943                         this.g = hue2rgb( q, p, h );
7944                         this.b = hue2rgb( q, p, h - 1 / 3 );
7945
7946                 }
7947
7948                 return this;
7949
7950         }
7951
7952         setStyle( style ) {
7953
7954                 function handleAlpha( string ) {
7955
7956                         if ( string === undefined ) return;
7957
7958                         if ( parseFloat( string ) < 1 ) {
7959
7960                                 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
7961
7962                         }
7963
7964                 }
7965
7966
7967                 let m;
7968
7969                 if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) {
7970
7971                         // rgb / hsl
7972
7973                         let color;
7974                         const name = m[ 1 ];
7975                         const components = m[ 2 ];
7976
7977                         switch ( name ) {
7978
7979                                 case 'rgb':
7980                                 case 'rgba':
7981
7982                                         if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
7983
7984                                                 // rgb(255,0,0) rgba(255,0,0,0.5)
7985                                                 this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
7986                                                 this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
7987                                                 this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
7988
7989                                                 handleAlpha( color[ 4 ] );
7990
7991                                                 return this;
7992
7993                                         }
7994
7995                                         if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
7996
7997                                                 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
7998                                                 this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
7999                                                 this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
8000                                                 this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
8001
8002                                                 handleAlpha( color[ 4 ] );
8003
8004                                                 return this;
8005
8006                                         }
8007
8008                                         break;
8009
8010                                 case 'hsl':
8011                                 case 'hsla':
8012
8013                                         if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8014
8015                                                 // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
8016                                                 const h = parseFloat( color[ 1 ] ) / 360;
8017                                                 const s = parseInt( color[ 2 ], 10 ) / 100;
8018                                                 const l = parseInt( color[ 3 ], 10 ) / 100;
8019
8020                                                 handleAlpha( color[ 4 ] );
8021
8022                                                 return this.setHSL( h, s, l );
8023
8024                                         }
8025
8026                                         break;
8027
8028                         }
8029
8030                 } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
8031
8032                         // hex color
8033
8034                         const hex = m[ 1 ];
8035                         const size = hex.length;
8036
8037                         if ( size === 3 ) {
8038
8039                                 // #ff0
8040                                 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
8041                                 this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
8042                                 this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
8043
8044                                 return this;
8045
8046                         } else if ( size === 6 ) {
8047
8048                                 // #ff0000
8049                                 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
8050                                 this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
8051                                 this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
8052
8053                                 return this;
8054
8055                         }
8056
8057                 }
8058
8059                 if ( style && style.length > 0 ) {
8060
8061                         return this.setColorName( style );
8062
8063                 }
8064
8065                 return this;
8066
8067         }
8068
8069         setColorName( style ) {
8070
8071                 // color keywords
8072                 const hex = _colorKeywords[ style ];
8073
8074                 if ( hex !== undefined ) {
8075
8076                         // red
8077                         this.setHex( hex );
8078
8079                 } else {
8080
8081                         // unknown color
8082                         console.warn( 'THREE.Color: Unknown color ' + style );
8083
8084                 }
8085
8086                 return this;
8087
8088         }
8089
8090         clone() {
8091
8092                 return new this.constructor( this.r, this.g, this.b );
8093
8094         }
8095
8096         copy( color ) {
8097
8098                 this.r = color.r;
8099                 this.g = color.g;
8100                 this.b = color.b;
8101
8102                 return this;
8103
8104         }
8105
8106         copyGammaToLinear( color, gammaFactor = 2.0 ) {
8107
8108                 this.r = Math.pow( color.r, gammaFactor );
8109                 this.g = Math.pow( color.g, gammaFactor );
8110                 this.b = Math.pow( color.b, gammaFactor );
8111
8112                 return this;
8113
8114         }
8115
8116         copyLinearToGamma( color, gammaFactor = 2.0 ) {
8117
8118                 const safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
8119
8120                 this.r = Math.pow( color.r, safeInverse );
8121                 this.g = Math.pow( color.g, safeInverse );
8122                 this.b = Math.pow( color.b, safeInverse );
8123
8124                 return this;
8125
8126         }
8127
8128         convertGammaToLinear( gammaFactor ) {
8129
8130                 this.copyGammaToLinear( this, gammaFactor );
8131
8132                 return this;
8133
8134         }
8135
8136         convertLinearToGamma( gammaFactor ) {
8137
8138                 this.copyLinearToGamma( this, gammaFactor );
8139
8140                 return this;
8141
8142         }
8143
8144         copySRGBToLinear( color ) {
8145
8146                 this.r = SRGBToLinear( color.r );
8147                 this.g = SRGBToLinear( color.g );
8148                 this.b = SRGBToLinear( color.b );
8149
8150                 return this;
8151
8152         }
8153
8154         copyLinearToSRGB( color ) {
8155
8156                 this.r = LinearToSRGB( color.r );
8157                 this.g = LinearToSRGB( color.g );
8158                 this.b = LinearToSRGB( color.b );
8159
8160                 return this;
8161
8162         }
8163
8164         convertSRGBToLinear() {
8165
8166                 this.copySRGBToLinear( this );
8167
8168                 return this;
8169
8170         }
8171
8172         convertLinearToSRGB() {
8173
8174                 this.copyLinearToSRGB( this );
8175
8176                 return this;
8177
8178         }
8179
8180         getHex() {
8181
8182                 return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
8183
8184         }
8185
8186         getHexString() {
8187
8188                 return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
8189
8190         }
8191
8192         getHSL( target ) {
8193
8194                 // h,s,l ranges are in 0.0 - 1.0
8195
8196                 if ( target === undefined ) {
8197
8198                         console.warn( 'THREE.Color: .getHSL() target is now required' );
8199                         target = { h: 0, s: 0, l: 0 };
8200
8201                 }
8202
8203                 const r = this.r, g = this.g, b = this.b;
8204
8205                 const max = Math.max( r, g, b );
8206                 const min = Math.min( r, g, b );
8207
8208                 let hue, saturation;
8209                 const lightness = ( min + max ) / 2.0;
8210
8211                 if ( min === max ) {
8212
8213                         hue = 0;
8214                         saturation = 0;
8215
8216                 } else {
8217
8218                         const delta = max - min;
8219
8220                         saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
8221
8222                         switch ( max ) {
8223
8224                                 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
8225                                 case g: hue = ( b - r ) / delta + 2; break;
8226                                 case b: hue = ( r - g ) / delta + 4; break;
8227
8228                         }
8229
8230                         hue /= 6;
8231
8232                 }
8233
8234                 target.h = hue;
8235                 target.s = saturation;
8236                 target.l = lightness;
8237
8238                 return target;
8239
8240         }
8241
8242         getStyle() {
8243
8244                 return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
8245
8246         }
8247
8248         offsetHSL( h, s, l ) {
8249
8250                 this.getHSL( _hslA );
8251
8252                 _hslA.h += h; _hslA.s += s; _hslA.l += l;
8253
8254                 this.setHSL( _hslA.h, _hslA.s, _hslA.l );
8255
8256                 return this;
8257
8258         }
8259
8260         add( color ) {
8261
8262                 this.r += color.r;
8263                 this.g += color.g;
8264                 this.b += color.b;
8265
8266                 return this;
8267
8268         }
8269
8270         addColors( color1, color2 ) {
8271
8272                 this.r = color1.r + color2.r;
8273                 this.g = color1.g + color2.g;
8274                 this.b = color1.b + color2.b;
8275
8276                 return this;
8277
8278         }
8279
8280         addScalar( s ) {
8281
8282                 this.r += s;
8283                 this.g += s;
8284                 this.b += s;
8285
8286                 return this;
8287
8288         }
8289
8290         sub( color ) {
8291
8292                 this.r = Math.max( 0, this.r - color.r );
8293                 this.g = Math.max( 0, this.g - color.g );
8294                 this.b = Math.max( 0, this.b - color.b );
8295
8296                 return this;
8297
8298         }
8299
8300         multiply( color ) {
8301
8302                 this.r *= color.r;
8303                 this.g *= color.g;
8304                 this.b *= color.b;
8305
8306                 return this;
8307
8308         }
8309
8310         multiplyScalar( s ) {
8311
8312                 this.r *= s;
8313                 this.g *= s;
8314                 this.b *= s;
8315
8316                 return this;
8317
8318         }
8319
8320         lerp( color, alpha ) {
8321
8322                 this.r += ( color.r - this.r ) * alpha;
8323                 this.g += ( color.g - this.g ) * alpha;
8324                 this.b += ( color.b - this.b ) * alpha;
8325
8326                 return this;
8327
8328         }
8329
8330         lerpColors( color1, color2, alpha ) {
8331
8332                 this.r = color1.r + ( color2.r - color1.r ) * alpha;
8333                 this.g = color1.g + ( color2.g - color1.g ) * alpha;
8334                 this.b = color1.b + ( color2.b - color1.b ) * alpha;
8335
8336                 return this;
8337
8338         }
8339
8340         lerpHSL( color, alpha ) {
8341
8342                 this.getHSL( _hslA );
8343                 color.getHSL( _hslB );
8344
8345                 const h = MathUtils.lerp( _hslA.h, _hslB.h, alpha );
8346                 const s = MathUtils.lerp( _hslA.s, _hslB.s, alpha );
8347                 const l = MathUtils.lerp( _hslA.l, _hslB.l, alpha );
8348
8349                 this.setHSL( h, s, l );
8350
8351                 return this;
8352
8353         }
8354
8355         equals( c ) {
8356
8357                 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
8358
8359         }
8360
8361         fromArray( array, offset = 0 ) {
8362
8363                 this.r = array[ offset ];
8364                 this.g = array[ offset + 1 ];
8365                 this.b = array[ offset + 2 ];
8366
8367                 return this;
8368
8369         }
8370
8371         toArray( array = [], offset = 0 ) {
8372
8373                 array[ offset ] = this.r;
8374                 array[ offset + 1 ] = this.g;
8375                 array[ offset + 2 ] = this.b;
8376
8377                 return array;
8378
8379         }
8380
8381         fromBufferAttribute( attribute, index ) {
8382
8383                 this.r = attribute.getX( index );
8384                 this.g = attribute.getY( index );
8385                 this.b = attribute.getZ( index );
8386
8387                 if ( attribute.normalized === true ) {
8388
8389                         // assuming Uint8Array
8390
8391                         this.r /= 255;
8392                         this.g /= 255;
8393                         this.b /= 255;
8394
8395                 }
8396
8397                 return this;
8398
8399         }
8400
8401         toJSON() {
8402
8403                 return this.getHex();
8404
8405         }
8406
8407 }
8408
8409 Color.NAMES = _colorKeywords;
8410 Color.prototype.r = 1;
8411 Color.prototype.g = 1;
8412 Color.prototype.b = 1;
8413
8414 class Face3 {
8415
8416         constructor( a, b, c, normal, color, materialIndex = 0 ) {
8417
8418                 this.a = a;
8419                 this.b = b;
8420                 this.c = c;
8421
8422                 this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
8423                 this.vertexNormals = Array.isArray( normal ) ? normal : [];
8424
8425                 this.color = ( color && color.isColor ) ? color : new Color();
8426                 this.vertexColors = Array.isArray( color ) ? color : [];
8427
8428                 this.materialIndex = materialIndex;
8429
8430         }
8431
8432         clone() {
8433
8434                 return new this.constructor().copy( this );
8435
8436         }
8437
8438         copy( source ) {
8439
8440                 this.a = source.a;
8441                 this.b = source.b;
8442                 this.c = source.c;
8443
8444                 this.normal.copy( source.normal );
8445                 this.color.copy( source.color );
8446
8447                 this.materialIndex = source.materialIndex;
8448
8449                 for ( let i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
8450
8451                         this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
8452
8453                 }
8454
8455                 for ( let i = 0, il = source.vertexColors.length; i < il; i ++ ) {
8456
8457                         this.vertexColors[ i ] = source.vertexColors[ i ].clone();
8458
8459                 }
8460
8461                 return this;
8462
8463         }
8464
8465 }
8466
8467 let materialId = 0;
8468
8469 function Material() {
8470
8471         Object.defineProperty( this, 'id', { value: materialId ++ } );
8472
8473         this.uuid = MathUtils.generateUUID();
8474
8475         this.name = '';
8476         this.type = 'Material';
8477
8478         this.fog = true;
8479
8480         this.blending = NormalBlending;
8481         this.side = FrontSide;
8482         this.flatShading = false;
8483         this.vertexColors = false;
8484
8485         this.opacity = 1;
8486         this.transparent = false;
8487
8488         this.blendSrc = SrcAlphaFactor;
8489         this.blendDst = OneMinusSrcAlphaFactor;
8490         this.blendEquation = AddEquation;
8491         this.blendSrcAlpha = null;
8492         this.blendDstAlpha = null;
8493         this.blendEquationAlpha = null;
8494
8495         this.depthFunc = LessEqualDepth;
8496         this.depthTest = true;
8497         this.depthWrite = true;
8498
8499         this.stencilWriteMask = 0xff;
8500         this.stencilFunc = AlwaysStencilFunc;
8501         this.stencilRef = 0;
8502         this.stencilFuncMask = 0xff;
8503         this.stencilFail = KeepStencilOp;
8504         this.stencilZFail = KeepStencilOp;
8505         this.stencilZPass = KeepStencilOp;
8506         this.stencilWrite = false;
8507
8508         this.clippingPlanes = null;
8509         this.clipIntersection = false;
8510         this.clipShadows = false;
8511
8512         this.shadowSide = null;
8513
8514         this.colorWrite = true;
8515
8516         this.precision = null; // override the renderer's default precision for this material
8517
8518         this.polygonOffset = false;
8519         this.polygonOffsetFactor = 0;
8520         this.polygonOffsetUnits = 0;
8521
8522         this.dithering = false;
8523
8524         this.alphaTest = 0;
8525         this.premultipliedAlpha = false;
8526
8527         this.visible = true;
8528
8529         this.toneMapped = true;
8530
8531         this.userData = {};
8532
8533         this.version = 0;
8534
8535 }
8536
8537 Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
8538
8539         constructor: Material,
8540
8541         isMaterial: true,
8542
8543         onBeforeCompile: function ( /* shaderobject, renderer */ ) {},
8544
8545         customProgramCacheKey: function () {
8546
8547                 return this.onBeforeCompile.toString();
8548
8549         },
8550
8551         setValues: function ( values ) {
8552
8553                 if ( values === undefined ) return;
8554
8555                 for ( const key in values ) {
8556
8557                         const newValue = values[ key ];
8558
8559                         if ( newValue === undefined ) {
8560
8561                                 console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
8562                                 continue;
8563
8564                         }
8565
8566                         // for backward compatability if shading is set in the constructor
8567                         if ( key === 'shading' ) {
8568
8569                                 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
8570                                 this.flatShading = ( newValue === FlatShading ) ? true : false;
8571                                 continue;
8572
8573                         }
8574
8575                         const currentValue = this[ key ];
8576
8577                         if ( currentValue === undefined ) {
8578
8579                                 console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' );
8580                                 continue;
8581
8582                         }
8583
8584                         if ( currentValue && currentValue.isColor ) {
8585
8586                                 currentValue.set( newValue );
8587
8588                         } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
8589
8590                                 currentValue.copy( newValue );
8591
8592                         } else {
8593
8594                                 this[ key ] = newValue;
8595
8596                         }
8597
8598                 }
8599
8600         },
8601
8602         toJSON: function ( meta ) {
8603
8604                 const isRoot = ( meta === undefined || typeof meta === 'string' );
8605
8606                 if ( isRoot ) {
8607
8608                         meta = {
8609                                 textures: {},
8610                                 images: {}
8611                         };
8612
8613                 }
8614
8615                 const data = {
8616                         metadata: {
8617                                 version: 4.5,
8618                                 type: 'Material',
8619                                 generator: 'Material.toJSON'
8620                         }
8621                 };
8622
8623                 // standard Material serialization
8624                 data.uuid = this.uuid;
8625                 data.type = this.type;
8626
8627                 if ( this.name !== '' ) data.name = this.name;
8628
8629                 if ( this.color && this.color.isColor ) data.color = this.color.getHex();
8630
8631                 if ( this.roughness !== undefined ) data.roughness = this.roughness;
8632                 if ( this.metalness !== undefined ) data.metalness = this.metalness;
8633
8634                 if ( this.sheen && this.sheen.isColor ) data.sheen = this.sheen.getHex();
8635                 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
8636                 if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
8637
8638                 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
8639                 if ( this.shininess !== undefined ) data.shininess = this.shininess;
8640                 if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
8641                 if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
8642
8643                 if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
8644
8645                         data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
8646
8647                 }
8648
8649                 if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
8650
8651                         data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
8652
8653                 }
8654
8655                 if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
8656
8657                         data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
8658                         data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
8659
8660                 }
8661
8662                 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
8663                 if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
8664                 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
8665                 if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
8666
8667                 if ( this.aoMap && this.aoMap.isTexture ) {
8668
8669                         data.aoMap = this.aoMap.toJSON( meta ).uuid;
8670                         data.aoMapIntensity = this.aoMapIntensity;
8671
8672                 }
8673
8674                 if ( this.bumpMap && this.bumpMap.isTexture ) {
8675
8676                         data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
8677                         data.bumpScale = this.bumpScale;
8678
8679                 }
8680
8681                 if ( this.normalMap && this.normalMap.isTexture ) {
8682
8683                         data.normalMap = this.normalMap.toJSON( meta ).uuid;
8684                         data.normalMapType = this.normalMapType;
8685                         data.normalScale = this.normalScale.toArray();
8686
8687                 }
8688
8689                 if ( this.displacementMap && this.displacementMap.isTexture ) {
8690
8691                         data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
8692                         data.displacementScale = this.displacementScale;
8693                         data.displacementBias = this.displacementBias;
8694
8695                 }
8696
8697                 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
8698                 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
8699
8700                 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
8701                 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
8702
8703                 if ( this.envMap && this.envMap.isTexture ) {
8704
8705                         data.envMap = this.envMap.toJSON( meta ).uuid;
8706                         data.reflectivity = this.reflectivity; // Scale behind envMap
8707                         data.refractionRatio = this.refractionRatio;
8708
8709                         if ( this.combine !== undefined ) data.combine = this.combine;
8710                         if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
8711
8712                 }
8713
8714                 if ( this.gradientMap && this.gradientMap.isTexture ) {
8715
8716                         data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
8717
8718                 }
8719
8720                 if ( this.size !== undefined ) data.size = this.size;
8721                 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
8722
8723                 if ( this.blending !== NormalBlending ) data.blending = this.blending;
8724                 if ( this.flatShading === true ) data.flatShading = this.flatShading;
8725                 if ( this.side !== FrontSide ) data.side = this.side;
8726                 if ( this.vertexColors ) data.vertexColors = true;
8727
8728                 if ( this.opacity < 1 ) data.opacity = this.opacity;
8729                 if ( this.transparent === true ) data.transparent = this.transparent;
8730
8731                 data.depthFunc = this.depthFunc;
8732                 data.depthTest = this.depthTest;
8733                 data.depthWrite = this.depthWrite;
8734
8735                 data.stencilWrite = this.stencilWrite;
8736                 data.stencilWriteMask = this.stencilWriteMask;
8737                 data.stencilFunc = this.stencilFunc;
8738                 data.stencilRef = this.stencilRef;
8739                 data.stencilFuncMask = this.stencilFuncMask;
8740                 data.stencilFail = this.stencilFail;
8741                 data.stencilZFail = this.stencilZFail;
8742                 data.stencilZPass = this.stencilZPass;
8743
8744                 // rotation (SpriteMaterial)
8745                 if ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation;
8746
8747                 if ( this.polygonOffset === true ) data.polygonOffset = true;
8748                 if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
8749                 if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
8750
8751                 if ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth;
8752                 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
8753                 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
8754                 if ( this.scale !== undefined ) data.scale = this.scale;
8755
8756                 if ( this.dithering === true ) data.dithering = true;
8757
8758                 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
8759                 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
8760
8761                 if ( this.wireframe === true ) data.wireframe = this.wireframe;
8762                 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
8763                 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
8764                 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
8765
8766                 if ( this.morphTargets === true ) data.morphTargets = true;
8767                 if ( this.morphNormals === true ) data.morphNormals = true;
8768                 if ( this.skinning === true ) data.skinning = true;
8769
8770                 if ( this.visible === false ) data.visible = false;
8771
8772                 if ( this.toneMapped === false ) data.toneMapped = false;
8773
8774                 if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
8775
8776                 // TODO: Copied from Object3D.toJSON
8777
8778                 function extractFromCache( cache ) {
8779
8780                         const values = [];
8781
8782                         for ( const key in cache ) {
8783
8784                                 const data = cache[ key ];
8785                                 delete data.metadata;
8786                                 values.push( data );
8787
8788                         }
8789
8790                         return values;
8791
8792                 }
8793
8794                 if ( isRoot ) {
8795
8796                         const textures = extractFromCache( meta.textures );
8797                         const images = extractFromCache( meta.images );
8798
8799                         if ( textures.length > 0 ) data.textures = textures;
8800                         if ( images.length > 0 ) data.images = images;
8801
8802                 }
8803
8804                 return data;
8805
8806         },
8807
8808         clone: function () {
8809
8810                 return new this.constructor().copy( this );
8811
8812         },
8813
8814         copy: function ( source ) {
8815
8816                 this.name = source.name;
8817
8818                 this.fog = source.fog;
8819
8820                 this.blending = source.blending;
8821                 this.side = source.side;
8822                 this.flatShading = source.flatShading;
8823                 this.vertexColors = source.vertexColors;
8824
8825                 this.opacity = source.opacity;
8826                 this.transparent = source.transparent;
8827
8828                 this.blendSrc = source.blendSrc;
8829                 this.blendDst = source.blendDst;
8830                 this.blendEquation = source.blendEquation;
8831                 this.blendSrcAlpha = source.blendSrcAlpha;
8832                 this.blendDstAlpha = source.blendDstAlpha;
8833                 this.blendEquationAlpha = source.blendEquationAlpha;
8834
8835                 this.depthFunc = source.depthFunc;
8836                 this.depthTest = source.depthTest;
8837                 this.depthWrite = source.depthWrite;
8838
8839                 this.stencilWriteMask = source.stencilWriteMask;
8840                 this.stencilFunc = source.stencilFunc;
8841                 this.stencilRef = source.stencilRef;
8842                 this.stencilFuncMask = source.stencilFuncMask;
8843                 this.stencilFail = source.stencilFail;
8844                 this.stencilZFail = source.stencilZFail;
8845                 this.stencilZPass = source.stencilZPass;
8846                 this.stencilWrite = source.stencilWrite;
8847
8848                 const srcPlanes = source.clippingPlanes;
8849                 let dstPlanes = null;
8850
8851                 if ( srcPlanes !== null ) {
8852
8853                         const n = srcPlanes.length;
8854                         dstPlanes = new Array( n );
8855
8856                         for ( let i = 0; i !== n; ++ i ) {
8857
8858                                 dstPlanes[ i ] = srcPlanes[ i ].clone();
8859
8860                         }
8861
8862                 }
8863
8864                 this.clippingPlanes = dstPlanes;
8865                 this.clipIntersection = source.clipIntersection;
8866                 this.clipShadows = source.clipShadows;
8867
8868                 this.shadowSide = source.shadowSide;
8869
8870                 this.colorWrite = source.colorWrite;
8871
8872                 this.precision = source.precision;
8873
8874                 this.polygonOffset = source.polygonOffset;
8875                 this.polygonOffsetFactor = source.polygonOffsetFactor;
8876                 this.polygonOffsetUnits = source.polygonOffsetUnits;
8877
8878                 this.dithering = source.dithering;
8879
8880                 this.alphaTest = source.alphaTest;
8881                 this.premultipliedAlpha = source.premultipliedAlpha;
8882
8883                 this.visible = source.visible;
8884
8885                 this.toneMapped = source.toneMapped;
8886
8887                 this.userData = JSON.parse( JSON.stringify( source.userData ) );
8888
8889                 return this;
8890
8891         },
8892
8893         dispose: function () {
8894
8895                 this.dispatchEvent( { type: 'dispose' } );
8896
8897         }
8898
8899 } );
8900
8901 Object.defineProperty( Material.prototype, 'needsUpdate', {
8902
8903         set: function ( value ) {
8904
8905                 if ( value === true ) this.version ++;
8906
8907         }
8908
8909 } );
8910
8911 /**
8912  * parameters = {
8913  *  color: <hex>,
8914  *  opacity: <float>,
8915  *  map: new THREE.Texture( <Image> ),
8916  *
8917  *  lightMap: new THREE.Texture( <Image> ),
8918  *  lightMapIntensity: <float>
8919  *
8920  *  aoMap: new THREE.Texture( <Image> ),
8921  *  aoMapIntensity: <float>
8922  *
8923  *  specularMap: new THREE.Texture( <Image> ),
8924  *
8925  *  alphaMap: new THREE.Texture( <Image> ),
8926  *
8927  *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
8928  *  combine: THREE.Multiply,
8929  *  reflectivity: <float>,
8930  *  refractionRatio: <float>,
8931  *
8932  *  depthTest: <bool>,
8933  *  depthWrite: <bool>,
8934  *
8935  *  wireframe: <boolean>,
8936  *  wireframeLinewidth: <float>,
8937  *
8938  *  skinning: <bool>,
8939  *  morphTargets: <bool>
8940  * }
8941  */
8942
8943 function MeshBasicMaterial( parameters ) {
8944
8945         Material.call( this );
8946
8947         this.type = 'MeshBasicMaterial';
8948
8949         this.color = new Color( 0xffffff ); // emissive
8950
8951         this.map = null;
8952
8953         this.lightMap = null;
8954         this.lightMapIntensity = 1.0;
8955
8956         this.aoMap = null;
8957         this.aoMapIntensity = 1.0;
8958
8959         this.specularMap = null;
8960
8961         this.alphaMap = null;
8962
8963         this.envMap = null;
8964         this.combine = MultiplyOperation;
8965         this.reflectivity = 1;
8966         this.refractionRatio = 0.98;
8967
8968         this.wireframe = false;
8969         this.wireframeLinewidth = 1;
8970         this.wireframeLinecap = 'round';
8971         this.wireframeLinejoin = 'round';
8972
8973         this.skinning = false;
8974         this.morphTargets = false;
8975
8976         this.setValues( parameters );
8977
8978 }
8979
8980 MeshBasicMaterial.prototype = Object.create( Material.prototype );
8981 MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
8982
8983 MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
8984
8985 MeshBasicMaterial.prototype.copy = function ( source ) {
8986
8987         Material.prototype.copy.call( this, source );
8988
8989         this.color.copy( source.color );
8990
8991         this.map = source.map;
8992
8993         this.lightMap = source.lightMap;
8994         this.lightMapIntensity = source.lightMapIntensity;
8995
8996         this.aoMap = source.aoMap;
8997         this.aoMapIntensity = source.aoMapIntensity;
8998
8999         this.specularMap = source.specularMap;
9000
9001         this.alphaMap = source.alphaMap;
9002
9003         this.envMap = source.envMap;
9004         this.combine = source.combine;
9005         this.reflectivity = source.reflectivity;
9006         this.refractionRatio = source.refractionRatio;
9007
9008         this.wireframe = source.wireframe;
9009         this.wireframeLinewidth = source.wireframeLinewidth;
9010         this.wireframeLinecap = source.wireframeLinecap;
9011         this.wireframeLinejoin = source.wireframeLinejoin;
9012
9013         this.skinning = source.skinning;
9014         this.morphTargets = source.morphTargets;
9015
9016         return this;
9017
9018 };
9019
9020 const _vector$3 = new Vector3();
9021 const _vector2$1 = new Vector2();
9022
9023 function BufferAttribute( array, itemSize, normalized ) {
9024
9025         if ( Array.isArray( array ) ) {
9026
9027                 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
9028
9029         }
9030
9031         this.name = '';
9032
9033         this.array = array;
9034         this.itemSize = itemSize;
9035         this.count = array !== undefined ? array.length / itemSize : 0;
9036         this.normalized = normalized === true;
9037
9038         this.usage = StaticDrawUsage;
9039         this.updateRange = { offset: 0, count: - 1 };
9040
9041         this.version = 0;
9042
9043 }
9044
9045 Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
9046
9047         set: function ( value ) {
9048
9049                 if ( value === true ) this.version ++;
9050
9051         }
9052
9053 } );
9054
9055 Object.assign( BufferAttribute.prototype, {
9056
9057         isBufferAttribute: true,
9058
9059         onUploadCallback: function () {},
9060
9061         setUsage: function ( value ) {
9062
9063                 this.usage = value;
9064
9065                 return this;
9066
9067         },
9068
9069         copy: function ( source ) {
9070
9071                 this.name = source.name;
9072                 this.array = new source.array.constructor( source.array );
9073                 this.itemSize = source.itemSize;
9074                 this.count = source.count;
9075                 this.normalized = source.normalized;
9076
9077                 this.usage = source.usage;
9078
9079                 return this;
9080
9081         },
9082
9083         copyAt: function ( index1, attribute, index2 ) {
9084
9085                 index1 *= this.itemSize;
9086                 index2 *= attribute.itemSize;
9087
9088                 for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
9089
9090                         this.array[ index1 + i ] = attribute.array[ index2 + i ];
9091
9092                 }
9093
9094                 return this;
9095
9096         },
9097
9098         copyArray: function ( array ) {
9099
9100                 this.array.set( array );
9101
9102                 return this;
9103
9104         },
9105
9106         copyColorsArray: function ( colors ) {
9107
9108                 const array = this.array;
9109                 let offset = 0;
9110
9111                 for ( let i = 0, l = colors.length; i < l; i ++ ) {
9112
9113                         let color = colors[ i ];
9114
9115                         if ( color === undefined ) {
9116
9117                                 console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
9118                                 color = new Color();
9119
9120                         }
9121
9122                         array[ offset ++ ] = color.r;
9123                         array[ offset ++ ] = color.g;
9124                         array[ offset ++ ] = color.b;
9125
9126                 }
9127
9128                 return this;
9129
9130         },
9131
9132         copyVector2sArray: function ( vectors ) {
9133
9134                 const array = this.array;
9135                 let offset = 0;
9136
9137                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
9138
9139                         let vector = vectors[ i ];
9140
9141                         if ( vector === undefined ) {
9142
9143                                 console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
9144                                 vector = new Vector2();
9145
9146                         }
9147
9148                         array[ offset ++ ] = vector.x;
9149                         array[ offset ++ ] = vector.y;
9150
9151                 }
9152
9153                 return this;
9154
9155         },
9156
9157         copyVector3sArray: function ( vectors ) {
9158
9159                 const array = this.array;
9160                 let offset = 0;
9161
9162                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
9163
9164                         let vector = vectors[ i ];
9165
9166                         if ( vector === undefined ) {
9167
9168                                 console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
9169                                 vector = new Vector3();
9170
9171                         }
9172
9173                         array[ offset ++ ] = vector.x;
9174                         array[ offset ++ ] = vector.y;
9175                         array[ offset ++ ] = vector.z;
9176
9177                 }
9178
9179                 return this;
9180
9181         },
9182
9183         copyVector4sArray: function ( vectors ) {
9184
9185                 const array = this.array;
9186                 let offset = 0;
9187
9188                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
9189
9190                         let vector = vectors[ i ];
9191
9192                         if ( vector === undefined ) {
9193
9194                                 console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
9195                                 vector = new Vector4();
9196
9197                         }
9198
9199                         array[ offset ++ ] = vector.x;
9200                         array[ offset ++ ] = vector.y;
9201                         array[ offset ++ ] = vector.z;
9202                         array[ offset ++ ] = vector.w;
9203
9204                 }
9205
9206                 return this;
9207
9208         },
9209
9210         applyMatrix3: function ( m ) {
9211
9212                 if ( this.itemSize === 2 ) {
9213
9214                         for ( let i = 0, l = this.count; i < l; i ++ ) {
9215
9216                                 _vector2$1.fromBufferAttribute( this, i );
9217                                 _vector2$1.applyMatrix3( m );
9218
9219                                 this.setXY( i, _vector2$1.x, _vector2$1.y );
9220
9221                         }
9222
9223                 } else if ( this.itemSize === 3 ) {
9224
9225                         for ( let i = 0, l = this.count; i < l; i ++ ) {
9226
9227                                 _vector$3.fromBufferAttribute( this, i );
9228                                 _vector$3.applyMatrix3( m );
9229
9230                                 this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9231
9232                         }
9233
9234                 }
9235
9236                 return this;
9237
9238         },
9239
9240         applyMatrix4: function ( m ) {
9241
9242                 for ( let i = 0, l = this.count; i < l; i ++ ) {
9243
9244                         _vector$3.x = this.getX( i );
9245                         _vector$3.y = this.getY( i );
9246                         _vector$3.z = this.getZ( i );
9247
9248                         _vector$3.applyMatrix4( m );
9249
9250                         this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9251
9252                 }
9253
9254                 return this;
9255
9256         },
9257
9258         applyNormalMatrix: function ( m ) {
9259
9260                 for ( let i = 0, l = this.count; i < l; i ++ ) {
9261
9262                         _vector$3.x = this.getX( i );
9263                         _vector$3.y = this.getY( i );
9264                         _vector$3.z = this.getZ( i );
9265
9266                         _vector$3.applyNormalMatrix( m );
9267
9268                         this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9269
9270                 }
9271
9272                 return this;
9273
9274         },
9275
9276         transformDirection: function ( m ) {
9277
9278                 for ( let i = 0, l = this.count; i < l; i ++ ) {
9279
9280                         _vector$3.x = this.getX( i );
9281                         _vector$3.y = this.getY( i );
9282                         _vector$3.z = this.getZ( i );
9283
9284                         _vector$3.transformDirection( m );
9285
9286                         this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9287
9288                 }
9289
9290                 return this;
9291
9292         },
9293
9294         set: function ( value, offset = 0 ) {
9295
9296                 this.array.set( value, offset );
9297
9298                 return this;
9299
9300         },
9301
9302         getX: function ( index ) {
9303
9304                 return this.array[ index * this.itemSize ];
9305
9306         },
9307
9308         setX: function ( index, x ) {
9309
9310                 this.array[ index * this.itemSize ] = x;
9311
9312                 return this;
9313
9314         },
9315
9316         getY: function ( index ) {
9317
9318                 return this.array[ index * this.itemSize + 1 ];
9319
9320         },
9321
9322         setY: function ( index, y ) {
9323
9324                 this.array[ index * this.itemSize + 1 ] = y;
9325
9326                 return this;
9327
9328         },
9329
9330         getZ: function ( index ) {
9331
9332                 return this.array[ index * this.itemSize + 2 ];
9333
9334         },
9335
9336         setZ: function ( index, z ) {
9337
9338                 this.array[ index * this.itemSize + 2 ] = z;
9339
9340                 return this;
9341
9342         },
9343
9344         getW: function ( index ) {
9345
9346                 return this.array[ index * this.itemSize + 3 ];
9347
9348         },
9349
9350         setW: function ( index, w ) {
9351
9352                 this.array[ index * this.itemSize + 3 ] = w;
9353
9354                 return this;
9355
9356         },
9357
9358         setXY: function ( index, x, y ) {
9359
9360                 index *= this.itemSize;
9361
9362                 this.array[ index + 0 ] = x;
9363                 this.array[ index + 1 ] = y;
9364
9365                 return this;
9366
9367         },
9368
9369         setXYZ: function ( index, x, y, z ) {
9370
9371                 index *= this.itemSize;
9372
9373                 this.array[ index + 0 ] = x;
9374                 this.array[ index + 1 ] = y;
9375                 this.array[ index + 2 ] = z;
9376
9377                 return this;
9378
9379         },
9380
9381         setXYZW: function ( index, x, y, z, w ) {
9382
9383                 index *= this.itemSize;
9384
9385                 this.array[ index + 0 ] = x;
9386                 this.array[ index + 1 ] = y;
9387                 this.array[ index + 2 ] = z;
9388                 this.array[ index + 3 ] = w;
9389
9390                 return this;
9391
9392         },
9393
9394         onUpload: function ( callback ) {
9395
9396                 this.onUploadCallback = callback;
9397
9398                 return this;
9399
9400         },
9401
9402         clone: function () {
9403
9404                 return new this.constructor( this.array, this.itemSize ).copy( this );
9405
9406         },
9407
9408         toJSON: function () {
9409
9410                 return {
9411                         itemSize: this.itemSize,
9412                         type: this.array.constructor.name,
9413                         array: Array.prototype.slice.call( this.array ),
9414                         normalized: this.normalized
9415                 };
9416
9417         }
9418
9419 } );
9420
9421 //
9422
9423 function Int8BufferAttribute( array, itemSize, normalized ) {
9424
9425         BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
9426
9427 }
9428
9429 Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9430 Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
9431
9432
9433 function Uint8BufferAttribute( array, itemSize, normalized ) {
9434
9435         BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
9436
9437 }
9438
9439 Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9440 Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
9441
9442
9443 function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
9444
9445         BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
9446
9447 }
9448
9449 Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9450 Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
9451
9452
9453 function Int16BufferAttribute( array, itemSize, normalized ) {
9454
9455         BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
9456
9457 }
9458
9459 Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9460 Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
9461
9462
9463 function Uint16BufferAttribute( array, itemSize, normalized ) {
9464
9465         BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
9466
9467 }
9468
9469 Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9470 Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
9471
9472
9473 function Int32BufferAttribute( array, itemSize, normalized ) {
9474
9475         BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
9476
9477 }
9478
9479 Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9480 Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
9481
9482
9483 function Uint32BufferAttribute( array, itemSize, normalized ) {
9484
9485         BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
9486
9487 }
9488
9489 Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9490 Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
9491
9492 function Float16BufferAttribute( array, itemSize, normalized ) {
9493
9494         BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
9495
9496 }
9497
9498 Float16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9499 Float16BufferAttribute.prototype.constructor = Float16BufferAttribute;
9500 Float16BufferAttribute.prototype.isFloat16BufferAttribute = true;
9501
9502 function Float32BufferAttribute( array, itemSize, normalized ) {
9503
9504         BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
9505
9506 }
9507
9508 Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9509 Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
9510
9511
9512 function Float64BufferAttribute( array, itemSize, normalized ) {
9513
9514         BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
9515
9516 }
9517
9518 Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9519 Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
9520
9521 function arrayMax( array ) {
9522
9523         if ( array.length === 0 ) return - Infinity;
9524
9525         let max = array[ 0 ];
9526
9527         for ( let i = 1, l = array.length; i < l; ++ i ) {
9528
9529                 if ( array[ i ] > max ) max = array[ i ];
9530
9531         }
9532
9533         return max;
9534
9535 }
9536
9537 const TYPED_ARRAYS = {
9538         Int8Array: Int8Array,
9539         Uint8Array: Uint8Array,
9540         // Workaround for IE11 pre KB2929437. See #11440
9541         Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
9542         Int16Array: Int16Array,
9543         Uint16Array: Uint16Array,
9544         Int32Array: Int32Array,
9545         Uint32Array: Uint32Array,
9546         Float32Array: Float32Array,
9547         Float64Array: Float64Array
9548 };
9549
9550 function getTypedArray( type, buffer ) {
9551
9552         return new TYPED_ARRAYS[ type ]( buffer );
9553
9554 }
9555
9556 let _id = 0;
9557
9558 const _m1$2 = new Matrix4();
9559 const _obj = new Object3D();
9560 const _offset = new Vector3();
9561 const _box$2 = new Box3();
9562 const _boxMorphTargets = new Box3();
9563 const _vector$4 = new Vector3();
9564
9565 function BufferGeometry() {
9566
9567         Object.defineProperty( this, 'id', { value: _id ++ } );
9568
9569         this.uuid = MathUtils.generateUUID();
9570
9571         this.name = '';
9572         this.type = 'BufferGeometry';
9573
9574         this.index = null;
9575         this.attributes = {};
9576
9577         this.morphAttributes = {};
9578         this.morphTargetsRelative = false;
9579
9580         this.groups = [];
9581
9582         this.boundingBox = null;
9583         this.boundingSphere = null;
9584
9585         this.drawRange = { start: 0, count: Infinity };
9586
9587         this.userData = {};
9588
9589 }
9590
9591 BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
9592
9593         constructor: BufferGeometry,
9594
9595         isBufferGeometry: true,
9596
9597         getIndex: function () {
9598
9599                 return this.index;
9600
9601         },
9602
9603         setIndex: function ( index ) {
9604
9605                 if ( Array.isArray( index ) ) {
9606
9607                         this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
9608
9609                 } else {
9610
9611                         this.index = index;
9612
9613                 }
9614
9615                 return this;
9616
9617         },
9618
9619         getAttribute: function ( name ) {
9620
9621                 return this.attributes[ name ];
9622
9623         },
9624
9625         setAttribute: function ( name, attribute ) {
9626
9627                 this.attributes[ name ] = attribute;
9628
9629                 return this;
9630
9631         },
9632
9633         deleteAttribute: function ( name ) {
9634
9635                 delete this.attributes[ name ];
9636
9637                 return this;
9638
9639         },
9640
9641         hasAttribute: function ( name ) {
9642
9643                 return this.attributes[ name ] !== undefined;
9644
9645         },
9646
9647         addGroup: function ( start, count, materialIndex = 0 ) {
9648
9649                 this.groups.push( {
9650
9651                         start: start,
9652                         count: count,
9653                         materialIndex: materialIndex
9654
9655                 } );
9656
9657         },
9658
9659         clearGroups: function () {
9660
9661                 this.groups = [];
9662
9663         },
9664
9665         setDrawRange: function ( start, count ) {
9666
9667                 this.drawRange.start = start;
9668                 this.drawRange.count = count;
9669
9670         },
9671
9672         applyMatrix4: function ( matrix ) {
9673
9674                 const position = this.attributes.position;
9675
9676                 if ( position !== undefined ) {
9677
9678                         position.applyMatrix4( matrix );
9679
9680                         position.needsUpdate = true;
9681
9682                 }
9683
9684                 const normal = this.attributes.normal;
9685
9686                 if ( normal !== undefined ) {
9687
9688                         const normalMatrix = new Matrix3().getNormalMatrix( matrix );
9689
9690                         normal.applyNormalMatrix( normalMatrix );
9691
9692                         normal.needsUpdate = true;
9693
9694                 }
9695
9696                 const tangent = this.attributes.tangent;
9697
9698                 if ( tangent !== undefined ) {
9699
9700                         tangent.transformDirection( matrix );
9701
9702                         tangent.needsUpdate = true;
9703
9704                 }
9705
9706                 if ( this.boundingBox !== null ) {
9707
9708                         this.computeBoundingBox();
9709
9710                 }
9711
9712                 if ( this.boundingSphere !== null ) {
9713
9714                         this.computeBoundingSphere();
9715
9716                 }
9717
9718                 return this;
9719
9720         },
9721
9722         rotateX: function ( angle ) {
9723
9724                 // rotate geometry around world x-axis
9725
9726                 _m1$2.makeRotationX( angle );
9727
9728                 this.applyMatrix4( _m1$2 );
9729
9730                 return this;
9731
9732         },
9733
9734         rotateY: function ( angle ) {
9735
9736                 // rotate geometry around world y-axis
9737
9738                 _m1$2.makeRotationY( angle );
9739
9740                 this.applyMatrix4( _m1$2 );
9741
9742                 return this;
9743
9744         },
9745
9746         rotateZ: function ( angle ) {
9747
9748                 // rotate geometry around world z-axis
9749
9750                 _m1$2.makeRotationZ( angle );
9751
9752                 this.applyMatrix4( _m1$2 );
9753
9754                 return this;
9755
9756         },
9757
9758         translate: function ( x, y, z ) {
9759
9760                 // translate geometry
9761
9762                 _m1$2.makeTranslation( x, y, z );
9763
9764                 this.applyMatrix4( _m1$2 );
9765
9766                 return this;
9767
9768         },
9769
9770         scale: function ( x, y, z ) {
9771
9772                 // scale geometry
9773
9774                 _m1$2.makeScale( x, y, z );
9775
9776                 this.applyMatrix4( _m1$2 );
9777
9778                 return this;
9779
9780         },
9781
9782         lookAt: function ( vector ) {
9783
9784                 _obj.lookAt( vector );
9785
9786                 _obj.updateMatrix();
9787
9788                 this.applyMatrix4( _obj.matrix );
9789
9790                 return this;
9791
9792         },
9793
9794         center: function () {
9795
9796                 this.computeBoundingBox();
9797
9798                 this.boundingBox.getCenter( _offset ).negate();
9799
9800                 this.translate( _offset.x, _offset.y, _offset.z );
9801
9802                 return this;
9803
9804         },
9805
9806         setFromPoints: function ( points ) {
9807
9808                 const position = [];
9809
9810                 for ( let i = 0, l = points.length; i < l; i ++ ) {
9811
9812                         const point = points[ i ];
9813                         position.push( point.x, point.y, point.z || 0 );
9814
9815                 }
9816
9817                 this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
9818
9819                 return this;
9820
9821         },
9822
9823         computeBoundingBox: function () {
9824
9825                 if ( this.boundingBox === null ) {
9826
9827                         this.boundingBox = new Box3();
9828
9829                 }
9830
9831                 const position = this.attributes.position;
9832                 const morphAttributesPosition = this.morphAttributes.position;
9833
9834                 if ( position && position.isGLBufferAttribute ) {
9835
9836                         console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this );
9837
9838                         this.boundingBox.set(
9839                                 new Vector3( - Infinity, - Infinity, - Infinity ),
9840                                 new Vector3( + Infinity, + Infinity, + Infinity )
9841                         );
9842
9843                         return;
9844
9845                 }
9846
9847                 if ( position !== undefined ) {
9848
9849                         this.boundingBox.setFromBufferAttribute( position );
9850
9851                         // process morph attributes if present
9852
9853                         if ( morphAttributesPosition ) {
9854
9855                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
9856
9857                                         const morphAttribute = morphAttributesPosition[ i ];
9858                                         _box$2.setFromBufferAttribute( morphAttribute );
9859
9860                                         if ( this.morphTargetsRelative ) {
9861
9862                                                 _vector$4.addVectors( this.boundingBox.min, _box$2.min );
9863                                                 this.boundingBox.expandByPoint( _vector$4 );
9864
9865                                                 _vector$4.addVectors( this.boundingBox.max, _box$2.max );
9866                                                 this.boundingBox.expandByPoint( _vector$4 );
9867
9868                                         } else {
9869
9870                                                 this.boundingBox.expandByPoint( _box$2.min );
9871                                                 this.boundingBox.expandByPoint( _box$2.max );
9872
9873                                         }
9874
9875                                 }
9876
9877                         }
9878
9879                 } else {
9880
9881                         this.boundingBox.makeEmpty();
9882
9883                 }
9884
9885                 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
9886
9887                         console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
9888
9889                 }
9890
9891         },
9892
9893         computeBoundingSphere: function () {
9894
9895                 if ( this.boundingSphere === null ) {
9896
9897                         this.boundingSphere = new Sphere();
9898
9899                 }
9900
9901                 const position = this.attributes.position;
9902                 const morphAttributesPosition = this.morphAttributes.position;
9903
9904                 if ( position && position.isGLBufferAttribute ) {
9905
9906                         console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this );
9907
9908                         this.boundingSphere.set( new Vector3(), Infinity );
9909
9910                         return;
9911
9912                 }
9913
9914                 if ( position ) {
9915
9916                         // first, find the center of the bounding sphere
9917
9918                         const center = this.boundingSphere.center;
9919
9920                         _box$2.setFromBufferAttribute( position );
9921
9922                         // process morph attributes if present
9923
9924                         if ( morphAttributesPosition ) {
9925
9926                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
9927
9928                                         const morphAttribute = morphAttributesPosition[ i ];
9929                                         _boxMorphTargets.setFromBufferAttribute( morphAttribute );
9930
9931                                         if ( this.morphTargetsRelative ) {
9932
9933                                                 _vector$4.addVectors( _box$2.min, _boxMorphTargets.min );
9934                                                 _box$2.expandByPoint( _vector$4 );
9935
9936                                                 _vector$4.addVectors( _box$2.max, _boxMorphTargets.max );
9937                                                 _box$2.expandByPoint( _vector$4 );
9938
9939                                         } else {
9940
9941                                                 _box$2.expandByPoint( _boxMorphTargets.min );
9942                                                 _box$2.expandByPoint( _boxMorphTargets.max );
9943
9944                                         }
9945
9946                                 }
9947
9948                         }
9949
9950                         _box$2.getCenter( center );
9951
9952                         // second, try to find a boundingSphere with a radius smaller than the
9953                         // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
9954
9955                         let maxRadiusSq = 0;
9956
9957                         for ( let i = 0, il = position.count; i < il; i ++ ) {
9958
9959                                 _vector$4.fromBufferAttribute( position, i );
9960
9961                                 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
9962
9963                         }
9964
9965                         // process morph attributes if present
9966
9967                         if ( morphAttributesPosition ) {
9968
9969                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
9970
9971                                         const morphAttribute = morphAttributesPosition[ i ];
9972                                         const morphTargetsRelative = this.morphTargetsRelative;
9973
9974                                         for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
9975
9976                                                 _vector$4.fromBufferAttribute( morphAttribute, j );
9977
9978                                                 if ( morphTargetsRelative ) {
9979
9980                                                         _offset.fromBufferAttribute( position, j );
9981                                                         _vector$4.add( _offset );
9982
9983                                                 }
9984
9985                                                 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
9986
9987                                         }
9988
9989                                 }
9990
9991                         }
9992
9993                         this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
9994
9995                         if ( isNaN( this.boundingSphere.radius ) ) {
9996
9997                                 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
9998
9999                         }
10000
10001                 }
10002
10003         },
10004
10005         computeFaceNormals: function () {
10006
10007                 // backwards compatibility
10008
10009         },
10010
10011         computeTangents: function () {
10012
10013                 const index = this.index;
10014                 const attributes = this.attributes;
10015
10016                 // based on http://www.terathon.com/code/tangent.html
10017                 // (per vertex tangents)
10018
10019                 if ( index === null ||
10020                          attributes.position === undefined ||
10021                          attributes.normal === undefined ||
10022                          attributes.uv === undefined ) {
10023
10024                         console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
10025                         return;
10026
10027                 }
10028
10029                 const indices = index.array;
10030                 const positions = attributes.position.array;
10031                 const normals = attributes.normal.array;
10032                 const uvs = attributes.uv.array;
10033
10034                 const nVertices = positions.length / 3;
10035
10036                 if ( attributes.tangent === undefined ) {
10037
10038                         this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
10039
10040                 }
10041
10042                 const tangents = attributes.tangent.array;
10043
10044                 const tan1 = [], tan2 = [];
10045
10046                 for ( let i = 0; i < nVertices; i ++ ) {
10047
10048                         tan1[ i ] = new Vector3();
10049                         tan2[ i ] = new Vector3();
10050
10051                 }
10052
10053                 const vA = new Vector3(),
10054                         vB = new Vector3(),
10055                         vC = new Vector3(),
10056
10057                         uvA = new Vector2(),
10058                         uvB = new Vector2(),
10059                         uvC = new Vector2(),
10060
10061                         sdir = new Vector3(),
10062                         tdir = new Vector3();
10063
10064                 function handleTriangle( a, b, c ) {
10065
10066                         vA.fromArray( positions, a * 3 );
10067                         vB.fromArray( positions, b * 3 );
10068                         vC.fromArray( positions, c * 3 );
10069
10070                         uvA.fromArray( uvs, a * 2 );
10071                         uvB.fromArray( uvs, b * 2 );
10072                         uvC.fromArray( uvs, c * 2 );
10073
10074                         vB.sub( vA );
10075                         vC.sub( vA );
10076
10077                         uvB.sub( uvA );
10078                         uvC.sub( uvA );
10079
10080                         const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
10081
10082                         // silently ignore degenerate uv triangles having coincident or colinear vertices
10083
10084                         if ( ! isFinite( r ) ) return;
10085
10086                         sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
10087                         tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
10088
10089                         tan1[ a ].add( sdir );
10090                         tan1[ b ].add( sdir );
10091                         tan1[ c ].add( sdir );
10092
10093                         tan2[ a ].add( tdir );
10094                         tan2[ b ].add( tdir );
10095                         tan2[ c ].add( tdir );
10096
10097                 }
10098
10099                 let groups = this.groups;
10100
10101                 if ( groups.length === 0 ) {
10102
10103                         groups = [ {
10104                                 start: 0,
10105                                 count: indices.length
10106                         } ];
10107
10108                 }
10109
10110                 for ( let i = 0, il = groups.length; i < il; ++ i ) {
10111
10112                         const group = groups[ i ];
10113
10114                         const start = group.start;
10115                         const count = group.count;
10116
10117                         for ( let j = start, jl = start + count; j < jl; j += 3 ) {
10118
10119                                 handleTriangle(
10120                                         indices[ j + 0 ],
10121                                         indices[ j + 1 ],
10122                                         indices[ j + 2 ]
10123                                 );
10124
10125                         }
10126
10127                 }
10128
10129                 const tmp = new Vector3(), tmp2 = new Vector3();
10130                 const n = new Vector3(), n2 = new Vector3();
10131
10132                 function handleVertex( v ) {
10133
10134                         n.fromArray( normals, v * 3 );
10135                         n2.copy( n );
10136
10137                         const t = tan1[ v ];
10138
10139                         // Gram-Schmidt orthogonalize
10140
10141                         tmp.copy( t );
10142                         tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
10143
10144                         // Calculate handedness
10145
10146                         tmp2.crossVectors( n2, t );
10147                         const test = tmp2.dot( tan2[ v ] );
10148                         const w = ( test < 0.0 ) ? - 1.0 : 1.0;
10149
10150                         tangents[ v * 4 ] = tmp.x;
10151                         tangents[ v * 4 + 1 ] = tmp.y;
10152                         tangents[ v * 4 + 2 ] = tmp.z;
10153                         tangents[ v * 4 + 3 ] = w;
10154
10155                 }
10156
10157                 for ( let i = 0, il = groups.length; i < il; ++ i ) {
10158
10159                         const group = groups[ i ];
10160
10161                         const start = group.start;
10162                         const count = group.count;
10163
10164                         for ( let j = start, jl = start + count; j < jl; j += 3 ) {
10165
10166                                 handleVertex( indices[ j + 0 ] );
10167                                 handleVertex( indices[ j + 1 ] );
10168                                 handleVertex( indices[ j + 2 ] );
10169
10170                         }
10171
10172                 }
10173
10174         },
10175
10176         computeVertexNormals: function () {
10177
10178                 const index = this.index;
10179                 const positionAttribute = this.getAttribute( 'position' );
10180
10181                 if ( positionAttribute !== undefined ) {
10182
10183                         let normalAttribute = this.getAttribute( 'normal' );
10184
10185                         if ( normalAttribute === undefined ) {
10186
10187                                 normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
10188                                 this.setAttribute( 'normal', normalAttribute );
10189
10190                         } else {
10191
10192                                 // reset existing normals to zero
10193
10194                                 for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
10195
10196                                         normalAttribute.setXYZ( i, 0, 0, 0 );
10197
10198                                 }
10199
10200                         }
10201
10202                         const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
10203                         const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
10204                         const cb = new Vector3(), ab = new Vector3();
10205
10206                         // indexed elements
10207
10208                         if ( index ) {
10209
10210                                 for ( let i = 0, il = index.count; i < il; i += 3 ) {
10211
10212                                         const vA = index.getX( i + 0 );
10213                                         const vB = index.getX( i + 1 );
10214                                         const vC = index.getX( i + 2 );
10215
10216                                         pA.fromBufferAttribute( positionAttribute, vA );
10217                                         pB.fromBufferAttribute( positionAttribute, vB );
10218                                         pC.fromBufferAttribute( positionAttribute, vC );
10219
10220                                         cb.subVectors( pC, pB );
10221                                         ab.subVectors( pA, pB );
10222                                         cb.cross( ab );
10223
10224                                         nA.fromBufferAttribute( normalAttribute, vA );
10225                                         nB.fromBufferAttribute( normalAttribute, vB );
10226                                         nC.fromBufferAttribute( normalAttribute, vC );
10227
10228                                         nA.add( cb );
10229                                         nB.add( cb );
10230                                         nC.add( cb );
10231
10232                                         normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
10233                                         normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
10234                                         normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
10235
10236                                 }
10237
10238                         } else {
10239
10240                                 // non-indexed elements (unconnected triangle soup)
10241
10242                                 for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
10243
10244                                         pA.fromBufferAttribute( positionAttribute, i + 0 );
10245                                         pB.fromBufferAttribute( positionAttribute, i + 1 );
10246                                         pC.fromBufferAttribute( positionAttribute, i + 2 );
10247
10248                                         cb.subVectors( pC, pB );
10249                                         ab.subVectors( pA, pB );
10250                                         cb.cross( ab );
10251
10252                                         normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
10253                                         normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
10254                                         normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
10255
10256                                 }
10257
10258                         }
10259
10260                         this.normalizeNormals();
10261
10262                         normalAttribute.needsUpdate = true;
10263
10264                 }
10265
10266         },
10267
10268         merge: function ( geometry, offset ) {
10269
10270                 if ( ! ( geometry && geometry.isBufferGeometry ) ) {
10271
10272                         console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
10273                         return;
10274
10275                 }
10276
10277                 if ( offset === undefined ) {
10278
10279                         offset = 0;
10280
10281                         console.warn(
10282                                 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
10283                                 + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
10284                         );
10285
10286                 }
10287
10288                 const attributes = this.attributes;
10289
10290                 for ( const key in attributes ) {
10291
10292                         if ( geometry.attributes[ key ] === undefined ) continue;
10293
10294                         const attribute1 = attributes[ key ];
10295                         const attributeArray1 = attribute1.array;
10296
10297                         const attribute2 = geometry.attributes[ key ];
10298                         const attributeArray2 = attribute2.array;
10299
10300                         const attributeOffset = attribute2.itemSize * offset;
10301                         const length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );
10302
10303                         for ( let i = 0, j = attributeOffset; i < length; i ++, j ++ ) {
10304
10305                                 attributeArray1[ j ] = attributeArray2[ i ];
10306
10307                         }
10308
10309                 }
10310
10311                 return this;
10312
10313         },
10314
10315         normalizeNormals: function () {
10316
10317                 const normals = this.attributes.normal;
10318
10319                 for ( let i = 0, il = normals.count; i < il; i ++ ) {
10320
10321                         _vector$4.fromBufferAttribute( normals, i );
10322
10323                         _vector$4.normalize();
10324
10325                         normals.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );
10326
10327                 }
10328
10329         },
10330
10331         toNonIndexed: function () {
10332
10333                 function convertBufferAttribute( attribute, indices ) {
10334
10335                         const array = attribute.array;
10336                         const itemSize = attribute.itemSize;
10337                         const normalized = attribute.normalized;
10338
10339                         const array2 = new array.constructor( indices.length * itemSize );
10340
10341                         let index = 0, index2 = 0;
10342
10343                         for ( let i = 0, l = indices.length; i < l; i ++ ) {
10344
10345                                 index = indices[ i ] * itemSize;
10346
10347                                 for ( let j = 0; j < itemSize; j ++ ) {
10348
10349                                         array2[ index2 ++ ] = array[ index ++ ];
10350
10351                                 }
10352
10353                         }
10354
10355                         return new BufferAttribute( array2, itemSize, normalized );
10356
10357                 }
10358
10359                 //
10360
10361                 if ( this.index === null ) {
10362
10363                         console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
10364                         return this;
10365
10366                 }
10367
10368                 const geometry2 = new BufferGeometry();
10369
10370                 const indices = this.index.array;
10371                 const attributes = this.attributes;
10372
10373                 // attributes
10374
10375                 for ( const name in attributes ) {
10376
10377                         const attribute = attributes[ name ];
10378
10379                         const newAttribute = convertBufferAttribute( attribute, indices );
10380
10381                         geometry2.setAttribute( name, newAttribute );
10382
10383                 }
10384
10385                 // morph attributes
10386
10387                 const morphAttributes = this.morphAttributes;
10388
10389                 for ( const name in morphAttributes ) {
10390
10391                         const morphArray = [];
10392                         const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
10393
10394                         for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
10395
10396                                 const attribute = morphAttribute[ i ];
10397
10398                                 const newAttribute = convertBufferAttribute( attribute, indices );
10399
10400                                 morphArray.push( newAttribute );
10401
10402                         }
10403
10404                         geometry2.morphAttributes[ name ] = morphArray;
10405
10406                 }
10407
10408                 geometry2.morphTargetsRelative = this.morphTargetsRelative;
10409
10410                 // groups
10411
10412                 const groups = this.groups;
10413
10414                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
10415
10416                         const group = groups[ i ];
10417                         geometry2.addGroup( group.start, group.count, group.materialIndex );
10418
10419                 }
10420
10421                 return geometry2;
10422
10423         },
10424
10425         toJSON: function () {
10426
10427                 const data = {
10428                         metadata: {
10429                                 version: 4.5,
10430                                 type: 'BufferGeometry',
10431                                 generator: 'BufferGeometry.toJSON'
10432                         }
10433                 };
10434
10435                 // standard BufferGeometry serialization
10436
10437                 data.uuid = this.uuid;
10438                 data.type = this.type;
10439                 if ( this.name !== '' ) data.name = this.name;
10440                 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
10441
10442                 if ( this.parameters !== undefined ) {
10443
10444                         const parameters = this.parameters;
10445
10446                         for ( const key in parameters ) {
10447
10448                                 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
10449
10450                         }
10451
10452                         return data;
10453
10454                 }
10455
10456                 data.data = { attributes: {} };
10457
10458                 const index = this.index;
10459
10460                 if ( index !== null ) {
10461
10462                         data.data.index = {
10463                                 type: index.array.constructor.name,
10464                                 array: Array.prototype.slice.call( index.array )
10465                         };
10466
10467                 }
10468
10469                 const attributes = this.attributes;
10470
10471                 for ( const key in attributes ) {
10472
10473                         const attribute = attributes[ key ];
10474
10475                         const attributeData = attribute.toJSON( data.data );
10476
10477                         if ( attribute.name !== '' ) attributeData.name = attribute.name;
10478
10479                         data.data.attributes[ key ] = attributeData;
10480
10481                 }
10482
10483                 const morphAttributes = {};
10484                 let hasMorphAttributes = false;
10485
10486                 for ( const key in this.morphAttributes ) {
10487
10488                         const attributeArray = this.morphAttributes[ key ];
10489
10490                         const array = [];
10491
10492                         for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
10493
10494                                 const attribute = attributeArray[ i ];
10495
10496                                 const attributeData = attribute.toJSON( data.data );
10497
10498                                 if ( attribute.name !== '' ) attributeData.name = attribute.name;
10499
10500                                 array.push( attributeData );
10501
10502                         }
10503
10504                         if ( array.length > 0 ) {
10505
10506                                 morphAttributes[ key ] = array;
10507
10508                                 hasMorphAttributes = true;
10509
10510                         }
10511
10512                 }
10513
10514                 if ( hasMorphAttributes ) {
10515
10516                         data.data.morphAttributes = morphAttributes;
10517                         data.data.morphTargetsRelative = this.morphTargetsRelative;
10518
10519                 }
10520
10521                 const groups = this.groups;
10522
10523                 if ( groups.length > 0 ) {
10524
10525                         data.data.groups = JSON.parse( JSON.stringify( groups ) );
10526
10527                 }
10528
10529                 const boundingSphere = this.boundingSphere;
10530
10531                 if ( boundingSphere !== null ) {
10532
10533                         data.data.boundingSphere = {
10534                                 center: boundingSphere.center.toArray(),
10535                                 radius: boundingSphere.radius
10536                         };
10537
10538                 }
10539
10540                 return data;
10541
10542         },
10543
10544         clone: function () {
10545
10546                 /*
10547                  // Handle primitives
10548
10549                  const parameters = this.parameters;
10550
10551                  if ( parameters !== undefined ) {
10552
10553                  const values = [];
10554
10555                  for ( const key in parameters ) {
10556
10557                  values.push( parameters[ key ] );
10558
10559                  }
10560
10561                  const geometry = Object.create( this.constructor.prototype );
10562                  this.constructor.apply( geometry, values );
10563                  return geometry;
10564
10565                  }
10566
10567                  return new this.constructor().copy( this );
10568                  */
10569
10570                 return new BufferGeometry().copy( this );
10571
10572         },
10573
10574         copy: function ( source ) {
10575
10576                 // reset
10577
10578                 this.index = null;
10579                 this.attributes = {};
10580                 this.morphAttributes = {};
10581                 this.groups = [];
10582                 this.boundingBox = null;
10583                 this.boundingSphere = null;
10584
10585                 // used for storing cloned, shared data
10586
10587                 const data = {};
10588
10589                 // name
10590
10591                 this.name = source.name;
10592
10593                 // index
10594
10595                 const index = source.index;
10596
10597                 if ( index !== null ) {
10598
10599                         this.setIndex( index.clone( data ) );
10600
10601                 }
10602
10603                 // attributes
10604
10605                 const attributes = source.attributes;
10606
10607                 for ( const name in attributes ) {
10608
10609                         const attribute = attributes[ name ];
10610                         this.setAttribute( name, attribute.clone( data ) );
10611
10612                 }
10613
10614                 // morph attributes
10615
10616                 const morphAttributes = source.morphAttributes;
10617
10618                 for ( const name in morphAttributes ) {
10619
10620                         const array = [];
10621                         const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
10622
10623                         for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
10624
10625                                 array.push( morphAttribute[ i ].clone( data ) );
10626
10627                         }
10628
10629                         this.morphAttributes[ name ] = array;
10630
10631                 }
10632
10633                 this.morphTargetsRelative = source.morphTargetsRelative;
10634
10635                 // groups
10636
10637                 const groups = source.groups;
10638
10639                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
10640
10641                         const group = groups[ i ];
10642                         this.addGroup( group.start, group.count, group.materialIndex );
10643
10644                 }
10645
10646                 // bounding box
10647
10648                 const boundingBox = source.boundingBox;
10649
10650                 if ( boundingBox !== null ) {
10651
10652                         this.boundingBox = boundingBox.clone();
10653
10654                 }
10655
10656                 // bounding sphere
10657
10658                 const boundingSphere = source.boundingSphere;
10659
10660                 if ( boundingSphere !== null ) {
10661
10662                         this.boundingSphere = boundingSphere.clone();
10663
10664                 }
10665
10666                 // draw range
10667
10668                 this.drawRange.start = source.drawRange.start;
10669                 this.drawRange.count = source.drawRange.count;
10670
10671                 // user data
10672
10673                 this.userData = source.userData;
10674
10675                 return this;
10676
10677         },
10678
10679         dispose: function () {
10680
10681                 this.dispatchEvent( { type: 'dispose' } );
10682
10683         }
10684
10685 } );
10686
10687 const _inverseMatrix = new Matrix4();
10688 const _ray = new Ray();
10689 const _sphere = new Sphere();
10690
10691 const _vA = new Vector3();
10692 const _vB = new Vector3();
10693 const _vC = new Vector3();
10694
10695 const _tempA = new Vector3();
10696 const _tempB = new Vector3();
10697 const _tempC = new Vector3();
10698
10699 const _morphA = new Vector3();
10700 const _morphB = new Vector3();
10701 const _morphC = new Vector3();
10702
10703 const _uvA = new Vector2();
10704 const _uvB = new Vector2();
10705 const _uvC = new Vector2();
10706
10707 const _intersectionPoint = new Vector3();
10708 const _intersectionPointWorld = new Vector3();
10709
10710 function Mesh( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
10711
10712         Object3D.call( this );
10713
10714         this.type = 'Mesh';
10715
10716         this.geometry = geometry;
10717         this.material = material;
10718
10719         this.updateMorphTargets();
10720
10721 }
10722
10723 Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
10724
10725         constructor: Mesh,
10726
10727         isMesh: true,
10728
10729         copy: function ( source ) {
10730
10731                 Object3D.prototype.copy.call( this, source );
10732
10733                 if ( source.morphTargetInfluences !== undefined ) {
10734
10735                         this.morphTargetInfluences = source.morphTargetInfluences.slice();
10736
10737                 }
10738
10739                 if ( source.morphTargetDictionary !== undefined ) {
10740
10741                         this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
10742
10743                 }
10744
10745                 this.material = source.material;
10746                 this.geometry = source.geometry;
10747
10748                 return this;
10749
10750         },
10751
10752         updateMorphTargets: function () {
10753
10754                 const geometry = this.geometry;
10755
10756                 if ( geometry.isBufferGeometry ) {
10757
10758                         const morphAttributes = geometry.morphAttributes;
10759                         const keys = Object.keys( morphAttributes );
10760
10761                         if ( keys.length > 0 ) {
10762
10763                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
10764
10765                                 if ( morphAttribute !== undefined ) {
10766
10767                                         this.morphTargetInfluences = [];
10768                                         this.morphTargetDictionary = {};
10769
10770                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
10771
10772                                                 const name = morphAttribute[ m ].name || String( m );
10773
10774                                                 this.morphTargetInfluences.push( 0 );
10775                                                 this.morphTargetDictionary[ name ] = m;
10776
10777                                         }
10778
10779                                 }
10780
10781                         }
10782
10783                 } else {
10784
10785                         const morphTargets = geometry.morphTargets;
10786
10787                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
10788
10789                                 console.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
10790
10791                         }
10792
10793                 }
10794
10795         },
10796
10797         raycast: function ( raycaster, intersects ) {
10798
10799                 const geometry = this.geometry;
10800                 const material = this.material;
10801                 const matrixWorld = this.matrixWorld;
10802
10803                 if ( material === undefined ) return;
10804
10805                 // Checking boundingSphere distance to ray
10806
10807                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
10808
10809                 _sphere.copy( geometry.boundingSphere );
10810                 _sphere.applyMatrix4( matrixWorld );
10811
10812                 if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
10813
10814                 //
10815
10816                 _inverseMatrix.copy( matrixWorld ).invert();
10817                 _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
10818
10819                 // Check boundingBox before continuing
10820
10821                 if ( geometry.boundingBox !== null ) {
10822
10823                         if ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;
10824
10825                 }
10826
10827                 let intersection;
10828
10829                 if ( geometry.isBufferGeometry ) {
10830
10831                         const index = geometry.index;
10832                         const position = geometry.attributes.position;
10833                         const morphPosition = geometry.morphAttributes.position;
10834                         const morphTargetsRelative = geometry.morphTargetsRelative;
10835                         const uv = geometry.attributes.uv;
10836                         const uv2 = geometry.attributes.uv2;
10837                         const groups = geometry.groups;
10838                         const drawRange = geometry.drawRange;
10839
10840                         if ( index !== null ) {
10841
10842                                 // indexed buffer geometry
10843
10844                                 if ( Array.isArray( material ) ) {
10845
10846                                         for ( let i = 0, il = groups.length; i < il; i ++ ) {
10847
10848                                                 const group = groups[ i ];
10849                                                 const groupMaterial = material[ group.materialIndex ];
10850
10851                                                 const start = Math.max( group.start, drawRange.start );
10852                                                 const end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
10853
10854                                                 for ( let j = start, jl = end; j < jl; j += 3 ) {
10855
10856                                                         const a = index.getX( j );
10857                                                         const b = index.getX( j + 1 );
10858                                                         const c = index.getX( j + 2 );
10859
10860                                                         intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
10861
10862                                                         if ( intersection ) {
10863
10864                                                                 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
10865                                                                 intersection.face.materialIndex = group.materialIndex;
10866                                                                 intersects.push( intersection );
10867
10868                                                         }
10869
10870                                                 }
10871
10872                                         }
10873
10874                                 } else {
10875
10876                                         const start = Math.max( 0, drawRange.start );
10877                                         const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
10878
10879                                         for ( let i = start, il = end; i < il; i += 3 ) {
10880
10881                                                 const a = index.getX( i );
10882                                                 const b = index.getX( i + 1 );
10883                                                 const c = index.getX( i + 2 );
10884
10885                                                 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
10886
10887                                                 if ( intersection ) {
10888
10889                                                         intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
10890                                                         intersects.push( intersection );
10891
10892                                                 }
10893
10894                                         }
10895
10896                                 }
10897
10898                         } else if ( position !== undefined ) {
10899
10900                                 // non-indexed buffer geometry
10901
10902                                 if ( Array.isArray( material ) ) {
10903
10904                                         for ( let i = 0, il = groups.length; i < il; i ++ ) {
10905
10906                                                 const group = groups[ i ];
10907                                                 const groupMaterial = material[ group.materialIndex ];
10908
10909                                                 const start = Math.max( group.start, drawRange.start );
10910                                                 const end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
10911
10912                                                 for ( let j = start, jl = end; j < jl; j += 3 ) {
10913
10914                                                         const a = j;
10915                                                         const b = j + 1;
10916                                                         const c = j + 2;
10917
10918                                                         intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
10919
10920                                                         if ( intersection ) {
10921
10922                                                                 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
10923                                                                 intersection.face.materialIndex = group.materialIndex;
10924                                                                 intersects.push( intersection );
10925
10926                                                         }
10927
10928                                                 }
10929
10930                                         }
10931
10932                                 } else {
10933
10934                                         const start = Math.max( 0, drawRange.start );
10935                                         const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
10936
10937                                         for ( let i = start, il = end; i < il; i += 3 ) {
10938
10939                                                 const a = i;
10940                                                 const b = i + 1;
10941                                                 const c = i + 2;
10942
10943                                                 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
10944
10945                                                 if ( intersection ) {
10946
10947                                                         intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
10948                                                         intersects.push( intersection );
10949
10950                                                 }
10951
10952                                         }
10953
10954                                 }
10955
10956                         }
10957
10958                 } else if ( geometry.isGeometry ) {
10959
10960                         console.error( 'THREE.Mesh.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
10961
10962                 }
10963
10964         }
10965
10966 } );
10967
10968 function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
10969
10970         let intersect;
10971
10972         if ( material.side === BackSide ) {
10973
10974                 intersect = ray.intersectTriangle( pC, pB, pA, true, point );
10975
10976         } else {
10977
10978                 intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
10979
10980         }
10981
10982         if ( intersect === null ) return null;
10983
10984         _intersectionPointWorld.copy( point );
10985         _intersectionPointWorld.applyMatrix4( object.matrixWorld );
10986
10987         const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
10988
10989         if ( distance < raycaster.near || distance > raycaster.far ) return null;
10990
10991         return {
10992                 distance: distance,
10993                 point: _intersectionPointWorld.clone(),
10994                 object: object
10995         };
10996
10997 }
10998
10999 function checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {
11000
11001         _vA.fromBufferAttribute( position, a );
11002         _vB.fromBufferAttribute( position, b );
11003         _vC.fromBufferAttribute( position, c );
11004
11005         const morphInfluences = object.morphTargetInfluences;
11006
11007         if ( material.morphTargets && morphPosition && morphInfluences ) {
11008
11009                 _morphA.set( 0, 0, 0 );
11010                 _morphB.set( 0, 0, 0 );
11011                 _morphC.set( 0, 0, 0 );
11012
11013                 for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
11014
11015                         const influence = morphInfluences[ i ];
11016                         const morphAttribute = morphPosition[ i ];
11017
11018                         if ( influence === 0 ) continue;
11019
11020                         _tempA.fromBufferAttribute( morphAttribute, a );
11021                         _tempB.fromBufferAttribute( morphAttribute, b );
11022                         _tempC.fromBufferAttribute( morphAttribute, c );
11023
11024                         if ( morphTargetsRelative ) {
11025
11026                                 _morphA.addScaledVector( _tempA, influence );
11027                                 _morphB.addScaledVector( _tempB, influence );
11028                                 _morphC.addScaledVector( _tempC, influence );
11029
11030                         } else {
11031
11032                                 _morphA.addScaledVector( _tempA.sub( _vA ), influence );
11033                                 _morphB.addScaledVector( _tempB.sub( _vB ), influence );
11034                                 _morphC.addScaledVector( _tempC.sub( _vC ), influence );
11035
11036                         }
11037
11038                 }
11039
11040                 _vA.add( _morphA );
11041                 _vB.add( _morphB );
11042                 _vC.add( _morphC );
11043
11044         }
11045
11046         if ( object.isSkinnedMesh ) {
11047
11048                 object.boneTransform( a, _vA );
11049                 object.boneTransform( b, _vB );
11050                 object.boneTransform( c, _vC );
11051
11052         }
11053
11054         const intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
11055
11056         if ( intersection ) {
11057
11058                 if ( uv ) {
11059
11060                         _uvA.fromBufferAttribute( uv, a );
11061                         _uvB.fromBufferAttribute( uv, b );
11062                         _uvC.fromBufferAttribute( uv, c );
11063
11064                         intersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
11065
11066                 }
11067
11068                 if ( uv2 ) {
11069
11070                         _uvA.fromBufferAttribute( uv2, a );
11071                         _uvB.fromBufferAttribute( uv2, b );
11072                         _uvC.fromBufferAttribute( uv2, c );
11073
11074                         intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
11075
11076                 }
11077
11078                 const face = new Face3( a, b, c );
11079                 Triangle.getNormal( _vA, _vB, _vC, face.normal );
11080
11081                 intersection.face = face;
11082
11083         }
11084
11085         return intersection;
11086
11087 }
11088
11089 class BoxGeometry extends BufferGeometry {
11090
11091         constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
11092
11093                 super();
11094
11095                 this.type = 'BoxGeometry';
11096
11097                 this.parameters = {
11098                         width: width,
11099                         height: height,
11100                         depth: depth,
11101                         widthSegments: widthSegments,
11102                         heightSegments: heightSegments,
11103                         depthSegments: depthSegments
11104                 };
11105
11106                 const scope = this;
11107
11108                 // segments
11109
11110                 widthSegments = Math.floor( widthSegments );
11111                 heightSegments = Math.floor( heightSegments );
11112                 depthSegments = Math.floor( depthSegments );
11113
11114                 // buffers
11115
11116                 const indices = [];
11117                 const vertices = [];
11118                 const normals = [];
11119                 const uvs = [];
11120
11121                 // helper variables
11122
11123                 let numberOfVertices = 0;
11124                 let groupStart = 0;
11125
11126                 // build each side of the box geometry
11127
11128                 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
11129                 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
11130                 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
11131                 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
11132                 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
11133                 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
11134
11135                 // build geometry
11136
11137                 this.setIndex( indices );
11138                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
11139                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
11140                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
11141
11142                 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
11143
11144                         const segmentWidth = width / gridX;
11145                         const segmentHeight = height / gridY;
11146
11147                         const widthHalf = width / 2;
11148                         const heightHalf = height / 2;
11149                         const depthHalf = depth / 2;
11150
11151                         const gridX1 = gridX + 1;
11152                         const gridY1 = gridY + 1;
11153
11154                         let vertexCounter = 0;
11155                         let groupCount = 0;
11156
11157                         const vector = new Vector3();
11158
11159                         // generate vertices, normals and uvs
11160
11161                         for ( let iy = 0; iy < gridY1; iy ++ ) {
11162
11163                                 const y = iy * segmentHeight - heightHalf;
11164
11165                                 for ( let ix = 0; ix < gridX1; ix ++ ) {
11166
11167                                         const x = ix * segmentWidth - widthHalf;
11168
11169                                         // set values to correct vector component
11170
11171                                         vector[ u ] = x * udir;
11172                                         vector[ v ] = y * vdir;
11173                                         vector[ w ] = depthHalf;
11174
11175                                         // now apply vector to vertex buffer
11176
11177                                         vertices.push( vector.x, vector.y, vector.z );
11178
11179                                         // set values to correct vector component
11180
11181                                         vector[ u ] = 0;
11182                                         vector[ v ] = 0;
11183                                         vector[ w ] = depth > 0 ? 1 : - 1;
11184
11185                                         // now apply vector to normal buffer
11186
11187                                         normals.push( vector.x, vector.y, vector.z );
11188
11189                                         // uvs
11190
11191                                         uvs.push( ix / gridX );
11192                                         uvs.push( 1 - ( iy / gridY ) );
11193
11194                                         // counters
11195
11196                                         vertexCounter += 1;
11197
11198                                 }
11199
11200                         }
11201
11202                         // indices
11203
11204                         // 1. you need three indices to draw a single face
11205                         // 2. a single segment consists of two faces
11206                         // 3. so we need to generate six (2*3) indices per segment
11207
11208                         for ( let iy = 0; iy < gridY; iy ++ ) {
11209
11210                                 for ( let ix = 0; ix < gridX; ix ++ ) {
11211
11212                                         const a = numberOfVertices + ix + gridX1 * iy;
11213                                         const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
11214                                         const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
11215                                         const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
11216
11217                                         // faces
11218
11219                                         indices.push( a, b, d );
11220                                         indices.push( b, c, d );
11221
11222                                         // increase counter
11223
11224                                         groupCount += 6;
11225
11226                                 }
11227
11228                         }
11229
11230                         // add a group to the geometry. this will ensure multi material support
11231
11232                         scope.addGroup( groupStart, groupCount, materialIndex );
11233
11234                         // calculate new start value for groups
11235
11236                         groupStart += groupCount;
11237
11238                         // update total number of vertices
11239
11240                         numberOfVertices += vertexCounter;
11241
11242                 }
11243
11244         }
11245
11246 }
11247
11248 /**
11249  * Uniform Utilities
11250  */
11251
11252 function cloneUniforms( src ) {
11253
11254         const dst = {};
11255
11256         for ( const u in src ) {
11257
11258                 dst[ u ] = {};
11259
11260                 for ( const p in src[ u ] ) {
11261
11262                         const property = src[ u ][ p ];
11263
11264                         if ( property && ( property.isColor ||
11265                                 property.isMatrix3 || property.isMatrix4 ||
11266                                 property.isVector2 || property.isVector3 || property.isVector4 ||
11267                                 property.isTexture ) ) {
11268
11269                                 dst[ u ][ p ] = property.clone();
11270
11271                         } else if ( Array.isArray( property ) ) {
11272
11273                                 dst[ u ][ p ] = property.slice();
11274
11275                         } else {
11276
11277                                 dst[ u ][ p ] = property;
11278
11279                         }
11280
11281                 }
11282
11283         }
11284
11285         return dst;
11286
11287 }
11288
11289 function mergeUniforms( uniforms ) {
11290
11291         const merged = {};
11292
11293         for ( let u = 0; u < uniforms.length; u ++ ) {
11294
11295                 const tmp = cloneUniforms( uniforms[ u ] );
11296
11297                 for ( const p in tmp ) {
11298
11299                         merged[ p ] = tmp[ p ];
11300
11301                 }
11302
11303         }
11304
11305         return merged;
11306
11307 }
11308
11309 // Legacy
11310
11311 const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
11312
11313 var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
11314
11315 var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
11316
11317 /**
11318  * parameters = {
11319  *  defines: { "label" : "value" },
11320  *  uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
11321  *
11322  *  fragmentShader: <string>,
11323  *  vertexShader: <string>,
11324  *
11325  *  wireframe: <boolean>,
11326  *  wireframeLinewidth: <float>,
11327  *
11328  *  lights: <bool>,
11329  *
11330  *  skinning: <bool>,
11331  *  morphTargets: <bool>,
11332  *  morphNormals: <bool>
11333  * }
11334  */
11335
11336 function ShaderMaterial( parameters ) {
11337
11338         Material.call( this );
11339
11340         this.type = 'ShaderMaterial';
11341
11342         this.defines = {};
11343         this.uniforms = {};
11344
11345         this.vertexShader = default_vertex;
11346         this.fragmentShader = default_fragment;
11347
11348         this.linewidth = 1;
11349
11350         this.wireframe = false;
11351         this.wireframeLinewidth = 1;
11352
11353         this.fog = false; // set to use scene fog
11354         this.lights = false; // set to use scene lights
11355         this.clipping = false; // set to use user-defined clipping planes
11356
11357         this.skinning = false; // set to use skinning attribute streams
11358         this.morphTargets = false; // set to use morph targets
11359         this.morphNormals = false; // set to use morph normals
11360
11361         this.extensions = {
11362                 derivatives: false, // set to use derivatives
11363                 fragDepth: false, // set to use fragment depth values
11364                 drawBuffers: false, // set to use draw buffers
11365                 shaderTextureLOD: false // set to use shader texture LOD
11366         };
11367
11368         // When rendered geometry doesn't include these attributes but the material does,
11369         // use these default values in WebGL. This avoids errors when buffer data is missing.
11370         this.defaultAttributeValues = {
11371                 'color': [ 1, 1, 1 ],
11372                 'uv': [ 0, 0 ],
11373                 'uv2': [ 0, 0 ]
11374         };
11375
11376         this.index0AttributeName = undefined;
11377         this.uniformsNeedUpdate = false;
11378
11379         this.glslVersion = null;
11380
11381         if ( parameters !== undefined ) {
11382
11383                 if ( parameters.attributes !== undefined ) {
11384
11385                         console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
11386
11387                 }
11388
11389                 this.setValues( parameters );
11390
11391         }
11392
11393 }
11394
11395 ShaderMaterial.prototype = Object.create( Material.prototype );
11396 ShaderMaterial.prototype.constructor = ShaderMaterial;
11397
11398 ShaderMaterial.prototype.isShaderMaterial = true;
11399
11400 ShaderMaterial.prototype.copy = function ( source ) {
11401
11402         Material.prototype.copy.call( this, source );
11403
11404         this.fragmentShader = source.fragmentShader;
11405         this.vertexShader = source.vertexShader;
11406
11407         this.uniforms = cloneUniforms( source.uniforms );
11408
11409         this.defines = Object.assign( {}, source.defines );
11410
11411         this.wireframe = source.wireframe;
11412         this.wireframeLinewidth = source.wireframeLinewidth;
11413
11414         this.lights = source.lights;
11415         this.clipping = source.clipping;
11416
11417         this.skinning = source.skinning;
11418
11419         this.morphTargets = source.morphTargets;
11420         this.morphNormals = source.morphNormals;
11421
11422         this.extensions = Object.assign( {}, source.extensions );
11423
11424         this.glslVersion = source.glslVersion;
11425
11426         return this;
11427
11428 };
11429
11430 ShaderMaterial.prototype.toJSON = function ( meta ) {
11431
11432         const data = Material.prototype.toJSON.call( this, meta );
11433
11434         data.glslVersion = this.glslVersion;
11435         data.uniforms = {};
11436
11437         for ( const name in this.uniforms ) {
11438
11439                 const uniform = this.uniforms[ name ];
11440                 const value = uniform.value;
11441
11442                 if ( value && value.isTexture ) {
11443
11444                         data.uniforms[ name ] = {
11445                                 type: 't',
11446                                 value: value.toJSON( meta ).uuid
11447                         };
11448
11449                 } else if ( value && value.isColor ) {
11450
11451                         data.uniforms[ name ] = {
11452                                 type: 'c',
11453                                 value: value.getHex()
11454                         };
11455
11456                 } else if ( value && value.isVector2 ) {
11457
11458                         data.uniforms[ name ] = {
11459                                 type: 'v2',
11460                                 value: value.toArray()
11461                         };
11462
11463                 } else if ( value && value.isVector3 ) {
11464
11465                         data.uniforms[ name ] = {
11466                                 type: 'v3',
11467                                 value: value.toArray()
11468                         };
11469
11470                 } else if ( value && value.isVector4 ) {
11471
11472                         data.uniforms[ name ] = {
11473                                 type: 'v4',
11474                                 value: value.toArray()
11475                         };
11476
11477                 } else if ( value && value.isMatrix3 ) {
11478
11479                         data.uniforms[ name ] = {
11480                                 type: 'm3',
11481                                 value: value.toArray()
11482                         };
11483
11484                 } else if ( value && value.isMatrix4 ) {
11485
11486                         data.uniforms[ name ] = {
11487                                 type: 'm4',
11488                                 value: value.toArray()
11489                         };
11490
11491                 } else {
11492
11493                         data.uniforms[ name ] = {
11494                                 value: value
11495                         };
11496
11497                         // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
11498
11499                 }
11500
11501         }
11502
11503         if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
11504
11505         data.vertexShader = this.vertexShader;
11506         data.fragmentShader = this.fragmentShader;
11507
11508         const extensions = {};
11509
11510         for ( const key in this.extensions ) {
11511
11512                 if ( this.extensions[ key ] === true ) extensions[ key ] = true;
11513
11514         }
11515
11516         if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
11517
11518         return data;
11519
11520 };
11521
11522 function Camera() {
11523
11524         Object3D.call( this );
11525
11526         this.type = 'Camera';
11527
11528         this.matrixWorldInverse = new Matrix4();
11529
11530         this.projectionMatrix = new Matrix4();
11531         this.projectionMatrixInverse = new Matrix4();
11532
11533 }
11534
11535 Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
11536
11537         constructor: Camera,
11538
11539         isCamera: true,
11540
11541         copy: function ( source, recursive ) {
11542
11543                 Object3D.prototype.copy.call( this, source, recursive );
11544
11545                 this.matrixWorldInverse.copy( source.matrixWorldInverse );
11546
11547                 this.projectionMatrix.copy( source.projectionMatrix );
11548                 this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
11549
11550                 return this;
11551
11552         },
11553
11554         getWorldDirection: function ( target ) {
11555
11556                 if ( target === undefined ) {
11557
11558                         console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
11559                         target = new Vector3();
11560
11561                 }
11562
11563                 this.updateWorldMatrix( true, false );
11564
11565                 const e = this.matrixWorld.elements;
11566
11567                 return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();
11568
11569         },
11570
11571         updateMatrixWorld: function ( force ) {
11572
11573                 Object3D.prototype.updateMatrixWorld.call( this, force );
11574
11575                 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
11576
11577         },
11578
11579         updateWorldMatrix: function ( updateParents, updateChildren ) {
11580
11581                 Object3D.prototype.updateWorldMatrix.call( this, updateParents, updateChildren );
11582
11583                 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
11584
11585         },
11586
11587         clone: function () {
11588
11589                 return new this.constructor().copy( this );
11590
11591         }
11592
11593 } );
11594
11595 function PerspectiveCamera( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
11596
11597         Camera.call( this );
11598
11599         this.type = 'PerspectiveCamera';
11600
11601         this.fov = fov;
11602         this.zoom = 1;
11603
11604         this.near = near;
11605         this.far = far;
11606         this.focus = 10;
11607
11608         this.aspect = aspect;
11609         this.view = null;
11610
11611         this.filmGauge = 35;    // width of the film (default in millimeters)
11612         this.filmOffset = 0;    // horizontal film offset (same unit as gauge)
11613
11614         this.updateProjectionMatrix();
11615
11616 }
11617
11618 PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
11619
11620         constructor: PerspectiveCamera,
11621
11622         isPerspectiveCamera: true,
11623
11624         copy: function ( source, recursive ) {
11625
11626                 Camera.prototype.copy.call( this, source, recursive );
11627
11628                 this.fov = source.fov;
11629                 this.zoom = source.zoom;
11630
11631                 this.near = source.near;
11632                 this.far = source.far;
11633                 this.focus = source.focus;
11634
11635                 this.aspect = source.aspect;
11636                 this.view = source.view === null ? null : Object.assign( {}, source.view );
11637
11638                 this.filmGauge = source.filmGauge;
11639                 this.filmOffset = source.filmOffset;
11640
11641                 return this;
11642
11643         },
11644
11645         /**
11646          * Sets the FOV by focal length in respect to the current .filmGauge.
11647          *
11648          * The default film gauge is 35, so that the focal length can be specified for
11649          * a 35mm (full frame) camera.
11650          *
11651          * Values for focal length and film gauge must have the same unit.
11652          */
11653         setFocalLength: function ( focalLength ) {
11654
11655                 /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
11656                 const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
11657
11658                 this.fov = MathUtils.RAD2DEG * 2 * Math.atan( vExtentSlope );
11659                 this.updateProjectionMatrix();
11660
11661         },
11662
11663         /**
11664          * Calculates the focal length from the current .fov and .filmGauge.
11665          */
11666         getFocalLength: function () {
11667
11668                 const vExtentSlope = Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov );
11669
11670                 return 0.5 * this.getFilmHeight() / vExtentSlope;
11671
11672         },
11673
11674         getEffectiveFOV: function () {
11675
11676                 return MathUtils.RAD2DEG * 2 * Math.atan(
11677                         Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom );
11678
11679         },
11680
11681         getFilmWidth: function () {
11682
11683                 // film not completely covered in portrait format (aspect < 1)
11684                 return this.filmGauge * Math.min( this.aspect, 1 );
11685
11686         },
11687
11688         getFilmHeight: function () {
11689
11690                 // film not completely covered in landscape format (aspect > 1)
11691                 return this.filmGauge / Math.max( this.aspect, 1 );
11692
11693         },
11694
11695         /**
11696          * Sets an offset in a larger frustum. This is useful for multi-window or
11697          * multi-monitor/multi-machine setups.
11698          *
11699          * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
11700          * the monitors are in grid like this
11701          *
11702          *   +---+---+---+
11703          *   | A | B | C |
11704          *   +---+---+---+
11705          *   | D | E | F |
11706          *   +---+---+---+
11707          *
11708          * then for each monitor you would call it like this
11709          *
11710          *   const w = 1920;
11711          *   const h = 1080;
11712          *   const fullWidth = w * 3;
11713          *   const fullHeight = h * 2;
11714          *
11715          *   --A--
11716          *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
11717          *   --B--
11718          *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
11719          *   --C--
11720          *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
11721          *   --D--
11722          *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
11723          *   --E--
11724          *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
11725          *   --F--
11726          *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
11727          *
11728          *   Note there is no reason monitors have to be the same size or in a grid.
11729          */
11730         setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
11731
11732                 this.aspect = fullWidth / fullHeight;
11733
11734                 if ( this.view === null ) {
11735
11736                         this.view = {
11737                                 enabled: true,
11738                                 fullWidth: 1,
11739                                 fullHeight: 1,
11740                                 offsetX: 0,
11741                                 offsetY: 0,
11742                                 width: 1,
11743                                 height: 1
11744                         };
11745
11746                 }
11747
11748                 this.view.enabled = true;
11749                 this.view.fullWidth = fullWidth;
11750                 this.view.fullHeight = fullHeight;
11751                 this.view.offsetX = x;
11752                 this.view.offsetY = y;
11753                 this.view.width = width;
11754                 this.view.height = height;
11755
11756                 this.updateProjectionMatrix();
11757
11758         },
11759
11760         clearViewOffset: function () {
11761
11762                 if ( this.view !== null ) {
11763
11764                         this.view.enabled = false;
11765
11766                 }
11767
11768                 this.updateProjectionMatrix();
11769
11770         },
11771
11772         updateProjectionMatrix: function () {
11773
11774                 const near = this.near;
11775                 let top = near * Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom;
11776                 let height = 2 * top;
11777                 let width = this.aspect * height;
11778                 let left = - 0.5 * width;
11779                 const view = this.view;
11780
11781                 if ( this.view !== null && this.view.enabled ) {
11782
11783                         const fullWidth = view.fullWidth,
11784                                 fullHeight = view.fullHeight;
11785
11786                         left += view.offsetX * width / fullWidth;
11787                         top -= view.offsetY * height / fullHeight;
11788                         width *= view.width / fullWidth;
11789                         height *= view.height / fullHeight;
11790
11791                 }
11792
11793                 const skew = this.filmOffset;
11794                 if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
11795
11796                 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
11797
11798                 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
11799
11800         },
11801
11802         toJSON: function ( meta ) {
11803
11804                 const data = Object3D.prototype.toJSON.call( this, meta );
11805
11806                 data.object.fov = this.fov;
11807                 data.object.zoom = this.zoom;
11808
11809                 data.object.near = this.near;
11810                 data.object.far = this.far;
11811                 data.object.focus = this.focus;
11812
11813                 data.object.aspect = this.aspect;
11814
11815                 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
11816
11817                 data.object.filmGauge = this.filmGauge;
11818                 data.object.filmOffset = this.filmOffset;
11819
11820                 return data;
11821
11822         }
11823
11824 } );
11825
11826 const fov = 90, aspect = 1;
11827
11828 function CubeCamera( near, far, renderTarget ) {
11829
11830         Object3D.call( this );
11831
11832         this.type = 'CubeCamera';
11833
11834         if ( renderTarget.isWebGLCubeRenderTarget !== true ) {
11835
11836                 console.error( 'THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.' );
11837                 return;
11838
11839         }
11840
11841         this.renderTarget = renderTarget;
11842
11843         const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
11844         cameraPX.layers = this.layers;
11845         cameraPX.up.set( 0, - 1, 0 );
11846         cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
11847         this.add( cameraPX );
11848
11849         const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
11850         cameraNX.layers = this.layers;
11851         cameraNX.up.set( 0, - 1, 0 );
11852         cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
11853         this.add( cameraNX );
11854
11855         const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
11856         cameraPY.layers = this.layers;
11857         cameraPY.up.set( 0, 0, 1 );
11858         cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
11859         this.add( cameraPY );
11860
11861         const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
11862         cameraNY.layers = this.layers;
11863         cameraNY.up.set( 0, 0, - 1 );
11864         cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
11865         this.add( cameraNY );
11866
11867         const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
11868         cameraPZ.layers = this.layers;
11869         cameraPZ.up.set( 0, - 1, 0 );
11870         cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
11871         this.add( cameraPZ );
11872
11873         const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
11874         cameraNZ.layers = this.layers;
11875         cameraNZ.up.set( 0, - 1, 0 );
11876         cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
11877         this.add( cameraNZ );
11878
11879         this.update = function ( renderer, scene ) {
11880
11881                 if ( this.parent === null ) this.updateMatrixWorld();
11882
11883                 const currentXrEnabled = renderer.xr.enabled;
11884                 const currentRenderTarget = renderer.getRenderTarget();
11885
11886                 renderer.xr.enabled = false;
11887
11888                 const generateMipmaps = renderTarget.texture.generateMipmaps;
11889
11890                 renderTarget.texture.generateMipmaps = false;
11891
11892                 renderer.setRenderTarget( renderTarget, 0 );
11893                 renderer.render( scene, cameraPX );
11894
11895                 renderer.setRenderTarget( renderTarget, 1 );
11896                 renderer.render( scene, cameraNX );
11897
11898                 renderer.setRenderTarget( renderTarget, 2 );
11899                 renderer.render( scene, cameraPY );
11900
11901                 renderer.setRenderTarget( renderTarget, 3 );
11902                 renderer.render( scene, cameraNY );
11903
11904                 renderer.setRenderTarget( renderTarget, 4 );
11905                 renderer.render( scene, cameraPZ );
11906
11907                 renderTarget.texture.generateMipmaps = generateMipmaps;
11908
11909                 renderer.setRenderTarget( renderTarget, 5 );
11910                 renderer.render( scene, cameraNZ );
11911
11912                 renderer.setRenderTarget( currentRenderTarget );
11913
11914                 renderer.xr.enabled = currentXrEnabled;
11915
11916         };
11917
11918 }
11919
11920 CubeCamera.prototype = Object.create( Object3D.prototype );
11921 CubeCamera.prototype.constructor = CubeCamera;
11922
11923 function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
11924
11925         images = images !== undefined ? images : [];
11926         mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
11927         format = format !== undefined ? format : RGBFormat;
11928
11929         Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
11930
11931         this.flipY = false;
11932
11933         // Why CubeTexture._needsFlipEnvMap is necessary:
11934         //
11935         // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
11936         // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
11937         // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
11938
11939         // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
11940         // and the flag _needsFlipEnvMap controls this conversion. The flip is not required (and thus _needsFlipEnvMap is set to false)
11941         // when using WebGLCubeRenderTarget.texture as a cube texture.
11942
11943         this._needsFlipEnvMap = true;
11944
11945 }
11946
11947 CubeTexture.prototype = Object.create( Texture.prototype );
11948 CubeTexture.prototype.constructor = CubeTexture;
11949
11950 CubeTexture.prototype.isCubeTexture = true;
11951
11952 Object.defineProperty( CubeTexture.prototype, 'images', {
11953
11954         get: function () {
11955
11956                 return this.image;
11957
11958         },
11959
11960         set: function ( value ) {
11961
11962                 this.image = value;
11963
11964         }
11965
11966 } );
11967
11968 class WebGLCubeRenderTarget extends WebGLRenderTarget {
11969
11970         constructor( size, options, dummy ) {
11971
11972                 if ( Number.isInteger( options ) ) {
11973
11974                         console.warn( 'THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )' );
11975
11976                         options = dummy;
11977
11978                 }
11979
11980                 super( size, size, options );
11981
11982                 Object.defineProperty( this, 'isWebGLCubeRenderTarget', { value: true } );
11983
11984                 options = options || {};
11985
11986                 this.texture = new CubeTexture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
11987
11988                 this.texture._needsFlipEnvMap = false;
11989
11990         }
11991
11992         fromEquirectangularTexture( renderer, texture ) {
11993
11994                 this.texture.type = texture.type;
11995                 this.texture.format = RGBAFormat; // see #18859
11996                 this.texture.encoding = texture.encoding;
11997
11998                 this.texture.generateMipmaps = texture.generateMipmaps;
11999                 this.texture.minFilter = texture.minFilter;
12000                 this.texture.magFilter = texture.magFilter;
12001
12002                 const shader = {
12003
12004                         uniforms: {
12005                                 tEquirect: { value: null },
12006                         },
12007
12008                         vertexShader: /* glsl */`
12009
12010                                 varying vec3 vWorldDirection;
12011
12012                                 vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
12013
12014                                         return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
12015
12016                                 }
12017
12018                                 void main() {
12019
12020                                         vWorldDirection = transformDirection( position, modelMatrix );
12021
12022                                         #include <begin_vertex>
12023                                         #include <project_vertex>
12024
12025                                 }
12026                         `,
12027
12028                         fragmentShader: /* glsl */`
12029
12030                                 uniform sampler2D tEquirect;
12031
12032                                 varying vec3 vWorldDirection;
12033
12034                                 #include <common>
12035
12036                                 void main() {
12037
12038                                         vec3 direction = normalize( vWorldDirection );
12039
12040                                         vec2 sampleUV = equirectUv( direction );
12041
12042                                         gl_FragColor = texture2D( tEquirect, sampleUV );
12043
12044                                 }
12045                         `
12046                 };
12047
12048                 const geometry = new BoxGeometry( 5, 5, 5 );
12049
12050                 const material = new ShaderMaterial( {
12051
12052                         name: 'CubemapFromEquirect',
12053
12054                         uniforms: cloneUniforms( shader.uniforms ),
12055                         vertexShader: shader.vertexShader,
12056                         fragmentShader: shader.fragmentShader,
12057                         side: BackSide,
12058                         blending: NoBlending
12059
12060                 } );
12061
12062                 material.uniforms.tEquirect.value = texture;
12063
12064                 const mesh = new Mesh( geometry, material );
12065
12066                 const currentMinFilter = texture.minFilter;
12067
12068                 // Avoid blurred poles
12069                 if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
12070
12071                 const camera = new CubeCamera( 1, 10, this );
12072                 camera.update( renderer, mesh );
12073
12074                 texture.minFilter = currentMinFilter;
12075
12076                 mesh.geometry.dispose();
12077                 mesh.material.dispose();
12078
12079                 return this;
12080
12081         }
12082
12083         clear( renderer, color, depth, stencil ) {
12084
12085                 const currentRenderTarget = renderer.getRenderTarget();
12086
12087                 for ( let i = 0; i < 6; i ++ ) {
12088
12089                         renderer.setRenderTarget( this, i );
12090
12091                         renderer.clear( color, depth, stencil );
12092
12093                 }
12094
12095                 renderer.setRenderTarget( currentRenderTarget );
12096
12097         }
12098
12099 }
12100
12101 function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
12102
12103         Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
12104
12105         this.image = { data: data || null, width: width || 1, height: height || 1 };
12106
12107         this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
12108         this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
12109
12110         this.generateMipmaps = false;
12111         this.flipY = false;
12112         this.unpackAlignment = 1;
12113
12114         this.needsUpdate = true;
12115
12116 }
12117
12118 DataTexture.prototype = Object.create( Texture.prototype );
12119 DataTexture.prototype.constructor = DataTexture;
12120
12121 DataTexture.prototype.isDataTexture = true;
12122
12123 const _sphere$1 = /*@__PURE__*/ new Sphere();
12124 const _vector$5 = /*@__PURE__*/ new Vector3();
12125
12126 class Frustum {
12127
12128         constructor( p0, p1, p2, p3, p4, p5 ) {
12129
12130                 this.planes = [
12131
12132                         ( p0 !== undefined ) ? p0 : new Plane(),
12133                         ( p1 !== undefined ) ? p1 : new Plane(),
12134                         ( p2 !== undefined ) ? p2 : new Plane(),
12135                         ( p3 !== undefined ) ? p3 : new Plane(),
12136                         ( p4 !== undefined ) ? p4 : new Plane(),
12137                         ( p5 !== undefined ) ? p5 : new Plane()
12138
12139                 ];
12140
12141         }
12142
12143         set( p0, p1, p2, p3, p4, p5 ) {
12144
12145                 const planes = this.planes;
12146
12147                 planes[ 0 ].copy( p0 );
12148                 planes[ 1 ].copy( p1 );
12149                 planes[ 2 ].copy( p2 );
12150                 planes[ 3 ].copy( p3 );
12151                 planes[ 4 ].copy( p4 );
12152                 planes[ 5 ].copy( p5 );
12153
12154                 return this;
12155
12156         }
12157
12158         clone() {
12159
12160                 return new this.constructor().copy( this );
12161
12162         }
12163
12164         copy( frustum ) {
12165
12166                 const planes = this.planes;
12167
12168                 for ( let i = 0; i < 6; i ++ ) {
12169
12170                         planes[ i ].copy( frustum.planes[ i ] );
12171
12172                 }
12173
12174                 return this;
12175
12176         }
12177
12178         setFromProjectionMatrix( m ) {
12179
12180                 const planes = this.planes;
12181                 const me = m.elements;
12182                 const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
12183                 const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
12184                 const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
12185                 const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
12186
12187                 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
12188                 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
12189                 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
12190                 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
12191                 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
12192                 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
12193
12194                 return this;
12195
12196         }
12197
12198         intersectsObject( object ) {
12199
12200                 const geometry = object.geometry;
12201
12202                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
12203
12204                 _sphere$1.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
12205
12206                 return this.intersectsSphere( _sphere$1 );
12207
12208         }
12209
12210         intersectsSprite( sprite ) {
12211
12212                 _sphere$1.center.set( 0, 0, 0 );
12213                 _sphere$1.radius = 0.7071067811865476;
12214                 _sphere$1.applyMatrix4( sprite.matrixWorld );
12215
12216                 return this.intersectsSphere( _sphere$1 );
12217
12218         }
12219
12220         intersectsSphere( sphere ) {
12221
12222                 const planes = this.planes;
12223                 const center = sphere.center;
12224                 const negRadius = - sphere.radius;
12225
12226                 for ( let i = 0; i < 6; i ++ ) {
12227
12228                         const distance = planes[ i ].distanceToPoint( center );
12229
12230                         if ( distance < negRadius ) {
12231
12232                                 return false;
12233
12234                         }
12235
12236                 }
12237
12238                 return true;
12239
12240         }
12241
12242         intersectsBox( box ) {
12243
12244                 const planes = this.planes;
12245
12246                 for ( let i = 0; i < 6; i ++ ) {
12247
12248                         const plane = planes[ i ];
12249
12250                         // corner at max distance
12251
12252                         _vector$5.x = plane.normal.x > 0 ? box.max.x : box.min.x;
12253                         _vector$5.y = plane.normal.y > 0 ? box.max.y : box.min.y;
12254                         _vector$5.z = plane.normal.z > 0 ? box.max.z : box.min.z;
12255
12256                         if ( plane.distanceToPoint( _vector$5 ) < 0 ) {
12257
12258                                 return false;
12259
12260                         }
12261
12262                 }
12263
12264                 return true;
12265
12266         }
12267
12268         containsPoint( point ) {
12269
12270                 const planes = this.planes;
12271
12272                 for ( let i = 0; i < 6; i ++ ) {
12273
12274                         if ( planes[ i ].distanceToPoint( point ) < 0 ) {
12275
12276                                 return false;
12277
12278                         }
12279
12280                 }
12281
12282                 return true;
12283
12284         }
12285
12286 }
12287
12288 function WebGLAnimation() {
12289
12290         let context = null;
12291         let isAnimating = false;
12292         let animationLoop = null;
12293         let requestId = null;
12294
12295         function onAnimationFrame( time, frame ) {
12296
12297                 animationLoop( time, frame );
12298
12299                 requestId = context.requestAnimationFrame( onAnimationFrame );
12300
12301         }
12302
12303         return {
12304
12305                 start: function () {
12306
12307                         if ( isAnimating === true ) return;
12308                         if ( animationLoop === null ) return;
12309
12310                         requestId = context.requestAnimationFrame( onAnimationFrame );
12311
12312                         isAnimating = true;
12313
12314                 },
12315
12316                 stop: function () {
12317
12318                         context.cancelAnimationFrame( requestId );
12319
12320                         isAnimating = false;
12321
12322                 },
12323
12324                 setAnimationLoop: function ( callback ) {
12325
12326                         animationLoop = callback;
12327
12328                 },
12329
12330                 setContext: function ( value ) {
12331
12332                         context = value;
12333
12334                 }
12335
12336         };
12337
12338 }
12339
12340 function WebGLAttributes( gl, capabilities ) {
12341
12342         const isWebGL2 = capabilities.isWebGL2;
12343
12344         const buffers = new WeakMap();
12345
12346         function createBuffer( attribute, bufferType ) {
12347
12348                 const array = attribute.array;
12349                 const usage = attribute.usage;
12350
12351                 const buffer = gl.createBuffer();
12352
12353                 gl.bindBuffer( bufferType, buffer );
12354                 gl.bufferData( bufferType, array, usage );
12355
12356                 attribute.onUploadCallback();
12357
12358                 let type = 5126;
12359
12360                 if ( array instanceof Float32Array ) {
12361
12362                         type = 5126;
12363
12364                 } else if ( array instanceof Float64Array ) {
12365
12366                         console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
12367
12368                 } else if ( array instanceof Uint16Array ) {
12369
12370                         if ( attribute.isFloat16BufferAttribute ) {
12371
12372                                 if ( isWebGL2 ) {
12373
12374                                         type = 5131;
12375
12376                                 } else {
12377
12378                                         console.warn( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' );
12379
12380                                 }
12381
12382                         } else {
12383
12384                                 type = 5123;
12385
12386                         }
12387
12388                 } else if ( array instanceof Int16Array ) {
12389
12390                         type = 5122;
12391
12392                 } else if ( array instanceof Uint32Array ) {
12393
12394                         type = 5125;
12395
12396                 } else if ( array instanceof Int32Array ) {
12397
12398                         type = 5124;
12399
12400                 } else if ( array instanceof Int8Array ) {
12401
12402                         type = 5120;
12403
12404                 } else if ( array instanceof Uint8Array ) {
12405
12406                         type = 5121;
12407
12408                 }
12409
12410                 return {
12411                         buffer: buffer,
12412                         type: type,
12413                         bytesPerElement: array.BYTES_PER_ELEMENT,
12414                         version: attribute.version
12415                 };
12416
12417         }
12418
12419         function updateBuffer( buffer, attribute, bufferType ) {
12420
12421                 const array = attribute.array;
12422                 const updateRange = attribute.updateRange;
12423
12424                 gl.bindBuffer( bufferType, buffer );
12425
12426                 if ( updateRange.count === - 1 ) {
12427
12428                         // Not using update ranges
12429
12430                         gl.bufferSubData( bufferType, 0, array );
12431
12432                 } else {
12433
12434                         if ( isWebGL2 ) {
12435
12436                                 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
12437                                         array, updateRange.offset, updateRange.count );
12438
12439                         } else {
12440
12441                                 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
12442                                         array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
12443
12444                         }
12445
12446                         updateRange.count = - 1; // reset range
12447
12448                 }
12449
12450         }
12451
12452         //
12453
12454         function get( attribute ) {
12455
12456                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
12457
12458                 return buffers.get( attribute );
12459
12460         }
12461
12462         function remove( attribute ) {
12463
12464                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
12465
12466                 const data = buffers.get( attribute );
12467
12468                 if ( data ) {
12469
12470                         gl.deleteBuffer( data.buffer );
12471
12472                         buffers.delete( attribute );
12473
12474                 }
12475
12476         }
12477
12478         function update( attribute, bufferType ) {
12479
12480                 if ( attribute.isGLBufferAttribute ) {
12481
12482                         const cached = buffers.get( attribute );
12483
12484                         if ( ! cached || cached.version < attribute.version ) {
12485
12486                                 buffers.set( attribute, {
12487                                         buffer: attribute.buffer,
12488                                         type: attribute.type,
12489                                         bytesPerElement: attribute.elementSize,
12490                                         version: attribute.version
12491                                 } );
12492
12493                         }
12494
12495                         return;
12496
12497                 }
12498
12499                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
12500
12501                 const data = buffers.get( attribute );
12502
12503                 if ( data === undefined ) {
12504
12505                         buffers.set( attribute, createBuffer( attribute, bufferType ) );
12506
12507                 } else if ( data.version < attribute.version ) {
12508
12509                         updateBuffer( data.buffer, attribute, bufferType );
12510
12511                         data.version = attribute.version;
12512
12513                 }
12514
12515         }
12516
12517         return {
12518
12519                 get: get,
12520                 remove: remove,
12521                 update: update
12522
12523         };
12524
12525 }
12526
12527 class PlaneGeometry extends BufferGeometry {
12528
12529         constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
12530
12531                 super();
12532                 this.type = 'PlaneGeometry';
12533
12534                 this.parameters = {
12535                         width: width,
12536                         height: height,
12537                         widthSegments: widthSegments,
12538                         heightSegments: heightSegments
12539                 };
12540
12541                 const width_half = width / 2;
12542                 const height_half = height / 2;
12543
12544                 const gridX = Math.floor( widthSegments );
12545                 const gridY = Math.floor( heightSegments );
12546
12547                 const gridX1 = gridX + 1;
12548                 const gridY1 = gridY + 1;
12549
12550                 const segment_width = width / gridX;
12551                 const segment_height = height / gridY;
12552
12553                 //
12554
12555                 const indices = [];
12556                 const vertices = [];
12557                 const normals = [];
12558                 const uvs = [];
12559
12560                 for ( let iy = 0; iy < gridY1; iy ++ ) {
12561
12562                         const y = iy * segment_height - height_half;
12563
12564                         for ( let ix = 0; ix < gridX1; ix ++ ) {
12565
12566                                 const x = ix * segment_width - width_half;
12567
12568                                 vertices.push( x, - y, 0 );
12569
12570                                 normals.push( 0, 0, 1 );
12571
12572                                 uvs.push( ix / gridX );
12573                                 uvs.push( 1 - ( iy / gridY ) );
12574
12575                         }
12576
12577                 }
12578
12579                 for ( let iy = 0; iy < gridY; iy ++ ) {
12580
12581                         for ( let ix = 0; ix < gridX; ix ++ ) {
12582
12583                                 const a = ix + gridX1 * iy;
12584                                 const b = ix + gridX1 * ( iy + 1 );
12585                                 const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
12586                                 const d = ( ix + 1 ) + gridX1 * iy;
12587
12588                                 indices.push( a, b, d );
12589                                 indices.push( b, c, d );
12590
12591                         }
12592
12593                 }
12594
12595                 this.setIndex( indices );
12596                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
12597                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
12598                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
12599
12600         }
12601
12602 }
12603
12604 var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
12605
12606 var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
12607
12608 var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif";
12609
12610 var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif";
12611
12612 var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
12613
12614 var begin_vertex = "vec3 transformed = vec3( position );";
12615
12616 var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
12617
12618 var bsdfs = "vec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\treturn vec2( -1.04, 1.04 ) * a004 + r.zw;\n}\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\treturn Fr * fresnel + F0;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie(float roughness, float NoH) {\n\tfloat invAlpha = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\nfloat V_Neubelt(float NoV, float NoL) {\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\n}\n#endif";
12619
12620 var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif";
12621
12622 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";
12623
12624 var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
12625
12626 var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
12627
12628 var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
12629
12630 var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
12631
12632 var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
12633
12634 var color_pars_vertex = "#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";
12635
12636 var color_vertex = "#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor.xyz *= color.xyz;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif";
12637
12638 var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}";
12639
12640 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";
12641
12642 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";
12643
12644 var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
12645
12646 var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif";
12647
12648 var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
12649
12650 var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
12651
12652 var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
12653
12654 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}";
12655
12656 var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifndef ENVMAP_TYPE_CUBE_UV\n\t\tenvColor = envMapTexelToLinear( envColor );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif";
12657
12658 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";
12659
12660 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";
12661
12662 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";
12663
12664 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";
12665
12666 var fog_vertex = "#ifdef USE_FOG\n\tfogDepth = - mvPosition.z;\n#endif";
12667
12668 var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif";
12669
12670 var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif";
12671
12672 var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif";
12673
12674 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}";
12675
12676 var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n#endif";
12677
12678 var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
12679
12680 var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\n#endif\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif";
12681
12682 var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif";
12683
12684 var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif";
12685
12686 var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
12687
12688 var lights_toon_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material )\t(0)";
12689
12690 var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
12691
12692 var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)";
12693
12694 var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n#ifdef REFLECTIVITY\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#endif\n#ifdef CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheen;\n#endif";
12695
12696 var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat specularRoughness;\n\tvec3 specularColor;\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(    0, 1,    0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tccIrradiance *= PI;\n\t\t#endif\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
12697
12698 var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
12699
12700 var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\t#ifdef CLEARCOAT\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\n\t#endif\n#endif";
12701
12702 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";
12703
12704 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";
12705
12706 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";
12707
12708 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";
12709
12710 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";
12711
12712 var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif";
12713
12714 var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
12715
12716 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";
12717
12718 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";
12719
12720 var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
12721
12722 var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
12723
12724 var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif";
12725
12726 var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifndef USE_MORPHNORMALS\n\t\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\t\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
12727
12728 var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t#endif\n#endif";
12729
12730 var normal_fragment_begin = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;";
12731
12732 var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( -vViewPosition, normal, mapN );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif";
12733
12734 var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tmat3 tsn = mat3( S, T, N );\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif";
12735
12736 var clearcoat_normal_fragment_begin = "#ifdef CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif";
12737
12738 var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );\n\t#endif\n#endif";
12739
12740 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";
12741
12742 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}";
12743
12744 var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
12745
12746 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;";
12747
12748 var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
12749
12750 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";
12751
12752 var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
12753
12754 var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
12755
12756 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";
12757
12758 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";
12759
12760 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";
12761
12762 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}";
12763
12764 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";
12765
12766 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";
12767
12768 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";
12769
12770 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";
12771
12772 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";
12773
12774 var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
12775
12776 var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
12777
12778 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; }";
12779
12780 var transmissionmap_fragment = "#ifdef USE_TRANSMISSIONMAP\n\ttotalTransmission *= texture2D( transmissionMap, vUv ).r;\n#endif";
12781
12782 var transmissionmap_pars_fragment = "#ifdef USE_TRANSMISSIONMAP\n\tuniform sampler2D transmissionMap;\n#endif";
12783
12784 var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif";
12785
12786 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";
12787
12788 var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
12789
12790 var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
12791
12792 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";
12793
12794 var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif";
12795
12796 var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif";
12797
12798 var background_frag = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
12799
12800 var background_vert = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}";
12801
12802 var cube_frag = "#include <envmap_common_pars_fragment>\nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include <envmap_fragment>\n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
12803
12804 var cube_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
12805
12806 var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}";
12807
12808 var depth_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}";
12809
12810 var distanceRGBA_frag = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}";
12811
12812 var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}";
12813
12814 var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
12815
12816 var equirect_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}";
12817
12818 var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
12819
12820 var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
12821
12822 var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
12823
12824 var meshbasic_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_ENVMAP\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}";
12825
12826 var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <emissivemap_fragment>\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include <lightmap_fragment>\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
12827
12828 var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <lights_lambert_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
12829
12830 var meshmatcap_frag = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
12831
12832 var meshmatcap_vert = "#define MATCAP\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}";
12833
12834 var meshtoon_frag = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_toon_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_toon_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
12835
12836 var meshtoon_vert = "#define TOON\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
12837
12838 var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
12839
12840 var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
12841
12842 var meshphysical_frag = "#define STANDARD\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSMISSION\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef TRANSMISSION\n\tuniform float transmission;\n#endif\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n#ifdef CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <transmissionmap_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#ifdef TRANSMISSION\n\t\tfloat totalTransmission = transmission;\n\t#endif\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <clearcoat_normal_fragment_begin>\n\t#include <clearcoat_normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <transmissionmap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#ifdef TRANSMISSION\n\t\tdiffuseColor.a *= mix( saturate( 1. - totalTransmission + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) ), 1.0, metalness );\n\t#endif\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
12843
12844 var meshphysical_vert = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
12845
12846 var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}";
12847
12848 var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}";
12849
12850 var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
12851
12852 var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}";
12853
12854 var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
12855
12856 var shadow_vert = "#include <common>\n#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
12857
12858 var sprite_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
12859
12860 var sprite_vert = "uniform float rotation;\nuniform vec2 center;\n#include <common>\n#include <uv_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
12861
12862 const ShaderChunk = {
12863         alphamap_fragment: alphamap_fragment,
12864         alphamap_pars_fragment: alphamap_pars_fragment,
12865         alphatest_fragment: alphatest_fragment,
12866         aomap_fragment: aomap_fragment,
12867         aomap_pars_fragment: aomap_pars_fragment,
12868         begin_vertex: begin_vertex,
12869         beginnormal_vertex: beginnormal_vertex,
12870         bsdfs: bsdfs,
12871         bumpmap_pars_fragment: bumpmap_pars_fragment,
12872         clipping_planes_fragment: clipping_planes_fragment,
12873         clipping_planes_pars_fragment: clipping_planes_pars_fragment,
12874         clipping_planes_pars_vertex: clipping_planes_pars_vertex,
12875         clipping_planes_vertex: clipping_planes_vertex,
12876         color_fragment: color_fragment,
12877         color_pars_fragment: color_pars_fragment,
12878         color_pars_vertex: color_pars_vertex,
12879         color_vertex: color_vertex,
12880         common: common,
12881         cube_uv_reflection_fragment: cube_uv_reflection_fragment,
12882         defaultnormal_vertex: defaultnormal_vertex,
12883         displacementmap_pars_vertex: displacementmap_pars_vertex,
12884         displacementmap_vertex: displacementmap_vertex,
12885         emissivemap_fragment: emissivemap_fragment,
12886         emissivemap_pars_fragment: emissivemap_pars_fragment,
12887         encodings_fragment: encodings_fragment,
12888         encodings_pars_fragment: encodings_pars_fragment,
12889         envmap_fragment: envmap_fragment,
12890         envmap_common_pars_fragment: envmap_common_pars_fragment,
12891         envmap_pars_fragment: envmap_pars_fragment,
12892         envmap_pars_vertex: envmap_pars_vertex,
12893         envmap_physical_pars_fragment: envmap_physical_pars_fragment,
12894         envmap_vertex: envmap_vertex,
12895         fog_vertex: fog_vertex,
12896         fog_pars_vertex: fog_pars_vertex,
12897         fog_fragment: fog_fragment,
12898         fog_pars_fragment: fog_pars_fragment,
12899         gradientmap_pars_fragment: gradientmap_pars_fragment,
12900         lightmap_fragment: lightmap_fragment,
12901         lightmap_pars_fragment: lightmap_pars_fragment,
12902         lights_lambert_vertex: lights_lambert_vertex,
12903         lights_pars_begin: lights_pars_begin,
12904         lights_toon_fragment: lights_toon_fragment,
12905         lights_toon_pars_fragment: lights_toon_pars_fragment,
12906         lights_phong_fragment: lights_phong_fragment,
12907         lights_phong_pars_fragment: lights_phong_pars_fragment,
12908         lights_physical_fragment: lights_physical_fragment,
12909         lights_physical_pars_fragment: lights_physical_pars_fragment,
12910         lights_fragment_begin: lights_fragment_begin,
12911         lights_fragment_maps: lights_fragment_maps,
12912         lights_fragment_end: lights_fragment_end,
12913         logdepthbuf_fragment: logdepthbuf_fragment,
12914         logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
12915         logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
12916         logdepthbuf_vertex: logdepthbuf_vertex,
12917         map_fragment: map_fragment,
12918         map_pars_fragment: map_pars_fragment,
12919         map_particle_fragment: map_particle_fragment,
12920         map_particle_pars_fragment: map_particle_pars_fragment,
12921         metalnessmap_fragment: metalnessmap_fragment,
12922         metalnessmap_pars_fragment: metalnessmap_pars_fragment,
12923         morphnormal_vertex: morphnormal_vertex,
12924         morphtarget_pars_vertex: morphtarget_pars_vertex,
12925         morphtarget_vertex: morphtarget_vertex,
12926         normal_fragment_begin: normal_fragment_begin,
12927         normal_fragment_maps: normal_fragment_maps,
12928         normalmap_pars_fragment: normalmap_pars_fragment,
12929         clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
12930         clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
12931         clearcoat_pars_fragment: clearcoat_pars_fragment,
12932         packing: packing,
12933         premultiplied_alpha_fragment: premultiplied_alpha_fragment,
12934         project_vertex: project_vertex,
12935         dithering_fragment: dithering_fragment,
12936         dithering_pars_fragment: dithering_pars_fragment,
12937         roughnessmap_fragment: roughnessmap_fragment,
12938         roughnessmap_pars_fragment: roughnessmap_pars_fragment,
12939         shadowmap_pars_fragment: shadowmap_pars_fragment,
12940         shadowmap_pars_vertex: shadowmap_pars_vertex,
12941         shadowmap_vertex: shadowmap_vertex,
12942         shadowmask_pars_fragment: shadowmask_pars_fragment,
12943         skinbase_vertex: skinbase_vertex,
12944         skinning_pars_vertex: skinning_pars_vertex,
12945         skinning_vertex: skinning_vertex,
12946         skinnormal_vertex: skinnormal_vertex,
12947         specularmap_fragment: specularmap_fragment,
12948         specularmap_pars_fragment: specularmap_pars_fragment,
12949         tonemapping_fragment: tonemapping_fragment,
12950         tonemapping_pars_fragment: tonemapping_pars_fragment,
12951         transmissionmap_fragment: transmissionmap_fragment,
12952         transmissionmap_pars_fragment: transmissionmap_pars_fragment,
12953         uv_pars_fragment: uv_pars_fragment,
12954         uv_pars_vertex: uv_pars_vertex,
12955         uv_vertex: uv_vertex,
12956         uv2_pars_fragment: uv2_pars_fragment,
12957         uv2_pars_vertex: uv2_pars_vertex,
12958         uv2_vertex: uv2_vertex,
12959         worldpos_vertex: worldpos_vertex,
12960
12961         background_frag: background_frag,
12962         background_vert: background_vert,
12963         cube_frag: cube_frag,
12964         cube_vert: cube_vert,
12965         depth_frag: depth_frag,
12966         depth_vert: depth_vert,
12967         distanceRGBA_frag: distanceRGBA_frag,
12968         distanceRGBA_vert: distanceRGBA_vert,
12969         equirect_frag: equirect_frag,
12970         equirect_vert: equirect_vert,
12971         linedashed_frag: linedashed_frag,
12972         linedashed_vert: linedashed_vert,
12973         meshbasic_frag: meshbasic_frag,
12974         meshbasic_vert: meshbasic_vert,
12975         meshlambert_frag: meshlambert_frag,
12976         meshlambert_vert: meshlambert_vert,
12977         meshmatcap_frag: meshmatcap_frag,
12978         meshmatcap_vert: meshmatcap_vert,
12979         meshtoon_frag: meshtoon_frag,
12980         meshtoon_vert: meshtoon_vert,
12981         meshphong_frag: meshphong_frag,
12982         meshphong_vert: meshphong_vert,
12983         meshphysical_frag: meshphysical_frag,
12984         meshphysical_vert: meshphysical_vert,
12985         normal_frag: normal_frag,
12986         normal_vert: normal_vert,
12987         points_frag: points_frag,
12988         points_vert: points_vert,
12989         shadow_frag: shadow_frag,
12990         shadow_vert: shadow_vert,
12991         sprite_frag: sprite_frag,
12992         sprite_vert: sprite_vert
12993 };
12994
12995 /**
12996  * Uniforms library for shared webgl shaders
12997  */
12998
12999 const UniformsLib = {
13000
13001         common: {
13002
13003                 diffuse: { value: new Color( 0xeeeeee ) },
13004                 opacity: { value: 1.0 },
13005
13006                 map: { value: null },
13007                 uvTransform: { value: new Matrix3() },
13008                 uv2Transform: { value: new Matrix3() },
13009
13010                 alphaMap: { value: null },
13011
13012         },
13013
13014         specularmap: {
13015
13016                 specularMap: { value: null },
13017
13018         },
13019
13020         envmap: {
13021
13022                 envMap: { value: null },
13023                 flipEnvMap: { value: - 1 },
13024                 reflectivity: { value: 1.0 },
13025                 refractionRatio: { value: 0.98 },
13026                 maxMipLevel: { value: 0 }
13027
13028         },
13029
13030         aomap: {
13031
13032                 aoMap: { value: null },
13033                 aoMapIntensity: { value: 1 }
13034
13035         },
13036
13037         lightmap: {
13038
13039                 lightMap: { value: null },
13040                 lightMapIntensity: { value: 1 }
13041
13042         },
13043
13044         emissivemap: {
13045
13046                 emissiveMap: { value: null }
13047
13048         },
13049
13050         bumpmap: {
13051
13052                 bumpMap: { value: null },
13053                 bumpScale: { value: 1 }
13054
13055         },
13056
13057         normalmap: {
13058
13059                 normalMap: { value: null },
13060                 normalScale: { value: new Vector2( 1, 1 ) }
13061
13062         },
13063
13064         displacementmap: {
13065
13066                 displacementMap: { value: null },
13067                 displacementScale: { value: 1 },
13068                 displacementBias: { value: 0 }
13069
13070         },
13071
13072         roughnessmap: {
13073
13074                 roughnessMap: { value: null }
13075
13076         },
13077
13078         metalnessmap: {
13079
13080                 metalnessMap: { value: null }
13081
13082         },
13083
13084         gradientmap: {
13085
13086                 gradientMap: { value: null }
13087
13088         },
13089
13090         fog: {
13091
13092                 fogDensity: { value: 0.00025 },
13093                 fogNear: { value: 1 },
13094                 fogFar: { value: 2000 },
13095                 fogColor: { value: new Color( 0xffffff ) }
13096
13097         },
13098
13099         lights: {
13100
13101                 ambientLightColor: { value: [] },
13102
13103                 lightProbe: { value: [] },
13104
13105                 directionalLights: { value: [], properties: {
13106                         direction: {},
13107                         color: {}
13108                 } },
13109
13110                 directionalLightShadows: { value: [], properties: {
13111                         shadowBias: {},
13112                         shadowNormalBias: {},
13113                         shadowRadius: {},
13114                         shadowMapSize: {}
13115                 } },
13116
13117                 directionalShadowMap: { value: [] },
13118                 directionalShadowMatrix: { value: [] },
13119
13120                 spotLights: { value: [], properties: {
13121                         color: {},
13122                         position: {},
13123                         direction: {},
13124                         distance: {},
13125                         coneCos: {},
13126                         penumbraCos: {},
13127                         decay: {}
13128                 } },
13129
13130                 spotLightShadows: { value: [], properties: {
13131                         shadowBias: {},
13132                         shadowNormalBias: {},
13133                         shadowRadius: {},
13134                         shadowMapSize: {}
13135                 } },
13136
13137                 spotShadowMap: { value: [] },
13138                 spotShadowMatrix: { value: [] },
13139
13140                 pointLights: { value: [], properties: {
13141                         color: {},
13142                         position: {},
13143                         decay: {},
13144                         distance: {}
13145                 } },
13146
13147                 pointLightShadows: { value: [], properties: {
13148                         shadowBias: {},
13149                         shadowNormalBias: {},
13150                         shadowRadius: {},
13151                         shadowMapSize: {},
13152                         shadowCameraNear: {},
13153                         shadowCameraFar: {}
13154                 } },
13155
13156                 pointShadowMap: { value: [] },
13157                 pointShadowMatrix: { value: [] },
13158
13159                 hemisphereLights: { value: [], properties: {
13160                         direction: {},
13161                         skyColor: {},
13162                         groundColor: {}
13163                 } },
13164
13165                 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
13166                 rectAreaLights: { value: [], properties: {
13167                         color: {},
13168                         position: {},
13169                         width: {},
13170                         height: {}
13171                 } },
13172
13173                 ltc_1: { value: null },
13174                 ltc_2: { value: null }
13175
13176         },
13177
13178         points: {
13179
13180                 diffuse: { value: new Color( 0xeeeeee ) },
13181                 opacity: { value: 1.0 },
13182                 size: { value: 1.0 },
13183                 scale: { value: 1.0 },
13184                 map: { value: null },
13185                 alphaMap: { value: null },
13186                 uvTransform: { value: new Matrix3() }
13187
13188         },
13189
13190         sprite: {
13191
13192                 diffuse: { value: new Color( 0xeeeeee ) },
13193                 opacity: { value: 1.0 },
13194                 center: { value: new Vector2( 0.5, 0.5 ) },
13195                 rotation: { value: 0.0 },
13196                 map: { value: null },
13197                 alphaMap: { value: null },
13198                 uvTransform: { value: new Matrix3() }
13199
13200         }
13201
13202 };
13203
13204 const ShaderLib = {
13205
13206         basic: {
13207
13208                 uniforms: mergeUniforms( [
13209                         UniformsLib.common,
13210                         UniformsLib.specularmap,
13211                         UniformsLib.envmap,
13212                         UniformsLib.aomap,
13213                         UniformsLib.lightmap,
13214                         UniformsLib.fog
13215                 ] ),
13216
13217                 vertexShader: ShaderChunk.meshbasic_vert,
13218                 fragmentShader: ShaderChunk.meshbasic_frag
13219
13220         },
13221
13222         lambert: {
13223
13224                 uniforms: mergeUniforms( [
13225                         UniformsLib.common,
13226                         UniformsLib.specularmap,
13227                         UniformsLib.envmap,
13228                         UniformsLib.aomap,
13229                         UniformsLib.lightmap,
13230                         UniformsLib.emissivemap,
13231                         UniformsLib.fog,
13232                         UniformsLib.lights,
13233                         {
13234                                 emissive: { value: new Color( 0x000000 ) }
13235                         }
13236                 ] ),
13237
13238                 vertexShader: ShaderChunk.meshlambert_vert,
13239                 fragmentShader: ShaderChunk.meshlambert_frag
13240
13241         },
13242
13243         phong: {
13244
13245                 uniforms: mergeUniforms( [
13246                         UniformsLib.common,
13247                         UniformsLib.specularmap,
13248                         UniformsLib.envmap,
13249                         UniformsLib.aomap,
13250                         UniformsLib.lightmap,
13251                         UniformsLib.emissivemap,
13252                         UniformsLib.bumpmap,
13253                         UniformsLib.normalmap,
13254                         UniformsLib.displacementmap,
13255                         UniformsLib.fog,
13256                         UniformsLib.lights,
13257                         {
13258                                 emissive: { value: new Color( 0x000000 ) },
13259                                 specular: { value: new Color( 0x111111 ) },
13260                                 shininess: { value: 30 }
13261                         }
13262                 ] ),
13263
13264                 vertexShader: ShaderChunk.meshphong_vert,
13265                 fragmentShader: ShaderChunk.meshphong_frag
13266
13267         },
13268
13269         standard: {
13270
13271                 uniforms: mergeUniforms( [
13272                         UniformsLib.common,
13273                         UniformsLib.envmap,
13274                         UniformsLib.aomap,
13275                         UniformsLib.lightmap,
13276                         UniformsLib.emissivemap,
13277                         UniformsLib.bumpmap,
13278                         UniformsLib.normalmap,
13279                         UniformsLib.displacementmap,
13280                         UniformsLib.roughnessmap,
13281                         UniformsLib.metalnessmap,
13282                         UniformsLib.fog,
13283                         UniformsLib.lights,
13284                         {
13285                                 emissive: { value: new Color( 0x000000 ) },
13286                                 roughness: { value: 1.0 },
13287                                 metalness: { value: 0.0 },
13288                                 envMapIntensity: { value: 1 } // temporary
13289                         }
13290                 ] ),
13291
13292                 vertexShader: ShaderChunk.meshphysical_vert,
13293                 fragmentShader: ShaderChunk.meshphysical_frag
13294
13295         },
13296
13297         toon: {
13298
13299                 uniforms: mergeUniforms( [
13300                         UniformsLib.common,
13301                         UniformsLib.aomap,
13302                         UniformsLib.lightmap,
13303                         UniformsLib.emissivemap,
13304                         UniformsLib.bumpmap,
13305                         UniformsLib.normalmap,
13306                         UniformsLib.displacementmap,
13307                         UniformsLib.gradientmap,
13308                         UniformsLib.fog,
13309                         UniformsLib.lights,
13310                         {
13311                                 emissive: { value: new Color( 0x000000 ) }
13312                         }
13313                 ] ),
13314
13315                 vertexShader: ShaderChunk.meshtoon_vert,
13316                 fragmentShader: ShaderChunk.meshtoon_frag
13317
13318         },
13319
13320         matcap: {
13321
13322                 uniforms: mergeUniforms( [
13323                         UniformsLib.common,
13324                         UniformsLib.bumpmap,
13325                         UniformsLib.normalmap,
13326                         UniformsLib.displacementmap,
13327                         UniformsLib.fog,
13328                         {
13329                                 matcap: { value: null }
13330                         }
13331                 ] ),
13332
13333                 vertexShader: ShaderChunk.meshmatcap_vert,
13334                 fragmentShader: ShaderChunk.meshmatcap_frag
13335
13336         },
13337
13338         points: {
13339
13340                 uniforms: mergeUniforms( [
13341                         UniformsLib.points,
13342                         UniformsLib.fog
13343                 ] ),
13344
13345                 vertexShader: ShaderChunk.points_vert,
13346                 fragmentShader: ShaderChunk.points_frag
13347
13348         },
13349
13350         dashed: {
13351
13352                 uniforms: mergeUniforms( [
13353                         UniformsLib.common,
13354                         UniformsLib.fog,
13355                         {
13356                                 scale: { value: 1 },
13357                                 dashSize: { value: 1 },
13358                                 totalSize: { value: 2 }
13359                         }
13360                 ] ),
13361
13362                 vertexShader: ShaderChunk.linedashed_vert,
13363                 fragmentShader: ShaderChunk.linedashed_frag
13364
13365         },
13366
13367         depth: {
13368
13369                 uniforms: mergeUniforms( [
13370                         UniformsLib.common,
13371                         UniformsLib.displacementmap
13372                 ] ),
13373
13374                 vertexShader: ShaderChunk.depth_vert,
13375                 fragmentShader: ShaderChunk.depth_frag
13376
13377         },
13378
13379         normal: {
13380
13381                 uniforms: mergeUniforms( [
13382                         UniformsLib.common,
13383                         UniformsLib.bumpmap,
13384                         UniformsLib.normalmap,
13385                         UniformsLib.displacementmap,
13386                         {
13387                                 opacity: { value: 1.0 }
13388                         }
13389                 ] ),
13390
13391                 vertexShader: ShaderChunk.normal_vert,
13392                 fragmentShader: ShaderChunk.normal_frag
13393
13394         },
13395
13396         sprite: {
13397
13398                 uniforms: mergeUniforms( [
13399                         UniformsLib.sprite,
13400                         UniformsLib.fog
13401                 ] ),
13402
13403                 vertexShader: ShaderChunk.sprite_vert,
13404                 fragmentShader: ShaderChunk.sprite_frag
13405
13406         },
13407
13408         background: {
13409
13410                 uniforms: {
13411                         uvTransform: { value: new Matrix3() },
13412                         t2D: { value: null },
13413                 },
13414
13415                 vertexShader: ShaderChunk.background_vert,
13416                 fragmentShader: ShaderChunk.background_frag
13417
13418         },
13419         /* -------------------------------------------------------------------------
13420         //      Cube map shader
13421          ------------------------------------------------------------------------- */
13422
13423         cube: {
13424
13425                 uniforms: mergeUniforms( [
13426                         UniformsLib.envmap,
13427                         {
13428                                 opacity: { value: 1.0 }
13429                         }
13430                 ] ),
13431
13432                 vertexShader: ShaderChunk.cube_vert,
13433                 fragmentShader: ShaderChunk.cube_frag
13434
13435         },
13436
13437         equirect: {
13438
13439                 uniforms: {
13440                         tEquirect: { value: null },
13441                 },
13442
13443                 vertexShader: ShaderChunk.equirect_vert,
13444                 fragmentShader: ShaderChunk.equirect_frag
13445
13446         },
13447
13448         distanceRGBA: {
13449
13450                 uniforms: mergeUniforms( [
13451                         UniformsLib.common,
13452                         UniformsLib.displacementmap,
13453                         {
13454                                 referencePosition: { value: new Vector3() },
13455                                 nearDistance: { value: 1 },
13456                                 farDistance: { value: 1000 }
13457                         }
13458                 ] ),
13459
13460                 vertexShader: ShaderChunk.distanceRGBA_vert,
13461                 fragmentShader: ShaderChunk.distanceRGBA_frag
13462
13463         },
13464
13465         shadow: {
13466
13467                 uniforms: mergeUniforms( [
13468                         UniformsLib.lights,
13469                         UniformsLib.fog,
13470                         {
13471                                 color: { value: new Color( 0x00000 ) },
13472                                 opacity: { value: 1.0 }
13473                         },
13474                 ] ),
13475
13476                 vertexShader: ShaderChunk.shadow_vert,
13477                 fragmentShader: ShaderChunk.shadow_frag
13478
13479         }
13480
13481 };
13482
13483 ShaderLib.physical = {
13484
13485         uniforms: mergeUniforms( [
13486                 ShaderLib.standard.uniforms,
13487                 {
13488                         clearcoat: { value: 0 },
13489                         clearcoatMap: { value: null },
13490                         clearcoatRoughness: { value: 0 },
13491                         clearcoatRoughnessMap: { value: null },
13492                         clearcoatNormalScale: { value: new Vector2( 1, 1 ) },
13493                         clearcoatNormalMap: { value: null },
13494                         sheen: { value: new Color( 0x000000 ) },
13495                         transmission: { value: 0 },
13496                         transmissionMap: { value: null },
13497                 }
13498         ] ),
13499
13500         vertexShader: ShaderChunk.meshphysical_vert,
13501         fragmentShader: ShaderChunk.meshphysical_frag
13502
13503 };
13504
13505 function WebGLBackground( renderer, cubemaps, state, objects, premultipliedAlpha ) {
13506
13507         const clearColor = new Color( 0x000000 );
13508         let clearAlpha = 0;
13509
13510         let planeMesh;
13511         let boxMesh;
13512
13513         let currentBackground = null;
13514         let currentBackgroundVersion = 0;
13515         let currentTonemapping = null;
13516
13517         function render( renderList, scene, camera, forceClear ) {
13518
13519                 let background = scene.isScene === true ? scene.background : null;
13520
13521                 if ( background && background.isTexture ) {
13522
13523                         background = cubemaps.get( background );
13524
13525                 }
13526
13527                 // Ignore background in AR
13528                 // TODO: Reconsider this.
13529
13530                 const xr = renderer.xr;
13531                 const session = xr.getSession && xr.getSession();
13532
13533                 if ( session && session.environmentBlendMode === 'additive' ) {
13534
13535                         background = null;
13536
13537                 }
13538
13539                 if ( background === null ) {
13540
13541                         setClear( clearColor, clearAlpha );
13542
13543                 } else if ( background && background.isColor ) {
13544
13545                         setClear( background, 1 );
13546                         forceClear = true;
13547
13548                 }
13549
13550                 if ( renderer.autoClear || forceClear ) {
13551
13552                         renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
13553
13554                 }
13555
13556                 if ( background && ( background.isCubeTexture || background.isWebGLCubeRenderTarget || background.mapping === CubeUVReflectionMapping ) ) {
13557
13558                         if ( boxMesh === undefined ) {
13559
13560                                 boxMesh = new Mesh(
13561                                         new BoxGeometry( 1, 1, 1 ),
13562                                         new ShaderMaterial( {
13563                                                 name: 'BackgroundCubeMaterial',
13564                                                 uniforms: cloneUniforms( ShaderLib.cube.uniforms ),
13565                                                 vertexShader: ShaderLib.cube.vertexShader,
13566                                                 fragmentShader: ShaderLib.cube.fragmentShader,
13567                                                 side: BackSide,
13568                                                 depthTest: false,
13569                                                 depthWrite: false,
13570                                                 fog: false
13571                                         } )
13572                                 );
13573
13574                                 boxMesh.geometry.deleteAttribute( 'normal' );
13575                                 boxMesh.geometry.deleteAttribute( 'uv' );
13576
13577                                 boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
13578
13579                                         this.matrixWorld.copyPosition( camera.matrixWorld );
13580
13581                                 };
13582
13583                                 // enable code injection for non-built-in material
13584                                 Object.defineProperty( boxMesh.material, 'envMap', {
13585
13586                                         get: function () {
13587
13588                                                 return this.uniforms.envMap.value;
13589
13590                                         }
13591
13592                                 } );
13593
13594                                 objects.update( boxMesh );
13595
13596                         }
13597
13598                         if ( background.isWebGLCubeRenderTarget ) {
13599
13600                                 // TODO Deprecate
13601
13602                                 background = background.texture;
13603
13604                         }
13605
13606                         boxMesh.material.uniforms.envMap.value = background;
13607                         boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background._needsFlipEnvMap ) ? - 1 : 1;
13608
13609                         if ( currentBackground !== background ||
13610                                 currentBackgroundVersion !== background.version ||
13611                                 currentTonemapping !== renderer.toneMapping ) {
13612
13613                                 boxMesh.material.needsUpdate = true;
13614
13615                                 currentBackground = background;
13616                                 currentBackgroundVersion = background.version;
13617                                 currentTonemapping = renderer.toneMapping;
13618
13619                         }
13620
13621                         // push to the pre-sorted opaque render list
13622                         renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
13623
13624                 } else if ( background && background.isTexture ) {
13625
13626                         if ( planeMesh === undefined ) {
13627
13628                                 planeMesh = new Mesh(
13629                                         new PlaneGeometry( 2, 2 ),
13630                                         new ShaderMaterial( {
13631                                                 name: 'BackgroundMaterial',
13632                                                 uniforms: cloneUniforms( ShaderLib.background.uniforms ),
13633                                                 vertexShader: ShaderLib.background.vertexShader,
13634                                                 fragmentShader: ShaderLib.background.fragmentShader,
13635                                                 side: FrontSide,
13636                                                 depthTest: false,
13637                                                 depthWrite: false,
13638                                                 fog: false
13639                                         } )
13640                                 );
13641
13642                                 planeMesh.geometry.deleteAttribute( 'normal' );
13643
13644                                 // enable code injection for non-built-in material
13645                                 Object.defineProperty( planeMesh.material, 'map', {
13646
13647                                         get: function () {
13648
13649                                                 return this.uniforms.t2D.value;
13650
13651                                         }
13652
13653                                 } );
13654
13655                                 objects.update( planeMesh );
13656
13657                         }
13658
13659                         planeMesh.material.uniforms.t2D.value = background;
13660
13661                         if ( background.matrixAutoUpdate === true ) {
13662
13663                                 background.updateMatrix();
13664
13665                         }
13666
13667                         planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
13668
13669                         if ( currentBackground !== background ||
13670                                 currentBackgroundVersion !== background.version ||
13671                                 currentTonemapping !== renderer.toneMapping ) {
13672
13673                                 planeMesh.material.needsUpdate = true;
13674
13675                                 currentBackground = background;
13676                                 currentBackgroundVersion = background.version;
13677                                 currentTonemapping = renderer.toneMapping;
13678
13679                         }
13680
13681
13682                         // push to the pre-sorted opaque render list
13683                         renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
13684
13685                 }
13686
13687         }
13688
13689         function setClear( color, alpha ) {
13690
13691                 state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
13692
13693         }
13694
13695         return {
13696
13697                 getClearColor: function () {
13698
13699                         return clearColor;
13700
13701                 },
13702                 setClearColor: function ( color, alpha = 1 ) {
13703
13704                         clearColor.set( color );
13705                         clearAlpha = alpha;
13706                         setClear( clearColor, clearAlpha );
13707
13708                 },
13709                 getClearAlpha: function () {
13710
13711                         return clearAlpha;
13712
13713                 },
13714                 setClearAlpha: function ( alpha ) {
13715
13716                         clearAlpha = alpha;
13717                         setClear( clearColor, clearAlpha );
13718
13719                 },
13720                 render: render
13721
13722         };
13723
13724 }
13725
13726 function WebGLBindingStates( gl, extensions, attributes, capabilities ) {
13727
13728         const maxVertexAttributes = gl.getParameter( 34921 );
13729
13730         const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' );
13731         const vaoAvailable = capabilities.isWebGL2 || extension !== null;
13732
13733         const bindingStates = {};
13734
13735         const defaultState = createBindingState( null );
13736         let currentState = defaultState;
13737
13738         function setup( object, material, program, geometry, index ) {
13739
13740                 let updateBuffers = false;
13741
13742                 if ( vaoAvailable ) {
13743
13744                         const state = getBindingState( geometry, program, material );
13745
13746                         if ( currentState !== state ) {
13747
13748                                 currentState = state;
13749                                 bindVertexArrayObject( currentState.object );
13750
13751                         }
13752
13753                         updateBuffers = needsUpdate( geometry, index );
13754
13755                         if ( updateBuffers ) saveCache( geometry, index );
13756
13757                 } else {
13758
13759                         const wireframe = ( material.wireframe === true );
13760
13761                         if ( currentState.geometry !== geometry.id ||
13762                                 currentState.program !== program.id ||
13763                                 currentState.wireframe !== wireframe ) {
13764
13765                                 currentState.geometry = geometry.id;
13766                                 currentState.program = program.id;
13767                                 currentState.wireframe = wireframe;
13768
13769                                 updateBuffers = true;
13770
13771                         }
13772
13773                 }
13774
13775                 if ( object.isInstancedMesh === true ) {
13776
13777                         updateBuffers = true;
13778
13779                 }
13780
13781                 if ( index !== null ) {
13782
13783                         attributes.update( index, 34963 );
13784
13785                 }
13786
13787                 if ( updateBuffers ) {
13788
13789                         setupVertexAttributes( object, material, program, geometry );
13790
13791                         if ( index !== null ) {
13792
13793                                 gl.bindBuffer( 34963, attributes.get( index ).buffer );
13794
13795                         }
13796
13797                 }
13798
13799         }
13800
13801         function createVertexArrayObject() {
13802
13803                 if ( capabilities.isWebGL2 ) return gl.createVertexArray();
13804
13805                 return extension.createVertexArrayOES();
13806
13807         }
13808
13809         function bindVertexArrayObject( vao ) {
13810
13811                 if ( capabilities.isWebGL2 ) return gl.bindVertexArray( vao );
13812
13813                 return extension.bindVertexArrayOES( vao );
13814
13815         }
13816
13817         function deleteVertexArrayObject( vao ) {
13818
13819                 if ( capabilities.isWebGL2 ) return gl.deleteVertexArray( vao );
13820
13821                 return extension.deleteVertexArrayOES( vao );
13822
13823         }
13824
13825         function getBindingState( geometry, program, material ) {
13826
13827                 const wireframe = ( material.wireframe === true );
13828
13829                 let programMap = bindingStates[ geometry.id ];
13830
13831                 if ( programMap === undefined ) {
13832
13833                         programMap = {};
13834                         bindingStates[ geometry.id ] = programMap;
13835
13836                 }
13837
13838                 let stateMap = programMap[ program.id ];
13839
13840                 if ( stateMap === undefined ) {
13841
13842                         stateMap = {};
13843                         programMap[ program.id ] = stateMap;
13844
13845                 }
13846
13847                 let state = stateMap[ wireframe ];
13848
13849                 if ( state === undefined ) {
13850
13851                         state = createBindingState( createVertexArrayObject() );
13852                         stateMap[ wireframe ] = state;
13853
13854                 }
13855
13856                 return state;
13857
13858         }
13859
13860         function createBindingState( vao ) {
13861
13862                 const newAttributes = [];
13863                 const enabledAttributes = [];
13864                 const attributeDivisors = [];
13865
13866                 for ( let i = 0; i < maxVertexAttributes; i ++ ) {
13867
13868                         newAttributes[ i ] = 0;
13869                         enabledAttributes[ i ] = 0;
13870                         attributeDivisors[ i ] = 0;
13871
13872                 }
13873
13874                 return {
13875
13876                         // for backward compatibility on non-VAO support browser
13877                         geometry: null,
13878                         program: null,
13879                         wireframe: false,
13880
13881                         newAttributes: newAttributes,
13882                         enabledAttributes: enabledAttributes,
13883                         attributeDivisors: attributeDivisors,
13884                         object: vao,
13885                         attributes: {},
13886                         index: null
13887
13888                 };
13889
13890         }
13891
13892         function needsUpdate( geometry, index ) {
13893
13894                 const cachedAttributes = currentState.attributes;
13895                 const geometryAttributes = geometry.attributes;
13896
13897                 let attributesNum = 0;
13898
13899                 for ( const key in geometryAttributes ) {
13900
13901                         const cachedAttribute = cachedAttributes[ key ];
13902                         const geometryAttribute = geometryAttributes[ key ];
13903
13904                         if ( cachedAttribute === undefined ) return true;
13905
13906                         if ( cachedAttribute.attribute !== geometryAttribute ) return true;
13907
13908                         if ( cachedAttribute.data !== geometryAttribute.data ) return true;
13909
13910                         attributesNum ++;
13911
13912                 }
13913
13914                 if ( currentState.attributesNum !== attributesNum ) return true;
13915
13916                 if ( currentState.index !== index ) return true;
13917
13918                 return false;
13919
13920         }
13921
13922         function saveCache( geometry, index ) {
13923
13924                 const cache = {};
13925                 const attributes = geometry.attributes;
13926                 let attributesNum = 0;
13927
13928                 for ( const key in attributes ) {
13929
13930                         const attribute = attributes[ key ];
13931
13932                         const data = {};
13933                         data.attribute = attribute;
13934
13935                         if ( attribute.data ) {
13936
13937                                 data.data = attribute.data;
13938
13939                         }
13940
13941                         cache[ key ] = data;
13942
13943                         attributesNum ++;
13944
13945                 }
13946
13947                 currentState.attributes = cache;
13948                 currentState.attributesNum = attributesNum;
13949
13950                 currentState.index = index;
13951
13952         }
13953
13954         function initAttributes() {
13955
13956                 const newAttributes = currentState.newAttributes;
13957
13958                 for ( let i = 0, il = newAttributes.length; i < il; i ++ ) {
13959
13960                         newAttributes[ i ] = 0;
13961
13962                 }
13963
13964         }
13965
13966         function enableAttribute( attribute ) {
13967
13968                 enableAttributeAndDivisor( attribute, 0 );
13969
13970         }
13971
13972         function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
13973
13974                 const newAttributes = currentState.newAttributes;
13975                 const enabledAttributes = currentState.enabledAttributes;
13976                 const attributeDivisors = currentState.attributeDivisors;
13977
13978                 newAttributes[ attribute ] = 1;
13979
13980                 if ( enabledAttributes[ attribute ] === 0 ) {
13981
13982                         gl.enableVertexAttribArray( attribute );
13983                         enabledAttributes[ attribute ] = 1;
13984
13985                 }
13986
13987                 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
13988
13989                         const extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
13990
13991                         extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
13992                         attributeDivisors[ attribute ] = meshPerAttribute;
13993
13994                 }
13995
13996         }
13997
13998         function disableUnusedAttributes() {
13999
14000                 const newAttributes = currentState.newAttributes;
14001                 const enabledAttributes = currentState.enabledAttributes;
14002
14003                 for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) {
14004
14005                         if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
14006
14007                                 gl.disableVertexAttribArray( i );
14008                                 enabledAttributes[ i ] = 0;
14009
14010                         }
14011
14012                 }
14013
14014         }
14015
14016         function vertexAttribPointer( index, size, type, normalized, stride, offset ) {
14017
14018                 if ( capabilities.isWebGL2 === true && ( type === 5124 || type === 5125 ) ) {
14019
14020                         gl.vertexAttribIPointer( index, size, type, stride, offset );
14021
14022                 } else {
14023
14024                         gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
14025
14026                 }
14027
14028         }
14029
14030         function setupVertexAttributes( object, material, program, geometry ) {
14031
14032                 if ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {
14033
14034                         if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return;
14035
14036                 }
14037
14038                 initAttributes();
14039
14040                 const geometryAttributes = geometry.attributes;
14041
14042                 const programAttributes = program.getAttributes();
14043
14044                 const materialDefaultAttributeValues = material.defaultAttributeValues;
14045
14046                 for ( const name in programAttributes ) {
14047
14048                         const programAttribute = programAttributes[ name ];
14049
14050                         if ( programAttribute >= 0 ) {
14051
14052                                 const geometryAttribute = geometryAttributes[ name ];
14053
14054                                 if ( geometryAttribute !== undefined ) {
14055
14056                                         const normalized = geometryAttribute.normalized;
14057                                         const size = geometryAttribute.itemSize;
14058
14059                                         const attribute = attributes.get( geometryAttribute );
14060
14061                                         // TODO Attribute may not be available on context restore
14062
14063                                         if ( attribute === undefined ) continue;
14064
14065                                         const buffer = attribute.buffer;
14066                                         const type = attribute.type;
14067                                         const bytesPerElement = attribute.bytesPerElement;
14068
14069                                         if ( geometryAttribute.isInterleavedBufferAttribute ) {
14070
14071                                                 const data = geometryAttribute.data;
14072                                                 const stride = data.stride;
14073                                                 const offset = geometryAttribute.offset;
14074
14075                                                 if ( data && data.isInstancedInterleavedBuffer ) {
14076
14077                                                         enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
14078
14079                                                         if ( geometry._maxInstanceCount === undefined ) {
14080
14081                                                                 geometry._maxInstanceCount = data.meshPerAttribute * data.count;
14082
14083                                                         }
14084
14085                                                 } else {
14086
14087                                                         enableAttribute( programAttribute );
14088
14089                                                 }
14090
14091                                                 gl.bindBuffer( 34962, buffer );
14092                                                 vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
14093
14094                                         } else {
14095
14096                                                 if ( geometryAttribute.isInstancedBufferAttribute ) {
14097
14098                                                         enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
14099
14100                                                         if ( geometry._maxInstanceCount === undefined ) {
14101
14102                                                                 geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
14103
14104                                                         }
14105
14106                                                 } else {
14107
14108                                                         enableAttribute( programAttribute );
14109
14110                                                 }
14111
14112                                                 gl.bindBuffer( 34962, buffer );
14113                                                 vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
14114
14115                                         }
14116
14117                                 } else if ( name === 'instanceMatrix' ) {
14118
14119                                         const attribute = attributes.get( object.instanceMatrix );
14120
14121                                         // TODO Attribute may not be available on context restore
14122
14123                                         if ( attribute === undefined ) continue;
14124
14125                                         const buffer = attribute.buffer;
14126                                         const type = attribute.type;
14127
14128                                         enableAttributeAndDivisor( programAttribute + 0, 1 );
14129                                         enableAttributeAndDivisor( programAttribute + 1, 1 );
14130                                         enableAttributeAndDivisor( programAttribute + 2, 1 );
14131                                         enableAttributeAndDivisor( programAttribute + 3, 1 );
14132
14133                                         gl.bindBuffer( 34962, buffer );
14134
14135                                         gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );
14136                                         gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );
14137                                         gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );
14138                                         gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );
14139
14140                                 } else if ( name === 'instanceColor' ) {
14141
14142                                         const attribute = attributes.get( object.instanceColor );
14143
14144                                         // TODO Attribute may not be available on context restore
14145
14146                                         if ( attribute === undefined ) continue;
14147
14148                                         const buffer = attribute.buffer;
14149                                         const type = attribute.type;
14150
14151                                         enableAttributeAndDivisor( programAttribute, 1 );
14152
14153                                         gl.bindBuffer( 34962, buffer );
14154
14155                                         gl.vertexAttribPointer( programAttribute, 3, type, false, 12, 0 );
14156
14157                                 } else if ( materialDefaultAttributeValues !== undefined ) {
14158
14159                                         const value = materialDefaultAttributeValues[ name ];
14160
14161                                         if ( value !== undefined ) {
14162
14163                                                 switch ( value.length ) {
14164
14165                                                         case 2:
14166                                                                 gl.vertexAttrib2fv( programAttribute, value );
14167                                                                 break;
14168
14169                                                         case 3:
14170                                                                 gl.vertexAttrib3fv( programAttribute, value );
14171                                                                 break;
14172
14173                                                         case 4:
14174                                                                 gl.vertexAttrib4fv( programAttribute, value );
14175                                                                 break;
14176
14177                                                         default:
14178                                                                 gl.vertexAttrib1fv( programAttribute, value );
14179
14180                                                 }
14181
14182                                         }
14183
14184                                 }
14185
14186                         }
14187
14188                 }
14189
14190                 disableUnusedAttributes();
14191
14192         }
14193
14194         function dispose() {
14195
14196                 reset();
14197
14198                 for ( const geometryId in bindingStates ) {
14199
14200                         const programMap = bindingStates[ geometryId ];
14201
14202                         for ( const programId in programMap ) {
14203
14204                                 const stateMap = programMap[ programId ];
14205
14206                                 for ( const wireframe in stateMap ) {
14207
14208                                         deleteVertexArrayObject( stateMap[ wireframe ].object );
14209
14210                                         delete stateMap[ wireframe ];
14211
14212                                 }
14213
14214                                 delete programMap[ programId ];
14215
14216                         }
14217
14218                         delete bindingStates[ geometryId ];
14219
14220                 }
14221
14222         }
14223
14224         function releaseStatesOfGeometry( geometry ) {
14225
14226                 if ( bindingStates[ geometry.id ] === undefined ) return;
14227
14228                 const programMap = bindingStates[ geometry.id ];
14229
14230                 for ( const programId in programMap ) {
14231
14232                         const stateMap = programMap[ programId ];
14233
14234                         for ( const wireframe in stateMap ) {
14235
14236                                 deleteVertexArrayObject( stateMap[ wireframe ].object );
14237
14238                                 delete stateMap[ wireframe ];
14239
14240                         }
14241
14242                         delete programMap[ programId ];
14243
14244                 }
14245
14246                 delete bindingStates[ geometry.id ];
14247
14248         }
14249
14250         function releaseStatesOfProgram( program ) {
14251
14252                 for ( const geometryId in bindingStates ) {
14253
14254                         const programMap = bindingStates[ geometryId ];
14255
14256                         if ( programMap[ program.id ] === undefined ) continue;
14257
14258                         const stateMap = programMap[ program.id ];
14259
14260                         for ( const wireframe in stateMap ) {
14261
14262                                 deleteVertexArrayObject( stateMap[ wireframe ].object );
14263
14264                                 delete stateMap[ wireframe ];
14265
14266                         }
14267
14268                         delete programMap[ program.id ];
14269
14270                 }
14271
14272         }
14273
14274         function reset() {
14275
14276                 resetDefaultState();
14277
14278                 if ( currentState === defaultState ) return;
14279
14280                 currentState = defaultState;
14281                 bindVertexArrayObject( currentState.object );
14282
14283         }
14284
14285         // for backward-compatilibity
14286
14287         function resetDefaultState() {
14288
14289                 defaultState.geometry = null;
14290                 defaultState.program = null;
14291                 defaultState.wireframe = false;
14292
14293         }
14294
14295         return {
14296
14297                 setup: setup,
14298                 reset: reset,
14299                 resetDefaultState: resetDefaultState,
14300                 dispose: dispose,
14301                 releaseStatesOfGeometry: releaseStatesOfGeometry,
14302                 releaseStatesOfProgram: releaseStatesOfProgram,
14303
14304                 initAttributes: initAttributes,
14305                 enableAttribute: enableAttribute,
14306                 disableUnusedAttributes: disableUnusedAttributes
14307
14308         };
14309
14310 }
14311
14312 function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
14313
14314         const isWebGL2 = capabilities.isWebGL2;
14315
14316         let mode;
14317
14318         function setMode( value ) {
14319
14320                 mode = value;
14321
14322         }
14323
14324         function render( start, count ) {
14325
14326                 gl.drawArrays( mode, start, count );
14327
14328                 info.update( count, mode, 1 );
14329
14330         }
14331
14332         function renderInstances( start, count, primcount ) {
14333
14334                 if ( primcount === 0 ) return;
14335
14336                 let extension, methodName;
14337
14338                 if ( isWebGL2 ) {
14339
14340                         extension = gl;
14341                         methodName = 'drawArraysInstanced';
14342
14343                 } else {
14344
14345                         extension = extensions.get( 'ANGLE_instanced_arrays' );
14346                         methodName = 'drawArraysInstancedANGLE';
14347
14348                         if ( extension === null ) {
14349
14350                                 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
14351                                 return;
14352
14353                         }
14354
14355                 }
14356
14357                 extension[ methodName ]( mode, start, count, primcount );
14358
14359                 info.update( count, mode, primcount );
14360
14361         }
14362
14363         //
14364
14365         this.setMode = setMode;
14366         this.render = render;
14367         this.renderInstances = renderInstances;
14368
14369 }
14370
14371 function WebGLCapabilities( gl, extensions, parameters ) {
14372
14373         let maxAnisotropy;
14374
14375         function getMaxAnisotropy() {
14376
14377                 if ( maxAnisotropy !== undefined ) return maxAnisotropy;
14378
14379                 const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
14380
14381                 if ( extension !== null ) {
14382
14383                         maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
14384
14385                 } else {
14386
14387                         maxAnisotropy = 0;
14388
14389                 }
14390
14391                 return maxAnisotropy;
14392
14393         }
14394
14395         function getMaxPrecision( precision ) {
14396
14397                 if ( precision === 'highp' ) {
14398
14399                         if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&
14400                                 gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {
14401
14402                                 return 'highp';
14403
14404                         }
14405
14406                         precision = 'mediump';
14407
14408                 }
14409
14410                 if ( precision === 'mediump' ) {
14411
14412                         if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&
14413                                 gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {
14414
14415                                 return 'mediump';
14416
14417                         }
14418
14419                 }
14420
14421                 return 'lowp';
14422
14423         }
14424
14425         /* eslint-disable no-undef */
14426         const isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||
14427                 ( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );
14428         /* eslint-enable no-undef */
14429
14430         let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
14431         const maxPrecision = getMaxPrecision( precision );
14432
14433         if ( maxPrecision !== precision ) {
14434
14435                 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
14436                 precision = maxPrecision;
14437
14438         }
14439
14440         const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
14441
14442         const maxTextures = gl.getParameter( 34930 );
14443         const maxVertexTextures = gl.getParameter( 35660 );
14444         const maxTextureSize = gl.getParameter( 3379 );
14445         const maxCubemapSize = gl.getParameter( 34076 );
14446
14447         const maxAttributes = gl.getParameter( 34921 );
14448         const maxVertexUniforms = gl.getParameter( 36347 );
14449         const maxVaryings = gl.getParameter( 36348 );
14450         const maxFragmentUniforms = gl.getParameter( 36349 );
14451
14452         const vertexTextures = maxVertexTextures > 0;
14453         const floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
14454         const floatVertexTextures = vertexTextures && floatFragmentTextures;
14455
14456         const maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;
14457
14458         return {
14459
14460                 isWebGL2: isWebGL2,
14461
14462                 getMaxAnisotropy: getMaxAnisotropy,
14463                 getMaxPrecision: getMaxPrecision,
14464
14465                 precision: precision,
14466                 logarithmicDepthBuffer: logarithmicDepthBuffer,
14467
14468                 maxTextures: maxTextures,
14469                 maxVertexTextures: maxVertexTextures,
14470                 maxTextureSize: maxTextureSize,
14471                 maxCubemapSize: maxCubemapSize,
14472
14473                 maxAttributes: maxAttributes,
14474                 maxVertexUniforms: maxVertexUniforms,
14475                 maxVaryings: maxVaryings,
14476                 maxFragmentUniforms: maxFragmentUniforms,
14477
14478                 vertexTextures: vertexTextures,
14479                 floatFragmentTextures: floatFragmentTextures,
14480                 floatVertexTextures: floatVertexTextures,
14481
14482                 maxSamples: maxSamples
14483
14484         };
14485
14486 }
14487
14488 function WebGLClipping( properties ) {
14489
14490         const scope = this;
14491
14492         let globalState = null,
14493                 numGlobalPlanes = 0,
14494                 localClippingEnabled = false,
14495                 renderingShadows = false;
14496
14497         const plane = new Plane(),
14498                 viewNormalMatrix = new Matrix3(),
14499
14500                 uniform = { value: null, needsUpdate: false };
14501
14502         this.uniform = uniform;
14503         this.numPlanes = 0;
14504         this.numIntersection = 0;
14505
14506         this.init = function ( planes, enableLocalClipping, camera ) {
14507
14508                 const enabled =
14509                         planes.length !== 0 ||
14510                         enableLocalClipping ||
14511                         // enable state of previous frame - the clipping code has to
14512                         // run another frame in order to reset the state:
14513                         numGlobalPlanes !== 0 ||
14514                         localClippingEnabled;
14515
14516                 localClippingEnabled = enableLocalClipping;
14517
14518                 globalState = projectPlanes( planes, camera, 0 );
14519                 numGlobalPlanes = planes.length;
14520
14521                 return enabled;
14522
14523         };
14524
14525         this.beginShadows = function () {
14526
14527                 renderingShadows = true;
14528                 projectPlanes( null );
14529
14530         };
14531
14532         this.endShadows = function () {
14533
14534                 renderingShadows = false;
14535                 resetGlobalState();
14536
14537         };
14538
14539         this.setState = function ( material, camera, useCache ) {
14540
14541                 const planes = material.clippingPlanes,
14542                         clipIntersection = material.clipIntersection,
14543                         clipShadows = material.clipShadows;
14544
14545                 const materialProperties = properties.get( material );
14546
14547                 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
14548
14549                         // there's no local clipping
14550
14551                         if ( renderingShadows ) {
14552
14553                                 // there's no global clipping
14554
14555                                 projectPlanes( null );
14556
14557                         } else {
14558
14559                                 resetGlobalState();
14560
14561                         }
14562
14563                 } else {
14564
14565                         const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
14566                                 lGlobal = nGlobal * 4;
14567
14568                         let dstArray = materialProperties.clippingState || null;
14569
14570                         uniform.value = dstArray; // ensure unique state
14571
14572                         dstArray = projectPlanes( planes, camera, lGlobal, useCache );
14573
14574                         for ( let i = 0; i !== lGlobal; ++ i ) {
14575
14576                                 dstArray[ i ] = globalState[ i ];
14577
14578                         }
14579
14580                         materialProperties.clippingState = dstArray;
14581                         this.numIntersection = clipIntersection ? this.numPlanes : 0;
14582                         this.numPlanes += nGlobal;
14583
14584                 }
14585
14586
14587         };
14588
14589         function resetGlobalState() {
14590
14591                 if ( uniform.value !== globalState ) {
14592
14593                         uniform.value = globalState;
14594                         uniform.needsUpdate = numGlobalPlanes > 0;
14595
14596                 }
14597
14598                 scope.numPlanes = numGlobalPlanes;
14599                 scope.numIntersection = 0;
14600
14601         }
14602
14603         function projectPlanes( planes, camera, dstOffset, skipTransform ) {
14604
14605                 const nPlanes = planes !== null ? planes.length : 0;
14606                 let dstArray = null;
14607
14608                 if ( nPlanes !== 0 ) {
14609
14610                         dstArray = uniform.value;
14611
14612                         if ( skipTransform !== true || dstArray === null ) {
14613
14614                                 const flatSize = dstOffset + nPlanes * 4,
14615                                         viewMatrix = camera.matrixWorldInverse;
14616
14617                                 viewNormalMatrix.getNormalMatrix( viewMatrix );
14618
14619                                 if ( dstArray === null || dstArray.length < flatSize ) {
14620
14621                                         dstArray = new Float32Array( flatSize );
14622
14623                                 }
14624
14625                                 for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
14626
14627                                         plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
14628
14629                                         plane.normal.toArray( dstArray, i4 );
14630                                         dstArray[ i4 + 3 ] = plane.constant;
14631
14632                                 }
14633
14634                         }
14635
14636                         uniform.value = dstArray;
14637                         uniform.needsUpdate = true;
14638
14639                 }
14640
14641                 scope.numPlanes = nPlanes;
14642                 scope.numIntersection = 0;
14643
14644                 return dstArray;
14645
14646         }
14647
14648 }
14649
14650 function WebGLCubeMaps( renderer ) {
14651
14652         let cubemaps = new WeakMap();
14653
14654         function mapTextureMapping( texture, mapping ) {
14655
14656                 if ( mapping === EquirectangularReflectionMapping ) {
14657
14658                         texture.mapping = CubeReflectionMapping;
14659
14660                 } else if ( mapping === EquirectangularRefractionMapping ) {
14661
14662                         texture.mapping = CubeRefractionMapping;
14663
14664                 }
14665
14666                 return texture;
14667
14668         }
14669
14670         function get( texture ) {
14671
14672                 if ( texture && texture.isTexture ) {
14673
14674                         const mapping = texture.mapping;
14675
14676                         if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
14677
14678                                 if ( cubemaps.has( texture ) ) {
14679
14680                                         const cubemap = cubemaps.get( texture ).texture;
14681                                         return mapTextureMapping( cubemap, texture.mapping );
14682
14683                                 } else {
14684
14685                                         const image = texture.image;
14686
14687                                         if ( image && image.height > 0 ) {
14688
14689                                                 const currentRenderList = renderer.getRenderList();
14690                                                 const currentRenderTarget = renderer.getRenderTarget();
14691
14692                                                 const renderTarget = new WebGLCubeRenderTarget( image.height / 2 );
14693                                                 renderTarget.fromEquirectangularTexture( renderer, texture );
14694                                                 cubemaps.set( texture, renderTarget );
14695
14696                                                 renderer.setRenderTarget( currentRenderTarget );
14697                                                 renderer.setRenderList( currentRenderList );
14698
14699                                                 texture.addEventListener( 'dispose', onTextureDispose );
14700
14701                                                 return mapTextureMapping( renderTarget.texture, texture.mapping );
14702
14703                                         } else {
14704
14705                                                 // image not yet ready. try the conversion next frame
14706
14707                                                 return null;
14708
14709                                         }
14710
14711                                 }
14712
14713                         }
14714
14715                 }
14716
14717                 return texture;
14718
14719         }
14720
14721         function onTextureDispose( event ) {
14722
14723                 const texture = event.target;
14724
14725                 texture.removeEventListener( 'dispose', onTextureDispose );
14726
14727                 const cubemap = cubemaps.get( texture );
14728
14729                 if ( cubemap !== undefined ) {
14730
14731                         cubemaps.delete( texture );
14732                         cubemap.dispose();
14733
14734                 }
14735
14736         }
14737
14738         function dispose() {
14739
14740                 cubemaps = new WeakMap();
14741
14742         }
14743
14744         return {
14745                 get: get,
14746                 dispose: dispose
14747         };
14748
14749 }
14750
14751 function WebGLExtensions( gl ) {
14752
14753         const extensions = {};
14754
14755         function getExtension( name ) {
14756
14757                 if ( extensions[ name ] !== undefined ) {
14758
14759                         return extensions[ name ];
14760
14761                 }
14762
14763                 let extension;
14764
14765                 switch ( name ) {
14766
14767                         case 'WEBGL_depth_texture':
14768                                 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
14769                                 break;
14770
14771                         case 'EXT_texture_filter_anisotropic':
14772                                 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
14773                                 break;
14774
14775                         case 'WEBGL_compressed_texture_s3tc':
14776                                 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
14777                                 break;
14778
14779                         case 'WEBGL_compressed_texture_pvrtc':
14780                                 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
14781                                 break;
14782
14783                         default:
14784                                 extension = gl.getExtension( name );
14785
14786                 }
14787
14788                 extensions[ name ] = extension;
14789
14790                 return extension;
14791
14792         }
14793
14794         return {
14795
14796                 has: function ( name ) {
14797
14798                         return getExtension( name ) !== null;
14799
14800                 },
14801
14802                 init: function ( capabilities ) {
14803
14804                         if ( capabilities.isWebGL2 ) {
14805
14806                                 getExtension( 'EXT_color_buffer_float' );
14807
14808                         } else {
14809
14810                                 getExtension( 'WEBGL_depth_texture' );
14811                                 getExtension( 'OES_texture_float' );
14812                                 getExtension( 'OES_texture_half_float' );
14813                                 getExtension( 'OES_texture_half_float_linear' );
14814                                 getExtension( 'OES_standard_derivatives' );
14815                                 getExtension( 'OES_element_index_uint' );
14816                                 getExtension( 'OES_vertex_array_object' );
14817                                 getExtension( 'ANGLE_instanced_arrays' );
14818
14819                         }
14820
14821                         getExtension( 'OES_texture_float_linear' );
14822                         getExtension( 'EXT_color_buffer_half_float' );
14823
14824                 },
14825
14826                 get: function ( name ) {
14827
14828                         const extension = getExtension( name );
14829
14830                         if ( extension === null ) {
14831
14832                                 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
14833
14834                         }
14835
14836                         return extension;
14837
14838                 }
14839
14840         };
14841
14842 }
14843
14844 function WebGLGeometries( gl, attributes, info, bindingStates ) {
14845
14846         const geometries = {};
14847         const wireframeAttributes = new WeakMap();
14848
14849         function onGeometryDispose( event ) {
14850
14851                 const geometry = event.target;
14852
14853                 if ( geometry.index !== null ) {
14854
14855                         attributes.remove( geometry.index );
14856
14857                 }
14858
14859                 for ( const name in geometry.attributes ) {
14860
14861                         attributes.remove( geometry.attributes[ name ] );
14862
14863                 }
14864
14865                 geometry.removeEventListener( 'dispose', onGeometryDispose );
14866
14867                 delete geometries[ geometry.id ];
14868
14869                 const attribute = wireframeAttributes.get( geometry );
14870
14871                 if ( attribute ) {
14872
14873                         attributes.remove( attribute );
14874                         wireframeAttributes.delete( geometry );
14875
14876                 }
14877
14878                 bindingStates.releaseStatesOfGeometry( geometry );
14879
14880                 if ( geometry.isInstancedBufferGeometry === true ) {
14881
14882                         delete geometry._maxInstanceCount;
14883
14884                 }
14885
14886                 //
14887
14888                 info.memory.geometries --;
14889
14890         }
14891
14892         function get( object, geometry ) {
14893
14894                 if ( geometries[ geometry.id ] === true ) return geometry;
14895
14896                 geometry.addEventListener( 'dispose', onGeometryDispose );
14897
14898                 geometries[ geometry.id ] = true;
14899
14900                 info.memory.geometries ++;
14901
14902                 return geometry;
14903
14904         }
14905
14906         function update( geometry ) {
14907
14908                 const geometryAttributes = geometry.attributes;
14909
14910                 // Updating index buffer in VAO now. See WebGLBindingStates.
14911
14912                 for ( const name in geometryAttributes ) {
14913
14914                         attributes.update( geometryAttributes[ name ], 34962 );
14915
14916                 }
14917
14918                 // morph targets
14919
14920                 const morphAttributes = geometry.morphAttributes;
14921
14922                 for ( const name in morphAttributes ) {
14923
14924                         const array = morphAttributes[ name ];
14925
14926                         for ( let i = 0, l = array.length; i < l; i ++ ) {
14927
14928                                 attributes.update( array[ i ], 34962 );
14929
14930                         }
14931
14932                 }
14933
14934         }
14935
14936         function updateWireframeAttribute( geometry ) {
14937
14938                 const indices = [];
14939
14940                 const geometryIndex = geometry.index;
14941                 const geometryPosition = geometry.attributes.position;
14942                 let version = 0;
14943
14944                 if ( geometryIndex !== null ) {
14945
14946                         const array = geometryIndex.array;
14947                         version = geometryIndex.version;
14948
14949                         for ( let i = 0, l = array.length; i < l; i += 3 ) {
14950
14951                                 const a = array[ i + 0 ];
14952                                 const b = array[ i + 1 ];
14953                                 const c = array[ i + 2 ];
14954
14955                                 indices.push( a, b, b, c, c, a );
14956
14957                         }
14958
14959                 } else {
14960
14961                         const array = geometryPosition.array;
14962                         version = geometryPosition.version;
14963
14964                         for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
14965
14966                                 const a = i + 0;
14967                                 const b = i + 1;
14968                                 const c = i + 2;
14969
14970                                 indices.push( a, b, b, c, c, a );
14971
14972                         }
14973
14974                 }
14975
14976                 const attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
14977                 attribute.version = version;
14978
14979                 // Updating index buffer in VAO now. See WebGLBindingStates
14980
14981                 //
14982
14983                 const previousAttribute = wireframeAttributes.get( geometry );
14984
14985                 if ( previousAttribute ) attributes.remove( previousAttribute );
14986
14987                 //
14988
14989                 wireframeAttributes.set( geometry, attribute );
14990
14991         }
14992
14993         function getWireframeAttribute( geometry ) {
14994
14995                 const currentAttribute = wireframeAttributes.get( geometry );
14996
14997                 if ( currentAttribute ) {
14998
14999                         const geometryIndex = geometry.index;
15000
15001                         if ( geometryIndex !== null ) {
15002
15003                                 // if the attribute is obsolete, create a new one
15004
15005                                 if ( currentAttribute.version < geometryIndex.version ) {
15006
15007                                         updateWireframeAttribute( geometry );
15008
15009                                 }
15010
15011                         }
15012
15013                 } else {
15014
15015                         updateWireframeAttribute( geometry );
15016
15017                 }
15018
15019                 return wireframeAttributes.get( geometry );
15020
15021         }
15022
15023         return {
15024
15025                 get: get,
15026                 update: update,
15027
15028                 getWireframeAttribute: getWireframeAttribute
15029
15030         };
15031
15032 }
15033
15034 function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
15035
15036         const isWebGL2 = capabilities.isWebGL2;
15037
15038         let mode;
15039
15040         function setMode( value ) {
15041
15042                 mode = value;
15043
15044         }
15045
15046         let type, bytesPerElement;
15047
15048         function setIndex( value ) {
15049
15050                 type = value.type;
15051                 bytesPerElement = value.bytesPerElement;
15052
15053         }
15054
15055         function render( start, count ) {
15056
15057                 gl.drawElements( mode, count, type, start * bytesPerElement );
15058
15059                 info.update( count, mode, 1 );
15060
15061         }
15062
15063         function renderInstances( start, count, primcount ) {
15064
15065                 if ( primcount === 0 ) return;
15066
15067                 let extension, methodName;
15068
15069                 if ( isWebGL2 ) {
15070
15071                         extension = gl;
15072                         methodName = 'drawElementsInstanced';
15073
15074                 } else {
15075
15076                         extension = extensions.get( 'ANGLE_instanced_arrays' );
15077                         methodName = 'drawElementsInstancedANGLE';
15078
15079                         if ( extension === null ) {
15080
15081                                 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
15082                                 return;
15083
15084                         }
15085
15086                 }
15087
15088                 extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );
15089
15090                 info.update( count, mode, primcount );
15091
15092         }
15093
15094         //
15095
15096         this.setMode = setMode;
15097         this.setIndex = setIndex;
15098         this.render = render;
15099         this.renderInstances = renderInstances;
15100
15101 }
15102
15103 function WebGLInfo( gl ) {
15104
15105         const memory = {
15106                 geometries: 0,
15107                 textures: 0
15108         };
15109
15110         const render = {
15111                 frame: 0,
15112                 calls: 0,
15113                 triangles: 0,
15114                 points: 0,
15115                 lines: 0
15116         };
15117
15118         function update( count, mode, instanceCount ) {
15119
15120                 render.calls ++;
15121
15122                 switch ( mode ) {
15123
15124                         case 4:
15125                                 render.triangles += instanceCount * ( count / 3 );
15126                                 break;
15127
15128                         case 1:
15129                                 render.lines += instanceCount * ( count / 2 );
15130                                 break;
15131
15132                         case 3:
15133                                 render.lines += instanceCount * ( count - 1 );
15134                                 break;
15135
15136                         case 2:
15137                                 render.lines += instanceCount * count;
15138                                 break;
15139
15140                         case 0:
15141                                 render.points += instanceCount * count;
15142                                 break;
15143
15144                         default:
15145                                 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
15146                                 break;
15147
15148                 }
15149
15150         }
15151
15152         function reset() {
15153
15154                 render.frame ++;
15155                 render.calls = 0;
15156                 render.triangles = 0;
15157                 render.points = 0;
15158                 render.lines = 0;
15159
15160         }
15161
15162         return {
15163                 memory: memory,
15164                 render: render,
15165                 programs: null,
15166                 autoReset: true,
15167                 reset: reset,
15168                 update: update
15169         };
15170
15171 }
15172
15173 function numericalSort( a, b ) {
15174
15175         return a[ 0 ] - b[ 0 ];
15176
15177 }
15178
15179 function absNumericalSort( a, b ) {
15180
15181         return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
15182
15183 }
15184
15185 function WebGLMorphtargets( gl ) {
15186
15187         const influencesList = {};
15188         const morphInfluences = new Float32Array( 8 );
15189
15190         const workInfluences = [];
15191
15192         for ( let i = 0; i < 8; i ++ ) {
15193
15194                 workInfluences[ i ] = [ i, 0 ];
15195
15196         }
15197
15198         function update( object, geometry, material, program ) {
15199
15200                 const objectInfluences = object.morphTargetInfluences;
15201
15202                 // When object doesn't have morph target influences defined, we treat it as a 0-length array
15203                 // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
15204
15205                 const length = objectInfluences === undefined ? 0 : objectInfluences.length;
15206
15207                 let influences = influencesList[ geometry.id ];
15208
15209                 if ( influences === undefined ) {
15210
15211                         // initialise list
15212
15213                         influences = [];
15214
15215                         for ( let i = 0; i < length; i ++ ) {
15216
15217                                 influences[ i ] = [ i, 0 ];
15218
15219                         }
15220
15221                         influencesList[ geometry.id ] = influences;
15222
15223                 }
15224
15225                 // Collect influences
15226
15227                 for ( let i = 0; i < length; i ++ ) {
15228
15229                         const influence = influences[ i ];
15230
15231                         influence[ 0 ] = i;
15232                         influence[ 1 ] = objectInfluences[ i ];
15233
15234                 }
15235
15236                 influences.sort( absNumericalSort );
15237
15238                 for ( let i = 0; i < 8; i ++ ) {
15239
15240                         if ( i < length && influences[ i ][ 1 ] ) {
15241
15242                                 workInfluences[ i ][ 0 ] = influences[ i ][ 0 ];
15243                                 workInfluences[ i ][ 1 ] = influences[ i ][ 1 ];
15244
15245                         } else {
15246
15247                                 workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER;
15248                                 workInfluences[ i ][ 1 ] = 0;
15249
15250                         }
15251
15252                 }
15253
15254                 workInfluences.sort( numericalSort );
15255
15256                 const morphTargets = material.morphTargets && geometry.morphAttributes.position;
15257                 const morphNormals = material.morphNormals && geometry.morphAttributes.normal;
15258
15259                 let morphInfluencesSum = 0;
15260
15261                 for ( let i = 0; i < 8; i ++ ) {
15262
15263                         const influence = workInfluences[ i ];
15264                         const index = influence[ 0 ];
15265                         const value = influence[ 1 ];
15266
15267                         if ( index !== Number.MAX_SAFE_INTEGER && value ) {
15268
15269                                 if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) {
15270
15271                                         geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );
15272
15273                                 }
15274
15275                                 if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) {
15276
15277                                         geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );
15278
15279                                 }
15280
15281                                 morphInfluences[ i ] = value;
15282                                 morphInfluencesSum += value;
15283
15284                         } else {
15285
15286                                 if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) {
15287
15288                                         geometry.deleteAttribute( 'morphTarget' + i );
15289
15290                                 }
15291
15292                                 if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) {
15293
15294                                         geometry.deleteAttribute( 'morphNormal' + i );
15295
15296                                 }
15297
15298                                 morphInfluences[ i ] = 0;
15299
15300                         }
15301
15302                 }
15303
15304                 // GLSL shader uses formula baseinfluence * base + sum(target * influence)
15305                 // This allows us to switch between absolute morphs and relative morphs without changing shader code
15306                 // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
15307                 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
15308
15309                 program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
15310                 program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
15311
15312         }
15313
15314         return {
15315
15316                 update: update
15317
15318         };
15319
15320 }
15321
15322 function WebGLObjects( gl, geometries, attributes, info ) {
15323
15324         let updateMap = new WeakMap();
15325
15326         function update( object ) {
15327
15328                 const frame = info.render.frame;
15329
15330                 const geometry = object.geometry;
15331                 const buffergeometry = geometries.get( object, geometry );
15332
15333                 // Update once per frame
15334
15335                 if ( updateMap.get( buffergeometry ) !== frame ) {
15336
15337                         geometries.update( buffergeometry );
15338
15339                         updateMap.set( buffergeometry, frame );
15340
15341                 }
15342
15343                 if ( object.isInstancedMesh ) {
15344
15345                         if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) {
15346
15347                                 object.addEventListener( 'dispose', onInstancedMeshDispose );
15348
15349                         }
15350
15351                         attributes.update( object.instanceMatrix, 34962 );
15352
15353                         if ( object.instanceColor !== null ) {
15354
15355                                 attributes.update( object.instanceColor, 34962 );
15356
15357                         }
15358
15359                 }
15360
15361                 return buffergeometry;
15362
15363         }
15364
15365         function dispose() {
15366
15367                 updateMap = new WeakMap();
15368
15369         }
15370
15371         function onInstancedMeshDispose( event ) {
15372
15373                 const instancedMesh = event.target;
15374
15375                 instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
15376
15377                 attributes.remove( instancedMesh.instanceMatrix );
15378
15379                 if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );
15380
15381         }
15382
15383         return {
15384
15385                 update: update,
15386                 dispose: dispose
15387
15388         };
15389
15390 }
15391
15392 function DataTexture2DArray( data = null, width = 1, height = 1, depth = 1 ) {
15393
15394         Texture.call( this, null );
15395
15396         this.image = { data, width, height, depth };
15397
15398         this.magFilter = NearestFilter;
15399         this.minFilter = NearestFilter;
15400
15401         this.wrapR = ClampToEdgeWrapping;
15402
15403         this.generateMipmaps = false;
15404         this.flipY = false;
15405
15406         this.needsUpdate = true;
15407
15408 }
15409
15410 DataTexture2DArray.prototype = Object.create( Texture.prototype );
15411 DataTexture2DArray.prototype.constructor = DataTexture2DArray;
15412 DataTexture2DArray.prototype.isDataTexture2DArray = true;
15413
15414 function DataTexture3D( data = null, width = 1, height = 1, depth = 1 ) {
15415
15416         // We're going to add .setXXX() methods for setting properties later.
15417         // Users can still set in DataTexture3D directly.
15418         //
15419         //      const texture = new THREE.DataTexture3D( data, width, height, depth );
15420         //      texture.anisotropy = 16;
15421         //
15422         // See #14839
15423
15424         Texture.call( this, null );
15425
15426         this.image = { data, width, height, depth };
15427
15428         this.magFilter = NearestFilter;
15429         this.minFilter = NearestFilter;
15430
15431         this.wrapR = ClampToEdgeWrapping;
15432
15433         this.generateMipmaps = false;
15434         this.flipY = false;
15435
15436         this.needsUpdate = true;
15437
15438
15439 }
15440
15441 DataTexture3D.prototype = Object.create( Texture.prototype );
15442 DataTexture3D.prototype.constructor = DataTexture3D;
15443 DataTexture3D.prototype.isDataTexture3D = true;
15444
15445 /**
15446  * Uniforms of a program.
15447  * Those form a tree structure with a special top-level container for the root,
15448  * which you get by calling 'new WebGLUniforms( gl, program )'.
15449  *
15450  *
15451  * Properties of inner nodes including the top-level container:
15452  *
15453  * .seq - array of nested uniforms
15454  * .map - nested uniforms by name
15455  *
15456  *
15457  * Methods of all nodes except the top-level container:
15458  *
15459  * .setValue( gl, value, [textures] )
15460  *
15461  *              uploads a uniform value(s)
15462  *      the 'textures' parameter is needed for sampler uniforms
15463  *
15464  *
15465  * Static methods of the top-level container (textures factorizations):
15466  *
15467  * .upload( gl, seq, values, textures )
15468  *
15469  *              sets uniforms in 'seq' to 'values[id].value'
15470  *
15471  * .seqWithValue( seq, values ) : filteredSeq
15472  *
15473  *              filters 'seq' entries with corresponding entry in values
15474  *
15475  *
15476  * Methods of the top-level container (textures factorizations):
15477  *
15478  * .setValue( gl, name, value, textures )
15479  *
15480  *              sets uniform with  name 'name' to 'value'
15481  *
15482  * .setOptional( gl, obj, prop )
15483  *
15484  *              like .set for an optional property of the object
15485  *
15486  */
15487
15488 const emptyTexture = new Texture();
15489 const emptyTexture2dArray = new DataTexture2DArray();
15490 const emptyTexture3d = new DataTexture3D();
15491 const emptyCubeTexture = new CubeTexture();
15492
15493 // --- Utilities ---
15494
15495 // Array Caches (provide typed arrays for temporary by size)
15496
15497 const arrayCacheF32 = [];
15498 const arrayCacheI32 = [];
15499
15500 // Float32Array caches used for uploading Matrix uniforms
15501
15502 const mat4array = new Float32Array( 16 );
15503 const mat3array = new Float32Array( 9 );
15504 const mat2array = new Float32Array( 4 );
15505
15506 // Flattening for arrays of vectors and matrices
15507
15508 function flatten( array, nBlocks, blockSize ) {
15509
15510         const firstElem = array[ 0 ];
15511
15512         if ( firstElem <= 0 || firstElem > 0 ) return array;
15513         // unoptimized: ! isNaN( firstElem )
15514         // see http://jacksondunstan.com/articles/983
15515
15516         const n = nBlocks * blockSize;
15517         let r = arrayCacheF32[ n ];
15518
15519         if ( r === undefined ) {
15520
15521                 r = new Float32Array( n );
15522                 arrayCacheF32[ n ] = r;
15523
15524         }
15525
15526         if ( nBlocks !== 0 ) {
15527
15528                 firstElem.toArray( r, 0 );
15529
15530                 for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) {
15531
15532                         offset += blockSize;
15533                         array[ i ].toArray( r, offset );
15534
15535                 }
15536
15537         }
15538
15539         return r;
15540
15541 }
15542
15543 function arraysEqual( a, b ) {
15544
15545         if ( a.length !== b.length ) return false;
15546
15547         for ( let i = 0, l = a.length; i < l; i ++ ) {
15548
15549                 if ( a[ i ] !== b[ i ] ) return false;
15550
15551         }
15552
15553         return true;
15554
15555 }
15556
15557 function copyArray( a, b ) {
15558
15559         for ( let i = 0, l = b.length; i < l; i ++ ) {
15560
15561                 a[ i ] = b[ i ];
15562
15563         }
15564
15565 }
15566
15567 // Texture unit allocation
15568
15569 function allocTexUnits( textures, n ) {
15570
15571         let r = arrayCacheI32[ n ];
15572
15573         if ( r === undefined ) {
15574
15575                 r = new Int32Array( n );
15576                 arrayCacheI32[ n ] = r;
15577
15578         }
15579
15580         for ( let i = 0; i !== n; ++ i ) {
15581
15582                 r[ i ] = textures.allocateTextureUnit();
15583
15584         }
15585
15586         return r;
15587
15588 }
15589
15590 // --- Setters ---
15591
15592 // Note: Defining these methods externally, because they come in a bunch
15593 // and this way their names minify.
15594
15595 // Single scalar
15596
15597 function setValueV1f( gl, v ) {
15598
15599         const cache = this.cache;
15600
15601         if ( cache[ 0 ] === v ) return;
15602
15603         gl.uniform1f( this.addr, v );
15604
15605         cache[ 0 ] = v;
15606
15607 }
15608
15609 // Single float vector (from flat array or THREE.VectorN)
15610
15611 function setValueV2f( gl, v ) {
15612
15613         const cache = this.cache;
15614
15615         if ( v.x !== undefined ) {
15616
15617                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
15618
15619                         gl.uniform2f( this.addr, v.x, v.y );
15620
15621                         cache[ 0 ] = v.x;
15622                         cache[ 1 ] = v.y;
15623
15624                 }
15625
15626         } else {
15627
15628                 if ( arraysEqual( cache, v ) ) return;
15629
15630                 gl.uniform2fv( this.addr, v );
15631
15632                 copyArray( cache, v );
15633
15634         }
15635
15636 }
15637
15638 function setValueV3f( gl, v ) {
15639
15640         const cache = this.cache;
15641
15642         if ( v.x !== undefined ) {
15643
15644                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
15645
15646                         gl.uniform3f( this.addr, v.x, v.y, v.z );
15647
15648                         cache[ 0 ] = v.x;
15649                         cache[ 1 ] = v.y;
15650                         cache[ 2 ] = v.z;
15651
15652                 }
15653
15654         } else if ( v.r !== undefined ) {
15655
15656                 if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
15657
15658                         gl.uniform3f( this.addr, v.r, v.g, v.b );
15659
15660                         cache[ 0 ] = v.r;
15661                         cache[ 1 ] = v.g;
15662                         cache[ 2 ] = v.b;
15663
15664                 }
15665
15666         } else {
15667
15668                 if ( arraysEqual( cache, v ) ) return;
15669
15670                 gl.uniform3fv( this.addr, v );
15671
15672                 copyArray( cache, v );
15673
15674         }
15675
15676 }
15677
15678 function setValueV4f( gl, v ) {
15679
15680         const cache = this.cache;
15681
15682         if ( v.x !== undefined ) {
15683
15684                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
15685
15686                         gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
15687
15688                         cache[ 0 ] = v.x;
15689                         cache[ 1 ] = v.y;
15690                         cache[ 2 ] = v.z;
15691                         cache[ 3 ] = v.w;
15692
15693                 }
15694
15695         } else {
15696
15697                 if ( arraysEqual( cache, v ) ) return;
15698
15699                 gl.uniform4fv( this.addr, v );
15700
15701                 copyArray( cache, v );
15702
15703         }
15704
15705 }
15706
15707 // Single matrix (from flat array or MatrixN)
15708
15709 function setValueM2( gl, v ) {
15710
15711         const cache = this.cache;
15712         const elements = v.elements;
15713
15714         if ( elements === undefined ) {
15715
15716                 if ( arraysEqual( cache, v ) ) return;
15717
15718                 gl.uniformMatrix2fv( this.addr, false, v );
15719
15720                 copyArray( cache, v );
15721
15722         } else {
15723
15724                 if ( arraysEqual( cache, elements ) ) return;
15725
15726                 mat2array.set( elements );
15727
15728                 gl.uniformMatrix2fv( this.addr, false, mat2array );
15729
15730                 copyArray( cache, elements );
15731
15732         }
15733
15734 }
15735
15736 function setValueM3( gl, v ) {
15737
15738         const cache = this.cache;
15739         const elements = v.elements;
15740
15741         if ( elements === undefined ) {
15742
15743                 if ( arraysEqual( cache, v ) ) return;
15744
15745                 gl.uniformMatrix3fv( this.addr, false, v );
15746
15747                 copyArray( cache, v );
15748
15749         } else {
15750
15751                 if ( arraysEqual( cache, elements ) ) return;
15752
15753                 mat3array.set( elements );
15754
15755                 gl.uniformMatrix3fv( this.addr, false, mat3array );
15756
15757                 copyArray( cache, elements );
15758
15759         }
15760
15761 }
15762
15763 function setValueM4( gl, v ) {
15764
15765         const cache = this.cache;
15766         const elements = v.elements;
15767
15768         if ( elements === undefined ) {
15769
15770                 if ( arraysEqual( cache, v ) ) return;
15771
15772                 gl.uniformMatrix4fv( this.addr, false, v );
15773
15774                 copyArray( cache, v );
15775
15776         } else {
15777
15778                 if ( arraysEqual( cache, elements ) ) return;
15779
15780                 mat4array.set( elements );
15781
15782                 gl.uniformMatrix4fv( this.addr, false, mat4array );
15783
15784                 copyArray( cache, elements );
15785
15786         }
15787
15788 }
15789
15790 // Single texture (2D / Cube)
15791
15792 function setValueT1( gl, v, textures ) {
15793
15794         const cache = this.cache;
15795         const unit = textures.allocateTextureUnit();
15796
15797         if ( cache[ 0 ] !== unit ) {
15798
15799                 gl.uniform1i( this.addr, unit );
15800                 cache[ 0 ] = unit;
15801
15802         }
15803
15804         textures.safeSetTexture2D( v || emptyTexture, unit );
15805
15806 }
15807
15808 function setValueT2DArray1( gl, v, textures ) {
15809
15810         const cache = this.cache;
15811         const unit = textures.allocateTextureUnit();
15812
15813         if ( cache[ 0 ] !== unit ) {
15814
15815                 gl.uniform1i( this.addr, unit );
15816                 cache[ 0 ] = unit;
15817
15818         }
15819
15820         textures.setTexture2DArray( v || emptyTexture2dArray, unit );
15821
15822 }
15823
15824 function setValueT3D1( gl, v, textures ) {
15825
15826         const cache = this.cache;
15827         const unit = textures.allocateTextureUnit();
15828
15829         if ( cache[ 0 ] !== unit ) {
15830
15831                 gl.uniform1i( this.addr, unit );
15832                 cache[ 0 ] = unit;
15833
15834         }
15835
15836         textures.setTexture3D( v || emptyTexture3d, unit );
15837
15838 }
15839
15840 function setValueT6( gl, v, textures ) {
15841
15842         const cache = this.cache;
15843         const unit = textures.allocateTextureUnit();
15844
15845         if ( cache[ 0 ] !== unit ) {
15846
15847                 gl.uniform1i( this.addr, unit );
15848                 cache[ 0 ] = unit;
15849
15850         }
15851
15852         textures.safeSetTextureCube( v || emptyCubeTexture, unit );
15853
15854 }
15855
15856 // Integer / Boolean vectors or arrays thereof (always flat arrays)
15857
15858 function setValueV1i( gl, v ) {
15859
15860         const cache = this.cache;
15861
15862         if ( cache[ 0 ] === v ) return;
15863
15864         gl.uniform1i( this.addr, v );
15865
15866         cache[ 0 ] = v;
15867
15868 }
15869
15870 function setValueV2i( gl, v ) {
15871
15872         const cache = this.cache;
15873
15874         if ( arraysEqual( cache, v ) ) return;
15875
15876         gl.uniform2iv( this.addr, v );
15877
15878         copyArray( cache, v );
15879
15880 }
15881
15882 function setValueV3i( gl, v ) {
15883
15884         const cache = this.cache;
15885
15886         if ( arraysEqual( cache, v ) ) return;
15887
15888         gl.uniform3iv( this.addr, v );
15889
15890         copyArray( cache, v );
15891
15892 }
15893
15894 function setValueV4i( gl, v ) {
15895
15896         const cache = this.cache;
15897
15898         if ( arraysEqual( cache, v ) ) return;
15899
15900         gl.uniform4iv( this.addr, v );
15901
15902         copyArray( cache, v );
15903
15904 }
15905
15906 // uint
15907
15908 function setValueV1ui( gl, v ) {
15909
15910         const cache = this.cache;
15911
15912         if ( cache[ 0 ] === v ) return;
15913
15914         gl.uniform1ui( this.addr, v );
15915
15916         cache[ 0 ] = v;
15917
15918 }
15919
15920 // Helper to pick the right setter for the singular case
15921
15922 function getSingularSetter( type ) {
15923
15924         switch ( type ) {
15925
15926                 case 0x1406: return setValueV1f; // FLOAT
15927                 case 0x8b50: return setValueV2f; // _VEC2
15928                 case 0x8b51: return setValueV3f; // _VEC3
15929                 case 0x8b52: return setValueV4f; // _VEC4
15930
15931                 case 0x8b5a: return setValueM2; // _MAT2
15932                 case 0x8b5b: return setValueM3; // _MAT3
15933                 case 0x8b5c: return setValueM4; // _MAT4
15934
15935                 case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
15936                 case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
15937                 case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
15938                 case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
15939
15940                 case 0x1405: return setValueV1ui; // UINT
15941
15942                 case 0x8b5e: // SAMPLER_2D
15943                 case 0x8d66: // SAMPLER_EXTERNAL_OES
15944                 case 0x8dca: // INT_SAMPLER_2D
15945                 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
15946                 case 0x8b62: // SAMPLER_2D_SHADOW
15947                         return setValueT1;
15948
15949                 case 0x8b5f: // SAMPLER_3D
15950                 case 0x8dcb: // INT_SAMPLER_3D
15951                 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
15952                         return setValueT3D1;
15953
15954                 case 0x8b60: // SAMPLER_CUBE
15955                 case 0x8dcc: // INT_SAMPLER_CUBE
15956                 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
15957                 case 0x8dc5: // SAMPLER_CUBE_SHADOW
15958                         return setValueT6;
15959
15960                 case 0x8dc1: // SAMPLER_2D_ARRAY
15961                 case 0x8dcf: // INT_SAMPLER_2D_ARRAY
15962                 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
15963                 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
15964                         return setValueT2DArray1;
15965
15966         }
15967
15968 }
15969
15970 // Array of scalars
15971 function setValueV1fArray( gl, v ) {
15972
15973         gl.uniform1fv( this.addr, v );
15974
15975 }
15976
15977 // Integer / Boolean vectors or arrays thereof (always flat arrays)
15978 function setValueV1iArray( gl, v ) {
15979
15980         gl.uniform1iv( this.addr, v );
15981
15982 }
15983
15984 function setValueV2iArray( gl, v ) {
15985
15986         gl.uniform2iv( this.addr, v );
15987
15988 }
15989
15990 function setValueV3iArray( gl, v ) {
15991
15992         gl.uniform3iv( this.addr, v );
15993
15994 }
15995
15996 function setValueV4iArray( gl, v ) {
15997
15998         gl.uniform4iv( this.addr, v );
15999
16000 }
16001
16002
16003 // Array of vectors (flat or from THREE classes)
16004
16005 function setValueV2fArray( gl, v ) {
16006
16007         const data = flatten( v, this.size, 2 );
16008
16009         gl.uniform2fv( this.addr, data );
16010
16011 }
16012
16013 function setValueV3fArray( gl, v ) {
16014
16015         const data = flatten( v, this.size, 3 );
16016
16017         gl.uniform3fv( this.addr, data );
16018
16019 }
16020
16021 function setValueV4fArray( gl, v ) {
16022
16023         const data = flatten( v, this.size, 4 );
16024
16025         gl.uniform4fv( this.addr, data );
16026
16027 }
16028
16029 // Array of matrices (flat or from THREE clases)
16030
16031 function setValueM2Array( gl, v ) {
16032
16033         const data = flatten( v, this.size, 4 );
16034
16035         gl.uniformMatrix2fv( this.addr, false, data );
16036
16037 }
16038
16039 function setValueM3Array( gl, v ) {
16040
16041         const data = flatten( v, this.size, 9 );
16042
16043         gl.uniformMatrix3fv( this.addr, false, data );
16044
16045 }
16046
16047 function setValueM4Array( gl, v ) {
16048
16049         const data = flatten( v, this.size, 16 );
16050
16051         gl.uniformMatrix4fv( this.addr, false, data );
16052
16053 }
16054
16055 // Array of textures (2D / Cube)
16056
16057 function setValueT1Array( gl, v, textures ) {
16058
16059         const n = v.length;
16060
16061         const units = allocTexUnits( textures, n );
16062
16063         gl.uniform1iv( this.addr, units );
16064
16065         for ( let i = 0; i !== n; ++ i ) {
16066
16067                 textures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );
16068
16069         }
16070
16071 }
16072
16073 function setValueT6Array( gl, v, textures ) {
16074
16075         const n = v.length;
16076
16077         const units = allocTexUnits( textures, n );
16078
16079         gl.uniform1iv( this.addr, units );
16080
16081         for ( let i = 0; i !== n; ++ i ) {
16082
16083                 textures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
16084
16085         }
16086
16087 }
16088
16089 // Helper to pick the right setter for a pure (bottom-level) array
16090
16091 function getPureArraySetter( type ) {
16092
16093         switch ( type ) {
16094
16095                 case 0x1406: return setValueV1fArray; // FLOAT
16096                 case 0x8b50: return setValueV2fArray; // _VEC2
16097                 case 0x8b51: return setValueV3fArray; // _VEC3
16098                 case 0x8b52: return setValueV4fArray; // _VEC4
16099
16100                 case 0x8b5a: return setValueM2Array; // _MAT2
16101                 case 0x8b5b: return setValueM3Array; // _MAT3
16102                 case 0x8b5c: return setValueM4Array; // _MAT4
16103
16104                 case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
16105                 case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
16106                 case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
16107                 case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
16108
16109                 case 0x8b5e: // SAMPLER_2D
16110                 case 0x8d66: // SAMPLER_EXTERNAL_OES
16111                 case 0x8dca: // INT_SAMPLER_2D
16112                 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
16113                 case 0x8b62: // SAMPLER_2D_SHADOW
16114                         return setValueT1Array;
16115
16116                 case 0x8b60: // SAMPLER_CUBE
16117                 case 0x8dcc: // INT_SAMPLER_CUBE
16118                 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
16119                 case 0x8dc5: // SAMPLER_CUBE_SHADOW
16120                         return setValueT6Array;
16121
16122         }
16123
16124 }
16125
16126 // --- Uniform Classes ---
16127
16128 function SingleUniform( id, activeInfo, addr ) {
16129
16130         this.id = id;
16131         this.addr = addr;
16132         this.cache = [];
16133         this.setValue = getSingularSetter( activeInfo.type );
16134
16135         // this.path = activeInfo.name; // DEBUG
16136
16137 }
16138
16139 function PureArrayUniform( id, activeInfo, addr ) {
16140
16141         this.id = id;
16142         this.addr = addr;
16143         this.cache = [];
16144         this.size = activeInfo.size;
16145         this.setValue = getPureArraySetter( activeInfo.type );
16146
16147         // this.path = activeInfo.name; // DEBUG
16148
16149 }
16150
16151 PureArrayUniform.prototype.updateCache = function ( data ) {
16152
16153         const cache = this.cache;
16154
16155         if ( data instanceof Float32Array && cache.length !== data.length ) {
16156
16157                 this.cache = new Float32Array( data.length );
16158
16159         }
16160
16161         copyArray( cache, data );
16162
16163 };
16164
16165 function StructuredUniform( id ) {
16166
16167         this.id = id;
16168
16169         this.seq = [];
16170         this.map = {};
16171
16172 }
16173
16174 StructuredUniform.prototype.setValue = function ( gl, value, textures ) {
16175
16176         const seq = this.seq;
16177
16178         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
16179
16180                 const u = seq[ i ];
16181                 u.setValue( gl, value[ u.id ], textures );
16182
16183         }
16184
16185 };
16186
16187 // --- Top-level ---
16188
16189 // Parser - builds up the property tree from the path strings
16190
16191 const RePathPart = /(\w+)(\])?(\[|\.)?/g;
16192
16193 // extracts
16194 //      - the identifier (member name or array index)
16195 //  - followed by an optional right bracket (found when array index)
16196 //  - followed by an optional left bracket or dot (type of subscript)
16197 //
16198 // Note: These portions can be read in a non-overlapping fashion and
16199 // allow straightforward parsing of the hierarchy that WebGL encodes
16200 // in the uniform names.
16201
16202 function addUniform( container, uniformObject ) {
16203
16204         container.seq.push( uniformObject );
16205         container.map[ uniformObject.id ] = uniformObject;
16206
16207 }
16208
16209 function parseUniform( activeInfo, addr, container ) {
16210
16211         const path = activeInfo.name,
16212                 pathLength = path.length;
16213
16214         // reset RegExp object, because of the early exit of a previous run
16215         RePathPart.lastIndex = 0;
16216
16217         while ( true ) {
16218
16219                 const match = RePathPart.exec( path ),
16220                         matchEnd = RePathPart.lastIndex;
16221
16222                 let id = match[ 1 ];
16223                 const idIsIndex = match[ 2 ] === ']',
16224                         subscript = match[ 3 ];
16225
16226                 if ( idIsIndex ) id = id | 0; // convert to integer
16227
16228                 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
16229
16230                         // bare name or "pure" bottom-level array "[0]" suffix
16231
16232                         addUniform( container, subscript === undefined ?
16233                                 new SingleUniform( id, activeInfo, addr ) :
16234                                 new PureArrayUniform( id, activeInfo, addr ) );
16235
16236                         break;
16237
16238                 } else {
16239
16240                         // step into inner node / create it in case it doesn't exist
16241
16242                         const map = container.map;
16243                         let next = map[ id ];
16244
16245                         if ( next === undefined ) {
16246
16247                                 next = new StructuredUniform( id );
16248                                 addUniform( container, next );
16249
16250                         }
16251
16252                         container = next;
16253
16254                 }
16255
16256         }
16257
16258 }
16259
16260 // Root Container
16261
16262 function WebGLUniforms( gl, program ) {
16263
16264         this.seq = [];
16265         this.map = {};
16266
16267         const n = gl.getProgramParameter( program, 35718 );
16268
16269         for ( let i = 0; i < n; ++ i ) {
16270
16271                 const info = gl.getActiveUniform( program, i ),
16272                         addr = gl.getUniformLocation( program, info.name );
16273
16274                 parseUniform( info, addr, this );
16275
16276         }
16277
16278 }
16279
16280 WebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {
16281
16282         const u = this.map[ name ];
16283
16284         if ( u !== undefined ) u.setValue( gl, value, textures );
16285
16286 };
16287
16288 WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
16289
16290         const v = object[ name ];
16291
16292         if ( v !== undefined ) this.setValue( gl, name, v );
16293
16294 };
16295
16296
16297 // Static interface
16298
16299 WebGLUniforms.upload = function ( gl, seq, values, textures ) {
16300
16301         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
16302
16303                 const u = seq[ i ],
16304                         v = values[ u.id ];
16305
16306                 if ( v.needsUpdate !== false ) {
16307
16308                         // note: always updating when .needsUpdate is undefined
16309                         u.setValue( gl, v.value, textures );
16310
16311                 }
16312
16313         }
16314
16315 };
16316
16317 WebGLUniforms.seqWithValue = function ( seq, values ) {
16318
16319         const r = [];
16320
16321         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
16322
16323                 const u = seq[ i ];
16324                 if ( u.id in values ) r.push( u );
16325
16326         }
16327
16328         return r;
16329
16330 };
16331
16332 function WebGLShader( gl, type, string ) {
16333
16334         const shader = gl.createShader( type );
16335
16336         gl.shaderSource( shader, string );
16337         gl.compileShader( shader );
16338
16339         return shader;
16340
16341 }
16342
16343 let programIdCount = 0;
16344
16345 function addLineNumbers( string ) {
16346
16347         const lines = string.split( '\n' );
16348
16349         for ( let i = 0; i < lines.length; i ++ ) {
16350
16351                 lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
16352
16353         }
16354
16355         return lines.join( '\n' );
16356
16357 }
16358
16359 function getEncodingComponents( encoding ) {
16360
16361         switch ( encoding ) {
16362
16363                 case LinearEncoding:
16364                         return [ 'Linear', '( value )' ];
16365                 case sRGBEncoding:
16366                         return [ 'sRGB', '( value )' ];
16367                 case RGBEEncoding:
16368                         return [ 'RGBE', '( value )' ];
16369                 case RGBM7Encoding:
16370                         return [ 'RGBM', '( value, 7.0 )' ];
16371                 case RGBM16Encoding:
16372                         return [ 'RGBM', '( value, 16.0 )' ];
16373                 case RGBDEncoding:
16374                         return [ 'RGBD', '( value, 256.0 )' ];
16375                 case GammaEncoding:
16376                         return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
16377                 case LogLuvEncoding:
16378                         return [ 'LogLuv', '( value )' ];
16379                 default:
16380                         console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding );
16381                         return [ 'Linear', '( value )' ];
16382
16383         }
16384
16385 }
16386
16387 function getShaderErrors( gl, shader, type ) {
16388
16389         const status = gl.getShaderParameter( shader, 35713 );
16390         const log = gl.getShaderInfoLog( shader ).trim();
16391
16392         if ( status && log === '' ) return '';
16393
16394         // --enable-privileged-webgl-extension
16395         // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
16396
16397         const source = gl.getShaderSource( shader );
16398
16399         return 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\n' + log + addLineNumbers( source );
16400
16401 }
16402
16403 function getTexelDecodingFunction( functionName, encoding ) {
16404
16405         const components = getEncodingComponents( encoding );
16406         return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
16407
16408 }
16409
16410 function getTexelEncodingFunction( functionName, encoding ) {
16411
16412         const components = getEncodingComponents( encoding );
16413         return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
16414
16415 }
16416
16417 function getToneMappingFunction( functionName, toneMapping ) {
16418
16419         let toneMappingName;
16420
16421         switch ( toneMapping ) {
16422
16423                 case LinearToneMapping:
16424                         toneMappingName = 'Linear';
16425                         break;
16426
16427                 case ReinhardToneMapping:
16428                         toneMappingName = 'Reinhard';
16429                         break;
16430
16431                 case CineonToneMapping:
16432                         toneMappingName = 'OptimizedCineon';
16433                         break;
16434
16435                 case ACESFilmicToneMapping:
16436                         toneMappingName = 'ACESFilmic';
16437                         break;
16438
16439                 case CustomToneMapping:
16440                         toneMappingName = 'Custom';
16441                         break;
16442
16443                 default:
16444                         console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping );
16445                         toneMappingName = 'Linear';
16446
16447         }
16448
16449         return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
16450
16451 }
16452
16453 function generateExtensions( parameters ) {
16454
16455         const chunks = [
16456                 ( parameters.extensionDerivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '',
16457                 ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',
16458                 ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '',
16459                 ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''
16460         ];
16461
16462         return chunks.filter( filterEmptyLine ).join( '\n' );
16463
16464 }
16465
16466 function generateDefines( defines ) {
16467
16468         const chunks = [];
16469
16470         for ( const name in defines ) {
16471
16472                 const value = defines[ name ];
16473
16474                 if ( value === false ) continue;
16475
16476                 chunks.push( '#define ' + name + ' ' + value );
16477
16478         }
16479
16480         return chunks.join( '\n' );
16481
16482 }
16483
16484 function fetchAttributeLocations( gl, program ) {
16485
16486         const attributes = {};
16487
16488         const n = gl.getProgramParameter( program, 35721 );
16489
16490         for ( let i = 0; i < n; i ++ ) {
16491
16492                 const info = gl.getActiveAttrib( program, i );
16493                 const name = info.name;
16494
16495                 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
16496
16497                 attributes[ name ] = gl.getAttribLocation( program, name );
16498
16499         }
16500
16501         return attributes;
16502
16503 }
16504
16505 function filterEmptyLine( string ) {
16506
16507         return string !== '';
16508
16509 }
16510
16511 function replaceLightNums( string, parameters ) {
16512
16513         return string
16514                 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
16515                 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
16516                 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
16517                 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
16518                 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
16519                 .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
16520                 .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
16521                 .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
16522
16523 }
16524
16525 function replaceClippingPlaneNums( string, parameters ) {
16526
16527         return string
16528                 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
16529                 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
16530
16531 }
16532
16533 // Resolve Includes
16534
16535 const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
16536
16537 function resolveIncludes( string ) {
16538
16539         return string.replace( includePattern, includeReplacer );
16540
16541 }
16542
16543 function includeReplacer( match, include ) {
16544
16545         const string = ShaderChunk[ include ];
16546
16547         if ( string === undefined ) {
16548
16549                 throw new Error( 'Can not resolve #include <' + include + '>' );
16550
16551         }
16552
16553         return resolveIncludes( string );
16554
16555 }
16556
16557 // Unroll Loops
16558
16559 const deprecatedUnrollLoopPattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
16560 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;
16561
16562 function unrollLoops( string ) {
16563
16564         return string
16565                 .replace( unrollLoopPattern, loopReplacer )
16566                 .replace( deprecatedUnrollLoopPattern, deprecatedLoopReplacer );
16567
16568 }
16569
16570 function deprecatedLoopReplacer( match, start, end, snippet ) {
16571
16572         console.warn( 'WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.' );
16573         return loopReplacer( match, start, end, snippet );
16574
16575 }
16576
16577 function loopReplacer( match, start, end, snippet ) {
16578
16579         let string = '';
16580
16581         for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) {
16582
16583                 string += snippet
16584                         .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' )
16585                         .replace( /UNROLLED_LOOP_INDEX/g, i );
16586
16587         }
16588
16589         return string;
16590
16591 }
16592
16593 //
16594
16595 function generatePrecision( parameters ) {
16596
16597         let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;';
16598
16599         if ( parameters.precision === 'highp' ) {
16600
16601                 precisionstring += '\n#define HIGH_PRECISION';
16602
16603         } else if ( parameters.precision === 'mediump' ) {
16604
16605                 precisionstring += '\n#define MEDIUM_PRECISION';
16606
16607         } else if ( parameters.precision === 'lowp' ) {
16608
16609                 precisionstring += '\n#define LOW_PRECISION';
16610
16611         }
16612
16613         return precisionstring;
16614
16615 }
16616
16617 function generateShadowMapTypeDefine( parameters ) {
16618
16619         let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
16620
16621         if ( parameters.shadowMapType === PCFShadowMap ) {
16622
16623                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
16624
16625         } else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
16626
16627                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
16628
16629         } else if ( parameters.shadowMapType === VSMShadowMap ) {
16630
16631                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
16632
16633         }
16634
16635         return shadowMapTypeDefine;
16636
16637 }
16638
16639 function generateEnvMapTypeDefine( parameters ) {
16640
16641         let envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
16642
16643         if ( parameters.envMap ) {
16644
16645                 switch ( parameters.envMapMode ) {
16646
16647                         case CubeReflectionMapping:
16648                         case CubeRefractionMapping:
16649                                 envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
16650                                 break;
16651
16652                         case CubeUVReflectionMapping:
16653                         case CubeUVRefractionMapping:
16654                                 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
16655                                 break;
16656
16657                 }
16658
16659         }
16660
16661         return envMapTypeDefine;
16662
16663 }
16664
16665 function generateEnvMapModeDefine( parameters ) {
16666
16667         let envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
16668
16669         if ( parameters.envMap ) {
16670
16671                 switch ( parameters.envMapMode ) {
16672
16673                         case CubeRefractionMapping:
16674                         case CubeUVRefractionMapping:
16675
16676                                 envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
16677                                 break;
16678
16679                 }
16680
16681         }
16682
16683         return envMapModeDefine;
16684
16685 }
16686
16687 function generateEnvMapBlendingDefine( parameters ) {
16688
16689         let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
16690
16691         if ( parameters.envMap ) {
16692
16693                 switch ( parameters.combine ) {
16694
16695                         case MultiplyOperation:
16696                                 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
16697                                 break;
16698
16699                         case MixOperation:
16700                                 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
16701                                 break;
16702
16703                         case AddOperation:
16704                                 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
16705                                 break;
16706
16707                 }
16708
16709         }
16710
16711         return envMapBlendingDefine;
16712
16713 }
16714
16715 function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
16716
16717         const gl = renderer.getContext();
16718
16719         const defines = parameters.defines;
16720
16721         let vertexShader = parameters.vertexShader;
16722         let fragmentShader = parameters.fragmentShader;
16723
16724         const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
16725         const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
16726         const envMapModeDefine = generateEnvMapModeDefine( parameters );
16727         const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
16728
16729
16730         const gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
16731
16732         const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );
16733
16734         const customDefines = generateDefines( defines );
16735
16736         const program = gl.createProgram();
16737
16738         let prefixVertex, prefixFragment;
16739         let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
16740
16741         if ( parameters.isRawShaderMaterial ) {
16742
16743                 prefixVertex = [
16744
16745                         customDefines
16746
16747                 ].filter( filterEmptyLine ).join( '\n' );
16748
16749                 if ( prefixVertex.length > 0 ) {
16750
16751                         prefixVertex += '\n';
16752
16753                 }
16754
16755                 prefixFragment = [
16756
16757                         customExtensions,
16758                         customDefines
16759
16760                 ].filter( filterEmptyLine ).join( '\n' );
16761
16762                 if ( prefixFragment.length > 0 ) {
16763
16764                         prefixFragment += '\n';
16765
16766                 }
16767
16768         } else {
16769
16770                 prefixVertex = [
16771
16772                         generatePrecision( parameters ),
16773
16774                         '#define SHADER_NAME ' + parameters.shaderName,
16775
16776                         customDefines,
16777
16778                         parameters.instancing ? '#define USE_INSTANCING' : '',
16779                         parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
16780
16781                         parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
16782
16783                         '#define GAMMA_FACTOR ' + gammaFactorDefine,
16784
16785                         '#define MAX_BONES ' + parameters.maxBones,
16786                         ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
16787                         ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
16788
16789                         parameters.map ? '#define USE_MAP' : '',
16790                         parameters.envMap ? '#define USE_ENVMAP' : '',
16791                         parameters.envMap ? '#define ' + envMapModeDefine : '',
16792                         parameters.lightMap ? '#define USE_LIGHTMAP' : '',
16793                         parameters.aoMap ? '#define USE_AOMAP' : '',
16794                         parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
16795                         parameters.bumpMap ? '#define USE_BUMPMAP' : '',
16796                         parameters.normalMap ? '#define USE_NORMALMAP' : '',
16797                         ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
16798                         ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
16799
16800                         parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
16801                         parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
16802                         parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
16803                         parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
16804                         parameters.specularMap ? '#define USE_SPECULARMAP' : '',
16805                         parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
16806                         parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
16807                         parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
16808                         parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
16809
16810                         parameters.vertexTangents ? '#define USE_TANGENT' : '',
16811                         parameters.vertexColors ? '#define USE_COLOR' : '',
16812                         parameters.vertexUvs ? '#define USE_UV' : '',
16813                         parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
16814
16815                         parameters.flatShading ? '#define FLAT_SHADED' : '',
16816
16817                         parameters.skinning ? '#define USE_SKINNING' : '',
16818                         parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
16819
16820                         parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
16821                         parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
16822                         parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
16823                         parameters.flipSided ? '#define FLIP_SIDED' : '',
16824
16825                         parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
16826                         parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
16827
16828                         parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
16829
16830                         parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
16831                         ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
16832
16833                         'uniform mat4 modelMatrix;',
16834                         'uniform mat4 modelViewMatrix;',
16835                         'uniform mat4 projectionMatrix;',
16836                         'uniform mat4 viewMatrix;',
16837                         'uniform mat3 normalMatrix;',
16838                         'uniform vec3 cameraPosition;',
16839                         'uniform bool isOrthographic;',
16840
16841                         '#ifdef USE_INSTANCING',
16842
16843                         '       attribute mat4 instanceMatrix;',
16844
16845                         '#endif',
16846
16847                         '#ifdef USE_INSTANCING_COLOR',
16848
16849                         '       attribute vec3 instanceColor;',
16850
16851                         '#endif',
16852
16853                         'attribute vec3 position;',
16854                         'attribute vec3 normal;',
16855                         'attribute vec2 uv;',
16856
16857                         '#ifdef USE_TANGENT',
16858
16859                         '       attribute vec4 tangent;',
16860
16861                         '#endif',
16862
16863                         '#ifdef USE_COLOR',
16864
16865                         '       attribute vec3 color;',
16866
16867                         '#endif',
16868
16869                         '#ifdef USE_MORPHTARGETS',
16870
16871                         '       attribute vec3 morphTarget0;',
16872                         '       attribute vec3 morphTarget1;',
16873                         '       attribute vec3 morphTarget2;',
16874                         '       attribute vec3 morphTarget3;',
16875
16876                         '       #ifdef USE_MORPHNORMALS',
16877
16878                         '               attribute vec3 morphNormal0;',
16879                         '               attribute vec3 morphNormal1;',
16880                         '               attribute vec3 morphNormal2;',
16881                         '               attribute vec3 morphNormal3;',
16882
16883                         '       #else',
16884
16885                         '               attribute vec3 morphTarget4;',
16886                         '               attribute vec3 morphTarget5;',
16887                         '               attribute vec3 morphTarget6;',
16888                         '               attribute vec3 morphTarget7;',
16889
16890                         '       #endif',
16891
16892                         '#endif',
16893
16894                         '#ifdef USE_SKINNING',
16895
16896                         '       attribute vec4 skinIndex;',
16897                         '       attribute vec4 skinWeight;',
16898
16899                         '#endif',
16900
16901                         '\n'
16902
16903                 ].filter( filterEmptyLine ).join( '\n' );
16904
16905                 prefixFragment = [
16906
16907                         customExtensions,
16908
16909                         generatePrecision( parameters ),
16910
16911                         '#define SHADER_NAME ' + parameters.shaderName,
16912
16913                         customDefines,
16914
16915                         parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer
16916
16917                         '#define GAMMA_FACTOR ' + gammaFactorDefine,
16918
16919                         ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
16920                         ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
16921
16922                         parameters.map ? '#define USE_MAP' : '',
16923                         parameters.matcap ? '#define USE_MATCAP' : '',
16924                         parameters.envMap ? '#define USE_ENVMAP' : '',
16925                         parameters.envMap ? '#define ' + envMapTypeDefine : '',
16926                         parameters.envMap ? '#define ' + envMapModeDefine : '',
16927                         parameters.envMap ? '#define ' + envMapBlendingDefine : '',
16928                         parameters.lightMap ? '#define USE_LIGHTMAP' : '',
16929                         parameters.aoMap ? '#define USE_AOMAP' : '',
16930                         parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
16931                         parameters.bumpMap ? '#define USE_BUMPMAP' : '',
16932                         parameters.normalMap ? '#define USE_NORMALMAP' : '',
16933                         ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
16934                         ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
16935                         parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
16936                         parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
16937                         parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
16938                         parameters.specularMap ? '#define USE_SPECULARMAP' : '',
16939                         parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
16940                         parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
16941                         parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
16942
16943                         parameters.sheen ? '#define USE_SHEEN' : '',
16944                         parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
16945
16946                         parameters.vertexTangents ? '#define USE_TANGENT' : '',
16947                         parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
16948                         parameters.vertexUvs ? '#define USE_UV' : '',
16949                         parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
16950
16951                         parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
16952
16953                         parameters.flatShading ? '#define FLAT_SHADED' : '',
16954
16955                         parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
16956                         parameters.flipSided ? '#define FLIP_SIDED' : '',
16957
16958                         parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
16959                         parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
16960
16961                         parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
16962
16963                         parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
16964
16965                         parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
16966                         ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
16967
16968                         ( ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ) ? '#define TEXTURE_LOD_EXT' : '',
16969
16970                         'uniform mat4 viewMatrix;',
16971                         'uniform vec3 cameraPosition;',
16972                         'uniform bool isOrthographic;',
16973
16974                         ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
16975                         ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
16976                         ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
16977
16978                         parameters.dithering ? '#define DITHERING' : '',
16979
16980                         ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below
16981                         parameters.map ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
16982                         parameters.matcap ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
16983                         parameters.envMap ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
16984                         parameters.emissiveMap ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
16985                         parameters.lightMap ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',
16986                         getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ),
16987
16988                         parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
16989
16990                         '\n'
16991
16992                 ].filter( filterEmptyLine ).join( '\n' );
16993
16994         }
16995
16996         vertexShader = resolveIncludes( vertexShader );
16997         vertexShader = replaceLightNums( vertexShader, parameters );
16998         vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
16999
17000         fragmentShader = resolveIncludes( fragmentShader );
17001         fragmentShader = replaceLightNums( fragmentShader, parameters );
17002         fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
17003
17004         vertexShader = unrollLoops( vertexShader );
17005         fragmentShader = unrollLoops( fragmentShader );
17006
17007         if ( parameters.isWebGL2 && parameters.isRawShaderMaterial !== true ) {
17008
17009                 // GLSL 3.0 conversion for built-in materials and ShaderMaterial
17010
17011                 versionString = '#version 300 es\n';
17012
17013                 prefixVertex = [
17014                         '#define attribute in',
17015                         '#define varying out',
17016                         '#define texture2D texture'
17017                 ].join( '\n' ) + '\n' + prefixVertex;
17018
17019                 prefixFragment = [
17020                         '#define varying in',
17021                         ( parameters.glslVersion === GLSL3 ) ? '' : 'out highp vec4 pc_fragColor;',
17022                         ( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor',
17023                         '#define gl_FragDepthEXT gl_FragDepth',
17024                         '#define texture2D texture',
17025                         '#define textureCube texture',
17026                         '#define texture2DProj textureProj',
17027                         '#define texture2DLodEXT textureLod',
17028                         '#define texture2DProjLodEXT textureProjLod',
17029                         '#define textureCubeLodEXT textureLod',
17030                         '#define texture2DGradEXT textureGrad',
17031                         '#define texture2DProjGradEXT textureProjGrad',
17032                         '#define textureCubeGradEXT textureGrad'
17033                 ].join( '\n' ) + '\n' + prefixFragment;
17034
17035         }
17036
17037         const vertexGlsl = versionString + prefixVertex + vertexShader;
17038         const fragmentGlsl = versionString + prefixFragment + fragmentShader;
17039
17040         // console.log( '*VERTEX*', vertexGlsl );
17041         // console.log( '*FRAGMENT*', fragmentGlsl );
17042
17043         const glVertexShader = WebGLShader( gl, 35633, vertexGlsl );
17044         const glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );
17045
17046         gl.attachShader( program, glVertexShader );
17047         gl.attachShader( program, glFragmentShader );
17048
17049         // Force a particular attribute to index 0.
17050
17051         if ( parameters.index0AttributeName !== undefined ) {
17052
17053                 gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
17054
17055         } else if ( parameters.morphTargets === true ) {
17056
17057                 // programs with morphTargets displace position out of attribute 0
17058                 gl.bindAttribLocation( program, 0, 'position' );
17059
17060         }
17061
17062         gl.linkProgram( program );
17063
17064         // check for link errors
17065         if ( renderer.debug.checkShaderErrors ) {
17066
17067                 const programLog = gl.getProgramInfoLog( program ).trim();
17068                 const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
17069                 const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
17070
17071                 let runnable = true;
17072                 let haveDiagnostics = true;
17073
17074                 if ( gl.getProgramParameter( program, 35714 ) === false ) {
17075
17076                         runnable = false;
17077
17078                         const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
17079                         const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
17080
17081                         console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), '35715', gl.getProgramParameter( program, 35715 ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );
17082
17083                 } else if ( programLog !== '' ) {
17084
17085                         console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
17086
17087                 } else if ( vertexLog === '' || fragmentLog === '' ) {
17088
17089                         haveDiagnostics = false;
17090
17091                 }
17092
17093                 if ( haveDiagnostics ) {
17094
17095                         this.diagnostics = {
17096
17097                                 runnable: runnable,
17098
17099                                 programLog: programLog,
17100
17101                                 vertexShader: {
17102
17103                                         log: vertexLog,
17104                                         prefix: prefixVertex
17105
17106                                 },
17107
17108                                 fragmentShader: {
17109
17110                                         log: fragmentLog,
17111                                         prefix: prefixFragment
17112
17113                                 }
17114
17115                         };
17116
17117                 }
17118
17119         }
17120
17121         // Clean up
17122
17123         // Crashes in iOS9 and iOS10. #18402
17124         // gl.detachShader( program, glVertexShader );
17125         // gl.detachShader( program, glFragmentShader );
17126
17127         gl.deleteShader( glVertexShader );
17128         gl.deleteShader( glFragmentShader );
17129
17130         // set up caching for uniform locations
17131
17132         let cachedUniforms;
17133
17134         this.getUniforms = function () {
17135
17136                 if ( cachedUniforms === undefined ) {
17137
17138                         cachedUniforms = new WebGLUniforms( gl, program );
17139
17140                 }
17141
17142                 return cachedUniforms;
17143
17144         };
17145
17146         // set up caching for attribute locations
17147
17148         let cachedAttributes;
17149
17150         this.getAttributes = function () {
17151
17152                 if ( cachedAttributes === undefined ) {
17153
17154                         cachedAttributes = fetchAttributeLocations( gl, program );
17155
17156                 }
17157
17158                 return cachedAttributes;
17159
17160         };
17161
17162         // free resource
17163
17164         this.destroy = function () {
17165
17166                 bindingStates.releaseStatesOfProgram( this );
17167
17168                 gl.deleteProgram( program );
17169                 this.program = undefined;
17170
17171         };
17172
17173         //
17174
17175         this.name = parameters.shaderName;
17176         this.id = programIdCount ++;
17177         this.cacheKey = cacheKey;
17178         this.usedTimes = 1;
17179         this.program = program;
17180         this.vertexShader = glVertexShader;
17181         this.fragmentShader = glFragmentShader;
17182
17183         return this;
17184
17185 }
17186
17187 function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingStates, clipping ) {
17188
17189         const programs = [];
17190
17191         const isWebGL2 = capabilities.isWebGL2;
17192         const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
17193         const floatVertexTextures = capabilities.floatVertexTextures;
17194         const maxVertexUniforms = capabilities.maxVertexUniforms;
17195         const vertexTextures = capabilities.vertexTextures;
17196
17197         let precision = capabilities.precision;
17198
17199         const shaderIDs = {
17200                 MeshDepthMaterial: 'depth',
17201                 MeshDistanceMaterial: 'distanceRGBA',
17202                 MeshNormalMaterial: 'normal',
17203                 MeshBasicMaterial: 'basic',
17204                 MeshLambertMaterial: 'lambert',
17205                 MeshPhongMaterial: 'phong',
17206                 MeshToonMaterial: 'toon',
17207                 MeshStandardMaterial: 'physical',
17208                 MeshPhysicalMaterial: 'physical',
17209                 MeshMatcapMaterial: 'matcap',
17210                 LineBasicMaterial: 'basic',
17211                 LineDashedMaterial: 'dashed',
17212                 PointsMaterial: 'points',
17213                 ShadowMaterial: 'shadow',
17214                 SpriteMaterial: 'sprite'
17215         };
17216
17217         const parameterNames = [
17218                 'precision', 'isWebGL2', 'supportsVertexTextures', 'outputEncoding', 'instancing', 'instancingColor',
17219                 'map', 'mapEncoding', 'matcap', 'matcapEncoding', 'envMap', 'envMapMode', 'envMapEncoding', 'envMapCubeUV',
17220                 'lightMap', 'lightMapEncoding', 'aoMap', 'emissiveMap', 'emissiveMapEncoding', 'bumpMap', 'normalMap', 'objectSpaceNormalMap', 'tangentSpaceNormalMap', 'clearcoatMap', 'clearcoatRoughnessMap', 'clearcoatNormalMap', 'displacementMap', 'specularMap',
17221                 'roughnessMap', 'metalnessMap', 'gradientMap',
17222                 'alphaMap', 'combine', 'vertexColors', 'vertexTangents', 'vertexUvs', 'uvsVertexOnly', 'fog', 'useFog', 'fogExp2',
17223                 'flatShading', 'sizeAttenuation', 'logarithmicDepthBuffer', 'skinning',
17224                 'maxBones', 'useVertexTexture', 'morphTargets', 'morphNormals',
17225                 'maxMorphTargets', 'maxMorphNormals', 'premultipliedAlpha',
17226                 'numDirLights', 'numPointLights', 'numSpotLights', 'numHemiLights', 'numRectAreaLights',
17227                 'numDirLightShadows', 'numPointLightShadows', 'numSpotLightShadows',
17228                 'shadowMapEnabled', 'shadowMapType', 'toneMapping', 'physicallyCorrectLights',
17229                 'alphaTest', 'doubleSided', 'flipSided', 'numClippingPlanes', 'numClipIntersection', 'depthPacking', 'dithering',
17230                 'sheen', 'transmissionMap'
17231         ];
17232
17233         function getMaxBones( object ) {
17234
17235                 const skeleton = object.skeleton;
17236                 const bones = skeleton.bones;
17237
17238                 if ( floatVertexTextures ) {
17239
17240                         return 1024;
17241
17242                 } else {
17243
17244                         // default for when object is not specified
17245                         // ( for example when prebuilding shader to be used with multiple objects )
17246                         //
17247                         //  - leave some extra space for other uniforms
17248                         //  - limit here is ANGLE's 254 max uniform vectors
17249                         //    (up to 54 should be safe)
17250
17251                         const nVertexUniforms = maxVertexUniforms;
17252                         const nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
17253
17254                         const maxBones = Math.min( nVertexMatrices, bones.length );
17255
17256                         if ( maxBones < bones.length ) {
17257
17258                                 console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
17259                                 return 0;
17260
17261                         }
17262
17263                         return maxBones;
17264
17265                 }
17266
17267         }
17268
17269         function getTextureEncodingFromMap( map ) {
17270
17271                 let encoding;
17272
17273                 if ( map && map.isTexture ) {
17274
17275                         encoding = map.encoding;
17276
17277                 } else if ( map && map.isWebGLRenderTarget ) {
17278
17279                         console.warn( 'THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.' );
17280                         encoding = map.texture.encoding;
17281
17282                 } else {
17283
17284                         encoding = LinearEncoding;
17285
17286                 }
17287
17288                 return encoding;
17289
17290         }
17291
17292         function getParameters( material, lights, shadows, scene, object ) {
17293
17294                 const fog = scene.fog;
17295                 const environment = material.isMeshStandardMaterial ? scene.environment : null;
17296
17297                 const envMap = cubemaps.get( material.envMap || environment );
17298
17299                 const shaderID = shaderIDs[ material.type ];
17300
17301                 // heuristics to create shader parameters according to lights in the scene
17302                 // (not to blow over maxLights budget)
17303
17304                 const maxBones = object.isSkinnedMesh ? getMaxBones( object ) : 0;
17305
17306                 if ( material.precision !== null ) {
17307
17308                         precision = capabilities.getMaxPrecision( material.precision );
17309
17310                         if ( precision !== material.precision ) {
17311
17312                                 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
17313
17314                         }
17315
17316                 }
17317
17318                 let vertexShader, fragmentShader;
17319
17320                 if ( shaderID ) {
17321
17322                         const shader = ShaderLib[ shaderID ];
17323
17324                         vertexShader = shader.vertexShader;
17325                         fragmentShader = shader.fragmentShader;
17326
17327                 } else {
17328
17329                         vertexShader = material.vertexShader;
17330                         fragmentShader = material.fragmentShader;
17331
17332                 }
17333
17334                 const currentRenderTarget = renderer.getRenderTarget();
17335
17336                 const parameters = {
17337
17338                         isWebGL2: isWebGL2,
17339
17340                         shaderID: shaderID,
17341                         shaderName: material.type,
17342
17343                         vertexShader: vertexShader,
17344                         fragmentShader: fragmentShader,
17345                         defines: material.defines,
17346
17347                         isRawShaderMaterial: material.isRawShaderMaterial === true,
17348                         glslVersion: material.glslVersion,
17349
17350                         precision: precision,
17351
17352                         instancing: object.isInstancedMesh === true,
17353                         instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
17354
17355                         supportsVertexTextures: vertexTextures,
17356                         outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,
17357                         map: !! material.map,
17358                         mapEncoding: getTextureEncodingFromMap( material.map ),
17359                         matcap: !! material.matcap,
17360                         matcapEncoding: getTextureEncodingFromMap( material.matcap ),
17361                         envMap: !! envMap,
17362                         envMapMode: envMap && envMap.mapping,
17363                         envMapEncoding: getTextureEncodingFromMap( envMap ),
17364                         envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),
17365                         lightMap: !! material.lightMap,
17366                         lightMapEncoding: getTextureEncodingFromMap( material.lightMap ),
17367                         aoMap: !! material.aoMap,
17368                         emissiveMap: !! material.emissiveMap,
17369                         emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),
17370                         bumpMap: !! material.bumpMap,
17371                         normalMap: !! material.normalMap,
17372                         objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
17373                         tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
17374                         clearcoatMap: !! material.clearcoatMap,
17375                         clearcoatRoughnessMap: !! material.clearcoatRoughnessMap,
17376                         clearcoatNormalMap: !! material.clearcoatNormalMap,
17377                         displacementMap: !! material.displacementMap,
17378                         roughnessMap: !! material.roughnessMap,
17379                         metalnessMap: !! material.metalnessMap,
17380                         specularMap: !! material.specularMap,
17381                         alphaMap: !! material.alphaMap,
17382
17383                         gradientMap: !! material.gradientMap,
17384
17385                         sheen: !! material.sheen,
17386
17387                         transmissionMap: !! material.transmissionMap,
17388
17389                         combine: material.combine,
17390
17391                         vertexTangents: ( material.normalMap && material.vertexTangents ),
17392                         vertexColors: material.vertexColors,
17393                         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,
17394                         uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.transmissionMap ) && !! material.displacementMap,
17395
17396                         fog: !! fog,
17397                         useFog: material.fog,
17398                         fogExp2: ( fog && fog.isFogExp2 ),
17399
17400                         flatShading: material.flatShading,
17401
17402                         sizeAttenuation: material.sizeAttenuation,
17403                         logarithmicDepthBuffer: logarithmicDepthBuffer,
17404
17405                         skinning: material.skinning && maxBones > 0,
17406                         maxBones: maxBones,
17407                         useVertexTexture: floatVertexTextures,
17408
17409                         morphTargets: material.morphTargets,
17410                         morphNormals: material.morphNormals,
17411                         maxMorphTargets: renderer.maxMorphTargets,
17412                         maxMorphNormals: renderer.maxMorphNormals,
17413
17414                         numDirLights: lights.directional.length,
17415                         numPointLights: lights.point.length,
17416                         numSpotLights: lights.spot.length,
17417                         numRectAreaLights: lights.rectArea.length,
17418                         numHemiLights: lights.hemi.length,
17419
17420                         numDirLightShadows: lights.directionalShadowMap.length,
17421                         numPointLightShadows: lights.pointShadowMap.length,
17422                         numSpotLightShadows: lights.spotShadowMap.length,
17423
17424                         numClippingPlanes: clipping.numPlanes,
17425                         numClipIntersection: clipping.numIntersection,
17426
17427                         dithering: material.dithering,
17428
17429                         shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
17430                         shadowMapType: renderer.shadowMap.type,
17431
17432                         toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
17433                         physicallyCorrectLights: renderer.physicallyCorrectLights,
17434
17435                         premultipliedAlpha: material.premultipliedAlpha,
17436
17437                         alphaTest: material.alphaTest,
17438                         doubleSided: material.side === DoubleSide,
17439                         flipSided: material.side === BackSide,
17440
17441                         depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,
17442
17443                         index0AttributeName: material.index0AttributeName,
17444
17445                         extensionDerivatives: material.extensions && material.extensions.derivatives,
17446                         extensionFragDepth: material.extensions && material.extensions.fragDepth,
17447                         extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
17448                         extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,
17449
17450                         rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ),
17451                         rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ),
17452                         rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ),
17453
17454                         customProgramCacheKey: material.customProgramCacheKey()
17455
17456                 };
17457
17458                 return parameters;
17459
17460         }
17461
17462         function getProgramCacheKey( parameters ) {
17463
17464                 const array = [];
17465
17466                 if ( parameters.shaderID ) {
17467
17468                         array.push( parameters.shaderID );
17469
17470                 } else {
17471
17472                         array.push( parameters.fragmentShader );
17473                         array.push( parameters.vertexShader );
17474
17475                 }
17476
17477                 if ( parameters.defines !== undefined ) {
17478
17479                         for ( const name in parameters.defines ) {
17480
17481                                 array.push( name );
17482                                 array.push( parameters.defines[ name ] );
17483
17484                         }
17485
17486                 }
17487
17488                 if ( parameters.isRawShaderMaterial === false ) {
17489
17490                         for ( let i = 0; i < parameterNames.length; i ++ ) {
17491
17492                                 array.push( parameters[ parameterNames[ i ] ] );
17493
17494                         }
17495
17496                         array.push( renderer.outputEncoding );
17497                         array.push( renderer.gammaFactor );
17498
17499                 }
17500
17501                 array.push( parameters.customProgramCacheKey );
17502
17503                 return array.join();
17504
17505         }
17506
17507         function getUniforms( material ) {
17508
17509                 const shaderID = shaderIDs[ material.type ];
17510                 let uniforms;
17511
17512                 if ( shaderID ) {
17513
17514                         const shader = ShaderLib[ shaderID ];
17515                         uniforms = UniformsUtils.clone( shader.uniforms );
17516
17517                 } else {
17518
17519                         uniforms = material.uniforms;
17520
17521                 }
17522
17523                 return uniforms;
17524
17525         }
17526
17527         function acquireProgram( parameters, cacheKey ) {
17528
17529                 let program;
17530
17531                 // Check if code has been already compiled
17532                 for ( let p = 0, pl = programs.length; p < pl; p ++ ) {
17533
17534                         const preexistingProgram = programs[ p ];
17535
17536                         if ( preexistingProgram.cacheKey === cacheKey ) {
17537
17538                                 program = preexistingProgram;
17539                                 ++ program.usedTimes;
17540
17541                                 break;
17542
17543                         }
17544
17545                 }
17546
17547                 if ( program === undefined ) {
17548
17549                         program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
17550                         programs.push( program );
17551
17552                 }
17553
17554                 return program;
17555
17556         }
17557
17558         function releaseProgram( program ) {
17559
17560                 if ( -- program.usedTimes === 0 ) {
17561
17562                         // Remove from unordered set
17563                         const i = programs.indexOf( program );
17564                         programs[ i ] = programs[ programs.length - 1 ];
17565                         programs.pop();
17566
17567                         // Free WebGL resources
17568                         program.destroy();
17569
17570                 }
17571
17572         }
17573
17574         return {
17575                 getParameters: getParameters,
17576                 getProgramCacheKey: getProgramCacheKey,
17577                 getUniforms: getUniforms,
17578                 acquireProgram: acquireProgram,
17579                 releaseProgram: releaseProgram,
17580                 // Exposed for resource monitoring & error feedback via renderer.info:
17581                 programs: programs
17582         };
17583
17584 }
17585
17586 function WebGLProperties() {
17587
17588         let properties = new WeakMap();
17589
17590         function get( object ) {
17591
17592                 let map = properties.get( object );
17593
17594                 if ( map === undefined ) {
17595
17596                         map = {};
17597                         properties.set( object, map );
17598
17599                 }
17600
17601                 return map;
17602
17603         }
17604
17605         function remove( object ) {
17606
17607                 properties.delete( object );
17608
17609         }
17610
17611         function update( object, key, value ) {
17612
17613                 properties.get( object )[ key ] = value;
17614
17615         }
17616
17617         function dispose() {
17618
17619                 properties = new WeakMap();
17620
17621         }
17622
17623         return {
17624                 get: get,
17625                 remove: remove,
17626                 update: update,
17627                 dispose: dispose
17628         };
17629
17630 }
17631
17632 function painterSortStable( a, b ) {
17633
17634         if ( a.groupOrder !== b.groupOrder ) {
17635
17636                 return a.groupOrder - b.groupOrder;
17637
17638         } else if ( a.renderOrder !== b.renderOrder ) {
17639
17640                 return a.renderOrder - b.renderOrder;
17641
17642         } else if ( a.program !== b.program ) {
17643
17644                 return a.program.id - b.program.id;
17645
17646         } else if ( a.material.id !== b.material.id ) {
17647
17648                 return a.material.id - b.material.id;
17649
17650         } else if ( a.z !== b.z ) {
17651
17652                 return a.z - b.z;
17653
17654         } else {
17655
17656                 return a.id - b.id;
17657
17658         }
17659
17660 }
17661
17662 function reversePainterSortStable( a, b ) {
17663
17664         if ( a.groupOrder !== b.groupOrder ) {
17665
17666                 return a.groupOrder - b.groupOrder;
17667
17668         } else if ( a.renderOrder !== b.renderOrder ) {
17669
17670                 return a.renderOrder - b.renderOrder;
17671
17672         } else if ( a.z !== b.z ) {
17673
17674                 return b.z - a.z;
17675
17676         } else {
17677
17678                 return a.id - b.id;
17679
17680         }
17681
17682 }
17683
17684
17685 function WebGLRenderList( properties ) {
17686
17687         const renderItems = [];
17688         let renderItemsIndex = 0;
17689
17690         const opaque = [];
17691         const transparent = [];
17692
17693         const defaultProgram = { id: - 1 };
17694
17695         function init() {
17696
17697                 renderItemsIndex = 0;
17698
17699                 opaque.length = 0;
17700                 transparent.length = 0;
17701
17702         }
17703
17704         function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
17705
17706                 let renderItem = renderItems[ renderItemsIndex ];
17707                 const materialProperties = properties.get( material );
17708
17709                 if ( renderItem === undefined ) {
17710
17711                         renderItem = {
17712                                 id: object.id,
17713                                 object: object,
17714                                 geometry: geometry,
17715                                 material: material,
17716                                 program: materialProperties.program || defaultProgram,
17717                                 groupOrder: groupOrder,
17718                                 renderOrder: object.renderOrder,
17719                                 z: z,
17720                                 group: group
17721                         };
17722
17723                         renderItems[ renderItemsIndex ] = renderItem;
17724
17725                 } else {
17726
17727                         renderItem.id = object.id;
17728                         renderItem.object = object;
17729                         renderItem.geometry = geometry;
17730                         renderItem.material = material;
17731                         renderItem.program = materialProperties.program || defaultProgram;
17732                         renderItem.groupOrder = groupOrder;
17733                         renderItem.renderOrder = object.renderOrder;
17734                         renderItem.z = z;
17735                         renderItem.group = group;
17736
17737                 }
17738
17739                 renderItemsIndex ++;
17740
17741                 return renderItem;
17742
17743         }
17744
17745         function push( object, geometry, material, groupOrder, z, group ) {
17746
17747                 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
17748
17749                 ( material.transparent === true ? transparent : opaque ).push( renderItem );
17750
17751         }
17752
17753         function unshift( object, geometry, material, groupOrder, z, group ) {
17754
17755                 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
17756
17757                 ( material.transparent === true ? transparent : opaque ).unshift( renderItem );
17758
17759         }
17760
17761         function sort( customOpaqueSort, customTransparentSort ) {
17762
17763                 if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
17764                 if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
17765
17766         }
17767
17768         function finish() {
17769
17770                 // Clear references from inactive renderItems in the list
17771
17772                 for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
17773
17774                         const renderItem = renderItems[ i ];
17775
17776                         if ( renderItem.id === null ) break;
17777
17778                         renderItem.id = null;
17779                         renderItem.object = null;
17780                         renderItem.geometry = null;
17781                         renderItem.material = null;
17782                         renderItem.program = null;
17783                         renderItem.group = null;
17784
17785                 }
17786
17787         }
17788
17789         return {
17790
17791                 opaque: opaque,
17792                 transparent: transparent,
17793
17794                 init: init,
17795                 push: push,
17796                 unshift: unshift,
17797                 finish: finish,
17798
17799                 sort: sort
17800         };
17801
17802 }
17803
17804 function WebGLRenderLists( properties ) {
17805
17806         let lists = new WeakMap();
17807
17808         function get( scene, camera ) {
17809
17810                 const cameras = lists.get( scene );
17811                 let list;
17812
17813                 if ( cameras === undefined ) {
17814
17815                         list = new WebGLRenderList( properties );
17816                         lists.set( scene, new WeakMap() );
17817                         lists.get( scene ).set( camera, list );
17818
17819                 } else {
17820
17821                         list = cameras.get( camera );
17822                         if ( list === undefined ) {
17823
17824                                 list = new WebGLRenderList( properties );
17825                                 cameras.set( camera, list );
17826
17827                         }
17828
17829                 }
17830
17831                 return list;
17832
17833         }
17834
17835         function dispose() {
17836
17837                 lists = new WeakMap();
17838
17839         }
17840
17841         return {
17842                 get: get,
17843                 dispose: dispose
17844         };
17845
17846 }
17847
17848 function UniformsCache() {
17849
17850         const lights = {};
17851
17852         return {
17853
17854                 get: function ( light ) {
17855
17856                         if ( lights[ light.id ] !== undefined ) {
17857
17858                                 return lights[ light.id ];
17859
17860                         }
17861
17862                         let uniforms;
17863
17864                         switch ( light.type ) {
17865
17866                                 case 'DirectionalLight':
17867                                         uniforms = {
17868                                                 direction: new Vector3(),
17869                                                 color: new Color()
17870                                         };
17871                                         break;
17872
17873                                 case 'SpotLight':
17874                                         uniforms = {
17875                                                 position: new Vector3(),
17876                                                 direction: new Vector3(),
17877                                                 color: new Color(),
17878                                                 distance: 0,
17879                                                 coneCos: 0,
17880                                                 penumbraCos: 0,
17881                                                 decay: 0
17882                                         };
17883                                         break;
17884
17885                                 case 'PointLight':
17886                                         uniforms = {
17887                                                 position: new Vector3(),
17888                                                 color: new Color(),
17889                                                 distance: 0,
17890                                                 decay: 0
17891                                         };
17892                                         break;
17893
17894                                 case 'HemisphereLight':
17895                                         uniforms = {
17896                                                 direction: new Vector3(),
17897                                                 skyColor: new Color(),
17898                                                 groundColor: new Color()
17899                                         };
17900                                         break;
17901
17902                                 case 'RectAreaLight':
17903                                         uniforms = {
17904                                                 color: new Color(),
17905                                                 position: new Vector3(),
17906                                                 halfWidth: new Vector3(),
17907                                                 halfHeight: new Vector3()
17908                                         };
17909                                         break;
17910
17911                         }
17912
17913                         lights[ light.id ] = uniforms;
17914
17915                         return uniforms;
17916
17917                 }
17918
17919         };
17920
17921 }
17922
17923 function ShadowUniformsCache() {
17924
17925         const lights = {};
17926
17927         return {
17928
17929                 get: function ( light ) {
17930
17931                         if ( lights[ light.id ] !== undefined ) {
17932
17933                                 return lights[ light.id ];
17934
17935                         }
17936
17937                         let uniforms;
17938
17939                         switch ( light.type ) {
17940
17941                                 case 'DirectionalLight':
17942                                         uniforms = {
17943                                                 shadowBias: 0,
17944                                                 shadowNormalBias: 0,
17945                                                 shadowRadius: 1,
17946                                                 shadowMapSize: new Vector2()
17947                                         };
17948                                         break;
17949
17950                                 case 'SpotLight':
17951                                         uniforms = {
17952                                                 shadowBias: 0,
17953                                                 shadowNormalBias: 0,
17954                                                 shadowRadius: 1,
17955                                                 shadowMapSize: new Vector2()
17956                                         };
17957                                         break;
17958
17959                                 case 'PointLight':
17960                                         uniforms = {
17961                                                 shadowBias: 0,
17962                                                 shadowNormalBias: 0,
17963                                                 shadowRadius: 1,
17964                                                 shadowMapSize: new Vector2(),
17965                                                 shadowCameraNear: 1,
17966                                                 shadowCameraFar: 1000
17967                                         };
17968                                         break;
17969
17970                                 // TODO (abelnation): set RectAreaLight shadow uniforms
17971
17972                         }
17973
17974                         lights[ light.id ] = uniforms;
17975
17976                         return uniforms;
17977
17978                 }
17979
17980         };
17981
17982 }
17983
17984
17985
17986 let nextVersion = 0;
17987
17988 function shadowCastingLightsFirst( lightA, lightB ) {
17989
17990         return ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );
17991
17992 }
17993
17994 function WebGLLights( extensions, capabilities ) {
17995
17996         const cache = new UniformsCache();
17997
17998         const shadowCache = ShadowUniformsCache();
17999
18000         const state = {
18001
18002                 version: 0,
18003
18004                 hash: {
18005                         directionalLength: - 1,
18006                         pointLength: - 1,
18007                         spotLength: - 1,
18008                         rectAreaLength: - 1,
18009                         hemiLength: - 1,
18010
18011                         numDirectionalShadows: - 1,
18012                         numPointShadows: - 1,
18013                         numSpotShadows: - 1
18014                 },
18015
18016                 ambient: [ 0, 0, 0 ],
18017                 probe: [],
18018                 directional: [],
18019                 directionalShadow: [],
18020                 directionalShadowMap: [],
18021                 directionalShadowMatrix: [],
18022                 spot: [],
18023                 spotShadow: [],
18024                 spotShadowMap: [],
18025                 spotShadowMatrix: [],
18026                 rectArea: [],
18027                 rectAreaLTC1: null,
18028                 rectAreaLTC2: null,
18029                 point: [],
18030                 pointShadow: [],
18031                 pointShadowMap: [],
18032                 pointShadowMatrix: [],
18033                 hemi: []
18034
18035         };
18036
18037         for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
18038
18039         const vector3 = new Vector3();
18040         const matrix4 = new Matrix4();
18041         const matrix42 = new Matrix4();
18042
18043         function setup( lights ) {
18044
18045                 let r = 0, g = 0, b = 0;
18046
18047                 for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
18048
18049                 let directionalLength = 0;
18050                 let pointLength = 0;
18051                 let spotLength = 0;
18052                 let rectAreaLength = 0;
18053                 let hemiLength = 0;
18054
18055                 let numDirectionalShadows = 0;
18056                 let numPointShadows = 0;
18057                 let numSpotShadows = 0;
18058
18059                 lights.sort( shadowCastingLightsFirst );
18060
18061                 for ( let i = 0, l = lights.length; i < l; i ++ ) {
18062
18063                         const light = lights[ i ];
18064
18065                         const color = light.color;
18066                         const intensity = light.intensity;
18067                         const distance = light.distance;
18068
18069                         const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
18070
18071                         if ( light.isAmbientLight ) {
18072
18073                                 r += color.r * intensity;
18074                                 g += color.g * intensity;
18075                                 b += color.b * intensity;
18076
18077                         } else if ( light.isLightProbe ) {
18078
18079                                 for ( let j = 0; j < 9; j ++ ) {
18080
18081                                         state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
18082
18083                                 }
18084
18085                         } else if ( light.isDirectionalLight ) {
18086
18087                                 const uniforms = cache.get( light );
18088
18089                                 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
18090
18091                                 if ( light.castShadow ) {
18092
18093                                         const shadow = light.shadow;
18094
18095                                         const shadowUniforms = shadowCache.get( light );
18096
18097                                         shadowUniforms.shadowBias = shadow.bias;
18098                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
18099                                         shadowUniforms.shadowRadius = shadow.radius;
18100                                         shadowUniforms.shadowMapSize = shadow.mapSize;
18101
18102                                         state.directionalShadow[ directionalLength ] = shadowUniforms;
18103                                         state.directionalShadowMap[ directionalLength ] = shadowMap;
18104                                         state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
18105
18106                                         numDirectionalShadows ++;
18107
18108                                 }
18109
18110                                 state.directional[ directionalLength ] = uniforms;
18111
18112                                 directionalLength ++;
18113
18114                         } else if ( light.isSpotLight ) {
18115
18116                                 const uniforms = cache.get( light );
18117
18118                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
18119
18120                                 uniforms.color.copy( color ).multiplyScalar( intensity );
18121                                 uniforms.distance = distance;
18122
18123                                 uniforms.coneCos = Math.cos( light.angle );
18124                                 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
18125                                 uniforms.decay = light.decay;
18126
18127                                 if ( light.castShadow ) {
18128
18129                                         const shadow = light.shadow;
18130
18131                                         const shadowUniforms = shadowCache.get( light );
18132
18133                                         shadowUniforms.shadowBias = shadow.bias;
18134                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
18135                                         shadowUniforms.shadowRadius = shadow.radius;
18136                                         shadowUniforms.shadowMapSize = shadow.mapSize;
18137
18138                                         state.spotShadow[ spotLength ] = shadowUniforms;
18139                                         state.spotShadowMap[ spotLength ] = shadowMap;
18140                                         state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
18141
18142                                         numSpotShadows ++;
18143
18144                                 }
18145
18146                                 state.spot[ spotLength ] = uniforms;
18147
18148                                 spotLength ++;
18149
18150                         } else if ( light.isRectAreaLight ) {
18151
18152                                 const uniforms = cache.get( light );
18153
18154                                 // (a) intensity is the total visible light emitted
18155                                 //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
18156
18157                                 // (b) intensity is the brightness of the light
18158                                 uniforms.color.copy( color ).multiplyScalar( intensity );
18159
18160                                 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
18161                                 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
18162
18163                                 state.rectArea[ rectAreaLength ] = uniforms;
18164
18165                                 rectAreaLength ++;
18166
18167                         } else if ( light.isPointLight ) {
18168
18169                                 const uniforms = cache.get( light );
18170
18171                                 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
18172                                 uniforms.distance = light.distance;
18173                                 uniforms.decay = light.decay;
18174
18175                                 if ( light.castShadow ) {
18176
18177                                         const shadow = light.shadow;
18178
18179                                         const shadowUniforms = shadowCache.get( light );
18180
18181                                         shadowUniforms.shadowBias = shadow.bias;
18182                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
18183                                         shadowUniforms.shadowRadius = shadow.radius;
18184                                         shadowUniforms.shadowMapSize = shadow.mapSize;
18185                                         shadowUniforms.shadowCameraNear = shadow.camera.near;
18186                                         shadowUniforms.shadowCameraFar = shadow.camera.far;
18187
18188                                         state.pointShadow[ pointLength ] = shadowUniforms;
18189                                         state.pointShadowMap[ pointLength ] = shadowMap;
18190                                         state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
18191
18192                                         numPointShadows ++;
18193
18194                                 }
18195
18196                                 state.point[ pointLength ] = uniforms;
18197
18198                                 pointLength ++;
18199
18200                         } else if ( light.isHemisphereLight ) {
18201
18202                                 const uniforms = cache.get( light );
18203
18204                                 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
18205                                 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
18206
18207                                 state.hemi[ hemiLength ] = uniforms;
18208
18209                                 hemiLength ++;
18210
18211                         }
18212
18213                 }
18214
18215                 if ( rectAreaLength > 0 ) {
18216
18217                         if ( capabilities.isWebGL2 ) {
18218
18219                                 // WebGL 2
18220
18221                                 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
18222                                 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
18223
18224                         } else {
18225
18226                                 // WebGL 1
18227
18228                                 if ( extensions.has( 'OES_texture_float_linear' ) === true ) {
18229
18230                                         state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
18231                                         state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
18232
18233                                 } else if ( extensions.has( 'OES_texture_half_float_linear' ) === true ) {
18234
18235                                         state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
18236                                         state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
18237
18238                                 } else {
18239
18240                                         console.error( 'THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.' );
18241
18242                                 }
18243
18244                         }
18245
18246                 }
18247
18248                 state.ambient[ 0 ] = r;
18249                 state.ambient[ 1 ] = g;
18250                 state.ambient[ 2 ] = b;
18251
18252                 const hash = state.hash;
18253
18254                 if ( hash.directionalLength !== directionalLength ||
18255                         hash.pointLength !== pointLength ||
18256                         hash.spotLength !== spotLength ||
18257                         hash.rectAreaLength !== rectAreaLength ||
18258                         hash.hemiLength !== hemiLength ||
18259                         hash.numDirectionalShadows !== numDirectionalShadows ||
18260                         hash.numPointShadows !== numPointShadows ||
18261                         hash.numSpotShadows !== numSpotShadows ) {
18262
18263                         state.directional.length = directionalLength;
18264                         state.spot.length = spotLength;
18265                         state.rectArea.length = rectAreaLength;
18266                         state.point.length = pointLength;
18267                         state.hemi.length = hemiLength;
18268
18269                         state.directionalShadow.length = numDirectionalShadows;
18270                         state.directionalShadowMap.length = numDirectionalShadows;
18271                         state.pointShadow.length = numPointShadows;
18272                         state.pointShadowMap.length = numPointShadows;
18273                         state.spotShadow.length = numSpotShadows;
18274                         state.spotShadowMap.length = numSpotShadows;
18275                         state.directionalShadowMatrix.length = numDirectionalShadows;
18276                         state.pointShadowMatrix.length = numPointShadows;
18277                         state.spotShadowMatrix.length = numSpotShadows;
18278
18279                         hash.directionalLength = directionalLength;
18280                         hash.pointLength = pointLength;
18281                         hash.spotLength = spotLength;
18282                         hash.rectAreaLength = rectAreaLength;
18283                         hash.hemiLength = hemiLength;
18284
18285                         hash.numDirectionalShadows = numDirectionalShadows;
18286                         hash.numPointShadows = numPointShadows;
18287                         hash.numSpotShadows = numSpotShadows;
18288
18289                         state.version = nextVersion ++;
18290
18291                 }
18292
18293         }
18294
18295         function setupView( lights, camera ) {
18296
18297                 let directionalLength = 0;
18298                 let pointLength = 0;
18299                 let spotLength = 0;
18300                 let rectAreaLength = 0;
18301                 let hemiLength = 0;
18302
18303                 const viewMatrix = camera.matrixWorldInverse;
18304
18305                 for ( let i = 0, l = lights.length; i < l; i ++ ) {
18306
18307                         const light = lights[ i ];
18308
18309                         if ( light.isDirectionalLight ) {
18310
18311                                 const uniforms = state.directional[ directionalLength ];
18312
18313                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
18314                                 vector3.setFromMatrixPosition( light.target.matrixWorld );
18315                                 uniforms.direction.sub( vector3 );
18316                                 uniforms.direction.transformDirection( viewMatrix );
18317
18318                                 directionalLength ++;
18319
18320                         } else if ( light.isSpotLight ) {
18321
18322                                 const uniforms = state.spot[ spotLength ];
18323
18324                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
18325                                 uniforms.position.applyMatrix4( viewMatrix );
18326
18327                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
18328                                 vector3.setFromMatrixPosition( light.target.matrixWorld );
18329                                 uniforms.direction.sub( vector3 );
18330                                 uniforms.direction.transformDirection( viewMatrix );
18331
18332                                 spotLength ++;
18333
18334                         } else if ( light.isRectAreaLight ) {
18335
18336                                 const uniforms = state.rectArea[ rectAreaLength ];
18337
18338                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
18339                                 uniforms.position.applyMatrix4( viewMatrix );
18340
18341                                 // extract local rotation of light to derive width/height half vectors
18342                                 matrix42.identity();
18343                                 matrix4.copy( light.matrixWorld );
18344                                 matrix4.premultiply( viewMatrix );
18345                                 matrix42.extractRotation( matrix4 );
18346
18347                                 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
18348                                 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
18349
18350                                 uniforms.halfWidth.applyMatrix4( matrix42 );
18351                                 uniforms.halfHeight.applyMatrix4( matrix42 );
18352
18353                                 rectAreaLength ++;
18354
18355                         } else if ( light.isPointLight ) {
18356
18357                                 const uniforms = state.point[ pointLength ];
18358
18359                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
18360                                 uniforms.position.applyMatrix4( viewMatrix );
18361
18362                                 pointLength ++;
18363
18364                         } else if ( light.isHemisphereLight ) {
18365
18366                                 const uniforms = state.hemi[ hemiLength ];
18367
18368                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
18369                                 uniforms.direction.transformDirection( viewMatrix );
18370                                 uniforms.direction.normalize();
18371
18372                                 hemiLength ++;
18373
18374                         }
18375
18376                 }
18377
18378         }
18379
18380         return {
18381                 setup: setup,
18382                 setupView: setupView,
18383                 state: state
18384         };
18385
18386 }
18387
18388 function WebGLRenderState( extensions, capabilities ) {
18389
18390         const lights = new WebGLLights( extensions, capabilities );
18391
18392         const lightsArray = [];
18393         const shadowsArray = [];
18394
18395         function init() {
18396
18397                 lightsArray.length = 0;
18398                 shadowsArray.length = 0;
18399
18400         }
18401
18402         function pushLight( light ) {
18403
18404                 lightsArray.push( light );
18405
18406         }
18407
18408         function pushShadow( shadowLight ) {
18409
18410                 shadowsArray.push( shadowLight );
18411
18412         }
18413
18414         function setupLights() {
18415
18416                 lights.setup( lightsArray );
18417
18418         }
18419
18420         function setupLightsView( camera ) {
18421
18422                 lights.setupView( lightsArray, camera );
18423
18424         }
18425
18426         const state = {
18427                 lightsArray: lightsArray,
18428                 shadowsArray: shadowsArray,
18429
18430                 lights: lights
18431         };
18432
18433         return {
18434                 init: init,
18435                 state: state,
18436                 setupLights: setupLights,
18437                 setupLightsView: setupLightsView,
18438
18439                 pushLight: pushLight,
18440                 pushShadow: pushShadow
18441         };
18442
18443 }
18444
18445 function WebGLRenderStates( extensions, capabilities ) {
18446
18447         let renderStates = new WeakMap();
18448
18449         function get( scene, renderCallDepth = 0 ) {
18450
18451                 let renderState;
18452
18453                 if ( renderStates.has( scene ) === false ) {
18454
18455                         renderState = new WebGLRenderState( extensions, capabilities );
18456                         renderStates.set( scene, [] );
18457                         renderStates.get( scene ).push( renderState );
18458
18459                 } else {
18460
18461                         if ( renderCallDepth >= renderStates.get( scene ).length ) {
18462
18463                                 renderState = new WebGLRenderState( extensions, capabilities );
18464                                 renderStates.get( scene ).push( renderState );
18465
18466                         } else {
18467
18468                                 renderState = renderStates.get( scene )[ renderCallDepth ];
18469
18470                         }
18471
18472                 }
18473
18474                 return renderState;
18475
18476         }
18477
18478         function dispose() {
18479
18480                 renderStates = new WeakMap();
18481
18482         }
18483
18484         return {
18485                 get: get,
18486                 dispose: dispose
18487         };
18488
18489 }
18490
18491 /**
18492  * parameters = {
18493  *
18494  *  opacity: <float>,
18495  *
18496  *  map: new THREE.Texture( <Image> ),
18497  *
18498  *  alphaMap: new THREE.Texture( <Image> ),
18499  *
18500  *  displacementMap: new THREE.Texture( <Image> ),
18501  *  displacementScale: <float>,
18502  *  displacementBias: <float>,
18503  *
18504  *  wireframe: <boolean>,
18505  *  wireframeLinewidth: <float>
18506  * }
18507  */
18508
18509 function MeshDepthMaterial( parameters ) {
18510
18511         Material.call( this );
18512
18513         this.type = 'MeshDepthMaterial';
18514
18515         this.depthPacking = BasicDepthPacking;
18516
18517         this.skinning = false;
18518         this.morphTargets = false;
18519
18520         this.map = null;
18521
18522         this.alphaMap = null;
18523
18524         this.displacementMap = null;
18525         this.displacementScale = 1;
18526         this.displacementBias = 0;
18527
18528         this.wireframe = false;
18529         this.wireframeLinewidth = 1;
18530
18531         this.fog = false;
18532
18533         this.setValues( parameters );
18534
18535 }
18536
18537 MeshDepthMaterial.prototype = Object.create( Material.prototype );
18538 MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
18539
18540 MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
18541
18542 MeshDepthMaterial.prototype.copy = function ( source ) {
18543
18544         Material.prototype.copy.call( this, source );
18545
18546         this.depthPacking = source.depthPacking;
18547
18548         this.skinning = source.skinning;
18549         this.morphTargets = source.morphTargets;
18550
18551         this.map = source.map;
18552
18553         this.alphaMap = source.alphaMap;
18554
18555         this.displacementMap = source.displacementMap;
18556         this.displacementScale = source.displacementScale;
18557         this.displacementBias = source.displacementBias;
18558
18559         this.wireframe = source.wireframe;
18560         this.wireframeLinewidth = source.wireframeLinewidth;
18561
18562         return this;
18563
18564 };
18565
18566 /**
18567  * parameters = {
18568  *
18569  *  referencePosition: <float>,
18570  *  nearDistance: <float>,
18571  *  farDistance: <float>,
18572  *
18573  *  skinning: <bool>,
18574  *  morphTargets: <bool>,
18575  *
18576  *  map: new THREE.Texture( <Image> ),
18577  *
18578  *  alphaMap: new THREE.Texture( <Image> ),
18579  *
18580  *  displacementMap: new THREE.Texture( <Image> ),
18581  *  displacementScale: <float>,
18582  *  displacementBias: <float>
18583  *
18584  * }
18585  */
18586
18587 function MeshDistanceMaterial( parameters ) {
18588
18589         Material.call( this );
18590
18591         this.type = 'MeshDistanceMaterial';
18592
18593         this.referencePosition = new Vector3();
18594         this.nearDistance = 1;
18595         this.farDistance = 1000;
18596
18597         this.skinning = false;
18598         this.morphTargets = false;
18599
18600         this.map = null;
18601
18602         this.alphaMap = null;
18603
18604         this.displacementMap = null;
18605         this.displacementScale = 1;
18606         this.displacementBias = 0;
18607
18608         this.fog = false;
18609
18610         this.setValues( parameters );
18611
18612 }
18613
18614 MeshDistanceMaterial.prototype = Object.create( Material.prototype );
18615 MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
18616
18617 MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
18618
18619 MeshDistanceMaterial.prototype.copy = function ( source ) {
18620
18621         Material.prototype.copy.call( this, source );
18622
18623         this.referencePosition.copy( source.referencePosition );
18624         this.nearDistance = source.nearDistance;
18625         this.farDistance = source.farDistance;
18626
18627         this.skinning = source.skinning;
18628         this.morphTargets = source.morphTargets;
18629
18630         this.map = source.map;
18631
18632         this.alphaMap = source.alphaMap;
18633
18634         this.displacementMap = source.displacementMap;
18635         this.displacementScale = source.displacementScale;
18636         this.displacementBias = source.displacementBias;
18637
18638         return this;
18639
18640 };
18641
18642 var vsm_frag = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\tfor ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean * HALF_SAMPLE_RATE;\n\tsquared_mean = squared_mean * HALF_SAMPLE_RATE;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
18643
18644 var vsm_vert = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
18645
18646 function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
18647
18648         let _frustum = new Frustum();
18649
18650         const _shadowMapSize = new Vector2(),
18651                 _viewportSize = new Vector2(),
18652
18653                 _viewport = new Vector4(),
18654
18655                 _depthMaterials = [],
18656                 _distanceMaterials = [],
18657
18658                 _materialCache = {};
18659
18660         const shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
18661
18662         const shadowMaterialVertical = new ShaderMaterial( {
18663
18664                 defines: {
18665                         SAMPLE_RATE: 2.0 / 8.0,
18666                         HALF_SAMPLE_RATE: 1.0 / 8.0
18667                 },
18668
18669                 uniforms: {
18670                         shadow_pass: { value: null },
18671                         resolution: { value: new Vector2() },
18672                         radius: { value: 4.0 }
18673                 },
18674
18675                 vertexShader: vsm_vert,
18676
18677                 fragmentShader: vsm_frag
18678
18679         } );
18680
18681         const shadowMaterialHorizontal = shadowMaterialVertical.clone();
18682         shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
18683
18684         const fullScreenTri = new BufferGeometry();
18685         fullScreenTri.setAttribute(
18686                 'position',
18687                 new BufferAttribute(
18688                         new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
18689                         3
18690                 )
18691         );
18692
18693         const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
18694
18695         const scope = this;
18696
18697         this.enabled = false;
18698
18699         this.autoUpdate = true;
18700         this.needsUpdate = false;
18701
18702         this.type = PCFShadowMap;
18703
18704         this.render = function ( lights, scene, camera ) {
18705
18706                 if ( scope.enabled === false ) return;
18707                 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
18708
18709                 if ( lights.length === 0 ) return;
18710
18711                 const currentRenderTarget = _renderer.getRenderTarget();
18712                 const activeCubeFace = _renderer.getActiveCubeFace();
18713                 const activeMipmapLevel = _renderer.getActiveMipmapLevel();
18714
18715                 const _state = _renderer.state;
18716
18717                 // Set GL state for depth map.
18718                 _state.setBlending( NoBlending );
18719                 _state.buffers.color.setClear( 1, 1, 1, 1 );
18720                 _state.buffers.depth.setTest( true );
18721                 _state.setScissorTest( false );
18722
18723                 // render depth map
18724
18725                 for ( let i = 0, il = lights.length; i < il; i ++ ) {
18726
18727                         const light = lights[ i ];
18728                         const shadow = light.shadow;
18729
18730                         if ( shadow === undefined ) {
18731
18732                                 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
18733                                 continue;
18734
18735                         }
18736
18737                         if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue;
18738
18739                         _shadowMapSize.copy( shadow.mapSize );
18740
18741                         const shadowFrameExtents = shadow.getFrameExtents();
18742
18743                         _shadowMapSize.multiply( shadowFrameExtents );
18744
18745                         _viewportSize.copy( shadow.mapSize );
18746
18747                         if ( _shadowMapSize.x > maxTextureSize || _shadowMapSize.y > maxTextureSize ) {
18748
18749                                 if ( _shadowMapSize.x > maxTextureSize ) {
18750
18751                                         _viewportSize.x = Math.floor( maxTextureSize / shadowFrameExtents.x );
18752                                         _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
18753                                         shadow.mapSize.x = _viewportSize.x;
18754
18755                                 }
18756
18757                                 if ( _shadowMapSize.y > maxTextureSize ) {
18758
18759                                         _viewportSize.y = Math.floor( maxTextureSize / shadowFrameExtents.y );
18760                                         _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
18761                                         shadow.mapSize.y = _viewportSize.y;
18762
18763                                 }
18764
18765                         }
18766
18767                         if ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
18768
18769                                 const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
18770
18771                                 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
18772                                 shadow.map.texture.name = light.name + '.shadowMap';
18773
18774                                 shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
18775
18776                                 shadow.camera.updateProjectionMatrix();
18777
18778                         }
18779
18780                         if ( shadow.map === null ) {
18781
18782                                 const pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
18783
18784                                 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
18785                                 shadow.map.texture.name = light.name + '.shadowMap';
18786
18787                                 shadow.camera.updateProjectionMatrix();
18788
18789                         }
18790
18791                         _renderer.setRenderTarget( shadow.map );
18792                         _renderer.clear();
18793
18794                         const viewportCount = shadow.getViewportCount();
18795
18796                         for ( let vp = 0; vp < viewportCount; vp ++ ) {
18797
18798                                 const viewport = shadow.getViewport( vp );
18799
18800                                 _viewport.set(
18801                                         _viewportSize.x * viewport.x,
18802                                         _viewportSize.y * viewport.y,
18803                                         _viewportSize.x * viewport.z,
18804                                         _viewportSize.y * viewport.w
18805                                 );
18806
18807                                 _state.viewport( _viewport );
18808
18809                                 shadow.updateMatrices( light, vp );
18810
18811                                 _frustum = shadow.getFrustum();
18812
18813                                 renderObject( scene, camera, shadow.camera, light, this.type );
18814
18815                         }
18816
18817                         // do blur pass for VSM
18818
18819                         if ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
18820
18821                                 VSMPass( shadow, camera );
18822
18823                         }
18824
18825                         shadow.needsUpdate = false;
18826
18827                 }
18828
18829                 scope.needsUpdate = false;
18830
18831                 _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
18832
18833         };
18834
18835         function VSMPass( shadow, camera ) {
18836
18837                 const geometry = _objects.update( fullScreenMesh );
18838
18839                 // vertical pass
18840
18841                 shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
18842                 shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
18843                 shadowMaterialVertical.uniforms.radius.value = shadow.radius;
18844                 _renderer.setRenderTarget( shadow.mapPass );
18845                 _renderer.clear();
18846                 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
18847
18848                 // horizontal pass
18849
18850                 shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
18851                 shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
18852                 shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
18853                 _renderer.setRenderTarget( shadow.map );
18854                 _renderer.clear();
18855                 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
18856
18857         }
18858
18859         function getDepthMaterialVariant( useMorphing, useSkinning, useInstancing ) {
18860
18861                 const index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
18862
18863                 let material = _depthMaterials[ index ];
18864
18865                 if ( material === undefined ) {
18866
18867                         material = new MeshDepthMaterial( {
18868
18869                                 depthPacking: RGBADepthPacking,
18870
18871                                 morphTargets: useMorphing,
18872                                 skinning: useSkinning
18873
18874                         } );
18875
18876                         _depthMaterials[ index ] = material;
18877
18878                 }
18879
18880                 return material;
18881
18882         }
18883
18884         function getDistanceMaterialVariant( useMorphing, useSkinning, useInstancing ) {
18885
18886                 const index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
18887
18888                 let material = _distanceMaterials[ index ];
18889
18890                 if ( material === undefined ) {
18891
18892                         material = new MeshDistanceMaterial( {
18893
18894                                 morphTargets: useMorphing,
18895                                 skinning: useSkinning
18896
18897                         } );
18898
18899                         _distanceMaterials[ index ] = material;
18900
18901                 }
18902
18903                 return material;
18904
18905         }
18906
18907         function getDepthMaterial( object, geometry, material, light, shadowCameraNear, shadowCameraFar, type ) {
18908
18909                 let result = null;
18910
18911                 let getMaterialVariant = getDepthMaterialVariant;
18912                 let customMaterial = object.customDepthMaterial;
18913
18914                 if ( light.isPointLight === true ) {
18915
18916                         getMaterialVariant = getDistanceMaterialVariant;
18917                         customMaterial = object.customDistanceMaterial;
18918
18919                 }
18920
18921                 if ( customMaterial === undefined ) {
18922
18923                         let useMorphing = false;
18924
18925                         if ( material.morphTargets === true ) {
18926
18927                                 useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
18928
18929                         }
18930
18931                         let useSkinning = false;
18932
18933                         if ( object.isSkinnedMesh === true ) {
18934
18935                                 if ( material.skinning === true ) {
18936
18937                                         useSkinning = true;
18938
18939                                 } else {
18940
18941                                         console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
18942
18943                                 }
18944
18945                         }
18946
18947                         const useInstancing = object.isInstancedMesh === true;
18948
18949                         result = getMaterialVariant( useMorphing, useSkinning, useInstancing );
18950
18951                 } else {
18952
18953                         result = customMaterial;
18954
18955                 }
18956
18957                 if ( _renderer.localClippingEnabled &&
18958                                 material.clipShadows === true &&
18959                                 material.clippingPlanes.length !== 0 ) {
18960
18961                         // in this case we need a unique material instance reflecting the
18962                         // appropriate state
18963
18964                         const keyA = result.uuid, keyB = material.uuid;
18965
18966                         let materialsForVariant = _materialCache[ keyA ];
18967
18968                         if ( materialsForVariant === undefined ) {
18969
18970                                 materialsForVariant = {};
18971                                 _materialCache[ keyA ] = materialsForVariant;
18972
18973                         }
18974
18975                         let cachedMaterial = materialsForVariant[ keyB ];
18976
18977                         if ( cachedMaterial === undefined ) {
18978
18979                                 cachedMaterial = result.clone();
18980                                 materialsForVariant[ keyB ] = cachedMaterial;
18981
18982                         }
18983
18984                         result = cachedMaterial;
18985
18986                 }
18987
18988                 result.visible = material.visible;
18989                 result.wireframe = material.wireframe;
18990
18991                 if ( type === VSMShadowMap ) {
18992
18993                         result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
18994
18995                 } else {
18996
18997                         result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
18998
18999                 }
19000
19001                 result.clipShadows = material.clipShadows;
19002                 result.clippingPlanes = material.clippingPlanes;
19003                 result.clipIntersection = material.clipIntersection;
19004
19005                 result.wireframeLinewidth = material.wireframeLinewidth;
19006                 result.linewidth = material.linewidth;
19007
19008                 if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
19009
19010                         result.referencePosition.setFromMatrixPosition( light.matrixWorld );
19011                         result.nearDistance = shadowCameraNear;
19012                         result.farDistance = shadowCameraFar;
19013
19014                 }
19015
19016                 return result;
19017
19018         }
19019
19020         function renderObject( object, camera, shadowCamera, light, type ) {
19021
19022                 if ( object.visible === false ) return;
19023
19024                 const visible = object.layers.test( camera.layers );
19025
19026                 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
19027
19028                         if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
19029
19030                                 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
19031
19032                                 const geometry = _objects.update( object );
19033                                 const material = object.material;
19034
19035                                 if ( Array.isArray( material ) ) {
19036
19037                                         const groups = geometry.groups;
19038
19039                                         for ( let k = 0, kl = groups.length; k < kl; k ++ ) {
19040
19041                                                 const group = groups[ k ];
19042                                                 const groupMaterial = material[ group.materialIndex ];
19043
19044                                                 if ( groupMaterial && groupMaterial.visible ) {
19045
19046                                                         const depthMaterial = getDepthMaterial( object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );
19047
19048                                                         _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
19049
19050                                                 }
19051
19052                                         }
19053
19054                                 } else if ( material.visible ) {
19055
19056                                         const depthMaterial = getDepthMaterial( object, geometry, material, light, shadowCamera.near, shadowCamera.far, type );
19057
19058                                         _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
19059
19060                                 }
19061
19062                         }
19063
19064                 }
19065
19066                 const children = object.children;
19067
19068                 for ( let i = 0, l = children.length; i < l; i ++ ) {
19069
19070                         renderObject( children[ i ], camera, shadowCamera, light, type );
19071
19072                 }
19073
19074         }
19075
19076 }
19077
19078 function WebGLState( gl, extensions, capabilities ) {
19079
19080         const isWebGL2 = capabilities.isWebGL2;
19081
19082         function ColorBuffer() {
19083
19084                 let locked = false;
19085
19086                 const color = new Vector4();
19087                 let currentColorMask = null;
19088                 const currentColorClear = new Vector4( 0, 0, 0, 0 );
19089
19090                 return {
19091
19092                         setMask: function ( colorMask ) {
19093
19094                                 if ( currentColorMask !== colorMask && ! locked ) {
19095
19096                                         gl.colorMask( colorMask, colorMask, colorMask, colorMask );
19097                                         currentColorMask = colorMask;
19098
19099                                 }
19100
19101                         },
19102
19103                         setLocked: function ( lock ) {
19104
19105                                 locked = lock;
19106
19107                         },
19108
19109                         setClear: function ( r, g, b, a, premultipliedAlpha ) {
19110
19111                                 if ( premultipliedAlpha === true ) {
19112
19113                                         r *= a; g *= a; b *= a;
19114
19115                                 }
19116
19117                                 color.set( r, g, b, a );
19118
19119                                 if ( currentColorClear.equals( color ) === false ) {
19120
19121                                         gl.clearColor( r, g, b, a );
19122                                         currentColorClear.copy( color );
19123
19124                                 }
19125
19126                         },
19127
19128                         reset: function () {
19129
19130                                 locked = false;
19131
19132                                 currentColorMask = null;
19133                                 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
19134
19135                         }
19136
19137                 };
19138
19139         }
19140
19141         function DepthBuffer() {
19142
19143                 let locked = false;
19144
19145                 let currentDepthMask = null;
19146                 let currentDepthFunc = null;
19147                 let currentDepthClear = null;
19148
19149                 return {
19150
19151                         setTest: function ( depthTest ) {
19152
19153                                 if ( depthTest ) {
19154
19155                                         enable( 2929 );
19156
19157                                 } else {
19158
19159                                         disable( 2929 );
19160
19161                                 }
19162
19163                         },
19164
19165                         setMask: function ( depthMask ) {
19166
19167                                 if ( currentDepthMask !== depthMask && ! locked ) {
19168
19169                                         gl.depthMask( depthMask );
19170                                         currentDepthMask = depthMask;
19171
19172                                 }
19173
19174                         },
19175
19176                         setFunc: function ( depthFunc ) {
19177
19178                                 if ( currentDepthFunc !== depthFunc ) {
19179
19180                                         if ( depthFunc ) {
19181
19182                                                 switch ( depthFunc ) {
19183
19184                                                         case NeverDepth:
19185
19186                                                                 gl.depthFunc( 512 );
19187                                                                 break;
19188
19189                                                         case AlwaysDepth:
19190
19191                                                                 gl.depthFunc( 519 );
19192                                                                 break;
19193
19194                                                         case LessDepth:
19195
19196                                                                 gl.depthFunc( 513 );
19197                                                                 break;
19198
19199                                                         case LessEqualDepth:
19200
19201                                                                 gl.depthFunc( 515 );
19202                                                                 break;
19203
19204                                                         case EqualDepth:
19205
19206                                                                 gl.depthFunc( 514 );
19207                                                                 break;
19208
19209                                                         case GreaterEqualDepth:
19210
19211                                                                 gl.depthFunc( 518 );
19212                                                                 break;
19213
19214                                                         case GreaterDepth:
19215
19216                                                                 gl.depthFunc( 516 );
19217                                                                 break;
19218
19219                                                         case NotEqualDepth:
19220
19221                                                                 gl.depthFunc( 517 );
19222                                                                 break;
19223
19224                                                         default:
19225
19226                                                                 gl.depthFunc( 515 );
19227
19228                                                 }
19229
19230                                         } else {
19231
19232                                                 gl.depthFunc( 515 );
19233
19234                                         }
19235
19236                                         currentDepthFunc = depthFunc;
19237
19238                                 }
19239
19240                         },
19241
19242                         setLocked: function ( lock ) {
19243
19244                                 locked = lock;
19245
19246                         },
19247
19248                         setClear: function ( depth ) {
19249
19250                                 if ( currentDepthClear !== depth ) {
19251
19252                                         gl.clearDepth( depth );
19253                                         currentDepthClear = depth;
19254
19255                                 }
19256
19257                         },
19258
19259                         reset: function () {
19260
19261                                 locked = false;
19262
19263                                 currentDepthMask = null;
19264                                 currentDepthFunc = null;
19265                                 currentDepthClear = null;
19266
19267                         }
19268
19269                 };
19270
19271         }
19272
19273         function StencilBuffer() {
19274
19275                 let locked = false;
19276
19277                 let currentStencilMask = null;
19278                 let currentStencilFunc = null;
19279                 let currentStencilRef = null;
19280                 let currentStencilFuncMask = null;
19281                 let currentStencilFail = null;
19282                 let currentStencilZFail = null;
19283                 let currentStencilZPass = null;
19284                 let currentStencilClear = null;
19285
19286                 return {
19287
19288                         setTest: function ( stencilTest ) {
19289
19290                                 if ( ! locked ) {
19291
19292                                         if ( stencilTest ) {
19293
19294                                                 enable( 2960 );
19295
19296                                         } else {
19297
19298                                                 disable( 2960 );
19299
19300                                         }
19301
19302                                 }
19303
19304                         },
19305
19306                         setMask: function ( stencilMask ) {
19307
19308                                 if ( currentStencilMask !== stencilMask && ! locked ) {
19309
19310                                         gl.stencilMask( stencilMask );
19311                                         currentStencilMask = stencilMask;
19312
19313                                 }
19314
19315                         },
19316
19317                         setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
19318
19319                                 if ( currentStencilFunc !== stencilFunc ||
19320                                      currentStencilRef !== stencilRef ||
19321                                      currentStencilFuncMask !== stencilMask ) {
19322
19323                                         gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
19324
19325                                         currentStencilFunc = stencilFunc;
19326                                         currentStencilRef = stencilRef;
19327                                         currentStencilFuncMask = stencilMask;
19328
19329                                 }
19330
19331                         },
19332
19333                         setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
19334
19335                                 if ( currentStencilFail !== stencilFail ||
19336                                      currentStencilZFail !== stencilZFail ||
19337                                      currentStencilZPass !== stencilZPass ) {
19338
19339                                         gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
19340
19341                                         currentStencilFail = stencilFail;
19342                                         currentStencilZFail = stencilZFail;
19343                                         currentStencilZPass = stencilZPass;
19344
19345                                 }
19346
19347                         },
19348
19349                         setLocked: function ( lock ) {
19350
19351                                 locked = lock;
19352
19353                         },
19354
19355                         setClear: function ( stencil ) {
19356
19357                                 if ( currentStencilClear !== stencil ) {
19358
19359                                         gl.clearStencil( stencil );
19360                                         currentStencilClear = stencil;
19361
19362                                 }
19363
19364                         },
19365
19366                         reset: function () {
19367
19368                                 locked = false;
19369
19370                                 currentStencilMask = null;
19371                                 currentStencilFunc = null;
19372                                 currentStencilRef = null;
19373                                 currentStencilFuncMask = null;
19374                                 currentStencilFail = null;
19375                                 currentStencilZFail = null;
19376                                 currentStencilZPass = null;
19377                                 currentStencilClear = null;
19378
19379                         }
19380
19381                 };
19382
19383         }
19384
19385         //
19386
19387         const colorBuffer = new ColorBuffer();
19388         const depthBuffer = new DepthBuffer();
19389         const stencilBuffer = new StencilBuffer();
19390
19391         let enabledCapabilities = {};
19392
19393         let currentProgram = null;
19394
19395         let currentBlendingEnabled = null;
19396         let currentBlending = null;
19397         let currentBlendEquation = null;
19398         let currentBlendSrc = null;
19399         let currentBlendDst = null;
19400         let currentBlendEquationAlpha = null;
19401         let currentBlendSrcAlpha = null;
19402         let currentBlendDstAlpha = null;
19403         let currentPremultipledAlpha = false;
19404
19405         let currentFlipSided = null;
19406         let currentCullFace = null;
19407
19408         let currentLineWidth = null;
19409
19410         let currentPolygonOffsetFactor = null;
19411         let currentPolygonOffsetUnits = null;
19412
19413         const maxTextures = gl.getParameter( 35661 );
19414
19415         let lineWidthAvailable = false;
19416         let version = 0;
19417         const glVersion = gl.getParameter( 7938 );
19418
19419         if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
19420
19421                 version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] );
19422                 lineWidthAvailable = ( version >= 1.0 );
19423
19424         } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
19425
19426                 version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] );
19427                 lineWidthAvailable = ( version >= 2.0 );
19428
19429         }
19430
19431         let currentTextureSlot = null;
19432         let currentBoundTextures = {};
19433
19434         const currentScissor = new Vector4();
19435         const currentViewport = new Vector4();
19436
19437         function createTexture( type, target, count ) {
19438
19439                 const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
19440                 const texture = gl.createTexture();
19441
19442                 gl.bindTexture( type, texture );
19443                 gl.texParameteri( type, 10241, 9728 );
19444                 gl.texParameteri( type, 10240, 9728 );
19445
19446                 for ( let i = 0; i < count; i ++ ) {
19447
19448                         gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );
19449
19450                 }
19451
19452                 return texture;
19453
19454         }
19455
19456         const emptyTextures = {};
19457         emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );
19458         emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );
19459
19460         // init
19461
19462         colorBuffer.setClear( 0, 0, 0, 1 );
19463         depthBuffer.setClear( 1 );
19464         stencilBuffer.setClear( 0 );
19465
19466         enable( 2929 );
19467         depthBuffer.setFunc( LessEqualDepth );
19468
19469         setFlipSided( false );
19470         setCullFace( CullFaceBack );
19471         enable( 2884 );
19472
19473         setBlending( NoBlending );
19474
19475         //
19476
19477         function enable( id ) {
19478
19479                 if ( enabledCapabilities[ id ] !== true ) {
19480
19481                         gl.enable( id );
19482                         enabledCapabilities[ id ] = true;
19483
19484                 }
19485
19486         }
19487
19488         function disable( id ) {
19489
19490                 if ( enabledCapabilities[ id ] !== false ) {
19491
19492                         gl.disable( id );
19493                         enabledCapabilities[ id ] = false;
19494
19495                 }
19496
19497         }
19498
19499         function useProgram( program ) {
19500
19501                 if ( currentProgram !== program ) {
19502
19503                         gl.useProgram( program );
19504
19505                         currentProgram = program;
19506
19507                         return true;
19508
19509                 }
19510
19511                 return false;
19512
19513         }
19514
19515         const equationToGL = {
19516                 [ AddEquation ]: 32774,
19517                 [ SubtractEquation ]: 32778,
19518                 [ ReverseSubtractEquation ]: 32779
19519         };
19520
19521         if ( isWebGL2 ) {
19522
19523                 equationToGL[ MinEquation ] = 32775;
19524                 equationToGL[ MaxEquation ] = 32776;
19525
19526         } else {
19527
19528                 const extension = extensions.get( 'EXT_blend_minmax' );
19529
19530                 if ( extension !== null ) {
19531
19532                         equationToGL[ MinEquation ] = extension.MIN_EXT;
19533                         equationToGL[ MaxEquation ] = extension.MAX_EXT;
19534
19535                 }
19536
19537         }
19538
19539         const factorToGL = {
19540                 [ ZeroFactor ]: 0,
19541                 [ OneFactor ]: 1,
19542                 [ SrcColorFactor ]: 768,
19543                 [ SrcAlphaFactor ]: 770,
19544                 [ SrcAlphaSaturateFactor ]: 776,
19545                 [ DstColorFactor ]: 774,
19546                 [ DstAlphaFactor ]: 772,
19547                 [ OneMinusSrcColorFactor ]: 769,
19548                 [ OneMinusSrcAlphaFactor ]: 771,
19549                 [ OneMinusDstColorFactor ]: 775,
19550                 [ OneMinusDstAlphaFactor ]: 773
19551         };
19552
19553         function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
19554
19555                 if ( blending === NoBlending ) {
19556
19557                         if ( currentBlendingEnabled ) {
19558
19559                                 disable( 3042 );
19560                                 currentBlendingEnabled = false;
19561
19562                         }
19563
19564                         return;
19565
19566                 }
19567
19568                 if ( ! currentBlendingEnabled ) {
19569
19570                         enable( 3042 );
19571                         currentBlendingEnabled = true;
19572
19573                 }
19574
19575                 if ( blending !== CustomBlending ) {
19576
19577                         if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
19578
19579                                 if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
19580
19581                                         gl.blendEquation( 32774 );
19582
19583                                         currentBlendEquation = AddEquation;
19584                                         currentBlendEquationAlpha = AddEquation;
19585
19586                                 }
19587
19588                                 if ( premultipliedAlpha ) {
19589
19590                                         switch ( blending ) {
19591
19592                                                 case NormalBlending:
19593                                                         gl.blendFuncSeparate( 1, 771, 1, 771 );
19594                                                         break;
19595
19596                                                 case AdditiveBlending:
19597                                                         gl.blendFunc( 1, 1 );
19598                                                         break;
19599
19600                                                 case SubtractiveBlending:
19601                                                         gl.blendFuncSeparate( 0, 0, 769, 771 );
19602                                                         break;
19603
19604                                                 case MultiplyBlending:
19605                                                         gl.blendFuncSeparate( 0, 768, 0, 770 );
19606                                                         break;
19607
19608                                                 default:
19609                                                         console.error( 'THREE.WebGLState: Invalid blending: ', blending );
19610                                                         break;
19611
19612                                         }
19613
19614                                 } else {
19615
19616                                         switch ( blending ) {
19617
19618                                                 case NormalBlending:
19619                                                         gl.blendFuncSeparate( 770, 771, 1, 771 );
19620                                                         break;
19621
19622                                                 case AdditiveBlending:
19623                                                         gl.blendFunc( 770, 1 );
19624                                                         break;
19625
19626                                                 case SubtractiveBlending:
19627                                                         gl.blendFunc( 0, 769 );
19628                                                         break;
19629
19630                                                 case MultiplyBlending:
19631                                                         gl.blendFunc( 0, 768 );
19632                                                         break;
19633
19634                                                 default:
19635                                                         console.error( 'THREE.WebGLState: Invalid blending: ', blending );
19636                                                         break;
19637
19638                                         }
19639
19640                                 }
19641
19642                                 currentBlendSrc = null;
19643                                 currentBlendDst = null;
19644                                 currentBlendSrcAlpha = null;
19645                                 currentBlendDstAlpha = null;
19646
19647                                 currentBlending = blending;
19648                                 currentPremultipledAlpha = premultipliedAlpha;
19649
19650                         }
19651
19652                         return;
19653
19654                 }
19655
19656                 // custom blending
19657
19658                 blendEquationAlpha = blendEquationAlpha || blendEquation;
19659                 blendSrcAlpha = blendSrcAlpha || blendSrc;
19660                 blendDstAlpha = blendDstAlpha || blendDst;
19661
19662                 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
19663
19664                         gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
19665
19666                         currentBlendEquation = blendEquation;
19667                         currentBlendEquationAlpha = blendEquationAlpha;
19668
19669                 }
19670
19671                 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
19672
19673                         gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
19674
19675                         currentBlendSrc = blendSrc;
19676                         currentBlendDst = blendDst;
19677                         currentBlendSrcAlpha = blendSrcAlpha;
19678                         currentBlendDstAlpha = blendDstAlpha;
19679
19680                 }
19681
19682                 currentBlending = blending;
19683                 currentPremultipledAlpha = null;
19684
19685         }
19686
19687         function setMaterial( material, frontFaceCW ) {
19688
19689                 material.side === DoubleSide
19690                         ? disable( 2884 )
19691                         : enable( 2884 );
19692
19693                 let flipSided = ( material.side === BackSide );
19694                 if ( frontFaceCW ) flipSided = ! flipSided;
19695
19696                 setFlipSided( flipSided );
19697
19698                 ( material.blending === NormalBlending && material.transparent === false )
19699                         ? setBlending( NoBlending )
19700                         : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
19701
19702                 depthBuffer.setFunc( material.depthFunc );
19703                 depthBuffer.setTest( material.depthTest );
19704                 depthBuffer.setMask( material.depthWrite );
19705                 colorBuffer.setMask( material.colorWrite );
19706
19707                 const stencilWrite = material.stencilWrite;
19708                 stencilBuffer.setTest( stencilWrite );
19709                 if ( stencilWrite ) {
19710
19711                         stencilBuffer.setMask( material.stencilWriteMask );
19712                         stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
19713                         stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
19714
19715                 }
19716
19717                 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
19718
19719         }
19720
19721         //
19722
19723         function setFlipSided( flipSided ) {
19724
19725                 if ( currentFlipSided !== flipSided ) {
19726
19727                         if ( flipSided ) {
19728
19729                                 gl.frontFace( 2304 );
19730
19731                         } else {
19732
19733                                 gl.frontFace( 2305 );
19734
19735                         }
19736
19737                         currentFlipSided = flipSided;
19738
19739                 }
19740
19741         }
19742
19743         function setCullFace( cullFace ) {
19744
19745                 if ( cullFace !== CullFaceNone ) {
19746
19747                         enable( 2884 );
19748
19749                         if ( cullFace !== currentCullFace ) {
19750
19751                                 if ( cullFace === CullFaceBack ) {
19752
19753                                         gl.cullFace( 1029 );
19754
19755                                 } else if ( cullFace === CullFaceFront ) {
19756
19757                                         gl.cullFace( 1028 );
19758
19759                                 } else {
19760
19761                                         gl.cullFace( 1032 );
19762
19763                                 }
19764
19765                         }
19766
19767                 } else {
19768
19769                         disable( 2884 );
19770
19771                 }
19772
19773                 currentCullFace = cullFace;
19774
19775         }
19776
19777         function setLineWidth( width ) {
19778
19779                 if ( width !== currentLineWidth ) {
19780
19781                         if ( lineWidthAvailable ) gl.lineWidth( width );
19782
19783                         currentLineWidth = width;
19784
19785                 }
19786
19787         }
19788
19789         function setPolygonOffset( polygonOffset, factor, units ) {
19790
19791                 if ( polygonOffset ) {
19792
19793                         enable( 32823 );
19794
19795                         if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
19796
19797                                 gl.polygonOffset( factor, units );
19798
19799                                 currentPolygonOffsetFactor = factor;
19800                                 currentPolygonOffsetUnits = units;
19801
19802                         }
19803
19804                 } else {
19805
19806                         disable( 32823 );
19807
19808                 }
19809
19810         }
19811
19812         function setScissorTest( scissorTest ) {
19813
19814                 if ( scissorTest ) {
19815
19816                         enable( 3089 );
19817
19818                 } else {
19819
19820                         disable( 3089 );
19821
19822                 }
19823
19824         }
19825
19826         // texture
19827
19828         function activeTexture( webglSlot ) {
19829
19830                 if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1;
19831
19832                 if ( currentTextureSlot !== webglSlot ) {
19833
19834                         gl.activeTexture( webglSlot );
19835                         currentTextureSlot = webglSlot;
19836
19837                 }
19838
19839         }
19840
19841         function bindTexture( webglType, webglTexture ) {
19842
19843                 if ( currentTextureSlot === null ) {
19844
19845                         activeTexture();
19846
19847                 }
19848
19849                 let boundTexture = currentBoundTextures[ currentTextureSlot ];
19850
19851                 if ( boundTexture === undefined ) {
19852
19853                         boundTexture = { type: undefined, texture: undefined };
19854                         currentBoundTextures[ currentTextureSlot ] = boundTexture;
19855
19856                 }
19857
19858                 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
19859
19860                         gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
19861
19862                         boundTexture.type = webglType;
19863                         boundTexture.texture = webglTexture;
19864
19865                 }
19866
19867         }
19868
19869         function unbindTexture() {
19870
19871                 const boundTexture = currentBoundTextures[ currentTextureSlot ];
19872
19873                 if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
19874
19875                         gl.bindTexture( boundTexture.type, null );
19876
19877                         boundTexture.type = undefined;
19878                         boundTexture.texture = undefined;
19879
19880                 }
19881
19882         }
19883
19884         function compressedTexImage2D() {
19885
19886                 try {
19887
19888                         gl.compressedTexImage2D.apply( gl, arguments );
19889
19890                 } catch ( error ) {
19891
19892                         console.error( 'THREE.WebGLState:', error );
19893
19894                 }
19895
19896         }
19897
19898         function texImage2D() {
19899
19900                 try {
19901
19902                         gl.texImage2D.apply( gl, arguments );
19903
19904                 } catch ( error ) {
19905
19906                         console.error( 'THREE.WebGLState:', error );
19907
19908                 }
19909
19910         }
19911
19912         function texImage3D() {
19913
19914                 try {
19915
19916                         gl.texImage3D.apply( gl, arguments );
19917
19918                 } catch ( error ) {
19919
19920                         console.error( 'THREE.WebGLState:', error );
19921
19922                 }
19923
19924         }
19925
19926         //
19927
19928         function scissor( scissor ) {
19929
19930                 if ( currentScissor.equals( scissor ) === false ) {
19931
19932                         gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
19933                         currentScissor.copy( scissor );
19934
19935                 }
19936
19937         }
19938
19939         function viewport( viewport ) {
19940
19941                 if ( currentViewport.equals( viewport ) === false ) {
19942
19943                         gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
19944                         currentViewport.copy( viewport );
19945
19946                 }
19947
19948         }
19949
19950         //
19951
19952         function reset() {
19953
19954                 enabledCapabilities = {};
19955
19956                 currentTextureSlot = null;
19957                 currentBoundTextures = {};
19958
19959                 currentProgram = null;
19960
19961                 currentBlendingEnabled = null;
19962                 currentBlending = null;
19963                 currentBlendEquation = null;
19964                 currentBlendSrc = null;
19965                 currentBlendDst = null;
19966                 currentBlendEquationAlpha = null;
19967                 currentBlendSrcAlpha = null;
19968                 currentBlendDstAlpha = null;
19969                 currentPremultipledAlpha = false;
19970
19971                 currentFlipSided = null;
19972                 currentCullFace = null;
19973
19974                 currentLineWidth = null;
19975
19976                 currentPolygonOffsetFactor = null;
19977                 currentPolygonOffsetUnits = null;
19978
19979                 colorBuffer.reset();
19980                 depthBuffer.reset();
19981                 stencilBuffer.reset();
19982
19983         }
19984
19985         return {
19986
19987                 buffers: {
19988                         color: colorBuffer,
19989                         depth: depthBuffer,
19990                         stencil: stencilBuffer
19991                 },
19992
19993                 enable: enable,
19994                 disable: disable,
19995
19996                 useProgram: useProgram,
19997
19998                 setBlending: setBlending,
19999                 setMaterial: setMaterial,
20000
20001                 setFlipSided: setFlipSided,
20002                 setCullFace: setCullFace,
20003
20004                 setLineWidth: setLineWidth,
20005                 setPolygonOffset: setPolygonOffset,
20006
20007                 setScissorTest: setScissorTest,
20008
20009                 activeTexture: activeTexture,
20010                 bindTexture: bindTexture,
20011                 unbindTexture: unbindTexture,
20012                 compressedTexImage2D: compressedTexImage2D,
20013                 texImage2D: texImage2D,
20014                 texImage3D: texImage3D,
20015
20016                 scissor: scissor,
20017                 viewport: viewport,
20018
20019                 reset: reset
20020
20021         };
20022
20023 }
20024
20025 function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
20026
20027         const isWebGL2 = capabilities.isWebGL2;
20028         const maxTextures = capabilities.maxTextures;
20029         const maxCubemapSize = capabilities.maxCubemapSize;
20030         const maxTextureSize = capabilities.maxTextureSize;
20031         const maxSamples = capabilities.maxSamples;
20032
20033         const _videoTextures = new WeakMap();
20034         let _canvas;
20035
20036         // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
20037         // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
20038         // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
20039
20040         let useOffscreenCanvas = false;
20041
20042         try {
20043
20044                 useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
20045                         && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null;
20046
20047         } catch ( err ) {
20048
20049                 // Ignore any errors
20050
20051         }
20052
20053         function createCanvas( width, height ) {
20054
20055                 // Use OffscreenCanvas when available. Specially needed in web workers
20056
20057                 return useOffscreenCanvas ?
20058                         new OffscreenCanvas( width, height ) :
20059                         document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
20060
20061         }
20062
20063         function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {
20064
20065                 let scale = 1;
20066
20067                 // handle case if texture exceeds max size
20068
20069                 if ( image.width > maxSize || image.height > maxSize ) {
20070
20071                         scale = maxSize / Math.max( image.width, image.height );
20072
20073                 }
20074
20075                 // only perform resize if necessary
20076
20077                 if ( scale < 1 || needsPowerOfTwo === true ) {
20078
20079                         // only perform resize for certain image types
20080
20081                         if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
20082                                 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
20083                                 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
20084
20085                                 const floor = needsPowerOfTwo ? MathUtils.floorPowerOfTwo : Math.floor;
20086
20087                                 const width = floor( scale * image.width );
20088                                 const height = floor( scale * image.height );
20089
20090                                 if ( _canvas === undefined ) _canvas = createCanvas( width, height );
20091
20092                                 // cube textures can't reuse the same canvas
20093
20094                                 const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
20095
20096                                 canvas.width = width;
20097                                 canvas.height = height;
20098
20099                                 const context = canvas.getContext( '2d' );
20100                                 context.drawImage( image, 0, 0, width, height );
20101
20102                                 console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );
20103
20104                                 return canvas;
20105
20106                         } else {
20107
20108                                 if ( 'data' in image ) {
20109
20110                                         console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
20111
20112                                 }
20113
20114                                 return image;
20115
20116                         }
20117
20118                 }
20119
20120                 return image;
20121
20122         }
20123
20124         function isPowerOfTwo( image ) {
20125
20126                 return MathUtils.isPowerOfTwo( image.width ) && MathUtils.isPowerOfTwo( image.height );
20127
20128         }
20129
20130         function textureNeedsPowerOfTwo( texture ) {
20131
20132                 if ( isWebGL2 ) return false;
20133
20134                 return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
20135                         ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
20136
20137         }
20138
20139         function textureNeedsGenerateMipmaps( texture, supportsMips ) {
20140
20141                 return texture.generateMipmaps && supportsMips &&
20142                         texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
20143
20144         }
20145
20146         function generateMipmap( target, texture, width, height ) {
20147
20148                 _gl.generateMipmap( target );
20149
20150                 const textureProperties = properties.get( texture );
20151
20152                 // Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
20153                 textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
20154
20155         }
20156
20157         function getInternalFormat( internalFormatName, glFormat, glType ) {
20158
20159                 if ( isWebGL2 === false ) return glFormat;
20160
20161                 if ( internalFormatName !== null ) {
20162
20163                         if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
20164
20165                         console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
20166
20167                 }
20168
20169                 let internalFormat = glFormat;
20170
20171                 if ( glFormat === 6403 ) {
20172
20173                         if ( glType === 5126 ) internalFormat = 33326;
20174                         if ( glType === 5131 ) internalFormat = 33325;
20175                         if ( glType === 5121 ) internalFormat = 33321;
20176
20177                 }
20178
20179                 if ( glFormat === 6407 ) {
20180
20181                         if ( glType === 5126 ) internalFormat = 34837;
20182                         if ( glType === 5131 ) internalFormat = 34843;
20183                         if ( glType === 5121 ) internalFormat = 32849;
20184
20185                 }
20186
20187                 if ( glFormat === 6408 ) {
20188
20189                         if ( glType === 5126 ) internalFormat = 34836;
20190                         if ( glType === 5131 ) internalFormat = 34842;
20191                         if ( glType === 5121 ) internalFormat = 32856;
20192
20193                 }
20194
20195                 if ( internalFormat === 33325 || internalFormat === 33326 ||
20196                         internalFormat === 34842 || internalFormat === 34836 ) {
20197
20198                         extensions.get( 'EXT_color_buffer_float' );
20199
20200                 }
20201
20202                 return internalFormat;
20203
20204         }
20205
20206         // Fallback filters for non-power-of-2 textures
20207
20208         function filterFallback( f ) {
20209
20210                 if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {
20211
20212                         return 9728;
20213
20214                 }
20215
20216                 return 9729;
20217
20218         }
20219
20220         //
20221
20222         function onTextureDispose( event ) {
20223
20224                 const texture = event.target;
20225
20226                 texture.removeEventListener( 'dispose', onTextureDispose );
20227
20228                 deallocateTexture( texture );
20229
20230                 if ( texture.isVideoTexture ) {
20231
20232                         _videoTextures.delete( texture );
20233
20234                 }
20235
20236                 info.memory.textures --;
20237
20238         }
20239
20240         function onRenderTargetDispose( event ) {
20241
20242                 const renderTarget = event.target;
20243
20244                 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
20245
20246                 deallocateRenderTarget( renderTarget );
20247
20248                 info.memory.textures --;
20249
20250         }
20251
20252         //
20253
20254         function deallocateTexture( texture ) {
20255
20256                 const textureProperties = properties.get( texture );
20257
20258                 if ( textureProperties.__webglInit === undefined ) return;
20259
20260                 _gl.deleteTexture( textureProperties.__webglTexture );
20261
20262                 properties.remove( texture );
20263
20264         }
20265
20266         function deallocateRenderTarget( renderTarget ) {
20267
20268                 const renderTargetProperties = properties.get( renderTarget );
20269                 const textureProperties = properties.get( renderTarget.texture );
20270
20271                 if ( ! renderTarget ) return;
20272
20273                 if ( textureProperties.__webglTexture !== undefined ) {
20274
20275                         _gl.deleteTexture( textureProperties.__webglTexture );
20276
20277                 }
20278
20279                 if ( renderTarget.depthTexture ) {
20280
20281                         renderTarget.depthTexture.dispose();
20282
20283                 }
20284
20285                 if ( renderTarget.isWebGLCubeRenderTarget ) {
20286
20287                         for ( let i = 0; i < 6; i ++ ) {
20288
20289                                 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
20290                                 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
20291
20292                         }
20293
20294                 } else {
20295
20296                         _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
20297                         if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
20298                         if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
20299                         if ( renderTargetProperties.__webglColorRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer );
20300                         if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
20301
20302                 }
20303
20304                 properties.remove( renderTarget.texture );
20305                 properties.remove( renderTarget );
20306
20307         }
20308
20309         //
20310
20311         let textureUnits = 0;
20312
20313         function resetTextureUnits() {
20314
20315                 textureUnits = 0;
20316
20317         }
20318
20319         function allocateTextureUnit() {
20320
20321                 const textureUnit = textureUnits;
20322
20323                 if ( textureUnit >= maxTextures ) {
20324
20325                         console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );
20326
20327                 }
20328
20329                 textureUnits += 1;
20330
20331                 return textureUnit;
20332
20333         }
20334
20335         //
20336
20337         function setTexture2D( texture, slot ) {
20338
20339                 const textureProperties = properties.get( texture );
20340
20341                 if ( texture.isVideoTexture ) updateVideoTexture( texture );
20342
20343                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20344
20345                         const image = texture.image;
20346
20347                         if ( image === undefined ) {
20348
20349                                 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );
20350
20351                         } else if ( image.complete === false ) {
20352
20353                                 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
20354
20355                         } else {
20356
20357                                 uploadTexture( textureProperties, texture, slot );
20358                                 return;
20359
20360                         }
20361
20362                 }
20363
20364                 state.activeTexture( 33984 + slot );
20365                 state.bindTexture( 3553, textureProperties.__webglTexture );
20366
20367         }
20368
20369         function setTexture2DArray( texture, slot ) {
20370
20371                 const textureProperties = properties.get( texture );
20372
20373                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20374
20375                         uploadTexture( textureProperties, texture, slot );
20376                         return;
20377
20378                 }
20379
20380                 state.activeTexture( 33984 + slot );
20381                 state.bindTexture( 35866, textureProperties.__webglTexture );
20382
20383         }
20384
20385         function setTexture3D( texture, slot ) {
20386
20387                 const textureProperties = properties.get( texture );
20388
20389                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20390
20391                         uploadTexture( textureProperties, texture, slot );
20392                         return;
20393
20394                 }
20395
20396                 state.activeTexture( 33984 + slot );
20397                 state.bindTexture( 32879, textureProperties.__webglTexture );
20398
20399         }
20400
20401         function setTextureCube( texture, slot ) {
20402
20403                 const textureProperties = properties.get( texture );
20404
20405                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20406
20407                         uploadCubeTexture( textureProperties, texture, slot );
20408                         return;
20409
20410                 }
20411
20412                 state.activeTexture( 33984 + slot );
20413                 state.bindTexture( 34067, textureProperties.__webglTexture );
20414
20415         }
20416
20417         const wrappingToGL = {
20418                 [ RepeatWrapping ]: 10497,
20419                 [ ClampToEdgeWrapping ]: 33071,
20420                 [ MirroredRepeatWrapping ]: 33648
20421         };
20422
20423         const filterToGL = {
20424                 [ NearestFilter ]: 9728,
20425                 [ NearestMipmapNearestFilter ]: 9984,
20426                 [ NearestMipmapLinearFilter ]: 9986,
20427
20428                 [ LinearFilter ]: 9729,
20429                 [ LinearMipmapNearestFilter ]: 9985,
20430                 [ LinearMipmapLinearFilter ]: 9987
20431         };
20432
20433         function setTextureParameters( textureType, texture, supportsMips ) {
20434
20435                 if ( supportsMips ) {
20436
20437                         _gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] );
20438                         _gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] );
20439
20440                         if ( textureType === 32879 || textureType === 35866 ) {
20441
20442                                 _gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] );
20443
20444                         }
20445
20446                         _gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] );
20447                         _gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] );
20448
20449                 } else {
20450
20451                         _gl.texParameteri( textureType, 10242, 33071 );
20452                         _gl.texParameteri( textureType, 10243, 33071 );
20453
20454                         if ( textureType === 32879 || textureType === 35866 ) {
20455
20456                                 _gl.texParameteri( textureType, 32882, 33071 );
20457
20458                         }
20459
20460                         if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
20461
20462                                 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
20463
20464                         }
20465
20466                         _gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );
20467                         _gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );
20468
20469                         if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
20470
20471                                 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
20472
20473                         }
20474
20475                 }
20476
20477                 const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
20478
20479                 if ( extension ) {
20480
20481                         if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
20482                         if ( texture.type === HalfFloatType && ( isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
20483
20484                         if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
20485
20486                                 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
20487                                 properties.get( texture ).__currentAnisotropy = texture.anisotropy;
20488
20489                         }
20490
20491                 }
20492
20493         }
20494
20495         function initTexture( textureProperties, texture ) {
20496
20497                 if ( textureProperties.__webglInit === undefined ) {
20498
20499                         textureProperties.__webglInit = true;
20500
20501                         texture.addEventListener( 'dispose', onTextureDispose );
20502
20503                         textureProperties.__webglTexture = _gl.createTexture();
20504
20505                         info.memory.textures ++;
20506
20507                 }
20508
20509         }
20510
20511         function uploadTexture( textureProperties, texture, slot ) {
20512
20513                 let textureType = 3553;
20514
20515                 if ( texture.isDataTexture2DArray ) textureType = 35866;
20516                 if ( texture.isDataTexture3D ) textureType = 32879;
20517
20518                 initTexture( textureProperties, texture );
20519
20520                 state.activeTexture( 33984 + slot );
20521                 state.bindTexture( textureType, textureProperties.__webglTexture );
20522
20523                 _gl.pixelStorei( 37440, texture.flipY );
20524                 _gl.pixelStorei( 37441, texture.premultiplyAlpha );
20525                 _gl.pixelStorei( 3317, texture.unpackAlignment );
20526
20527                 const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;
20528                 const image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );
20529
20530                 const supportsMips = isPowerOfTwo( image ) || isWebGL2,
20531                         glFormat = utils.convert( texture.format );
20532
20533                 let glType = utils.convert( texture.type ),
20534                         glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
20535
20536                 setTextureParameters( textureType, texture, supportsMips );
20537
20538                 let mipmap;
20539                 const mipmaps = texture.mipmaps;
20540
20541                 if ( texture.isDepthTexture ) {
20542
20543                         // populate depth texture with dummy data
20544
20545                         glInternalFormat = 6402;
20546
20547                         if ( isWebGL2 ) {
20548
20549                                 if ( texture.type === FloatType ) {
20550
20551                                         glInternalFormat = 36012;
20552
20553                                 } else if ( texture.type === UnsignedIntType ) {
20554
20555                                         glInternalFormat = 33190;
20556
20557                                 } else if ( texture.type === UnsignedInt248Type ) {
20558
20559                                         glInternalFormat = 35056;
20560
20561                                 } else {
20562
20563                                         glInternalFormat = 33189; // WebGL2 requires sized internalformat for glTexImage2D
20564
20565                                 }
20566
20567                         } else {
20568
20569                                 if ( texture.type === FloatType ) {
20570
20571                                         console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );
20572
20573                                 }
20574
20575                         }
20576
20577                         // validation checks for WebGL 1
20578
20579                         if ( texture.format === DepthFormat && glInternalFormat === 6402 ) {
20580
20581                                 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20582                                 // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
20583                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20584                                 if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
20585
20586                                         console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
20587
20588                                         texture.type = UnsignedShortType;
20589                                         glType = utils.convert( texture.type );
20590
20591                                 }
20592
20593                         }
20594
20595                         if ( texture.format === DepthStencilFormat && glInternalFormat === 6402 ) {
20596
20597                                 // Depth stencil textures need the DEPTH_STENCIL internal format
20598                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20599                                 glInternalFormat = 34041;
20600
20601                                 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20602                                 // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
20603                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20604                                 if ( texture.type !== UnsignedInt248Type ) {
20605
20606                                         console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
20607
20608                                         texture.type = UnsignedInt248Type;
20609                                         glType = utils.convert( texture.type );
20610
20611                                 }
20612
20613                         }
20614
20615                         //
20616
20617                         state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
20618
20619                 } else if ( texture.isDataTexture ) {
20620
20621                         // use manually created mipmaps if available
20622                         // if there are no manual mipmaps
20623                         // set 0 level mipmap and then use GL to generate other mipmap levels
20624
20625                         if ( mipmaps.length > 0 && supportsMips ) {
20626
20627                                 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
20628
20629                                         mipmap = mipmaps[ i ];
20630                                         state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20631
20632                                 }
20633
20634                                 texture.generateMipmaps = false;
20635                                 textureProperties.__maxMipLevel = mipmaps.length - 1;
20636
20637                         } else {
20638
20639                                 state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
20640                                 textureProperties.__maxMipLevel = 0;
20641
20642                         }
20643
20644                 } else if ( texture.isCompressedTexture ) {
20645
20646                         for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
20647
20648                                 mipmap = mipmaps[ i ];
20649
20650                                 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
20651
20652                                         if ( glFormat !== null ) {
20653
20654                                                 state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
20655
20656                                         } else {
20657
20658                                                 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
20659
20660                                         }
20661
20662                                 } else {
20663
20664                                         state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20665
20666                                 }
20667
20668                         }
20669
20670                         textureProperties.__maxMipLevel = mipmaps.length - 1;
20671
20672                 } else if ( texture.isDataTexture2DArray ) {
20673
20674                         state.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
20675                         textureProperties.__maxMipLevel = 0;
20676
20677                 } else if ( texture.isDataTexture3D ) {
20678
20679                         state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
20680                         textureProperties.__maxMipLevel = 0;
20681
20682                 } else {
20683
20684                         // regular Texture (image, video, canvas)
20685
20686                         // use manually created mipmaps if available
20687                         // if there are no manual mipmaps
20688                         // set 0 level mipmap and then use GL to generate other mipmap levels
20689
20690                         if ( mipmaps.length > 0 && supportsMips ) {
20691
20692                                 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
20693
20694                                         mipmap = mipmaps[ i ];
20695                                         state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );
20696
20697                                 }
20698
20699                                 texture.generateMipmaps = false;
20700                                 textureProperties.__maxMipLevel = mipmaps.length - 1;
20701
20702                         } else {
20703
20704                                 state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );
20705                                 textureProperties.__maxMipLevel = 0;
20706
20707                         }
20708
20709                 }
20710
20711                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
20712
20713                         generateMipmap( textureType, texture, image.width, image.height );
20714
20715                 }
20716
20717                 textureProperties.__version = texture.version;
20718
20719                 if ( texture.onUpdate ) texture.onUpdate( texture );
20720
20721         }
20722
20723         function uploadCubeTexture( textureProperties, texture, slot ) {
20724
20725                 if ( texture.image.length !== 6 ) return;
20726
20727                 initTexture( textureProperties, texture );
20728
20729                 state.activeTexture( 33984 + slot );
20730                 state.bindTexture( 34067, textureProperties.__webglTexture );
20731
20732                 _gl.pixelStorei( 37440, texture.flipY );
20733                 _gl.pixelStorei( 37441, texture.premultiplyAlpha );
20734                 _gl.pixelStorei( 3317, texture.unpackAlignment );
20735
20736                 const isCompressed = ( texture && ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ) );
20737                 const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
20738
20739                 const cubeImage = [];
20740
20741                 for ( let i = 0; i < 6; i ++ ) {
20742
20743                         if ( ! isCompressed && ! isDataTexture ) {
20744
20745                                 cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );
20746
20747                         } else {
20748
20749                                 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
20750
20751                         }
20752
20753                 }
20754
20755                 const image = cubeImage[ 0 ],
20756                         supportsMips = isPowerOfTwo( image ) || isWebGL2,
20757                         glFormat = utils.convert( texture.format ),
20758                         glType = utils.convert( texture.type ),
20759                         glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
20760
20761                 setTextureParameters( 34067, texture, supportsMips );
20762
20763                 let mipmaps;
20764
20765                 if ( isCompressed ) {
20766
20767                         for ( let i = 0; i < 6; i ++ ) {
20768
20769                                 mipmaps = cubeImage[ i ].mipmaps;
20770
20771                                 for ( let j = 0; j < mipmaps.length; j ++ ) {
20772
20773                                         const mipmap = mipmaps[ j ];
20774
20775                                         if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
20776
20777                                                 if ( glFormat !== null ) {
20778
20779                                                         state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
20780
20781                                                 } else {
20782
20783                                                         console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
20784
20785                                                 }
20786
20787                                         } else {
20788
20789                                                 state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20790
20791                                         }
20792
20793                                 }
20794
20795                         }
20796
20797                         textureProperties.__maxMipLevel = mipmaps.length - 1;
20798
20799                 } else {
20800
20801                         mipmaps = texture.mipmaps;
20802
20803                         for ( let i = 0; i < 6; i ++ ) {
20804
20805                                 if ( isDataTexture ) {
20806
20807                                         state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
20808
20809                                         for ( let j = 0; j < mipmaps.length; j ++ ) {
20810
20811                                                 const mipmap = mipmaps[ j ];
20812                                                 const mipmapImage = mipmap.image[ i ].image;
20813
20814                                                 state.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
20815
20816                                         }
20817
20818                                 } else {
20819
20820                                         state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
20821
20822                                         for ( let j = 0; j < mipmaps.length; j ++ ) {
20823
20824                                                 const mipmap = mipmaps[ j ];
20825
20826                                                 state.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
20827
20828                                         }
20829
20830                                 }
20831
20832                         }
20833
20834                         textureProperties.__maxMipLevel = mipmaps.length;
20835
20836                 }
20837
20838                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
20839
20840                         // We assume images for cube map have the same size.
20841                         generateMipmap( 34067, texture, image.width, image.height );
20842
20843                 }
20844
20845                 textureProperties.__version = texture.version;
20846
20847                 if ( texture.onUpdate ) texture.onUpdate( texture );
20848
20849         }
20850
20851         // Render targets
20852
20853         // Setup storage for target texture and bind it to correct framebuffer
20854         function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
20855
20856                 const glFormat = utils.convert( renderTarget.texture.format );
20857                 const glType = utils.convert( renderTarget.texture.type );
20858                 const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
20859                 state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
20860                 _gl.bindFramebuffer( 36160, framebuffer );
20861                 _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
20862                 _gl.bindFramebuffer( 36160, null );
20863
20864         }
20865
20866         // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
20867         function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
20868
20869                 _gl.bindRenderbuffer( 36161, renderbuffer );
20870
20871                 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
20872
20873                         let glInternalFormat = 33189;
20874
20875                         if ( isMultisample ) {
20876
20877                                 const depthTexture = renderTarget.depthTexture;
20878
20879                                 if ( depthTexture && depthTexture.isDepthTexture ) {
20880
20881                                         if ( depthTexture.type === FloatType ) {
20882
20883                                                 glInternalFormat = 36012;
20884
20885                                         } else if ( depthTexture.type === UnsignedIntType ) {
20886
20887                                                 glInternalFormat = 33190;
20888
20889                                         }
20890
20891                                 }
20892
20893                                 const samples = getRenderTargetSamples( renderTarget );
20894
20895                                 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
20896
20897                         } else {
20898
20899                                 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
20900
20901                         }
20902
20903                         _gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );
20904
20905                 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
20906
20907                         if ( isMultisample ) {
20908
20909                                 const samples = getRenderTargetSamples( renderTarget );
20910
20911                                 _gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height );
20912
20913                         } else {
20914
20915                                 _gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );
20916
20917                         }
20918
20919
20920                         _gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );
20921
20922                 } else {
20923
20924                         const glFormat = utils.convert( renderTarget.texture.format );
20925                         const glType = utils.convert( renderTarget.texture.type );
20926                         const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
20927
20928                         if ( isMultisample ) {
20929
20930                                 const samples = getRenderTargetSamples( renderTarget );
20931
20932                                 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
20933
20934                         } else {
20935
20936                                 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
20937
20938                         }
20939
20940                 }
20941
20942                 _gl.bindRenderbuffer( 36161, null );
20943
20944         }
20945
20946         // Setup resources for a Depth Texture for a FBO (needs an extension)
20947         function setupDepthTexture( framebuffer, renderTarget ) {
20948
20949                 const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
20950                 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
20951
20952                 _gl.bindFramebuffer( 36160, framebuffer );
20953
20954                 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
20955
20956                         throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
20957
20958                 }
20959
20960                 // upload an empty depth texture with framebuffer size
20961                 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
20962                                 renderTarget.depthTexture.image.width !== renderTarget.width ||
20963                                 renderTarget.depthTexture.image.height !== renderTarget.height ) {
20964
20965                         renderTarget.depthTexture.image.width = renderTarget.width;
20966                         renderTarget.depthTexture.image.height = renderTarget.height;
20967                         renderTarget.depthTexture.needsUpdate = true;
20968
20969                 }
20970
20971                 setTexture2D( renderTarget.depthTexture, 0 );
20972
20973                 const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
20974
20975                 if ( renderTarget.depthTexture.format === DepthFormat ) {
20976
20977                         _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );
20978
20979                 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
20980
20981                         _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );
20982
20983                 } else {
20984
20985                         throw new Error( 'Unknown depthTexture format' );
20986
20987                 }
20988
20989         }
20990
20991         // Setup GL resources for a non-texture depth buffer
20992         function setupDepthRenderbuffer( renderTarget ) {
20993
20994                 const renderTargetProperties = properties.get( renderTarget );
20995
20996                 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
20997
20998                 if ( renderTarget.depthTexture ) {
20999
21000                         if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
21001
21002                         setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
21003
21004                 } else {
21005
21006                         if ( isCube ) {
21007
21008                                 renderTargetProperties.__webglDepthbuffer = [];
21009
21010                                 for ( let i = 0; i < 6; i ++ ) {
21011
21012                                         _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );
21013                                         renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
21014                                         setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );
21015
21016                                 }
21017
21018                         } else {
21019
21020                                 _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
21021                                 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
21022                                 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );
21023
21024                         }
21025
21026                 }
21027
21028                 _gl.bindFramebuffer( 36160, null );
21029
21030         }
21031
21032         // Set up GL resources for the render target
21033         function setupRenderTarget( renderTarget ) {
21034
21035                 const renderTargetProperties = properties.get( renderTarget );
21036                 const textureProperties = properties.get( renderTarget.texture );
21037
21038                 renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
21039
21040                 textureProperties.__webglTexture = _gl.createTexture();
21041
21042                 info.memory.textures ++;
21043
21044                 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
21045                 const isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );
21046                 const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
21047
21048                 // Handles WebGL2 RGBFormat fallback - #18858
21049
21050                 if ( isWebGL2 && renderTarget.texture.format === RGBFormat && ( renderTarget.texture.type === FloatType || renderTarget.texture.type === HalfFloatType ) ) {
21051
21052                         renderTarget.texture.format = RGBAFormat;
21053
21054                         console.warn( 'THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.' );
21055
21056                 }
21057
21058                 // Setup framebuffer
21059
21060                 if ( isCube ) {
21061
21062                         renderTargetProperties.__webglFramebuffer = [];
21063
21064                         for ( let i = 0; i < 6; i ++ ) {
21065
21066                                 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
21067
21068                         }
21069
21070                 } else {
21071
21072                         renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
21073
21074                         if ( isMultisample ) {
21075
21076                                 if ( isWebGL2 ) {
21077
21078                                         renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
21079                                         renderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();
21080
21081                                         _gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer );
21082
21083                                         const glFormat = utils.convert( renderTarget.texture.format );
21084                                         const glType = utils.convert( renderTarget.texture.type );
21085                                         const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
21086                                         const samples = getRenderTargetSamples( renderTarget );
21087                                         _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
21088
21089                                         _gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
21090                                         _gl.framebufferRenderbuffer( 36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer );
21091                                         _gl.bindRenderbuffer( 36161, null );
21092
21093                                         if ( renderTarget.depthBuffer ) {
21094
21095                                                 renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
21096                                                 setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
21097
21098                                         }
21099
21100                                         _gl.bindFramebuffer( 36160, null );
21101
21102
21103                                 } else {
21104
21105                                         console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
21106
21107                                 }
21108
21109                         }
21110
21111                 }
21112
21113                 // Setup color buffer
21114
21115                 if ( isCube ) {
21116
21117                         state.bindTexture( 34067, textureProperties.__webglTexture );
21118                         setTextureParameters( 34067, renderTarget.texture, supportsMips );
21119
21120                         for ( let i = 0; i < 6; i ++ ) {
21121
21122                                 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, 36064, 34069 + i );
21123
21124                         }
21125
21126                         if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
21127
21128                                 generateMipmap( 34067, renderTarget.texture, renderTarget.width, renderTarget.height );
21129
21130                         }
21131
21132                         state.bindTexture( 34067, null );
21133
21134                 } else {
21135
21136                         state.bindTexture( 3553, textureProperties.__webglTexture );
21137                         setTextureParameters( 3553, renderTarget.texture, supportsMips );
21138                         setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, 36064, 3553 );
21139
21140                         if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
21141
21142                                 generateMipmap( 3553, renderTarget.texture, renderTarget.width, renderTarget.height );
21143
21144                         }
21145
21146                         state.bindTexture( 3553, null );
21147
21148                 }
21149
21150                 // Setup depth and stencil buffers
21151
21152                 if ( renderTarget.depthBuffer ) {
21153
21154                         setupDepthRenderbuffer( renderTarget );
21155
21156                 }
21157
21158         }
21159
21160         function updateRenderTargetMipmap( renderTarget ) {
21161
21162                 const texture = renderTarget.texture;
21163                 const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
21164
21165                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
21166
21167                         const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553;
21168                         const webglTexture = properties.get( texture ).__webglTexture;
21169
21170                         state.bindTexture( target, webglTexture );
21171                         generateMipmap( target, texture, renderTarget.width, renderTarget.height );
21172                         state.bindTexture( target, null );
21173
21174                 }
21175
21176         }
21177
21178         function updateMultisampleRenderTarget( renderTarget ) {
21179
21180                 if ( renderTarget.isWebGLMultisampleRenderTarget ) {
21181
21182                         if ( isWebGL2 ) {
21183
21184                                 const renderTargetProperties = properties.get( renderTarget );
21185
21186                                 _gl.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );
21187                                 _gl.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );
21188
21189                                 const width = renderTarget.width;
21190                                 const height = renderTarget.height;
21191                                 let mask = 16384;
21192
21193                                 if ( renderTarget.depthBuffer ) mask |= 256;
21194                                 if ( renderTarget.stencilBuffer ) mask |= 1024;
21195
21196                                 _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );
21197
21198                                 _gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); // see #18905
21199
21200                         } else {
21201
21202                                 console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
21203
21204                         }
21205
21206                 }
21207
21208         }
21209
21210         function getRenderTargetSamples( renderTarget ) {
21211
21212                 return ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?
21213                         Math.min( maxSamples, renderTarget.samples ) : 0;
21214
21215         }
21216
21217         function updateVideoTexture( texture ) {
21218
21219                 const frame = info.render.frame;
21220
21221                 // Check the last frame we updated the VideoTexture
21222
21223                 if ( _videoTextures.get( texture ) !== frame ) {
21224
21225                         _videoTextures.set( texture, frame );
21226                         texture.update();
21227
21228                 }
21229
21230         }
21231
21232         // backwards compatibility
21233
21234         let warnedTexture2D = false;
21235         let warnedTextureCube = false;
21236
21237         function safeSetTexture2D( texture, slot ) {
21238
21239                 if ( texture && texture.isWebGLRenderTarget ) {
21240
21241                         if ( warnedTexture2D === false ) {
21242
21243                                 console.warn( 'THREE.WebGLTextures.safeSetTexture2D: don\'t use render targets as textures. Use their .texture property instead.' );
21244                                 warnedTexture2D = true;
21245
21246                         }
21247
21248                         texture = texture.texture;
21249
21250                 }
21251
21252                 setTexture2D( texture, slot );
21253
21254         }
21255
21256         function safeSetTextureCube( texture, slot ) {
21257
21258                 if ( texture && texture.isWebGLCubeRenderTarget ) {
21259
21260                         if ( warnedTextureCube === false ) {
21261
21262                                 console.warn( 'THREE.WebGLTextures.safeSetTextureCube: don\'t use cube render targets as textures. Use their .texture property instead.' );
21263                                 warnedTextureCube = true;
21264
21265                         }
21266
21267                         texture = texture.texture;
21268
21269                 }
21270
21271
21272                 setTextureCube( texture, slot );
21273
21274         }
21275
21276         //
21277
21278         this.allocateTextureUnit = allocateTextureUnit;
21279         this.resetTextureUnits = resetTextureUnits;
21280
21281         this.setTexture2D = setTexture2D;
21282         this.setTexture2DArray = setTexture2DArray;
21283         this.setTexture3D = setTexture3D;
21284         this.setTextureCube = setTextureCube;
21285         this.setupRenderTarget = setupRenderTarget;
21286         this.updateRenderTargetMipmap = updateRenderTargetMipmap;
21287         this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
21288
21289         this.safeSetTexture2D = safeSetTexture2D;
21290         this.safeSetTextureCube = safeSetTextureCube;
21291
21292 }
21293
21294 function WebGLUtils( gl, extensions, capabilities ) {
21295
21296         const isWebGL2 = capabilities.isWebGL2;
21297
21298         function convert( p ) {
21299
21300                 let extension;
21301
21302                 if ( p === UnsignedByteType ) return 5121;
21303                 if ( p === UnsignedShort4444Type ) return 32819;
21304                 if ( p === UnsignedShort5551Type ) return 32820;
21305                 if ( p === UnsignedShort565Type ) return 33635;
21306
21307                 if ( p === ByteType ) return 5120;
21308                 if ( p === ShortType ) return 5122;
21309                 if ( p === UnsignedShortType ) return 5123;
21310                 if ( p === IntType ) return 5124;
21311                 if ( p === UnsignedIntType ) return 5125;
21312                 if ( p === FloatType ) return 5126;
21313
21314                 if ( p === HalfFloatType ) {
21315
21316                         if ( isWebGL2 ) return 5131;
21317
21318                         extension = extensions.get( 'OES_texture_half_float' );
21319
21320                         if ( extension !== null ) {
21321
21322                                 return extension.HALF_FLOAT_OES;
21323
21324                         } else {
21325
21326                                 return null;
21327
21328                         }
21329
21330                 }
21331
21332                 if ( p === AlphaFormat ) return 6406;
21333                 if ( p === RGBFormat ) return 6407;
21334                 if ( p === RGBAFormat ) return 6408;
21335                 if ( p === LuminanceFormat ) return 6409;
21336                 if ( p === LuminanceAlphaFormat ) return 6410;
21337                 if ( p === DepthFormat ) return 6402;
21338                 if ( p === DepthStencilFormat ) return 34041;
21339                 if ( p === RedFormat ) return 6403;
21340
21341                 // WebGL2 formats.
21342
21343                 if ( p === RedIntegerFormat ) return 36244;
21344                 if ( p === RGFormat ) return 33319;
21345                 if ( p === RGIntegerFormat ) return 33320;
21346                 if ( p === RGBIntegerFormat ) return 36248;
21347                 if ( p === RGBAIntegerFormat ) return 36249;
21348
21349                 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
21350                         p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
21351
21352                         extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
21353
21354                         if ( extension !== null ) {
21355
21356                                 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
21357                                 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
21358                                 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
21359                                 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
21360
21361                         } else {
21362
21363                                 return null;
21364
21365                         }
21366
21367                 }
21368
21369                 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
21370                         p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
21371
21372                         extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
21373
21374                         if ( extension !== null ) {
21375
21376                                 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
21377                                 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
21378                                 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
21379                                 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
21380
21381                         } else {
21382
21383                                 return null;
21384
21385                         }
21386
21387                 }
21388
21389                 if ( p === RGB_ETC1_Format ) {
21390
21391                         extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
21392
21393                         if ( extension !== null ) {
21394
21395                                 return extension.COMPRESSED_RGB_ETC1_WEBGL;
21396
21397                         } else {
21398
21399                                 return null;
21400
21401                         }
21402
21403                 }
21404
21405                 if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {
21406
21407                         extension = extensions.get( 'WEBGL_compressed_texture_etc' );
21408
21409                         if ( extension !== null ) {
21410
21411                                 if ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2;
21412                                 if ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC;
21413
21414                         }
21415
21416                 }
21417
21418                 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
21419                         p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
21420                         p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
21421                         p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
21422                         p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ||
21423                         p === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format ||
21424                         p === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format ||
21425                         p === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format ||
21426                         p === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format ||
21427                         p === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) {
21428
21429                         extension = extensions.get( 'WEBGL_compressed_texture_astc' );
21430
21431                         if ( extension !== null ) {
21432
21433                                 // TODO Complete?
21434
21435                                 return p;
21436
21437                         } else {
21438
21439                                 return null;
21440
21441                         }
21442
21443                 }
21444
21445                 if ( p === RGBA_BPTC_Format ) {
21446
21447                         extension = extensions.get( 'EXT_texture_compression_bptc' );
21448
21449                         if ( extension !== null ) {
21450
21451                                 // TODO Complete?
21452
21453                                 return p;
21454
21455                         } else {
21456
21457                                 return null;
21458
21459                         }
21460
21461                 }
21462
21463                 if ( p === UnsignedInt248Type ) {
21464
21465                         if ( isWebGL2 ) return 34042;
21466
21467                         extension = extensions.get( 'WEBGL_depth_texture' );
21468
21469                         if ( extension !== null ) {
21470
21471                                 return extension.UNSIGNED_INT_24_8_WEBGL;
21472
21473                         } else {
21474
21475                                 return null;
21476
21477                         }
21478
21479                 }
21480
21481         }
21482
21483         return { convert: convert };
21484
21485 }
21486
21487 function ArrayCamera( array = [] ) {
21488
21489         PerspectiveCamera.call( this );
21490
21491         this.cameras = array;
21492
21493 }
21494
21495 ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
21496
21497         constructor: ArrayCamera,
21498
21499         isArrayCamera: true
21500
21501 } );
21502
21503 function Group() {
21504
21505         Object3D.call( this );
21506
21507         this.type = 'Group';
21508
21509 }
21510
21511 Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
21512
21513         constructor: Group,
21514
21515         isGroup: true
21516
21517 } );
21518
21519 function WebXRController() {
21520
21521         this._targetRay = null;
21522         this._grip = null;
21523         this._hand = null;
21524
21525 }
21526
21527 Object.assign( WebXRController.prototype, {
21528
21529         constructor: WebXRController,
21530
21531         getHandSpace: function () {
21532
21533                 if ( this._hand === null ) {
21534
21535                         this._hand = new Group();
21536                         this._hand.matrixAutoUpdate = false;
21537                         this._hand.visible = false;
21538
21539                         this._hand.joints = {};
21540                         this._hand.inputState = { pinching: false };
21541
21542                 }
21543
21544                 return this._hand;
21545
21546         },
21547
21548         getTargetRaySpace: function () {
21549
21550                 if ( this._targetRay === null ) {
21551
21552                         this._targetRay = new Group();
21553                         this._targetRay.matrixAutoUpdate = false;
21554                         this._targetRay.visible = false;
21555
21556                 }
21557
21558                 return this._targetRay;
21559
21560         },
21561
21562         getGripSpace: function () {
21563
21564                 if ( this._grip === null ) {
21565
21566                         this._grip = new Group();
21567                         this._grip.matrixAutoUpdate = false;
21568                         this._grip.visible = false;
21569
21570                 }
21571
21572                 return this._grip;
21573
21574         },
21575
21576         dispatchEvent: function ( event ) {
21577
21578                 if ( this._targetRay !== null ) {
21579
21580                         this._targetRay.dispatchEvent( event );
21581
21582                 }
21583
21584                 if ( this._grip !== null ) {
21585
21586                         this._grip.dispatchEvent( event );
21587
21588                 }
21589
21590                 if ( this._hand !== null ) {
21591
21592                         this._hand.dispatchEvent( event );
21593
21594                 }
21595
21596                 return this;
21597
21598         },
21599
21600         disconnect: function ( inputSource ) {
21601
21602                 this.dispatchEvent( { type: 'disconnected', data: inputSource } );
21603
21604                 if ( this._targetRay !== null ) {
21605
21606                         this._targetRay.visible = false;
21607
21608                 }
21609
21610                 if ( this._grip !== null ) {
21611
21612                         this._grip.visible = false;
21613
21614                 }
21615
21616                 if ( this._hand !== null ) {
21617
21618                         this._hand.visible = false;
21619
21620                 }
21621
21622                 return this;
21623
21624         },
21625
21626         update: function ( inputSource, frame, referenceSpace ) {
21627
21628                 let inputPose = null;
21629                 let gripPose = null;
21630                 let handPose = null;
21631
21632                 const targetRay = this._targetRay;
21633                 const grip = this._grip;
21634                 const hand = this._hand;
21635
21636                 if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
21637
21638                         if ( hand && inputSource.hand ) {
21639
21640                                 handPose = true;
21641
21642                                 for ( const inputjoint of inputSource.hand.values() ) {
21643
21644                                         // Update the joints groups with the XRJoint poses
21645                                         const jointPose = frame.getJointPose( inputjoint, referenceSpace );
21646
21647                                         if ( hand.joints[ inputjoint.jointName ] === undefined ) {
21648
21649                                                 // The transform of this joint will be updated with the joint pose on each frame
21650                                                 const joint = new Group();
21651                                                 joint.matrixAutoUpdate = false;
21652                                                 joint.visible = false;
21653                                                 hand.joints[ inputjoint.jointName ] = joint;
21654                                                 // ??
21655                                                 hand.add( joint );
21656
21657                                         }
21658
21659                                         const joint = hand.joints[ inputjoint.jointName ];
21660
21661                                         if ( jointPose !== null ) {
21662
21663                                                 joint.matrix.fromArray( jointPose.transform.matrix );
21664                                                 joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
21665                                                 joint.jointRadius = jointPose.radius;
21666
21667                                         }
21668
21669                                         joint.visible = jointPose !== null;
21670
21671                                 }
21672
21673                                 // Custom events
21674
21675                                 // Check pinchz
21676                                 const indexTip = hand.joints[ 'index-finger-tip' ];
21677                                 const thumbTip = hand.joints[ 'thumb-tip' ];
21678                                 const distance = indexTip.position.distanceTo( thumbTip.position );
21679
21680                                 const distanceToPinch = 0.02;
21681                                 const threshold = 0.005;
21682
21683                                 if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
21684
21685                                         hand.inputState.pinching = false;
21686                                         this.dispatchEvent( {
21687                                                 type: 'pinchend',
21688                                                 handedness: inputSource.handedness,
21689                                                 target: this
21690                                         } );
21691
21692                                 } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
21693
21694                                         hand.inputState.pinching = true;
21695                                         this.dispatchEvent( {
21696                                                 type: 'pinchstart',
21697                                                 handedness: inputSource.handedness,
21698                                                 target: this
21699                                         } );
21700
21701                                 }
21702
21703                         } else {
21704
21705                                 if ( targetRay !== null ) {
21706
21707                                         inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
21708
21709                                         if ( inputPose !== null ) {
21710
21711                                                 targetRay.matrix.fromArray( inputPose.transform.matrix );
21712                                                 targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
21713
21714                                         }
21715
21716                                 }
21717
21718                                 if ( grip !== null && inputSource.gripSpace ) {
21719
21720                                         gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
21721
21722                                         if ( gripPose !== null ) {
21723
21724                                                 grip.matrix.fromArray( gripPose.transform.matrix );
21725                                                 grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
21726
21727                                         }
21728
21729                                 }
21730
21731                         }
21732
21733                 }
21734
21735                 if ( targetRay !== null ) {
21736
21737                         targetRay.visible = ( inputPose !== null );
21738
21739                 }
21740
21741                 if ( grip !== null ) {
21742
21743                         grip.visible = ( gripPose !== null );
21744
21745                 }
21746
21747                 if ( hand !== null ) {
21748
21749                         hand.visible = ( handPose !== null );
21750
21751                 }
21752
21753                 return this;
21754
21755         }
21756
21757 } );
21758
21759 function WebXRManager( renderer, gl ) {
21760
21761         const scope = this;
21762
21763         let session = null;
21764
21765         let framebufferScaleFactor = 1.0;
21766
21767         let referenceSpace = null;
21768         let referenceSpaceType = 'local-floor';
21769
21770         let pose = null;
21771
21772         const controllers = [];
21773         const inputSourcesMap = new Map();
21774
21775         //
21776
21777         const cameraL = new PerspectiveCamera();
21778         cameraL.layers.enable( 1 );
21779         cameraL.viewport = new Vector4();
21780
21781         const cameraR = new PerspectiveCamera();
21782         cameraR.layers.enable( 2 );
21783         cameraR.viewport = new Vector4();
21784
21785         const cameras = [ cameraL, cameraR ];
21786
21787         const cameraVR = new ArrayCamera();
21788         cameraVR.layers.enable( 1 );
21789         cameraVR.layers.enable( 2 );
21790
21791         let _currentDepthNear = null;
21792         let _currentDepthFar = null;
21793
21794         //
21795
21796         this.enabled = false;
21797
21798         this.isPresenting = false;
21799
21800         this.getController = function ( index ) {
21801
21802                 let controller = controllers[ index ];
21803
21804                 if ( controller === undefined ) {
21805
21806                         controller = new WebXRController();
21807                         controllers[ index ] = controller;
21808
21809                 }
21810
21811                 return controller.getTargetRaySpace();
21812
21813         };
21814
21815         this.getControllerGrip = function ( index ) {
21816
21817                 let controller = controllers[ index ];
21818
21819                 if ( controller === undefined ) {
21820
21821                         controller = new WebXRController();
21822                         controllers[ index ] = controller;
21823
21824                 }
21825
21826                 return controller.getGripSpace();
21827
21828         };
21829
21830         this.getHand = function ( index ) {
21831
21832                 let controller = controllers[ index ];
21833
21834                 if ( controller === undefined ) {
21835
21836                         controller = new WebXRController();
21837                         controllers[ index ] = controller;
21838
21839                 }
21840
21841                 return controller.getHandSpace();
21842
21843         };
21844
21845         //
21846
21847         function onSessionEvent( event ) {
21848
21849                 const controller = inputSourcesMap.get( event.inputSource );
21850
21851                 if ( controller ) {
21852
21853                         controller.dispatchEvent( { type: event.type, data: event.inputSource } );
21854
21855                 }
21856
21857         }
21858
21859         function onSessionEnd() {
21860
21861                 inputSourcesMap.forEach( function ( controller, inputSource ) {
21862
21863                         controller.disconnect( inputSource );
21864
21865                 } );
21866
21867                 inputSourcesMap.clear();
21868
21869                 _currentDepthNear = null;
21870                 _currentDepthFar = null;
21871
21872                 //
21873
21874                 renderer.setFramebuffer( null );
21875                 renderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830
21876                 animation.stop();
21877
21878                 scope.isPresenting = false;
21879
21880                 scope.dispatchEvent( { type: 'sessionend' } );
21881
21882         }
21883
21884         this.setFramebufferScaleFactor = function ( value ) {
21885
21886                 framebufferScaleFactor = value;
21887
21888                 if ( scope.isPresenting === true ) {
21889
21890                         console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
21891
21892                 }
21893
21894         };
21895
21896         this.setReferenceSpaceType = function ( value ) {
21897
21898                 referenceSpaceType = value;
21899
21900                 if ( scope.isPresenting === true ) {
21901
21902                         console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
21903
21904                 }
21905
21906         };
21907
21908         this.getReferenceSpace = function () {
21909
21910                 return referenceSpace;
21911
21912         };
21913
21914         this.getSession = function () {
21915
21916                 return session;
21917
21918         };
21919
21920         this.setSession = async function ( value ) {
21921
21922                 session = value;
21923
21924                 if ( session !== null ) {
21925
21926                         session.addEventListener( 'select', onSessionEvent );
21927                         session.addEventListener( 'selectstart', onSessionEvent );
21928                         session.addEventListener( 'selectend', onSessionEvent );
21929                         session.addEventListener( 'squeeze', onSessionEvent );
21930                         session.addEventListener( 'squeezestart', onSessionEvent );
21931                         session.addEventListener( 'squeezeend', onSessionEvent );
21932                         session.addEventListener( 'end', onSessionEnd );
21933                         session.addEventListener( 'inputsourceschange', onInputSourcesChange );
21934
21935                         const attributes = gl.getContextAttributes();
21936
21937                         if ( attributes.xrCompatible !== true ) {
21938
21939                                 await gl.makeXRCompatible();
21940
21941                         }
21942
21943                         const layerInit = {
21944                                 antialias: attributes.antialias,
21945                                 alpha: attributes.alpha,
21946                                 depth: attributes.depth,
21947                                 stencil: attributes.stencil,
21948                                 framebufferScaleFactor: framebufferScaleFactor
21949                         };
21950
21951                         // eslint-disable-next-line no-undef
21952                         const baseLayer = new XRWebGLLayer( session, gl, layerInit );
21953
21954                         session.updateRenderState( { baseLayer: baseLayer } );
21955
21956                         referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
21957
21958                         animation.setContext( session );
21959                         animation.start();
21960
21961                         scope.isPresenting = true;
21962
21963                         scope.dispatchEvent( { type: 'sessionstart' } );
21964
21965                 }
21966
21967         };
21968
21969         function onInputSourcesChange( event ) {
21970
21971                 const inputSources = session.inputSources;
21972
21973                 // Assign inputSources to available controllers
21974
21975                 for ( let i = 0; i < controllers.length; i ++ ) {
21976
21977                         inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
21978
21979                 }
21980
21981                 // Notify disconnected
21982
21983                 for ( let i = 0; i < event.removed.length; i ++ ) {
21984
21985                         const inputSource = event.removed[ i ];
21986                         const controller = inputSourcesMap.get( inputSource );
21987
21988                         if ( controller ) {
21989
21990                                 controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
21991                                 inputSourcesMap.delete( inputSource );
21992
21993                         }
21994
21995                 }
21996
21997                 // Notify connected
21998
21999                 for ( let i = 0; i < event.added.length; i ++ ) {
22000
22001                         const inputSource = event.added[ i ];
22002                         const controller = inputSourcesMap.get( inputSource );
22003
22004                         if ( controller ) {
22005
22006                                 controller.dispatchEvent( { type: 'connected', data: inputSource } );
22007
22008                         }
22009
22010                 }
22011
22012         }
22013
22014         //
22015
22016         const cameraLPos = new Vector3();
22017         const cameraRPos = new Vector3();
22018
22019         /**
22020          * Assumes 2 cameras that are parallel and share an X-axis, and that
22021          * the cameras' projection and world matrices have already been set.
22022          * And that near and far planes are identical for both cameras.
22023          * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
22024          */
22025         function setProjectionFromUnion( camera, cameraL, cameraR ) {
22026
22027                 cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
22028                 cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
22029
22030                 const ipd = cameraLPos.distanceTo( cameraRPos );
22031
22032                 const projL = cameraL.projectionMatrix.elements;
22033                 const projR = cameraR.projectionMatrix.elements;
22034
22035                 // VR systems will have identical far and near planes, and
22036                 // most likely identical top and bottom frustum extents.
22037                 // Use the left camera for these values.
22038                 const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
22039                 const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
22040                 const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
22041                 const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
22042
22043                 const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
22044                 const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
22045                 const left = near * leftFov;
22046                 const right = near * rightFov;
22047
22048                 // Calculate the new camera's position offset from the
22049                 // left camera. xOffset should be roughly half `ipd`.
22050                 const zOffset = ipd / ( - leftFov + rightFov );
22051                 const xOffset = zOffset * - leftFov;
22052
22053                 // TODO: Better way to apply this offset?
22054                 cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
22055                 camera.translateX( xOffset );
22056                 camera.translateZ( zOffset );
22057                 camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
22058                 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
22059
22060                 // Find the union of the frustum values of the cameras and scale
22061                 // the values so that the near plane's position does not change in world space,
22062                 // although must now be relative to the new union camera.
22063                 const near2 = near + zOffset;
22064                 const far2 = far + zOffset;
22065                 const left2 = left - xOffset;
22066                 const right2 = right + ( ipd - xOffset );
22067                 const top2 = topFov * far / far2 * near2;
22068                 const bottom2 = bottomFov * far / far2 * near2;
22069
22070                 camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
22071
22072         }
22073
22074         function updateCamera( camera, parent ) {
22075
22076                 if ( parent === null ) {
22077
22078                         camera.matrixWorld.copy( camera.matrix );
22079
22080                 } else {
22081
22082                         camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
22083
22084                 }
22085
22086                 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
22087
22088         }
22089
22090         this.getCamera = function ( camera ) {
22091
22092                 cameraVR.near = cameraR.near = cameraL.near = camera.near;
22093                 cameraVR.far = cameraR.far = cameraL.far = camera.far;
22094
22095                 if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
22096
22097                         // Note that the new renderState won't apply until the next frame. See #18320
22098
22099                         session.updateRenderState( {
22100                                 depthNear: cameraVR.near,
22101                                 depthFar: cameraVR.far
22102                         } );
22103
22104                         _currentDepthNear = cameraVR.near;
22105                         _currentDepthFar = cameraVR.far;
22106
22107                 }
22108
22109                 const parent = camera.parent;
22110                 const cameras = cameraVR.cameras;
22111
22112                 updateCamera( cameraVR, parent );
22113
22114                 for ( let i = 0; i < cameras.length; i ++ ) {
22115
22116                         updateCamera( cameras[ i ], parent );
22117
22118                 }
22119
22120                 // update camera and its children
22121
22122                 camera.matrixWorld.copy( cameraVR.matrixWorld );
22123                 camera.matrix.copy( cameraVR.matrix );
22124                 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
22125
22126                 const children = camera.children;
22127
22128                 for ( let i = 0, l = children.length; i < l; i ++ ) {
22129
22130                         children[ i ].updateMatrixWorld( true );
22131
22132                 }
22133
22134                 // update projection matrix for proper view frustum culling
22135
22136                 if ( cameras.length === 2 ) {
22137
22138                         setProjectionFromUnion( cameraVR, cameraL, cameraR );
22139
22140                 } else {
22141
22142                         // assume single camera setup (AR)
22143
22144                         cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
22145
22146                 }
22147
22148                 return cameraVR;
22149
22150         };
22151
22152         // Animation Loop
22153
22154         let onAnimationFrameCallback = null;
22155
22156         function onAnimationFrame( time, frame ) {
22157
22158                 pose = frame.getViewerPose( referenceSpace );
22159
22160                 if ( pose !== null ) {
22161
22162                         const views = pose.views;
22163                         const baseLayer = session.renderState.baseLayer;
22164
22165                         renderer.setFramebuffer( baseLayer.framebuffer );
22166
22167                         let cameraVRNeedsUpdate = false;
22168
22169                         // check if it's necessary to rebuild cameraVR's camera list
22170
22171                         if ( views.length !== cameraVR.cameras.length ) {
22172
22173                                 cameraVR.cameras.length = 0;
22174                                 cameraVRNeedsUpdate = true;
22175
22176                         }
22177
22178                         for ( let i = 0; i < views.length; i ++ ) {
22179
22180                                 const view = views[ i ];
22181                                 const viewport = baseLayer.getViewport( view );
22182
22183                                 const camera = cameras[ i ];
22184                                 camera.matrix.fromArray( view.transform.matrix );
22185                                 camera.projectionMatrix.fromArray( view.projectionMatrix );
22186                                 camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
22187
22188                                 if ( i === 0 ) {
22189
22190                                         cameraVR.matrix.copy( camera.matrix );
22191
22192                                 }
22193
22194                                 if ( cameraVRNeedsUpdate === true ) {
22195
22196                                         cameraVR.cameras.push( camera );
22197
22198                                 }
22199
22200                         }
22201
22202                 }
22203
22204                 //
22205
22206                 const inputSources = session.inputSources;
22207
22208                 for ( let i = 0; i < controllers.length; i ++ ) {
22209
22210                         const controller = controllers[ i ];
22211                         const inputSource = inputSources[ i ];
22212
22213                         controller.update( inputSource, frame, referenceSpace );
22214
22215                 }
22216
22217                 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
22218
22219         }
22220
22221         const animation = new WebGLAnimation();
22222         animation.setAnimationLoop( onAnimationFrame );
22223
22224         this.setAnimationLoop = function ( callback ) {
22225
22226                 onAnimationFrameCallback = callback;
22227
22228         };
22229
22230         this.dispose = function () {};
22231
22232 }
22233
22234 Object.assign( WebXRManager.prototype, EventDispatcher.prototype );
22235
22236 function WebGLMaterials( properties ) {
22237
22238         function refreshFogUniforms( uniforms, fog ) {
22239
22240                 uniforms.fogColor.value.copy( fog.color );
22241
22242                 if ( fog.isFog ) {
22243
22244                         uniforms.fogNear.value = fog.near;
22245                         uniforms.fogFar.value = fog.far;
22246
22247                 } else if ( fog.isFogExp2 ) {
22248
22249                         uniforms.fogDensity.value = fog.density;
22250
22251                 }
22252
22253         }
22254
22255         function refreshMaterialUniforms( uniforms, material, pixelRatio, height ) {
22256
22257                 if ( material.isMeshBasicMaterial ) {
22258
22259                         refreshUniformsCommon( uniforms, material );
22260
22261                 } else if ( material.isMeshLambertMaterial ) {
22262
22263                         refreshUniformsCommon( uniforms, material );
22264                         refreshUniformsLambert( uniforms, material );
22265
22266                 } else if ( material.isMeshToonMaterial ) {
22267
22268                         refreshUniformsCommon( uniforms, material );
22269                         refreshUniformsToon( uniforms, material );
22270
22271                 } else if ( material.isMeshPhongMaterial ) {
22272
22273                         refreshUniformsCommon( uniforms, material );
22274                         refreshUniformsPhong( uniforms, material );
22275
22276                 } else if ( material.isMeshStandardMaterial ) {
22277
22278                         refreshUniformsCommon( uniforms, material );
22279
22280                         if ( material.isMeshPhysicalMaterial ) {
22281
22282                                 refreshUniformsPhysical( uniforms, material );
22283
22284                         } else {
22285
22286                                 refreshUniformsStandard( uniforms, material );
22287
22288                         }
22289
22290                 } else if ( material.isMeshMatcapMaterial ) {
22291
22292                         refreshUniformsCommon( uniforms, material );
22293                         refreshUniformsMatcap( uniforms, material );
22294
22295                 } else if ( material.isMeshDepthMaterial ) {
22296
22297                         refreshUniformsCommon( uniforms, material );
22298                         refreshUniformsDepth( uniforms, material );
22299
22300                 } else if ( material.isMeshDistanceMaterial ) {
22301
22302                         refreshUniformsCommon( uniforms, material );
22303                         refreshUniformsDistance( uniforms, material );
22304
22305                 } else if ( material.isMeshNormalMaterial ) {
22306
22307                         refreshUniformsCommon( uniforms, material );
22308                         refreshUniformsNormal( uniforms, material );
22309
22310                 } else if ( material.isLineBasicMaterial ) {
22311
22312                         refreshUniformsLine( uniforms, material );
22313
22314                         if ( material.isLineDashedMaterial ) {
22315
22316                                 refreshUniformsDash( uniforms, material );
22317
22318                         }
22319
22320                 } else if ( material.isPointsMaterial ) {
22321
22322                         refreshUniformsPoints( uniforms, material, pixelRatio, height );
22323
22324                 } else if ( material.isSpriteMaterial ) {
22325
22326                         refreshUniformsSprites( uniforms, material );
22327
22328                 } else if ( material.isShadowMaterial ) {
22329
22330                         uniforms.color.value.copy( material.color );
22331                         uniforms.opacity.value = material.opacity;
22332
22333                 } else if ( material.isShaderMaterial ) {
22334
22335                         material.uniformsNeedUpdate = false; // #15581
22336
22337                 }
22338
22339         }
22340
22341         function refreshUniformsCommon( uniforms, material ) {
22342
22343                 uniforms.opacity.value = material.opacity;
22344
22345                 if ( material.color ) {
22346
22347                         uniforms.diffuse.value.copy( material.color );
22348
22349                 }
22350
22351                 if ( material.emissive ) {
22352
22353                         uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
22354
22355                 }
22356
22357                 if ( material.map ) {
22358
22359                         uniforms.map.value = material.map;
22360
22361                 }
22362
22363                 if ( material.alphaMap ) {
22364
22365                         uniforms.alphaMap.value = material.alphaMap;
22366
22367                 }
22368
22369                 if ( material.specularMap ) {
22370
22371                         uniforms.specularMap.value = material.specularMap;
22372
22373                 }
22374
22375                 const envMap = properties.get( material ).envMap;
22376
22377                 if ( envMap ) {
22378
22379                         uniforms.envMap.value = envMap;
22380
22381                         uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap._needsFlipEnvMap ) ? - 1 : 1;
22382
22383                         uniforms.reflectivity.value = material.reflectivity;
22384                         uniforms.refractionRatio.value = material.refractionRatio;
22385
22386                         const maxMipLevel = properties.get( envMap ).__maxMipLevel;
22387
22388                         if ( maxMipLevel !== undefined ) {
22389
22390                                 uniforms.maxMipLevel.value = maxMipLevel;
22391
22392                         }
22393
22394                 }
22395
22396                 if ( material.lightMap ) {
22397
22398                         uniforms.lightMap.value = material.lightMap;
22399                         uniforms.lightMapIntensity.value = material.lightMapIntensity;
22400
22401                 }
22402
22403                 if ( material.aoMap ) {
22404
22405                         uniforms.aoMap.value = material.aoMap;
22406                         uniforms.aoMapIntensity.value = material.aoMapIntensity;
22407
22408                 }
22409
22410                 // uv repeat and offset setting priorities
22411                 // 1. color map
22412                 // 2. specular map
22413                 // 3. displacementMap map
22414                 // 4. normal map
22415                 // 5. bump map
22416                 // 6. roughnessMap map
22417                 // 7. metalnessMap map
22418                 // 8. alphaMap map
22419                 // 9. emissiveMap map
22420                 // 10. clearcoat map
22421                 // 11. clearcoat normal map
22422                 // 12. clearcoat roughnessMap map
22423
22424                 let uvScaleMap;
22425
22426                 if ( material.map ) {
22427
22428                         uvScaleMap = material.map;
22429
22430                 } else if ( material.specularMap ) {
22431
22432                         uvScaleMap = material.specularMap;
22433
22434                 } else if ( material.displacementMap ) {
22435
22436                         uvScaleMap = material.displacementMap;
22437
22438                 } else if ( material.normalMap ) {
22439
22440                         uvScaleMap = material.normalMap;
22441
22442                 } else if ( material.bumpMap ) {
22443
22444                         uvScaleMap = material.bumpMap;
22445
22446                 } else if ( material.roughnessMap ) {
22447
22448                         uvScaleMap = material.roughnessMap;
22449
22450                 } else if ( material.metalnessMap ) {
22451
22452                         uvScaleMap = material.metalnessMap;
22453
22454                 } else if ( material.alphaMap ) {
22455
22456                         uvScaleMap = material.alphaMap;
22457
22458                 } else if ( material.emissiveMap ) {
22459
22460                         uvScaleMap = material.emissiveMap;
22461
22462                 } else if ( material.clearcoatMap ) {
22463
22464                         uvScaleMap = material.clearcoatMap;
22465
22466                 } else if ( material.clearcoatNormalMap ) {
22467
22468                         uvScaleMap = material.clearcoatNormalMap;
22469
22470                 } else if ( material.clearcoatRoughnessMap ) {
22471
22472                         uvScaleMap = material.clearcoatRoughnessMap;
22473
22474                 }
22475
22476                 if ( uvScaleMap !== undefined ) {
22477
22478                         // backwards compatibility
22479                         if ( uvScaleMap.isWebGLRenderTarget ) {
22480
22481                                 uvScaleMap = uvScaleMap.texture;
22482
22483                         }
22484
22485                         if ( uvScaleMap.matrixAutoUpdate === true ) {
22486
22487                                 uvScaleMap.updateMatrix();
22488
22489                         }
22490
22491                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
22492
22493                 }
22494
22495                 // uv repeat and offset setting priorities for uv2
22496                 // 1. ao map
22497                 // 2. light map
22498
22499                 let uv2ScaleMap;
22500
22501                 if ( material.aoMap ) {
22502
22503                         uv2ScaleMap = material.aoMap;
22504
22505                 } else if ( material.lightMap ) {
22506
22507                         uv2ScaleMap = material.lightMap;
22508
22509                 }
22510
22511                 if ( uv2ScaleMap !== undefined ) {
22512
22513                         // backwards compatibility
22514                         if ( uv2ScaleMap.isWebGLRenderTarget ) {
22515
22516                                 uv2ScaleMap = uv2ScaleMap.texture;
22517
22518                         }
22519
22520                         if ( uv2ScaleMap.matrixAutoUpdate === true ) {
22521
22522                                 uv2ScaleMap.updateMatrix();
22523
22524                         }
22525
22526                         uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );
22527
22528                 }
22529
22530         }
22531
22532         function refreshUniformsLine( uniforms, material ) {
22533
22534                 uniforms.diffuse.value.copy( material.color );
22535                 uniforms.opacity.value = material.opacity;
22536
22537         }
22538
22539         function refreshUniformsDash( uniforms, material ) {
22540
22541                 uniforms.dashSize.value = material.dashSize;
22542                 uniforms.totalSize.value = material.dashSize + material.gapSize;
22543                 uniforms.scale.value = material.scale;
22544
22545         }
22546
22547         function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
22548
22549                 uniforms.diffuse.value.copy( material.color );
22550                 uniforms.opacity.value = material.opacity;
22551                 uniforms.size.value = material.size * pixelRatio;
22552                 uniforms.scale.value = height * 0.5;
22553
22554                 if ( material.map ) {
22555
22556                         uniforms.map.value = material.map;
22557
22558                 }
22559
22560                 if ( material.alphaMap ) {
22561
22562                         uniforms.alphaMap.value = material.alphaMap;
22563
22564                 }
22565
22566                 // uv repeat and offset setting priorities
22567                 // 1. color map
22568                 // 2. alpha map
22569
22570                 let uvScaleMap;
22571
22572                 if ( material.map ) {
22573
22574                         uvScaleMap = material.map;
22575
22576                 } else if ( material.alphaMap ) {
22577
22578                         uvScaleMap = material.alphaMap;
22579
22580                 }
22581
22582                 if ( uvScaleMap !== undefined ) {
22583
22584                         if ( uvScaleMap.matrixAutoUpdate === true ) {
22585
22586                                 uvScaleMap.updateMatrix();
22587
22588                         }
22589
22590                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
22591
22592                 }
22593
22594         }
22595
22596         function refreshUniformsSprites( uniforms, material ) {
22597
22598                 uniforms.diffuse.value.copy( material.color );
22599                 uniforms.opacity.value = material.opacity;
22600                 uniforms.rotation.value = material.rotation;
22601
22602                 if ( material.map ) {
22603
22604                         uniforms.map.value = material.map;
22605
22606                 }
22607
22608                 if ( material.alphaMap ) {
22609
22610                         uniforms.alphaMap.value = material.alphaMap;
22611
22612                 }
22613
22614                 // uv repeat and offset setting priorities
22615                 // 1. color map
22616                 // 2. alpha map
22617
22618                 let uvScaleMap;
22619
22620                 if ( material.map ) {
22621
22622                         uvScaleMap = material.map;
22623
22624                 } else if ( material.alphaMap ) {
22625
22626                         uvScaleMap = material.alphaMap;
22627
22628                 }
22629
22630                 if ( uvScaleMap !== undefined ) {
22631
22632                         if ( uvScaleMap.matrixAutoUpdate === true ) {
22633
22634                                 uvScaleMap.updateMatrix();
22635
22636                         }
22637
22638                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
22639
22640                 }
22641
22642         }
22643
22644         function refreshUniformsLambert( uniforms, material ) {
22645
22646                 if ( material.emissiveMap ) {
22647
22648                         uniforms.emissiveMap.value = material.emissiveMap;
22649
22650                 }
22651
22652         }
22653
22654         function refreshUniformsPhong( uniforms, material ) {
22655
22656                 uniforms.specular.value.copy( material.specular );
22657                 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
22658
22659                 if ( material.emissiveMap ) {
22660
22661                         uniforms.emissiveMap.value = material.emissiveMap;
22662
22663                 }
22664
22665                 if ( material.bumpMap ) {
22666
22667                         uniforms.bumpMap.value = material.bumpMap;
22668                         uniforms.bumpScale.value = material.bumpScale;
22669                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
22670
22671                 }
22672
22673                 if ( material.normalMap ) {
22674
22675                         uniforms.normalMap.value = material.normalMap;
22676                         uniforms.normalScale.value.copy( material.normalScale );
22677                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
22678
22679                 }
22680
22681                 if ( material.displacementMap ) {
22682
22683                         uniforms.displacementMap.value = material.displacementMap;
22684                         uniforms.displacementScale.value = material.displacementScale;
22685                         uniforms.displacementBias.value = material.displacementBias;
22686
22687                 }
22688
22689         }
22690
22691         function refreshUniformsToon( uniforms, material ) {
22692
22693                 if ( material.gradientMap ) {
22694
22695                         uniforms.gradientMap.value = material.gradientMap;
22696
22697                 }
22698
22699                 if ( material.emissiveMap ) {
22700
22701                         uniforms.emissiveMap.value = material.emissiveMap;
22702
22703                 }
22704
22705                 if ( material.bumpMap ) {
22706
22707                         uniforms.bumpMap.value = material.bumpMap;
22708                         uniforms.bumpScale.value = material.bumpScale;
22709                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
22710
22711                 }
22712
22713                 if ( material.normalMap ) {
22714
22715                         uniforms.normalMap.value = material.normalMap;
22716                         uniforms.normalScale.value.copy( material.normalScale );
22717                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
22718
22719                 }
22720
22721                 if ( material.displacementMap ) {
22722
22723                         uniforms.displacementMap.value = material.displacementMap;
22724                         uniforms.displacementScale.value = material.displacementScale;
22725                         uniforms.displacementBias.value = material.displacementBias;
22726
22727                 }
22728
22729         }
22730
22731         function refreshUniformsStandard( uniforms, material ) {
22732
22733                 uniforms.roughness.value = material.roughness;
22734                 uniforms.metalness.value = material.metalness;
22735
22736                 if ( material.roughnessMap ) {
22737
22738                         uniforms.roughnessMap.value = material.roughnessMap;
22739
22740                 }
22741
22742                 if ( material.metalnessMap ) {
22743
22744                         uniforms.metalnessMap.value = material.metalnessMap;
22745
22746                 }
22747
22748                 if ( material.emissiveMap ) {
22749
22750                         uniforms.emissiveMap.value = material.emissiveMap;
22751
22752                 }
22753
22754                 if ( material.bumpMap ) {
22755
22756                         uniforms.bumpMap.value = material.bumpMap;
22757                         uniforms.bumpScale.value = material.bumpScale;
22758                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
22759
22760                 }
22761
22762                 if ( material.normalMap ) {
22763
22764                         uniforms.normalMap.value = material.normalMap;
22765                         uniforms.normalScale.value.copy( material.normalScale );
22766                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
22767
22768                 }
22769
22770                 if ( material.displacementMap ) {
22771
22772                         uniforms.displacementMap.value = material.displacementMap;
22773                         uniforms.displacementScale.value = material.displacementScale;
22774                         uniforms.displacementBias.value = material.displacementBias;
22775
22776                 }
22777
22778                 const envMap = properties.get( material ).envMap;
22779
22780                 if ( envMap ) {
22781
22782                         //uniforms.envMap.value = material.envMap; // part of uniforms common
22783                         uniforms.envMapIntensity.value = material.envMapIntensity;
22784
22785                 }
22786
22787         }
22788
22789         function refreshUniformsPhysical( uniforms, material ) {
22790
22791                 refreshUniformsStandard( uniforms, material );
22792
22793                 uniforms.reflectivity.value = material.reflectivity; // also part of uniforms common
22794
22795                 uniforms.clearcoat.value = material.clearcoat;
22796                 uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
22797                 if ( material.sheen ) uniforms.sheen.value.copy( material.sheen );
22798
22799                 if ( material.clearcoatMap ) {
22800
22801                         uniforms.clearcoatMap.value = material.clearcoatMap;
22802
22803                 }
22804
22805                 if ( material.clearcoatRoughnessMap ) {
22806
22807                         uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
22808
22809                 }
22810
22811                 if ( material.clearcoatNormalMap ) {
22812
22813                         uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
22814                         uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
22815
22816                         if ( material.side === BackSide ) {
22817
22818                                 uniforms.clearcoatNormalScale.value.negate();
22819
22820                         }
22821
22822                 }
22823
22824                 uniforms.transmission.value = material.transmission;
22825
22826                 if ( material.transmissionMap ) {
22827
22828                         uniforms.transmissionMap.value = material.transmissionMap;
22829
22830                 }
22831
22832         }
22833
22834         function refreshUniformsMatcap( uniforms, material ) {
22835
22836                 if ( material.matcap ) {
22837
22838                         uniforms.matcap.value = material.matcap;
22839
22840                 }
22841
22842                 if ( material.bumpMap ) {
22843
22844                         uniforms.bumpMap.value = material.bumpMap;
22845                         uniforms.bumpScale.value = material.bumpScale;
22846                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
22847
22848                 }
22849
22850                 if ( material.normalMap ) {
22851
22852                         uniforms.normalMap.value = material.normalMap;
22853                         uniforms.normalScale.value.copy( material.normalScale );
22854                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
22855
22856                 }
22857
22858                 if ( material.displacementMap ) {
22859
22860                         uniforms.displacementMap.value = material.displacementMap;
22861                         uniforms.displacementScale.value = material.displacementScale;
22862                         uniforms.displacementBias.value = material.displacementBias;
22863
22864                 }
22865
22866         }
22867
22868         function refreshUniformsDepth( uniforms, material ) {
22869
22870                 if ( material.displacementMap ) {
22871
22872                         uniforms.displacementMap.value = material.displacementMap;
22873                         uniforms.displacementScale.value = material.displacementScale;
22874                         uniforms.displacementBias.value = material.displacementBias;
22875
22876                 }
22877
22878         }
22879
22880         function refreshUniformsDistance( uniforms, material ) {
22881
22882                 if ( material.displacementMap ) {
22883
22884                         uniforms.displacementMap.value = material.displacementMap;
22885                         uniforms.displacementScale.value = material.displacementScale;
22886                         uniforms.displacementBias.value = material.displacementBias;
22887
22888                 }
22889
22890                 uniforms.referencePosition.value.copy( material.referencePosition );
22891                 uniforms.nearDistance.value = material.nearDistance;
22892                 uniforms.farDistance.value = material.farDistance;
22893
22894         }
22895
22896         function refreshUniformsNormal( uniforms, material ) {
22897
22898                 if ( material.bumpMap ) {
22899
22900                         uniforms.bumpMap.value = material.bumpMap;
22901                         uniforms.bumpScale.value = material.bumpScale;
22902                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
22903
22904                 }
22905
22906                 if ( material.normalMap ) {
22907
22908                         uniforms.normalMap.value = material.normalMap;
22909                         uniforms.normalScale.value.copy( material.normalScale );
22910                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
22911
22912                 }
22913
22914                 if ( material.displacementMap ) {
22915
22916                         uniforms.displacementMap.value = material.displacementMap;
22917                         uniforms.displacementScale.value = material.displacementScale;
22918                         uniforms.displacementBias.value = material.displacementBias;
22919
22920                 }
22921
22922         }
22923
22924         return {
22925                 refreshFogUniforms: refreshFogUniforms,
22926                 refreshMaterialUniforms: refreshMaterialUniforms
22927         };
22928
22929 }
22930
22931 function createCanvasElement() {
22932
22933         const canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
22934         canvas.style.display = 'block';
22935         return canvas;
22936
22937 }
22938
22939 function WebGLRenderer( parameters ) {
22940
22941         parameters = parameters || {};
22942
22943         const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(),
22944                 _context = parameters.context !== undefined ? parameters.context : null,
22945
22946                 _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
22947                 _depth = parameters.depth !== undefined ? parameters.depth : true,
22948                 _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
22949                 _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
22950                 _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
22951                 _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
22952                 _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',
22953                 _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;
22954
22955         let currentRenderList = null;
22956         let currentRenderState = null;
22957
22958         // render() can be called from within a callback triggered by another render.
22959         // We track this so that the nested render call gets its state isolated from the parent render call.
22960
22961         const renderStateStack = [];
22962
22963         // public properties
22964
22965         this.domElement = _canvas;
22966
22967         // Debug configuration container
22968         this.debug = {
22969
22970                 /**
22971                  * Enables error checking and reporting when shader programs are being compiled
22972                  * @type {boolean}
22973                  */
22974                 checkShaderErrors: true
22975         };
22976
22977         // clearing
22978
22979         this.autoClear = true;
22980         this.autoClearColor = true;
22981         this.autoClearDepth = true;
22982         this.autoClearStencil = true;
22983
22984         // scene graph
22985
22986         this.sortObjects = true;
22987
22988         // user-defined clipping
22989
22990         this.clippingPlanes = [];
22991         this.localClippingEnabled = false;
22992
22993         // physically based shading
22994
22995         this.gammaFactor = 2.0; // for backwards compatibility
22996         this.outputEncoding = LinearEncoding;
22997
22998         // physical lights
22999
23000         this.physicallyCorrectLights = false;
23001
23002         // tone mapping
23003
23004         this.toneMapping = NoToneMapping;
23005         this.toneMappingExposure = 1.0;
23006
23007         // morphs
23008
23009         this.maxMorphTargets = 8;
23010         this.maxMorphNormals = 4;
23011
23012         // internal properties
23013
23014         const _this = this;
23015
23016         let _isContextLost = false;
23017
23018         // internal state cache
23019
23020         let _framebuffer = null;
23021
23022         let _currentActiveCubeFace = 0;
23023         let _currentActiveMipmapLevel = 0;
23024         let _currentRenderTarget = null;
23025         let _currentFramebuffer = null;
23026         let _currentMaterialId = - 1;
23027
23028         let _currentCamera = null;
23029
23030         const _currentViewport = new Vector4();
23031         const _currentScissor = new Vector4();
23032         let _currentScissorTest = null;
23033
23034         //
23035
23036         let _width = _canvas.width;
23037         let _height = _canvas.height;
23038
23039         let _pixelRatio = 1;
23040         let _opaqueSort = null;
23041         let _transparentSort = null;
23042
23043         const _viewport = new Vector4( 0, 0, _width, _height );
23044         const _scissor = new Vector4( 0, 0, _width, _height );
23045         let _scissorTest = false;
23046
23047         // frustum
23048
23049         const _frustum = new Frustum();
23050
23051         // clipping
23052
23053         let _clippingEnabled = false;
23054         let _localClippingEnabled = false;
23055
23056         // camera matrices cache
23057
23058         const _projScreenMatrix = new Matrix4();
23059
23060         const _vector3 = new Vector3();
23061
23062         const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
23063
23064         function getTargetPixelRatio() {
23065
23066                 return _currentRenderTarget === null ? _pixelRatio : 1;
23067
23068         }
23069
23070         // initialize
23071
23072         let _gl = _context;
23073
23074         function getContext( contextNames, contextAttributes ) {
23075
23076                 for ( let i = 0; i < contextNames.length; i ++ ) {
23077
23078                         const contextName = contextNames[ i ];
23079                         const context = _canvas.getContext( contextName, contextAttributes );
23080                         if ( context !== null ) return context;
23081
23082                 }
23083
23084                 return null;
23085
23086         }
23087
23088         try {
23089
23090                 const contextAttributes = {
23091                         alpha: _alpha,
23092                         depth: _depth,
23093                         stencil: _stencil,
23094                         antialias: _antialias,
23095                         premultipliedAlpha: _premultipliedAlpha,
23096                         preserveDrawingBuffer: _preserveDrawingBuffer,
23097                         powerPreference: _powerPreference,
23098                         failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat
23099                 };
23100
23101                 // event listeners must be registered before WebGL context is created, see #12753
23102
23103                 _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
23104                 _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
23105
23106                 if ( _gl === null ) {
23107
23108                         const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ];
23109
23110                         if ( _this.isWebGL1Renderer === true ) {
23111
23112                                 contextNames.shift();
23113
23114                         }
23115
23116                         _gl = getContext( contextNames, contextAttributes );
23117
23118                         if ( _gl === null ) {
23119
23120                                 if ( getContext( contextNames ) ) {
23121
23122                                         throw new Error( 'Error creating WebGL context with your selected attributes.' );
23123
23124                                 } else {
23125
23126                                         throw new Error( 'Error creating WebGL context.' );
23127
23128                                 }
23129
23130                         }
23131
23132                 }
23133
23134                 // Some experimental-webgl implementations do not have getShaderPrecisionFormat
23135
23136                 if ( _gl.getShaderPrecisionFormat === undefined ) {
23137
23138                         _gl.getShaderPrecisionFormat = function () {
23139
23140                                 return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
23141
23142                         };
23143
23144                 }
23145
23146         } catch ( error ) {
23147
23148                 console.error( 'THREE.WebGLRenderer: ' + error.message );
23149                 throw error;
23150
23151         }
23152
23153         let extensions, capabilities, state, info;
23154         let properties, textures, cubemaps, attributes, geometries, objects;
23155         let programCache, materials, renderLists, renderStates, clipping;
23156
23157         let background, morphtargets, bufferRenderer, indexedBufferRenderer;
23158
23159         let utils, bindingStates;
23160
23161         function initGLContext() {
23162
23163                 extensions = new WebGLExtensions( _gl );
23164
23165                 capabilities = new WebGLCapabilities( _gl, extensions, parameters );
23166
23167                 extensions.init( capabilities );
23168
23169                 utils = new WebGLUtils( _gl, extensions, capabilities );
23170
23171                 state = new WebGLState( _gl, extensions, capabilities );
23172                 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
23173                 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
23174
23175                 info = new WebGLInfo( _gl );
23176                 properties = new WebGLProperties();
23177                 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
23178                 cubemaps = new WebGLCubeMaps( _this );
23179                 attributes = new WebGLAttributes( _gl, capabilities );
23180                 bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities );
23181                 geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
23182                 objects = new WebGLObjects( _gl, geometries, attributes, info );
23183                 morphtargets = new WebGLMorphtargets( _gl );
23184                 clipping = new WebGLClipping( properties );
23185                 programCache = new WebGLPrograms( _this, cubemaps, extensions, capabilities, bindingStates, clipping );
23186                 materials = new WebGLMaterials( properties );
23187                 renderLists = new WebGLRenderLists( properties );
23188                 renderStates = new WebGLRenderStates( extensions, capabilities );
23189                 background = new WebGLBackground( _this, cubemaps, state, objects, _premultipliedAlpha );
23190
23191                 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
23192                 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
23193
23194                 info.programs = programCache.programs;
23195
23196                 _this.capabilities = capabilities;
23197                 _this.extensions = extensions;
23198                 _this.properties = properties;
23199                 _this.renderLists = renderLists;
23200                 _this.state = state;
23201                 _this.info = info;
23202
23203         }
23204
23205         initGLContext();
23206
23207         // xr
23208
23209         const xr = new WebXRManager( _this, _gl );
23210
23211         this.xr = xr;
23212
23213         // shadow map
23214
23215         const shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
23216
23217         this.shadowMap = shadowMap;
23218
23219         // API
23220
23221         this.getContext = function () {
23222
23223                 return _gl;
23224
23225         };
23226
23227         this.getContextAttributes = function () {
23228
23229                 return _gl.getContextAttributes();
23230
23231         };
23232
23233         this.forceContextLoss = function () {
23234
23235                 const extension = extensions.get( 'WEBGL_lose_context' );
23236                 if ( extension ) extension.loseContext();
23237
23238         };
23239
23240         this.forceContextRestore = function () {
23241
23242                 const extension = extensions.get( 'WEBGL_lose_context' );
23243                 if ( extension ) extension.restoreContext();
23244
23245         };
23246
23247         this.getPixelRatio = function () {
23248
23249                 return _pixelRatio;
23250
23251         };
23252
23253         this.setPixelRatio = function ( value ) {
23254
23255                 if ( value === undefined ) return;
23256
23257                 _pixelRatio = value;
23258
23259                 this.setSize( _width, _height, false );
23260
23261         };
23262
23263         this.getSize = function ( target ) {
23264
23265                 if ( target === undefined ) {
23266
23267                         console.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );
23268
23269                         target = new Vector2();
23270
23271                 }
23272
23273                 return target.set( _width, _height );
23274
23275         };
23276
23277         this.setSize = function ( width, height, updateStyle ) {
23278
23279                 if ( xr.isPresenting ) {
23280
23281                         console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
23282                         return;
23283
23284                 }
23285
23286                 _width = width;
23287                 _height = height;
23288
23289                 _canvas.width = Math.floor( width * _pixelRatio );
23290                 _canvas.height = Math.floor( height * _pixelRatio );
23291
23292                 if ( updateStyle !== false ) {
23293
23294                         _canvas.style.width = width + 'px';
23295                         _canvas.style.height = height + 'px';
23296
23297                 }
23298
23299                 this.setViewport( 0, 0, width, height );
23300
23301         };
23302
23303         this.getDrawingBufferSize = function ( target ) {
23304
23305                 if ( target === undefined ) {
23306
23307                         console.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );
23308
23309                         target = new Vector2();
23310
23311                 }
23312
23313                 return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
23314
23315         };
23316
23317         this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
23318
23319                 _width = width;
23320                 _height = height;
23321
23322                 _pixelRatio = pixelRatio;
23323
23324                 _canvas.width = Math.floor( width * pixelRatio );
23325                 _canvas.height = Math.floor( height * pixelRatio );
23326
23327                 this.setViewport( 0, 0, width, height );
23328
23329         };
23330
23331         this.getCurrentViewport = function ( target ) {
23332
23333                 if ( target === undefined ) {
23334
23335                         console.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );
23336
23337                         target = new Vector4();
23338
23339                 }
23340
23341                 return target.copy( _currentViewport );
23342
23343         };
23344
23345         this.getViewport = function ( target ) {
23346
23347                 return target.copy( _viewport );
23348
23349         };
23350
23351         this.setViewport = function ( x, y, width, height ) {
23352
23353                 if ( x.isVector4 ) {
23354
23355                         _viewport.set( x.x, x.y, x.z, x.w );
23356
23357                 } else {
23358
23359                         _viewport.set( x, y, width, height );
23360
23361                 }
23362
23363                 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
23364
23365         };
23366
23367         this.getScissor = function ( target ) {
23368
23369                 return target.copy( _scissor );
23370
23371         };
23372
23373         this.setScissor = function ( x, y, width, height ) {
23374
23375                 if ( x.isVector4 ) {
23376
23377                         _scissor.set( x.x, x.y, x.z, x.w );
23378
23379                 } else {
23380
23381                         _scissor.set( x, y, width, height );
23382
23383                 }
23384
23385                 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
23386
23387         };
23388
23389         this.getScissorTest = function () {
23390
23391                 return _scissorTest;
23392
23393         };
23394
23395         this.setScissorTest = function ( boolean ) {
23396
23397                 state.setScissorTest( _scissorTest = boolean );
23398
23399         };
23400
23401         this.setOpaqueSort = function ( method ) {
23402
23403                 _opaqueSort = method;
23404
23405         };
23406
23407         this.setTransparentSort = function ( method ) {
23408
23409                 _transparentSort = method;
23410
23411         };
23412
23413         // Clearing
23414
23415         this.getClearColor = function ( target ) {
23416
23417                 if ( target === undefined ) {
23418
23419                         console.warn( 'WebGLRenderer: .getClearColor() now requires a Color as an argument' );
23420
23421                         target = new Color();
23422
23423                 }
23424
23425                 return target.copy( background.getClearColor() );
23426
23427         };
23428
23429         this.setClearColor = function () {
23430
23431                 background.setClearColor.apply( background, arguments );
23432
23433         };
23434
23435         this.getClearAlpha = function () {
23436
23437                 return background.getClearAlpha();
23438
23439         };
23440
23441         this.setClearAlpha = function () {
23442
23443                 background.setClearAlpha.apply( background, arguments );
23444
23445         };
23446
23447         this.clear = function ( color, depth, stencil ) {
23448
23449                 let bits = 0;
23450
23451                 if ( color === undefined || color ) bits |= 16384;
23452                 if ( depth === undefined || depth ) bits |= 256;
23453                 if ( stencil === undefined || stencil ) bits |= 1024;
23454
23455                 _gl.clear( bits );
23456
23457         };
23458
23459         this.clearColor = function () {
23460
23461                 this.clear( true, false, false );
23462
23463         };
23464
23465         this.clearDepth = function () {
23466
23467                 this.clear( false, true, false );
23468
23469         };
23470
23471         this.clearStencil = function () {
23472
23473                 this.clear( false, false, true );
23474
23475         };
23476
23477         //
23478
23479         this.dispose = function () {
23480
23481                 _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
23482                 _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
23483
23484                 renderLists.dispose();
23485                 renderStates.dispose();
23486                 properties.dispose();
23487                 cubemaps.dispose();
23488                 objects.dispose();
23489                 bindingStates.dispose();
23490
23491                 xr.dispose();
23492
23493                 animation.stop();
23494
23495         };
23496
23497         // Events
23498
23499         function onContextLost( event ) {
23500
23501                 event.preventDefault();
23502
23503                 console.log( 'THREE.WebGLRenderer: Context Lost.' );
23504
23505                 _isContextLost = true;
23506
23507         }
23508
23509         function onContextRestore( /* event */ ) {
23510
23511                 console.log( 'THREE.WebGLRenderer: Context Restored.' );
23512
23513                 _isContextLost = false;
23514
23515                 initGLContext();
23516
23517         }
23518
23519         function onMaterialDispose( event ) {
23520
23521                 const material = event.target;
23522
23523                 material.removeEventListener( 'dispose', onMaterialDispose );
23524
23525                 deallocateMaterial( material );
23526
23527         }
23528
23529         // Buffer deallocation
23530
23531         function deallocateMaterial( material ) {
23532
23533                 releaseMaterialProgramReference( material );
23534
23535                 properties.remove( material );
23536
23537         }
23538
23539
23540         function releaseMaterialProgramReference( material ) {
23541
23542                 const programInfo = properties.get( material ).program;
23543
23544                 if ( programInfo !== undefined ) {
23545
23546                         programCache.releaseProgram( programInfo );
23547
23548                 }
23549
23550         }
23551
23552         // Buffer rendering
23553
23554         function renderObjectImmediate( object, program ) {
23555
23556                 object.render( function ( object ) {
23557
23558                         _this.renderBufferImmediate( object, program );
23559
23560                 } );
23561
23562         }
23563
23564         this.renderBufferImmediate = function ( object, program ) {
23565
23566                 bindingStates.initAttributes();
23567
23568                 const buffers = properties.get( object );
23569
23570                 if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
23571                 if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
23572                 if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
23573                 if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
23574
23575                 const programAttributes = program.getAttributes();
23576
23577                 if ( object.hasPositions ) {
23578
23579                         _gl.bindBuffer( 34962, buffers.position );
23580                         _gl.bufferData( 34962, object.positionArray, 35048 );
23581
23582                         bindingStates.enableAttribute( programAttributes.position );
23583                         _gl.vertexAttribPointer( programAttributes.position, 3, 5126, false, 0, 0 );
23584
23585                 }
23586
23587                 if ( object.hasNormals ) {
23588
23589                         _gl.bindBuffer( 34962, buffers.normal );
23590                         _gl.bufferData( 34962, object.normalArray, 35048 );
23591
23592                         bindingStates.enableAttribute( programAttributes.normal );
23593                         _gl.vertexAttribPointer( programAttributes.normal, 3, 5126, false, 0, 0 );
23594
23595                 }
23596
23597                 if ( object.hasUvs ) {
23598
23599                         _gl.bindBuffer( 34962, buffers.uv );
23600                         _gl.bufferData( 34962, object.uvArray, 35048 );
23601
23602                         bindingStates.enableAttribute( programAttributes.uv );
23603                         _gl.vertexAttribPointer( programAttributes.uv, 2, 5126, false, 0, 0 );
23604
23605                 }
23606
23607                 if ( object.hasColors ) {
23608
23609                         _gl.bindBuffer( 34962, buffers.color );
23610                         _gl.bufferData( 34962, object.colorArray, 35048 );
23611
23612                         bindingStates.enableAttribute( programAttributes.color );
23613                         _gl.vertexAttribPointer( programAttributes.color, 3, 5126, false, 0, 0 );
23614
23615                 }
23616
23617                 bindingStates.disableUnusedAttributes();
23618
23619                 _gl.drawArrays( 4, 0, object.count );
23620
23621                 object.count = 0;
23622
23623         };
23624
23625         this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {
23626
23627                 if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null)
23628
23629                 const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
23630
23631                 const program = setProgram( camera, scene, material, object );
23632
23633                 state.setMaterial( material, frontFaceCW );
23634
23635                 //
23636
23637                 let index = geometry.index;
23638                 const position = geometry.attributes.position;
23639
23640                 //
23641
23642                 if ( index === null ) {
23643
23644                         if ( position === undefined || position.count === 0 ) return;
23645
23646                 } else if ( index.count === 0 ) {
23647
23648                         return;
23649
23650                 }
23651
23652                 //
23653
23654                 let rangeFactor = 1;
23655
23656                 if ( material.wireframe === true ) {
23657
23658                         index = geometries.getWireframeAttribute( geometry );
23659                         rangeFactor = 2;
23660
23661                 }
23662
23663                 if ( material.morphTargets || material.morphNormals ) {
23664
23665                         morphtargets.update( object, geometry, material, program );
23666
23667                 }
23668
23669                 bindingStates.setup( object, material, program, geometry, index );
23670
23671                 let attribute;
23672                 let renderer = bufferRenderer;
23673
23674                 if ( index !== null ) {
23675
23676                         attribute = attributes.get( index );
23677
23678                         renderer = indexedBufferRenderer;
23679                         renderer.setIndex( attribute );
23680
23681                 }
23682
23683                 //
23684
23685                 const dataCount = ( index !== null ) ? index.count : position.count;
23686
23687                 const rangeStart = geometry.drawRange.start * rangeFactor;
23688                 const rangeCount = geometry.drawRange.count * rangeFactor;
23689
23690                 const groupStart = group !== null ? group.start * rangeFactor : 0;
23691                 const groupCount = group !== null ? group.count * rangeFactor : Infinity;
23692
23693                 const drawStart = Math.max( rangeStart, groupStart );
23694                 const drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
23695
23696                 const drawCount = Math.max( 0, drawEnd - drawStart + 1 );
23697
23698                 if ( drawCount === 0 ) return;
23699
23700                 //
23701
23702                 if ( object.isMesh ) {
23703
23704                         if ( material.wireframe === true ) {
23705
23706                                 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
23707                                 renderer.setMode( 1 );
23708
23709                         } else {
23710
23711                                 renderer.setMode( 4 );
23712
23713                         }
23714
23715                 } else if ( object.isLine ) {
23716
23717                         let lineWidth = material.linewidth;
23718
23719                         if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
23720
23721                         state.setLineWidth( lineWidth * getTargetPixelRatio() );
23722
23723                         if ( object.isLineSegments ) {
23724
23725                                 renderer.setMode( 1 );
23726
23727                         } else if ( object.isLineLoop ) {
23728
23729                                 renderer.setMode( 2 );
23730
23731                         } else {
23732
23733                                 renderer.setMode( 3 );
23734
23735                         }
23736
23737                 } else if ( object.isPoints ) {
23738
23739                         renderer.setMode( 0 );
23740
23741                 } else if ( object.isSprite ) {
23742
23743                         renderer.setMode( 4 );
23744
23745                 }
23746
23747                 if ( object.isInstancedMesh ) {
23748
23749                         renderer.renderInstances( drawStart, drawCount, object.count );
23750
23751                 } else if ( geometry.isInstancedBufferGeometry ) {
23752
23753                         const instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );
23754
23755                         renderer.renderInstances( drawStart, drawCount, instanceCount );
23756
23757                 } else {
23758
23759                         renderer.render( drawStart, drawCount );
23760
23761                 }
23762
23763         };
23764
23765         // Compile
23766
23767         this.compile = function ( scene, camera ) {
23768
23769                 currentRenderState = renderStates.get( scene );
23770                 currentRenderState.init();
23771
23772                 scene.traverseVisible( function ( object ) {
23773
23774                         if ( object.isLight && object.layers.test( camera.layers ) ) {
23775
23776                                 currentRenderState.pushLight( object );
23777
23778                                 if ( object.castShadow ) {
23779
23780                                         currentRenderState.pushShadow( object );
23781
23782                                 }
23783
23784                         }
23785
23786                 } );
23787
23788                 currentRenderState.setupLights();
23789
23790                 const compiled = new WeakMap();
23791
23792                 scene.traverse( function ( object ) {
23793
23794                         const material = object.material;
23795
23796                         if ( material ) {
23797
23798                                 if ( Array.isArray( material ) ) {
23799
23800                                         for ( let i = 0; i < material.length; i ++ ) {
23801
23802                                                 const material2 = material[ i ];
23803
23804                                                 if ( compiled.has( material2 ) === false ) {
23805
23806                                                         initMaterial( material2, scene, object );
23807                                                         compiled.set( material2 );
23808
23809                                                 }
23810
23811                                         }
23812
23813                                 } else if ( compiled.has( material ) === false ) {
23814
23815                                         initMaterial( material, scene, object );
23816                                         compiled.set( material );
23817
23818                                 }
23819
23820                         }
23821
23822                 } );
23823
23824         };
23825
23826         // Animation Loop
23827
23828         let onAnimationFrameCallback = null;
23829
23830         function onAnimationFrame( time ) {
23831
23832                 if ( xr.isPresenting ) return;
23833                 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
23834
23835         }
23836
23837         const animation = new WebGLAnimation();
23838         animation.setAnimationLoop( onAnimationFrame );
23839
23840         if ( typeof window !== 'undefined' ) animation.setContext( window );
23841
23842         this.setAnimationLoop = function ( callback ) {
23843
23844                 onAnimationFrameCallback = callback;
23845                 xr.setAnimationLoop( callback );
23846
23847                 ( callback === null ) ? animation.stop() : animation.start();
23848
23849         };
23850
23851         // Rendering
23852
23853         this.render = function ( scene, camera ) {
23854
23855                 let renderTarget, forceClear;
23856
23857                 if ( arguments[ 2 ] !== undefined ) {
23858
23859                         console.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );
23860                         renderTarget = arguments[ 2 ];
23861
23862                 }
23863
23864                 if ( arguments[ 3 ] !== undefined ) {
23865
23866                         console.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );
23867                         forceClear = arguments[ 3 ];
23868
23869                 }
23870
23871                 if ( camera !== undefined && camera.isCamera !== true ) {
23872
23873                         console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
23874                         return;
23875
23876                 }
23877
23878                 if ( _isContextLost === true ) return;
23879
23880                 // reset caching for this frame
23881
23882                 bindingStates.resetDefaultState();
23883                 _currentMaterialId = - 1;
23884                 _currentCamera = null;
23885
23886                 // update scene graph
23887
23888                 if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
23889
23890                 // update camera matrices and frustum
23891
23892                 if ( camera.parent === null ) camera.updateMatrixWorld();
23893
23894                 if ( xr.enabled === true && xr.isPresenting === true ) {
23895
23896                         camera = xr.getCamera( camera );
23897
23898                 }
23899
23900                 //
23901                 if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );
23902
23903                 currentRenderState = renderStates.get( scene, renderStateStack.length );
23904                 currentRenderState.init();
23905
23906                 renderStateStack.push( currentRenderState );
23907
23908                 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
23909                 _frustum.setFromProjectionMatrix( _projScreenMatrix );
23910
23911                 _localClippingEnabled = this.localClippingEnabled;
23912                 _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
23913
23914                 currentRenderList = renderLists.get( scene, camera );
23915                 currentRenderList.init();
23916
23917                 projectObject( scene, camera, 0, _this.sortObjects );
23918
23919                 currentRenderList.finish();
23920
23921                 if ( _this.sortObjects === true ) {
23922
23923                         currentRenderList.sort( _opaqueSort, _transparentSort );
23924
23925                 }
23926
23927                 //
23928
23929                 if ( _clippingEnabled === true ) clipping.beginShadows();
23930
23931                 const shadowsArray = currentRenderState.state.shadowsArray;
23932
23933                 shadowMap.render( shadowsArray, scene, camera );
23934
23935                 currentRenderState.setupLights();
23936                 currentRenderState.setupLightsView( camera );
23937
23938                 if ( _clippingEnabled === true ) clipping.endShadows();
23939
23940                 //
23941
23942                 if ( this.info.autoReset === true ) this.info.reset();
23943
23944                 if ( renderTarget !== undefined ) {
23945
23946                         this.setRenderTarget( renderTarget );
23947
23948                 }
23949
23950                 //
23951
23952                 background.render( currentRenderList, scene, camera, forceClear );
23953
23954                 // render scene
23955
23956                 const opaqueObjects = currentRenderList.opaque;
23957                 const transparentObjects = currentRenderList.transparent;
23958
23959                 if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
23960                 if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
23961
23962                 //
23963
23964                 if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );
23965
23966                 //
23967
23968                 if ( _currentRenderTarget !== null ) {
23969
23970                         // Generate mipmap if we're using any kind of mipmap filtering
23971
23972                         textures.updateRenderTargetMipmap( _currentRenderTarget );
23973
23974                         // resolve multisample renderbuffers to a single-sample texture if necessary
23975
23976                         textures.updateMultisampleRenderTarget( _currentRenderTarget );
23977
23978                 }
23979
23980                 // Ensure depth buffer writing is enabled so it can be cleared on next render
23981
23982                 state.buffers.depth.setTest( true );
23983                 state.buffers.depth.setMask( true );
23984                 state.buffers.color.setMask( true );
23985
23986                 state.setPolygonOffset( false );
23987
23988                 // _gl.finish();
23989
23990                 renderStateStack.pop();
23991                 if ( renderStateStack.length > 0 ) {
23992
23993                         currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
23994
23995                 } else {
23996
23997                         currentRenderState = null;
23998
23999                 }
24000
24001                 currentRenderList = null;
24002
24003         };
24004
24005         function projectObject( object, camera, groupOrder, sortObjects ) {
24006
24007                 if ( object.visible === false ) return;
24008
24009                 const visible = object.layers.test( camera.layers );
24010
24011                 if ( visible ) {
24012
24013                         if ( object.isGroup ) {
24014
24015                                 groupOrder = object.renderOrder;
24016
24017                         } else if ( object.isLOD ) {
24018
24019                                 if ( object.autoUpdate === true ) object.update( camera );
24020
24021                         } else if ( object.isLight ) {
24022
24023                                 currentRenderState.pushLight( object );
24024
24025                                 if ( object.castShadow ) {
24026
24027                                         currentRenderState.pushShadow( object );
24028
24029                                 }
24030
24031                         } else if ( object.isSprite ) {
24032
24033                                 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
24034
24035                                         if ( sortObjects ) {
24036
24037                                                 _vector3.setFromMatrixPosition( object.matrixWorld )
24038                                                         .applyMatrix4( _projScreenMatrix );
24039
24040                                         }
24041
24042                                         const geometry = objects.update( object );
24043                                         const material = object.material;
24044
24045                                         if ( material.visible ) {
24046
24047                                                 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
24048
24049                                         }
24050
24051                                 }
24052
24053                         } else if ( object.isImmediateRenderObject ) {
24054
24055                                 if ( sortObjects ) {
24056
24057                                         _vector3.setFromMatrixPosition( object.matrixWorld )
24058                                                 .applyMatrix4( _projScreenMatrix );
24059
24060                                 }
24061
24062                                 currentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );
24063
24064                         } else if ( object.isMesh || object.isLine || object.isPoints ) {
24065
24066                                 if ( object.isSkinnedMesh ) {
24067
24068                                         // update skeleton only once in a frame
24069
24070                                         if ( object.skeleton.frame !== info.render.frame ) {
24071
24072                                                 object.skeleton.update();
24073                                                 object.skeleton.frame = info.render.frame;
24074
24075                                         }
24076
24077                                 }
24078
24079                                 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
24080
24081                                         if ( sortObjects ) {
24082
24083                                                 _vector3.setFromMatrixPosition( object.matrixWorld )
24084                                                         .applyMatrix4( _projScreenMatrix );
24085
24086                                         }
24087
24088                                         const geometry = objects.update( object );
24089                                         const material = object.material;
24090
24091                                         if ( Array.isArray( material ) ) {
24092
24093                                                 const groups = geometry.groups;
24094
24095                                                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
24096
24097                                                         const group = groups[ i ];
24098                                                         const groupMaterial = material[ group.materialIndex ];
24099
24100                                                         if ( groupMaterial && groupMaterial.visible ) {
24101
24102                                                                 currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
24103
24104                                                         }
24105
24106                                                 }
24107
24108                                         } else if ( material.visible ) {
24109
24110                                                 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
24111
24112                                         }
24113
24114                                 }
24115
24116                         }
24117
24118                 }
24119
24120                 const children = object.children;
24121
24122                 for ( let i = 0, l = children.length; i < l; i ++ ) {
24123
24124                         projectObject( children[ i ], camera, groupOrder, sortObjects );
24125
24126                 }
24127
24128         }
24129
24130         function renderObjects( renderList, scene, camera ) {
24131
24132                 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
24133
24134                 for ( let i = 0, l = renderList.length; i < l; i ++ ) {
24135
24136                         const renderItem = renderList[ i ];
24137
24138                         const object = renderItem.object;
24139                         const geometry = renderItem.geometry;
24140                         const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
24141                         const group = renderItem.group;
24142
24143                         if ( camera.isArrayCamera ) {
24144
24145                                 const cameras = camera.cameras;
24146
24147                                 for ( let j = 0, jl = cameras.length; j < jl; j ++ ) {
24148
24149                                         const camera2 = cameras[ j ];
24150
24151                                         if ( object.layers.test( camera2.layers ) ) {
24152
24153                                                 state.viewport( _currentViewport.copy( camera2.viewport ) );
24154
24155                                                 currentRenderState.setupLightsView( camera2 );
24156
24157                                                 renderObject( object, scene, camera2, geometry, material, group );
24158
24159                                         }
24160
24161                                 }
24162
24163                         } else {
24164
24165                                 renderObject( object, scene, camera, geometry, material, group );
24166
24167                         }
24168
24169                 }
24170
24171         }
24172
24173         function renderObject( object, scene, camera, geometry, material, group ) {
24174
24175                 object.onBeforeRender( _this, scene, camera, geometry, material, group );
24176
24177                 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
24178                 object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
24179
24180                 if ( object.isImmediateRenderObject ) {
24181
24182                         const program = setProgram( camera, scene, material, object );
24183
24184                         state.setMaterial( material );
24185
24186                         bindingStates.reset();
24187
24188                         renderObjectImmediate( object, program );
24189
24190                 } else {
24191
24192                         _this.renderBufferDirect( camera, scene, geometry, material, object, group );
24193
24194                 }
24195
24196                 object.onAfterRender( _this, scene, camera, geometry, material, group );
24197
24198         }
24199
24200         function initMaterial( material, scene, object ) {
24201
24202                 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
24203
24204                 const materialProperties = properties.get( material );
24205
24206                 const lights = currentRenderState.state.lights;
24207                 const shadowsArray = currentRenderState.state.shadowsArray;
24208
24209                 const lightsStateVersion = lights.state.version;
24210
24211                 const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object );
24212                 const programCacheKey = programCache.getProgramCacheKey( parameters );
24213
24214                 let program = materialProperties.program;
24215                 let programChange = true;
24216
24217                 // always update environment and fog - changing these trigger an initMaterial call, but it's possible that the program doesn't change
24218
24219                 materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
24220                 materialProperties.fog = scene.fog;
24221                 materialProperties.envMap = cubemaps.get( material.envMap || materialProperties.environment );
24222
24223                 if ( program === undefined ) {
24224
24225                         // new material
24226                         material.addEventListener( 'dispose', onMaterialDispose );
24227
24228                 } else if ( program.cacheKey !== programCacheKey ) {
24229
24230                         // changed glsl or parameters
24231                         releaseMaterialProgramReference( material );
24232
24233                 } else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) {
24234
24235                         programChange = false;
24236
24237                 } else if ( parameters.shaderID !== undefined ) {
24238
24239                         // same glsl and uniform list
24240                         return;
24241
24242                 } else {
24243
24244                         // only rebuild uniform list
24245                         programChange = false;
24246
24247                 }
24248
24249                 if ( programChange ) {
24250
24251                         parameters.uniforms = programCache.getUniforms( material );
24252
24253                         material.onBeforeCompile( parameters, _this );
24254
24255                         program = programCache.acquireProgram( parameters, programCacheKey );
24256
24257                         materialProperties.program = program;
24258                         materialProperties.uniforms = parameters.uniforms;
24259                         materialProperties.outputEncoding = parameters.outputEncoding;
24260
24261                 }
24262
24263                 const uniforms = materialProperties.uniforms;
24264
24265                 if ( ! material.isShaderMaterial &&
24266                         ! material.isRawShaderMaterial ||
24267                         material.clipping === true ) {
24268
24269                         materialProperties.numClippingPlanes = clipping.numPlanes;
24270                         materialProperties.numIntersection = clipping.numIntersection;
24271                         uniforms.clippingPlanes = clipping.uniform;
24272
24273                 }
24274
24275                 // store the light setup it was created for
24276
24277                 materialProperties.needsLights = materialNeedsLights( material );
24278                 materialProperties.lightsStateVersion = lightsStateVersion;
24279
24280                 if ( materialProperties.needsLights ) {
24281
24282                         // wire up the material to this renderer's lighting state
24283
24284                         uniforms.ambientLightColor.value = lights.state.ambient;
24285                         uniforms.lightProbe.value = lights.state.probe;
24286                         uniforms.directionalLights.value = lights.state.directional;
24287                         uniforms.directionalLightShadows.value = lights.state.directionalShadow;
24288                         uniforms.spotLights.value = lights.state.spot;
24289                         uniforms.spotLightShadows.value = lights.state.spotShadow;
24290                         uniforms.rectAreaLights.value = lights.state.rectArea;
24291                         uniforms.ltc_1.value = lights.state.rectAreaLTC1;
24292                         uniforms.ltc_2.value = lights.state.rectAreaLTC2;
24293                         uniforms.pointLights.value = lights.state.point;
24294                         uniforms.pointLightShadows.value = lights.state.pointShadow;
24295                         uniforms.hemisphereLights.value = lights.state.hemi;
24296
24297                         uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
24298                         uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
24299                         uniforms.spotShadowMap.value = lights.state.spotShadowMap;
24300                         uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
24301                         uniforms.pointShadowMap.value = lights.state.pointShadowMap;
24302                         uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
24303                         // TODO (abelnation): add area lights shadow info to uniforms
24304
24305                 }
24306
24307                 const progUniforms = materialProperties.program.getUniforms();
24308                 const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
24309
24310                 materialProperties.uniformsList = uniformsList;
24311
24312         }
24313
24314         function setProgram( camera, scene, material, object ) {
24315
24316                 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
24317
24318                 textures.resetTextureUnits();
24319
24320                 const fog = scene.fog;
24321                 const environment = material.isMeshStandardMaterial ? scene.environment : null;
24322                 const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding;
24323                 const envMap = cubemaps.get( material.envMap || environment );
24324
24325                 const materialProperties = properties.get( material );
24326                 const lights = currentRenderState.state.lights;
24327
24328                 if ( _clippingEnabled === true ) {
24329
24330                         if ( _localClippingEnabled === true || camera !== _currentCamera ) {
24331
24332                                 const useCache =
24333                                         camera === _currentCamera &&
24334                                         material.id === _currentMaterialId;
24335
24336                                 // we might want to call this function with some ClippingGroup
24337                                 // object instead of the material, once it becomes feasible
24338                                 // (#8465, #8379)
24339                                 clipping.setState( material, camera, useCache );
24340
24341                         }
24342
24343                 }
24344
24345                 if ( material.version === materialProperties.__version ) {
24346
24347                         if ( material.fog && materialProperties.fog !== fog ) {
24348
24349                                 initMaterial( material, scene, object );
24350
24351                         } else if ( materialProperties.environment !== environment ) {
24352
24353                                 initMaterial( material, scene, object );
24354
24355                         } else if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
24356
24357                                 initMaterial( material, scene, object );
24358
24359                         } else if ( materialProperties.numClippingPlanes !== undefined &&
24360                                 ( materialProperties.numClippingPlanes !== clipping.numPlanes ||
24361                                 materialProperties.numIntersection !== clipping.numIntersection ) ) {
24362
24363                                 initMaterial( material, scene, object );
24364
24365                         } else if ( materialProperties.outputEncoding !== encoding ) {
24366
24367                                 initMaterial( material, scene, object );
24368
24369                         } else if ( materialProperties.envMap !== envMap ) {
24370
24371                                 initMaterial( material, scene, object );
24372
24373                         }
24374
24375                 } else {
24376
24377                         initMaterial( material, scene, object );
24378                         materialProperties.__version = material.version;
24379
24380                 }
24381
24382                 let refreshProgram = false;
24383                 let refreshMaterial = false;
24384                 let refreshLights = false;
24385
24386                 const program = materialProperties.program,
24387                         p_uniforms = program.getUniforms(),
24388                         m_uniforms = materialProperties.uniforms;
24389
24390                 if ( state.useProgram( program.program ) ) {
24391
24392                         refreshProgram = true;
24393                         refreshMaterial = true;
24394                         refreshLights = true;
24395
24396                 }
24397
24398                 if ( material.id !== _currentMaterialId ) {
24399
24400                         _currentMaterialId = material.id;
24401
24402                         refreshMaterial = true;
24403
24404                 }
24405
24406                 if ( refreshProgram || _currentCamera !== camera ) {
24407
24408                         p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
24409
24410                         if ( capabilities.logarithmicDepthBuffer ) {
24411
24412                                 p_uniforms.setValue( _gl, 'logDepthBufFC',
24413                                         2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
24414
24415                         }
24416
24417                         if ( _currentCamera !== camera ) {
24418
24419                                 _currentCamera = camera;
24420
24421                                 // lighting uniforms depend on the camera so enforce an update
24422                                 // now, in case this material supports lights - or later, when
24423                                 // the next material that does gets activated:
24424
24425                                 refreshMaterial = true;         // set to true on material change
24426                                 refreshLights = true;           // remains set until update done
24427
24428                         }
24429
24430                         // load material specific uniforms
24431                         // (shader material also gets them for the sake of genericity)
24432
24433                         if ( material.isShaderMaterial ||
24434                                 material.isMeshPhongMaterial ||
24435                                 material.isMeshToonMaterial ||
24436                                 material.isMeshStandardMaterial ||
24437                                 material.envMap ) {
24438
24439                                 const uCamPos = p_uniforms.map.cameraPosition;
24440
24441                                 if ( uCamPos !== undefined ) {
24442
24443                                         uCamPos.setValue( _gl,
24444                                                 _vector3.setFromMatrixPosition( camera.matrixWorld ) );
24445
24446                                 }
24447
24448                         }
24449
24450                         if ( material.isMeshPhongMaterial ||
24451                                 material.isMeshToonMaterial ||
24452                                 material.isMeshLambertMaterial ||
24453                                 material.isMeshBasicMaterial ||
24454                                 material.isMeshStandardMaterial ||
24455                                 material.isShaderMaterial ) {
24456
24457                                 p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );
24458
24459                         }
24460
24461                         if ( material.isMeshPhongMaterial ||
24462                                 material.isMeshToonMaterial ||
24463                                 material.isMeshLambertMaterial ||
24464                                 material.isMeshBasicMaterial ||
24465                                 material.isMeshStandardMaterial ||
24466                                 material.isShaderMaterial ||
24467                                 material.isShadowMaterial ||
24468                                 material.skinning ) {
24469
24470                                 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
24471
24472                         }
24473
24474                 }
24475
24476                 // skinning uniforms must be set even if material didn't change
24477                 // auto-setting of texture unit for bone texture must go before other textures
24478                 // otherwise textures used for skinning can take over texture units reserved for other material textures
24479
24480                 if ( material.skinning ) {
24481
24482                         p_uniforms.setOptional( _gl, object, 'bindMatrix' );
24483                         p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
24484
24485                         const skeleton = object.skeleton;
24486
24487                         if ( skeleton ) {
24488
24489                                 const bones = skeleton.bones;
24490
24491                                 if ( capabilities.floatVertexTextures ) {
24492
24493                                         if ( skeleton.boneTexture === null ) {
24494
24495                                                 // layout (1 matrix = 4 pixels)
24496                                                 //      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
24497                                                 //  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
24498                                                 //       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
24499                                                 //       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
24500                                                 //       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
24501
24502
24503                                                 let size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
24504                                                 size = MathUtils.ceilPowerOfTwo( size );
24505                                                 size = Math.max( size, 4 );
24506
24507                                                 const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
24508                                                 boneMatrices.set( skeleton.boneMatrices ); // copy current values
24509
24510                                                 const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
24511
24512                                                 skeleton.boneMatrices = boneMatrices;
24513                                                 skeleton.boneTexture = boneTexture;
24514                                                 skeleton.boneTextureSize = size;
24515
24516                                         }
24517
24518                                         p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );
24519                                         p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
24520
24521                                 } else {
24522
24523                                         p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
24524
24525                                 }
24526
24527                         }
24528
24529                 }
24530
24531                 if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {
24532
24533                         materialProperties.receiveShadow = object.receiveShadow;
24534                         p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );
24535
24536                 }
24537
24538                 if ( refreshMaterial ) {
24539
24540                         p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
24541
24542                         if ( materialProperties.needsLights ) {
24543
24544                                 // the current material requires lighting info
24545
24546                                 // note: all lighting uniforms are always set correctly
24547                                 // they simply reference the renderer's state for their
24548                                 // values
24549                                 //
24550                                 // use the current material's .needsUpdate flags to set
24551                                 // the GL state when required
24552
24553                                 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
24554
24555                         }
24556
24557                         // refresh uniforms common to several materials
24558
24559                         if ( fog && material.fog ) {
24560
24561                                 materials.refreshFogUniforms( m_uniforms, fog );
24562
24563                         }
24564
24565                         materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height );
24566
24567                         WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
24568
24569                 }
24570
24571                 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
24572
24573                         WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
24574                         material.uniformsNeedUpdate = false;
24575
24576                 }
24577
24578                 if ( material.isSpriteMaterial ) {
24579
24580                         p_uniforms.setValue( _gl, 'center', object.center );
24581
24582                 }
24583
24584                 // common matrices
24585
24586                 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
24587                 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
24588                 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
24589
24590                 return program;
24591
24592         }
24593
24594         // If uniforms are marked as clean, they don't need to be loaded to the GPU.
24595
24596         function markUniformsLightsNeedsUpdate( uniforms, value ) {
24597
24598                 uniforms.ambientLightColor.needsUpdate = value;
24599                 uniforms.lightProbe.needsUpdate = value;
24600
24601                 uniforms.directionalLights.needsUpdate = value;
24602                 uniforms.directionalLightShadows.needsUpdate = value;
24603                 uniforms.pointLights.needsUpdate = value;
24604                 uniforms.pointLightShadows.needsUpdate = value;
24605                 uniforms.spotLights.needsUpdate = value;
24606                 uniforms.spotLightShadows.needsUpdate = value;
24607                 uniforms.rectAreaLights.needsUpdate = value;
24608                 uniforms.hemisphereLights.needsUpdate = value;
24609
24610         }
24611
24612         function materialNeedsLights( material ) {
24613
24614                 return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
24615                         material.isMeshStandardMaterial || material.isShadowMaterial ||
24616                         ( material.isShaderMaterial && material.lights === true );
24617
24618         }
24619
24620         //
24621         this.setFramebuffer = function ( value ) {
24622
24623                 if ( _framebuffer !== value && _currentRenderTarget === null ) _gl.bindFramebuffer( 36160, value );
24624
24625                 _framebuffer = value;
24626
24627         };
24628
24629         this.getActiveCubeFace = function () {
24630
24631                 return _currentActiveCubeFace;
24632
24633         };
24634
24635         this.getActiveMipmapLevel = function () {
24636
24637                 return _currentActiveMipmapLevel;
24638
24639         };
24640
24641         this.getRenderList = function () {
24642
24643                 return currentRenderList;
24644
24645         };
24646
24647         this.setRenderList = function ( renderList ) {
24648
24649                 currentRenderList = renderList;
24650
24651         };
24652
24653         this.getRenderTarget = function () {
24654
24655                 return _currentRenderTarget;
24656
24657         };
24658
24659         this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) {
24660
24661                 _currentRenderTarget = renderTarget;
24662                 _currentActiveCubeFace = activeCubeFace;
24663                 _currentActiveMipmapLevel = activeMipmapLevel;
24664
24665                 if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
24666
24667                         textures.setupRenderTarget( renderTarget );
24668
24669                 }
24670
24671                 let framebuffer = _framebuffer;
24672                 let isCube = false;
24673
24674                 if ( renderTarget ) {
24675
24676                         const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
24677
24678                         if ( renderTarget.isWebGLCubeRenderTarget ) {
24679
24680                                 framebuffer = __webglFramebuffer[ activeCubeFace ];
24681                                 isCube = true;
24682
24683                         } else if ( renderTarget.isWebGLMultisampleRenderTarget ) {
24684
24685                                 framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
24686
24687                         } else {
24688
24689                                 framebuffer = __webglFramebuffer;
24690
24691                         }
24692
24693                         _currentViewport.copy( renderTarget.viewport );
24694                         _currentScissor.copy( renderTarget.scissor );
24695                         _currentScissorTest = renderTarget.scissorTest;
24696
24697                 } else {
24698
24699                         _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
24700                         _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
24701                         _currentScissorTest = _scissorTest;
24702
24703                 }
24704
24705                 if ( _currentFramebuffer !== framebuffer ) {
24706
24707                         _gl.bindFramebuffer( 36160, framebuffer );
24708                         _currentFramebuffer = framebuffer;
24709
24710                 }
24711
24712                 state.viewport( _currentViewport );
24713                 state.scissor( _currentScissor );
24714                 state.setScissorTest( _currentScissorTest );
24715
24716                 if ( isCube ) {
24717
24718                         const textureProperties = properties.get( renderTarget.texture );
24719                         _gl.framebufferTexture2D( 36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel );
24720
24721                 }
24722
24723         };
24724
24725         this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
24726
24727                 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
24728
24729                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
24730                         return;
24731
24732                 }
24733
24734                 let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
24735
24736                 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
24737
24738                         framebuffer = framebuffer[ activeCubeFaceIndex ];
24739
24740                 }
24741
24742                 if ( framebuffer ) {
24743
24744                         let restore = false;
24745
24746                         if ( framebuffer !== _currentFramebuffer ) {
24747
24748                                 _gl.bindFramebuffer( 36160, framebuffer );
24749
24750                                 restore = true;
24751
24752                         }
24753
24754                         try {
24755
24756                                 const texture = renderTarget.texture;
24757                                 const textureFormat = texture.format;
24758                                 const textureType = texture.type;
24759
24760                                 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {
24761
24762                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
24763                                         return;
24764
24765                                 }
24766
24767                                 const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) );
24768
24769                                 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // IE11, Edge and Chrome Mac < 52 (#9513)
24770                                         ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
24771                                         ! halfFloatSupportedByExt ) {
24772
24773                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
24774                                         return;
24775
24776                                 }
24777
24778                                 if ( _gl.checkFramebufferStatus( 36160 ) === 36053 ) {
24779
24780                                         // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
24781
24782                                         if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
24783
24784                                                 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
24785
24786                                         }
24787
24788                                 } else {
24789
24790                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
24791
24792                                 }
24793
24794                         } finally {
24795
24796                                 if ( restore ) {
24797
24798                                         _gl.bindFramebuffer( 36160, _currentFramebuffer );
24799
24800                                 }
24801
24802                         }
24803
24804                 }
24805
24806         };
24807
24808         this.copyFramebufferToTexture = function ( position, texture, level = 0 ) {
24809
24810                 const levelScale = Math.pow( 2, - level );
24811                 const width = Math.floor( texture.image.width * levelScale );
24812                 const height = Math.floor( texture.image.height * levelScale );
24813                 const glFormat = utils.convert( texture.format );
24814
24815                 textures.setTexture2D( texture, 0 );
24816
24817                 _gl.copyTexImage2D( 3553, level, glFormat, position.x, position.y, width, height, 0 );
24818
24819                 state.unbindTexture();
24820
24821         };
24822
24823         this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) {
24824
24825                 const width = srcTexture.image.width;
24826                 const height = srcTexture.image.height;
24827                 const glFormat = utils.convert( dstTexture.format );
24828                 const glType = utils.convert( dstTexture.type );
24829
24830                 textures.setTexture2D( dstTexture, 0 );
24831
24832                 // As another texture upload may have changed pixelStorei
24833                 // parameters, make sure they are correct for the dstTexture
24834                 _gl.pixelStorei( 37440, dstTexture.flipY );
24835                 _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha );
24836                 _gl.pixelStorei( 3317, dstTexture.unpackAlignment );
24837
24838                 if ( srcTexture.isDataTexture ) {
24839
24840                         _gl.texSubImage2D( 3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
24841
24842                 } else {
24843
24844                         if ( srcTexture.isCompressedTexture ) {
24845
24846                                 _gl.compressedTexSubImage2D( 3553, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
24847
24848                         } else {
24849
24850                                 _gl.texSubImage2D( 3553, level, position.x, position.y, glFormat, glType, srcTexture.image );
24851
24852                         }
24853
24854                 }
24855
24856                 // Generate mipmaps only when copying level 0
24857                 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( 3553 );
24858
24859                 state.unbindTexture();
24860
24861         };
24862
24863         this.initTexture = function ( texture ) {
24864
24865                 textures.setTexture2D( texture, 0 );
24866
24867                 state.unbindTexture();
24868
24869         };
24870
24871         this.resetState = function () {
24872
24873                 state.reset();
24874                 bindingStates.reset();
24875
24876         };
24877
24878         if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
24879
24880                 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
24881
24882         }
24883
24884 }
24885
24886 function WebGL1Renderer( parameters ) {
24887
24888         WebGLRenderer.call( this, parameters );
24889
24890 }
24891
24892 WebGL1Renderer.prototype = Object.assign( Object.create( WebGLRenderer.prototype ), {
24893
24894         constructor: WebGL1Renderer,
24895
24896         isWebGL1Renderer: true
24897
24898 } );
24899
24900 class FogExp2 {
24901
24902         constructor( color, density ) {
24903
24904                 Object.defineProperty( this, 'isFogExp2', { value: true } );
24905
24906                 this.name = '';
24907
24908                 this.color = new Color( color );
24909                 this.density = ( density !== undefined ) ? density : 0.00025;
24910
24911         }
24912
24913         clone() {
24914
24915                 return new FogExp2( this.color, this.density );
24916
24917         }
24918
24919         toJSON( /* meta */ ) {
24920
24921                 return {
24922                         type: 'FogExp2',
24923                         color: this.color.getHex(),
24924                         density: this.density
24925                 };
24926
24927         }
24928
24929 }
24930
24931 class Fog {
24932
24933         constructor( color, near, far ) {
24934
24935                 Object.defineProperty( this, 'isFog', { value: true } );
24936
24937                 this.name = '';
24938
24939                 this.color = new Color( color );
24940
24941                 this.near = ( near !== undefined ) ? near : 1;
24942                 this.far = ( far !== undefined ) ? far : 1000;
24943
24944         }
24945
24946         clone() {
24947
24948                 return new Fog( this.color, this.near, this.far );
24949
24950         }
24951
24952         toJSON( /* meta */ ) {
24953
24954                 return {
24955                         type: 'Fog',
24956                         color: this.color.getHex(),
24957                         near: this.near,
24958                         far: this.far
24959                 };
24960
24961         }
24962
24963 }
24964
24965 class Scene extends Object3D {
24966
24967         constructor() {
24968
24969                 super();
24970
24971                 Object.defineProperty( this, 'isScene', { value: true } );
24972
24973                 this.type = 'Scene';
24974
24975                 this.background = null;
24976                 this.environment = null;
24977                 this.fog = null;
24978
24979                 this.overrideMaterial = null;
24980
24981                 this.autoUpdate = true; // checked by the renderer
24982
24983                 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
24984
24985                         __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
24986
24987                 }
24988
24989         }
24990
24991         copy( source, recursive ) {
24992
24993                 super.copy( source, recursive );
24994
24995                 if ( source.background !== null ) this.background = source.background.clone();
24996                 if ( source.environment !== null ) this.environment = source.environment.clone();
24997                 if ( source.fog !== null ) this.fog = source.fog.clone();
24998
24999                 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
25000
25001                 this.autoUpdate = source.autoUpdate;
25002                 this.matrixAutoUpdate = source.matrixAutoUpdate;
25003
25004                 return this;
25005
25006         }
25007
25008         toJSON( meta ) {
25009
25010                 const data = super.toJSON( meta );
25011
25012                 if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
25013                 if ( this.environment !== null ) data.object.environment = this.environment.toJSON( meta );
25014                 if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
25015
25016                 return data;
25017
25018         }
25019
25020 }
25021
25022 function InterleavedBuffer( array, stride ) {
25023
25024         this.array = array;
25025         this.stride = stride;
25026         this.count = array !== undefined ? array.length / stride : 0;
25027
25028         this.usage = StaticDrawUsage;
25029         this.updateRange = { offset: 0, count: - 1 };
25030
25031         this.version = 0;
25032
25033         this.uuid = MathUtils.generateUUID();
25034
25035 }
25036
25037 Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
25038
25039         set: function ( value ) {
25040
25041                 if ( value === true ) this.version ++;
25042
25043         }
25044
25045 } );
25046
25047 Object.assign( InterleavedBuffer.prototype, {
25048
25049         isInterleavedBuffer: true,
25050
25051         onUploadCallback: function () {},
25052
25053         setUsage: function ( value ) {
25054
25055                 this.usage = value;
25056
25057                 return this;
25058
25059         },
25060
25061         copy: function ( source ) {
25062
25063                 this.array = new source.array.constructor( source.array );
25064                 this.count = source.count;
25065                 this.stride = source.stride;
25066                 this.usage = source.usage;
25067
25068                 return this;
25069
25070         },
25071
25072         copyAt: function ( index1, attribute, index2 ) {
25073
25074                 index1 *= this.stride;
25075                 index2 *= attribute.stride;
25076
25077                 for ( let i = 0, l = this.stride; i < l; i ++ ) {
25078
25079                         this.array[ index1 + i ] = attribute.array[ index2 + i ];
25080
25081                 }
25082
25083                 return this;
25084
25085         },
25086
25087         set: function ( value, offset = 0 ) {
25088
25089                 this.array.set( value, offset );
25090
25091                 return this;
25092
25093         },
25094
25095         clone: function ( data ) {
25096
25097                 if ( data.arrayBuffers === undefined ) {
25098
25099                         data.arrayBuffers = {};
25100
25101                 }
25102
25103                 if ( this.array.buffer._uuid === undefined ) {
25104
25105                         this.array.buffer._uuid = MathUtils.generateUUID();
25106
25107                 }
25108
25109                 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
25110
25111                         data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
25112
25113                 }
25114
25115                 const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
25116
25117                 const ib = new InterleavedBuffer( array, this.stride );
25118                 ib.setUsage( this.usage );
25119
25120                 return ib;
25121
25122         },
25123
25124         onUpload: function ( callback ) {
25125
25126                 this.onUploadCallback = callback;
25127
25128                 return this;
25129
25130         },
25131
25132         toJSON: function ( data ) {
25133
25134                 if ( data.arrayBuffers === undefined ) {
25135
25136                         data.arrayBuffers = {};
25137
25138                 }
25139
25140                 // generate UUID for array buffer if necessary
25141
25142                 if ( this.array.buffer._uuid === undefined ) {
25143
25144                         this.array.buffer._uuid = MathUtils.generateUUID();
25145
25146                 }
25147
25148                 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
25149
25150                         data.arrayBuffers[ this.array.buffer._uuid ] = Array.prototype.slice.call( new Uint32Array( this.array.buffer ) );
25151
25152                 }
25153
25154                 //
25155
25156                 return {
25157                         uuid: this.uuid,
25158                         buffer: this.array.buffer._uuid,
25159                         type: this.array.constructor.name,
25160                         stride: this.stride
25161                 };
25162
25163         }
25164
25165 } );
25166
25167 const _vector$6 = new Vector3();
25168
25169 function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
25170
25171         this.name = '';
25172
25173         this.data = interleavedBuffer;
25174         this.itemSize = itemSize;
25175         this.offset = offset;
25176
25177         this.normalized = normalized === true;
25178
25179 }
25180
25181 Object.defineProperties( InterleavedBufferAttribute.prototype, {
25182
25183         count: {
25184
25185                 get: function () {
25186
25187                         return this.data.count;
25188
25189                 }
25190
25191         },
25192
25193         array: {
25194
25195                 get: function () {
25196
25197                         return this.data.array;
25198
25199                 }
25200
25201         },
25202
25203         needsUpdate: {
25204
25205                 set: function ( value ) {
25206
25207                         this.data.needsUpdate = value;
25208
25209                 }
25210
25211         }
25212
25213 } );
25214
25215 Object.assign( InterleavedBufferAttribute.prototype, {
25216
25217         isInterleavedBufferAttribute: true,
25218
25219         applyMatrix4: function ( m ) {
25220
25221                 for ( let i = 0, l = this.data.count; i < l; i ++ ) {
25222
25223                         _vector$6.x = this.getX( i );
25224                         _vector$6.y = this.getY( i );
25225                         _vector$6.z = this.getZ( i );
25226
25227                         _vector$6.applyMatrix4( m );
25228
25229                         this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
25230
25231                 }
25232
25233                 return this;
25234
25235         },
25236
25237         setX: function ( index, x ) {
25238
25239                 this.data.array[ index * this.data.stride + this.offset ] = x;
25240
25241                 return this;
25242
25243         },
25244
25245         setY: function ( index, y ) {
25246
25247                 this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
25248
25249                 return this;
25250
25251         },
25252
25253         setZ: function ( index, z ) {
25254
25255                 this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
25256
25257                 return this;
25258
25259         },
25260
25261         setW: function ( index, w ) {
25262
25263                 this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
25264
25265                 return this;
25266
25267         },
25268
25269         getX: function ( index ) {
25270
25271                 return this.data.array[ index * this.data.stride + this.offset ];
25272
25273         },
25274
25275         getY: function ( index ) {
25276
25277                 return this.data.array[ index * this.data.stride + this.offset + 1 ];
25278
25279         },
25280
25281         getZ: function ( index ) {
25282
25283                 return this.data.array[ index * this.data.stride + this.offset + 2 ];
25284
25285         },
25286
25287         getW: function ( index ) {
25288
25289                 return this.data.array[ index * this.data.stride + this.offset + 3 ];
25290
25291         },
25292
25293         setXY: function ( index, x, y ) {
25294
25295                 index = index * this.data.stride + this.offset;
25296
25297                 this.data.array[ index + 0 ] = x;
25298                 this.data.array[ index + 1 ] = y;
25299
25300                 return this;
25301
25302         },
25303
25304         setXYZ: function ( index, x, y, z ) {
25305
25306                 index = index * this.data.stride + this.offset;
25307
25308                 this.data.array[ index + 0 ] = x;
25309                 this.data.array[ index + 1 ] = y;
25310                 this.data.array[ index + 2 ] = z;
25311
25312                 return this;
25313
25314         },
25315
25316         setXYZW: function ( index, x, y, z, w ) {
25317
25318                 index = index * this.data.stride + this.offset;
25319
25320                 this.data.array[ index + 0 ] = x;
25321                 this.data.array[ index + 1 ] = y;
25322                 this.data.array[ index + 2 ] = z;
25323                 this.data.array[ index + 3 ] = w;
25324
25325                 return this;
25326
25327         },
25328
25329         clone: function ( data ) {
25330
25331                 if ( data === undefined ) {
25332
25333                         console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interlaved buffer attribute will deinterleave buffer data.' );
25334
25335                         const array = [];
25336
25337                         for ( let i = 0; i < this.count; i ++ ) {
25338
25339                                 const index = i * this.data.stride + this.offset;
25340
25341                                 for ( let j = 0; j < this.itemSize; j ++ ) {
25342
25343                                         array.push( this.data.array[ index + j ] );
25344
25345                                 }
25346
25347                         }
25348
25349                         return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
25350
25351                 } else {
25352
25353                         if ( data.interleavedBuffers === undefined ) {
25354
25355                                 data.interleavedBuffers = {};
25356
25357                         }
25358
25359                         if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
25360
25361                                 data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
25362
25363                         }
25364
25365                         return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
25366
25367                 }
25368
25369         },
25370
25371         toJSON: function ( data ) {
25372
25373                 if ( data === undefined ) {
25374
25375                         console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.' );
25376
25377                         const array = [];
25378
25379                         for ( let i = 0; i < this.count; i ++ ) {
25380
25381                                 const index = i * this.data.stride + this.offset;
25382
25383                                 for ( let j = 0; j < this.itemSize; j ++ ) {
25384
25385                                         array.push( this.data.array[ index + j ] );
25386
25387                                 }
25388
25389                         }
25390
25391                         // deinterleave data and save it as an ordinary buffer attribute for now
25392
25393                         return {
25394                                 itemSize: this.itemSize,
25395                                 type: this.array.constructor.name,
25396                                 array: array,
25397                                 normalized: this.normalized
25398                         };
25399
25400                 } else {
25401
25402                         // save as true interlaved attribtue
25403
25404                         if ( data.interleavedBuffers === undefined ) {
25405
25406                                 data.interleavedBuffers = {};
25407
25408                         }
25409
25410                         if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
25411
25412                                 data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
25413
25414                         }
25415
25416                         return {
25417                                 isInterleavedBufferAttribute: true,
25418                                 itemSize: this.itemSize,
25419                                 data: this.data.uuid,
25420                                 offset: this.offset,
25421                                 normalized: this.normalized
25422                         };
25423
25424                 }
25425
25426         }
25427
25428 } );
25429
25430 /**
25431  * parameters = {
25432  *  color: <hex>,
25433  *  map: new THREE.Texture( <Image> ),
25434  *  alphaMap: new THREE.Texture( <Image> ),
25435  *  rotation: <float>,
25436  *  sizeAttenuation: <bool>
25437  * }
25438  */
25439
25440 function SpriteMaterial( parameters ) {
25441
25442         Material.call( this );
25443
25444         this.type = 'SpriteMaterial';
25445
25446         this.color = new Color( 0xffffff );
25447
25448         this.map = null;
25449
25450         this.alphaMap = null;
25451
25452         this.rotation = 0;
25453
25454         this.sizeAttenuation = true;
25455
25456         this.transparent = true;
25457
25458         this.setValues( parameters );
25459
25460 }
25461
25462 SpriteMaterial.prototype = Object.create( Material.prototype );
25463 SpriteMaterial.prototype.constructor = SpriteMaterial;
25464 SpriteMaterial.prototype.isSpriteMaterial = true;
25465
25466 SpriteMaterial.prototype.copy = function ( source ) {
25467
25468         Material.prototype.copy.call( this, source );
25469
25470         this.color.copy( source.color );
25471
25472         this.map = source.map;
25473
25474         this.alphaMap = source.alphaMap;
25475
25476         this.rotation = source.rotation;
25477
25478         this.sizeAttenuation = source.sizeAttenuation;
25479
25480         return this;
25481
25482 };
25483
25484 let _geometry;
25485
25486 const _intersectPoint = new Vector3();
25487 const _worldScale = new Vector3();
25488 const _mvPosition = new Vector3();
25489
25490 const _alignedPosition = new Vector2();
25491 const _rotatedPosition = new Vector2();
25492 const _viewWorldMatrix = new Matrix4();
25493
25494 const _vA$1 = new Vector3();
25495 const _vB$1 = new Vector3();
25496 const _vC$1 = new Vector3();
25497
25498 const _uvA$1 = new Vector2();
25499 const _uvB$1 = new Vector2();
25500 const _uvC$1 = new Vector2();
25501
25502 function Sprite( material ) {
25503
25504         Object3D.call( this );
25505
25506         this.type = 'Sprite';
25507
25508         if ( _geometry === undefined ) {
25509
25510                 _geometry = new BufferGeometry();
25511
25512                 const float32Array = new Float32Array( [
25513                         - 0.5, - 0.5, 0, 0, 0,
25514                         0.5, - 0.5, 0, 1, 0,
25515                         0.5, 0.5, 0, 1, 1,
25516                         - 0.5, 0.5, 0, 0, 1
25517                 ] );
25518
25519                 const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
25520
25521                 _geometry.setIndex( [ 0, 1, 2,  0, 2, 3 ] );
25522                 _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
25523                 _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
25524
25525         }
25526
25527         this.geometry = _geometry;
25528         this.material = ( material !== undefined ) ? material : new SpriteMaterial();
25529
25530         this.center = new Vector2( 0.5, 0.5 );
25531
25532 }
25533
25534 Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
25535
25536         constructor: Sprite,
25537
25538         isSprite: true,
25539
25540         raycast: function ( raycaster, intersects ) {
25541
25542                 if ( raycaster.camera === null ) {
25543
25544                         console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
25545
25546                 }
25547
25548                 _worldScale.setFromMatrixScale( this.matrixWorld );
25549
25550                 _viewWorldMatrix.copy( raycaster.camera.matrixWorld );
25551                 this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
25552
25553                 _mvPosition.setFromMatrixPosition( this.modelViewMatrix );
25554
25555                 if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
25556
25557                         _worldScale.multiplyScalar( - _mvPosition.z );
25558
25559                 }
25560
25561                 const rotation = this.material.rotation;
25562                 let sin, cos;
25563
25564                 if ( rotation !== 0 ) {
25565
25566                         cos = Math.cos( rotation );
25567                         sin = Math.sin( rotation );
25568
25569                 }
25570
25571                 const center = this.center;
25572
25573                 transformVertex( _vA$1.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
25574                 transformVertex( _vB$1.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
25575                 transformVertex( _vC$1.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
25576
25577                 _uvA$1.set( 0, 0 );
25578                 _uvB$1.set( 1, 0 );
25579                 _uvC$1.set( 1, 1 );
25580
25581                 // check first triangle
25582                 let intersect = raycaster.ray.intersectTriangle( _vA$1, _vB$1, _vC$1, false, _intersectPoint );
25583
25584                 if ( intersect === null ) {
25585
25586                         // check second triangle
25587                         transformVertex( _vB$1.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
25588                         _uvB$1.set( 0, 1 );
25589
25590                         intersect = raycaster.ray.intersectTriangle( _vA$1, _vC$1, _vB$1, false, _intersectPoint );
25591                         if ( intersect === null ) {
25592
25593                                 return;
25594
25595                         }
25596
25597                 }
25598
25599                 const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
25600
25601                 if ( distance < raycaster.near || distance > raycaster.far ) return;
25602
25603                 intersects.push( {
25604
25605                         distance: distance,
25606                         point: _intersectPoint.clone(),
25607                         uv: Triangle.getUV( _intersectPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ),
25608                         face: null,
25609                         object: this
25610
25611                 } );
25612
25613         },
25614
25615         copy: function ( source ) {
25616
25617                 Object3D.prototype.copy.call( this, source );
25618
25619                 if ( source.center !== undefined ) this.center.copy( source.center );
25620
25621                 this.material = source.material;
25622
25623                 return this;
25624
25625         }
25626
25627 } );
25628
25629 function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
25630
25631         // compute position in camera space
25632         _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
25633
25634         // to check if rotation is not zero
25635         if ( sin !== undefined ) {
25636
25637                 _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
25638                 _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
25639
25640         } else {
25641
25642                 _rotatedPosition.copy( _alignedPosition );
25643
25644         }
25645
25646
25647         vertexPosition.copy( mvPosition );
25648         vertexPosition.x += _rotatedPosition.x;
25649         vertexPosition.y += _rotatedPosition.y;
25650
25651         // transform to world space
25652         vertexPosition.applyMatrix4( _viewWorldMatrix );
25653
25654 }
25655
25656 const _v1$4 = new Vector3();
25657 const _v2$2 = new Vector3();
25658
25659 function LOD() {
25660
25661         Object3D.call( this );
25662
25663         this._currentLevel = 0;
25664
25665         this.type = 'LOD';
25666
25667         Object.defineProperties( this, {
25668                 levels: {
25669                         enumerable: true,
25670                         value: []
25671                 }
25672         } );
25673
25674         this.autoUpdate = true;
25675
25676 }
25677
25678 LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
25679
25680         constructor: LOD,
25681
25682         isLOD: true,
25683
25684         copy: function ( source ) {
25685
25686                 Object3D.prototype.copy.call( this, source, false );
25687
25688                 const levels = source.levels;
25689
25690                 for ( let i = 0, l = levels.length; i < l; i ++ ) {
25691
25692                         const level = levels[ i ];
25693
25694                         this.addLevel( level.object.clone(), level.distance );
25695
25696                 }
25697
25698                 this.autoUpdate = source.autoUpdate;
25699
25700                 return this;
25701
25702         },
25703
25704         addLevel: function ( object, distance = 0 ) {
25705
25706                 distance = Math.abs( distance );
25707
25708                 const levels = this.levels;
25709
25710                 let l;
25711
25712                 for ( l = 0; l < levels.length; l ++ ) {
25713
25714                         if ( distance < levels[ l ].distance ) {
25715
25716                                 break;
25717
25718                         }
25719
25720                 }
25721
25722                 levels.splice( l, 0, { distance: distance, object: object } );
25723
25724                 this.add( object );
25725
25726                 return this;
25727
25728         },
25729
25730         getCurrentLevel: function () {
25731
25732                 return this._currentLevel;
25733
25734         },
25735
25736         getObjectForDistance: function ( distance ) {
25737
25738                 const levels = this.levels;
25739
25740                 if ( levels.length > 0 ) {
25741
25742                         let i, l;
25743
25744                         for ( i = 1, l = levels.length; i < l; i ++ ) {
25745
25746                                 if ( distance < levels[ i ].distance ) {
25747
25748                                         break;
25749
25750                                 }
25751
25752                         }
25753
25754                         return levels[ i - 1 ].object;
25755
25756                 }
25757
25758                 return null;
25759
25760         },
25761
25762         raycast: function ( raycaster, intersects ) {
25763
25764                 const levels = this.levels;
25765
25766                 if ( levels.length > 0 ) {
25767
25768                         _v1$4.setFromMatrixPosition( this.matrixWorld );
25769
25770                         const distance = raycaster.ray.origin.distanceTo( _v1$4 );
25771
25772                         this.getObjectForDistance( distance ).raycast( raycaster, intersects );
25773
25774                 }
25775
25776         },
25777
25778         update: function ( camera ) {
25779
25780                 const levels = this.levels;
25781
25782                 if ( levels.length > 1 ) {
25783
25784                         _v1$4.setFromMatrixPosition( camera.matrixWorld );
25785                         _v2$2.setFromMatrixPosition( this.matrixWorld );
25786
25787                         const distance = _v1$4.distanceTo( _v2$2 ) / camera.zoom;
25788
25789                         levels[ 0 ].object.visible = true;
25790
25791                         let i, l;
25792
25793                         for ( i = 1, l = levels.length; i < l; i ++ ) {
25794
25795                                 if ( distance >= levels[ i ].distance ) {
25796
25797                                         levels[ i - 1 ].object.visible = false;
25798                                         levels[ i ].object.visible = true;
25799
25800                                 } else {
25801
25802                                         break;
25803
25804                                 }
25805
25806                         }
25807
25808                         this._currentLevel = i - 1;
25809
25810                         for ( ; i < l; i ++ ) {
25811
25812                                 levels[ i ].object.visible = false;
25813
25814                         }
25815
25816                 }
25817
25818         },
25819
25820         toJSON: function ( meta ) {
25821
25822                 const data = Object3D.prototype.toJSON.call( this, meta );
25823
25824                 if ( this.autoUpdate === false ) data.object.autoUpdate = false;
25825
25826                 data.object.levels = [];
25827
25828                 const levels = this.levels;
25829
25830                 for ( let i = 0, l = levels.length; i < l; i ++ ) {
25831
25832                         const level = levels[ i ];
25833
25834                         data.object.levels.push( {
25835                                 object: level.object.uuid,
25836                                 distance: level.distance
25837                         } );
25838
25839                 }
25840
25841                 return data;
25842
25843         }
25844
25845 } );
25846
25847 const _basePosition = new Vector3();
25848
25849 const _skinIndex = new Vector4();
25850 const _skinWeight = new Vector4();
25851
25852 const _vector$7 = new Vector3();
25853 const _matrix$1 = new Matrix4();
25854
25855 function SkinnedMesh( geometry, material ) {
25856
25857         if ( geometry && geometry.isGeometry ) {
25858
25859                 console.error( 'THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
25860
25861         }
25862
25863         Mesh.call( this, geometry, material );
25864
25865         this.type = 'SkinnedMesh';
25866
25867         this.bindMode = 'attached';
25868         this.bindMatrix = new Matrix4();
25869         this.bindMatrixInverse = new Matrix4();
25870
25871 }
25872
25873 SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
25874
25875         constructor: SkinnedMesh,
25876
25877         isSkinnedMesh: true,
25878
25879         copy: function ( source ) {
25880
25881                 Mesh.prototype.copy.call( this, source );
25882
25883                 this.bindMode = source.bindMode;
25884                 this.bindMatrix.copy( source.bindMatrix );
25885                 this.bindMatrixInverse.copy( source.bindMatrixInverse );
25886
25887                 this.skeleton = source.skeleton;
25888
25889                 return this;
25890
25891         },
25892
25893         bind: function ( skeleton, bindMatrix ) {
25894
25895                 this.skeleton = skeleton;
25896
25897                 if ( bindMatrix === undefined ) {
25898
25899                         this.updateMatrixWorld( true );
25900
25901                         this.skeleton.calculateInverses();
25902
25903                         bindMatrix = this.matrixWorld;
25904
25905                 }
25906
25907                 this.bindMatrix.copy( bindMatrix );
25908                 this.bindMatrixInverse.copy( bindMatrix ).invert();
25909
25910         },
25911
25912         pose: function () {
25913
25914                 this.skeleton.pose();
25915
25916         },
25917
25918         normalizeSkinWeights: function () {
25919
25920                 const vector = new Vector4();
25921
25922                 const skinWeight = this.geometry.attributes.skinWeight;
25923
25924                 for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
25925
25926                         vector.x = skinWeight.getX( i );
25927                         vector.y = skinWeight.getY( i );
25928                         vector.z = skinWeight.getZ( i );
25929                         vector.w = skinWeight.getW( i );
25930
25931                         const scale = 1.0 / vector.manhattanLength();
25932
25933                         if ( scale !== Infinity ) {
25934
25935                                 vector.multiplyScalar( scale );
25936
25937                         } else {
25938
25939                                 vector.set( 1, 0, 0, 0 ); // do something reasonable
25940
25941                         }
25942
25943                         skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
25944
25945                 }
25946
25947         },
25948
25949         updateMatrixWorld: function ( force ) {
25950
25951                 Mesh.prototype.updateMatrixWorld.call( this, force );
25952
25953                 if ( this.bindMode === 'attached' ) {
25954
25955                         this.bindMatrixInverse.copy( this.matrixWorld ).invert();
25956
25957                 } else if ( this.bindMode === 'detached' ) {
25958
25959                         this.bindMatrixInverse.copy( this.bindMatrix ).invert();
25960
25961                 } else {
25962
25963                         console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
25964
25965                 }
25966
25967         },
25968
25969         boneTransform: function ( index, target ) {
25970
25971                 const skeleton = this.skeleton;
25972                 const geometry = this.geometry;
25973
25974                 _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
25975                 _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
25976
25977                 _basePosition.fromBufferAttribute( geometry.attributes.position, index ).applyMatrix4( this.bindMatrix );
25978
25979                 target.set( 0, 0, 0 );
25980
25981                 for ( let i = 0; i < 4; i ++ ) {
25982
25983                         const weight = _skinWeight.getComponent( i );
25984
25985                         if ( weight !== 0 ) {
25986
25987                                 const boneIndex = _skinIndex.getComponent( i );
25988
25989                                 _matrix$1.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
25990
25991                                 target.addScaledVector( _vector$7.copy( _basePosition ).applyMatrix4( _matrix$1 ), weight );
25992
25993                         }
25994
25995                 }
25996
25997                 return target.applyMatrix4( this.bindMatrixInverse );
25998
25999         }
26000
26001 } );
26002
26003 function Bone() {
26004
26005         Object3D.call( this );
26006
26007         this.type = 'Bone';
26008
26009 }
26010
26011 Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
26012
26013         constructor: Bone,
26014
26015         isBone: true
26016
26017 } );
26018
26019 const _offsetMatrix = new Matrix4();
26020 const _identityMatrix = new Matrix4();
26021
26022 function Skeleton( bones = [], boneInverses = [] ) {
26023
26024         this.uuid = MathUtils.generateUUID();
26025
26026         this.bones = bones.slice( 0 );
26027         this.boneInverses = boneInverses;
26028         this.boneMatrices = null;
26029
26030         this.boneTexture = null;
26031         this.boneTextureSize = 0;
26032
26033         this.frame = - 1;
26034
26035         this.init();
26036
26037 }
26038
26039 Object.assign( Skeleton.prototype, {
26040
26041         init: function () {
26042
26043                 const bones = this.bones;
26044                 const boneInverses = this.boneInverses;
26045
26046                 this.boneMatrices = new Float32Array( bones.length * 16 );
26047
26048                 // calculate inverse bone matrices if necessary
26049
26050                 if ( boneInverses.length === 0 ) {
26051
26052                         this.calculateInverses();
26053
26054                 } else {
26055
26056                         // handle special case
26057
26058                         if ( bones.length !== boneInverses.length ) {
26059
26060                                 console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' );
26061
26062                                 this.boneInverses = [];
26063
26064                                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26065
26066                                         this.boneInverses.push( new Matrix4() );
26067
26068                                 }
26069
26070                         }
26071
26072                 }
26073
26074         },
26075
26076         calculateInverses: function () {
26077
26078                 this.boneInverses.length = 0;
26079
26080                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26081
26082                         const inverse = new Matrix4();
26083
26084                         if ( this.bones[ i ] ) {
26085
26086                                 inverse.copy( this.bones[ i ].matrixWorld ).invert();
26087
26088                         }
26089
26090                         this.boneInverses.push( inverse );
26091
26092                 }
26093
26094         },
26095
26096         pose: function () {
26097
26098                 // recover the bind-time world matrices
26099
26100                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26101
26102                         const bone = this.bones[ i ];
26103
26104                         if ( bone ) {
26105
26106                                 bone.matrixWorld.copy( this.boneInverses[ i ] ).invert();
26107
26108                         }
26109
26110                 }
26111
26112                 // compute the local matrices, positions, rotations and scales
26113
26114                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26115
26116                         const bone = this.bones[ i ];
26117
26118                         if ( bone ) {
26119
26120                                 if ( bone.parent && bone.parent.isBone ) {
26121
26122                                         bone.matrix.copy( bone.parent.matrixWorld ).invert();
26123                                         bone.matrix.multiply( bone.matrixWorld );
26124
26125                                 } else {
26126
26127                                         bone.matrix.copy( bone.matrixWorld );
26128
26129                                 }
26130
26131                                 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
26132
26133                         }
26134
26135                 }
26136
26137         },
26138
26139         update: function () {
26140
26141                 const bones = this.bones;
26142                 const boneInverses = this.boneInverses;
26143                 const boneMatrices = this.boneMatrices;
26144                 const boneTexture = this.boneTexture;
26145
26146                 // flatten bone matrices to array
26147
26148                 for ( let i = 0, il = bones.length; i < il; i ++ ) {
26149
26150                         // compute the offset between the current and the original transform
26151
26152                         const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;
26153
26154                         _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
26155                         _offsetMatrix.toArray( boneMatrices, i * 16 );
26156
26157                 }
26158
26159                 if ( boneTexture !== null ) {
26160
26161                         boneTexture.needsUpdate = true;
26162
26163                 }
26164
26165         },
26166
26167         clone: function () {
26168
26169                 return new Skeleton( this.bones, this.boneInverses );
26170
26171         },
26172
26173         getBoneByName: function ( name ) {
26174
26175                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26176
26177                         const bone = this.bones[ i ];
26178
26179                         if ( bone.name === name ) {
26180
26181                                 return bone;
26182
26183                         }
26184
26185                 }
26186
26187                 return undefined;
26188
26189         },
26190
26191         dispose: function ( ) {
26192
26193                 if ( this.boneTexture !== null ) {
26194
26195                         this.boneTexture.dispose();
26196
26197                         this.boneTexture = null;
26198
26199                 }
26200
26201         },
26202
26203         fromJSON: function ( json, bones ) {
26204
26205                 this.uuid = json.uuid;
26206
26207                 for ( let i = 0, l = json.bones.length; i < l; i ++ ) {
26208
26209                         const uuid = json.bones[ i ];
26210                         let bone = bones[ uuid ];
26211
26212                         if ( bone === undefined ) {
26213
26214                                 console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid );
26215                                 bone = new Bone();
26216
26217                         }
26218
26219                         this.bones.push( bone );
26220                         this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) );
26221
26222                 }
26223
26224                 this.init();
26225
26226                 return this;
26227
26228         },
26229
26230         toJSON: function () {
26231
26232                 const data = {
26233                         metadata: {
26234                                 version: 4.5,
26235                                 type: 'Skeleton',
26236                                 generator: 'Skeleton.toJSON'
26237                         },
26238                         bones: [],
26239                         boneInverses: []
26240                 };
26241
26242                 data.uuid = this.uuid;
26243
26244                 const bones = this.bones;
26245                 const boneInverses = this.boneInverses;
26246
26247                 for ( let i = 0, l = bones.length; i < l; i ++ ) {
26248
26249                         const bone = bones[ i ];
26250                         data.bones.push( bone.uuid );
26251
26252                         const boneInverse = boneInverses[ i ];
26253                         data.boneInverses.push( boneInverse.toArray() );
26254
26255                 }
26256
26257                 return data;
26258
26259         }
26260
26261 } );
26262
26263 const _instanceLocalMatrix = new Matrix4();
26264 const _instanceWorldMatrix = new Matrix4();
26265
26266 const _instanceIntersects = [];
26267
26268 const _mesh = new Mesh();
26269
26270 function InstancedMesh( geometry, material, count ) {
26271
26272         Mesh.call( this, geometry, material );
26273
26274         this.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 );
26275         this.instanceColor = null;
26276
26277         this.count = count;
26278
26279         this.frustumCulled = false;
26280
26281 }
26282
26283 InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
26284
26285         constructor: InstancedMesh,
26286
26287         isInstancedMesh: true,
26288
26289         copy: function ( source ) {
26290
26291                 Mesh.prototype.copy.call( this, source );
26292
26293                 this.instanceMatrix.copy( source.instanceMatrix );
26294
26295                 if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
26296
26297                 this.count = source.count;
26298
26299                 return this;
26300
26301         },
26302
26303         getColorAt: function ( index, color ) {
26304
26305                 color.fromArray( this.instanceColor.array, index * 3 );
26306
26307         },
26308
26309         getMatrixAt: function ( index, matrix ) {
26310
26311                 matrix.fromArray( this.instanceMatrix.array, index * 16 );
26312
26313         },
26314
26315         raycast: function ( raycaster, intersects ) {
26316
26317                 const matrixWorld = this.matrixWorld;
26318                 const raycastTimes = this.count;
26319
26320                 _mesh.geometry = this.geometry;
26321                 _mesh.material = this.material;
26322
26323                 if ( _mesh.material === undefined ) return;
26324
26325                 for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
26326
26327                         // calculate the world matrix for each instance
26328
26329                         this.getMatrixAt( instanceId, _instanceLocalMatrix );
26330
26331                         _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
26332
26333                         // the mesh represents this single instance
26334
26335                         _mesh.matrixWorld = _instanceWorldMatrix;
26336
26337                         _mesh.raycast( raycaster, _instanceIntersects );
26338
26339                         // process the result of raycast
26340
26341                         for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
26342
26343                                 const intersect = _instanceIntersects[ i ];
26344                                 intersect.instanceId = instanceId;
26345                                 intersect.object = this;
26346                                 intersects.push( intersect );
26347
26348                         }
26349
26350                         _instanceIntersects.length = 0;
26351
26352                 }
26353
26354         },
26355
26356         setColorAt: function ( index, color ) {
26357
26358                 if ( this.instanceColor === null ) {
26359
26360                         this.instanceColor = new BufferAttribute( new Float32Array( this.count * 3 ), 3 );
26361
26362                 }
26363
26364                 color.toArray( this.instanceColor.array, index * 3 );
26365
26366         },
26367
26368         setMatrixAt: function ( index, matrix ) {
26369
26370                 matrix.toArray( this.instanceMatrix.array, index * 16 );
26371
26372         },
26373
26374         updateMorphTargets: function () {
26375
26376         },
26377
26378         dispose: function () {
26379
26380                 this.dispatchEvent( { type: 'dispose' } );
26381
26382         }
26383
26384 } );
26385
26386 /**
26387  * parameters = {
26388  *  color: <hex>,
26389  *  opacity: <float>,
26390  *
26391  *  linewidth: <float>,
26392  *  linecap: "round",
26393  *  linejoin: "round"
26394  * }
26395  */
26396
26397 function LineBasicMaterial( parameters ) {
26398
26399         Material.call( this );
26400
26401         this.type = 'LineBasicMaterial';
26402
26403         this.color = new Color( 0xffffff );
26404
26405         this.linewidth = 1;
26406         this.linecap = 'round';
26407         this.linejoin = 'round';
26408
26409         this.morphTargets = false;
26410
26411         this.setValues( parameters );
26412
26413 }
26414
26415 LineBasicMaterial.prototype = Object.create( Material.prototype );
26416 LineBasicMaterial.prototype.constructor = LineBasicMaterial;
26417
26418 LineBasicMaterial.prototype.isLineBasicMaterial = true;
26419
26420 LineBasicMaterial.prototype.copy = function ( source ) {
26421
26422         Material.prototype.copy.call( this, source );
26423
26424         this.color.copy( source.color );
26425
26426         this.linewidth = source.linewidth;
26427         this.linecap = source.linecap;
26428         this.linejoin = source.linejoin;
26429
26430         this.morphTargets = source.morphTargets;
26431
26432         return this;
26433
26434 };
26435
26436 const _start = new Vector3();
26437 const _end = new Vector3();
26438 const _inverseMatrix$1 = new Matrix4();
26439 const _ray$1 = new Ray();
26440 const _sphere$2 = new Sphere();
26441
26442 function Line( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
26443
26444         Object3D.call( this );
26445
26446         this.type = 'Line';
26447
26448         this.geometry = geometry;
26449         this.material = material;
26450
26451         this.updateMorphTargets();
26452
26453 }
26454
26455 Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
26456
26457         constructor: Line,
26458
26459         isLine: true,
26460
26461         copy: function ( source ) {
26462
26463                 Object3D.prototype.copy.call( this, source );
26464
26465                 this.material = source.material;
26466                 this.geometry = source.geometry;
26467
26468                 return this;
26469
26470         },
26471
26472         computeLineDistances: function () {
26473
26474                 const geometry = this.geometry;
26475
26476                 if ( geometry.isBufferGeometry ) {
26477
26478                         // we assume non-indexed geometry
26479
26480                         if ( geometry.index === null ) {
26481
26482                                 const positionAttribute = geometry.attributes.position;
26483                                 const lineDistances = [ 0 ];
26484
26485                                 for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
26486
26487                                         _start.fromBufferAttribute( positionAttribute, i - 1 );
26488                                         _end.fromBufferAttribute( positionAttribute, i );
26489
26490                                         lineDistances[ i ] = lineDistances[ i - 1 ];
26491                                         lineDistances[ i ] += _start.distanceTo( _end );
26492
26493                                 }
26494
26495                                 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
26496
26497                         } else {
26498
26499                                 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
26500
26501                         }
26502
26503                 } else if ( geometry.isGeometry ) {
26504
26505                         console.error( 'THREE.Line.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
26506
26507                 }
26508
26509                 return this;
26510
26511         },
26512
26513         raycast: function ( raycaster, intersects ) {
26514
26515                 const geometry = this.geometry;
26516                 const matrixWorld = this.matrixWorld;
26517                 const threshold = raycaster.params.Line.threshold;
26518
26519                 // Checking boundingSphere distance to ray
26520
26521                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
26522
26523                 _sphere$2.copy( geometry.boundingSphere );
26524                 _sphere$2.applyMatrix4( matrixWorld );
26525                 _sphere$2.radius += threshold;
26526
26527                 if ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) return;
26528
26529                 //
26530
26531                 _inverseMatrix$1.copy( matrixWorld ).invert();
26532                 _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
26533
26534                 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
26535                 const localThresholdSq = localThreshold * localThreshold;
26536
26537                 const vStart = new Vector3();
26538                 const vEnd = new Vector3();
26539                 const interSegment = new Vector3();
26540                 const interRay = new Vector3();
26541                 const step = this.isLineSegments ? 2 : 1;
26542
26543                 if ( geometry.isBufferGeometry ) {
26544
26545                         const index = geometry.index;
26546                         const attributes = geometry.attributes;
26547                         const positionAttribute = attributes.position;
26548
26549                         if ( index !== null ) {
26550
26551                                 const indices = index.array;
26552
26553                                 for ( let i = 0, l = indices.length - 1; i < l; i += step ) {
26554
26555                                         const a = indices[ i ];
26556                                         const b = indices[ i + 1 ];
26557
26558                                         vStart.fromBufferAttribute( positionAttribute, a );
26559                                         vEnd.fromBufferAttribute( positionAttribute, b );
26560
26561                                         const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
26562
26563                                         if ( distSq > localThresholdSq ) continue;
26564
26565                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
26566
26567                                         const distance = raycaster.ray.origin.distanceTo( interRay );
26568
26569                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
26570
26571                                         intersects.push( {
26572
26573                                                 distance: distance,
26574                                                 // What do we want? intersection point on the ray or on the segment??
26575                                                 // point: raycaster.ray.at( distance ),
26576                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
26577                                                 index: i,
26578                                                 face: null,
26579                                                 faceIndex: null,
26580                                                 object: this
26581
26582                                         } );
26583
26584                                 }
26585
26586                         } else {
26587
26588                                 for ( let i = 0, l = positionAttribute.count - 1; i < l; i += step ) {
26589
26590                                         vStart.fromBufferAttribute( positionAttribute, i );
26591                                         vEnd.fromBufferAttribute( positionAttribute, i + 1 );
26592
26593                                         const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
26594
26595                                         if ( distSq > localThresholdSq ) continue;
26596
26597                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
26598
26599                                         const distance = raycaster.ray.origin.distanceTo( interRay );
26600
26601                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
26602
26603                                         intersects.push( {
26604
26605                                                 distance: distance,
26606                                                 // What do we want? intersection point on the ray or on the segment??
26607                                                 // point: raycaster.ray.at( distance ),
26608                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
26609                                                 index: i,
26610                                                 face: null,
26611                                                 faceIndex: null,
26612                                                 object: this
26613
26614                                         } );
26615
26616                                 }
26617
26618                         }
26619
26620                 } else if ( geometry.isGeometry ) {
26621
26622                         console.error( 'THREE.Line.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
26623
26624                 }
26625
26626         },
26627
26628         updateMorphTargets: function () {
26629
26630                 const geometry = this.geometry;
26631
26632                 if ( geometry.isBufferGeometry ) {
26633
26634                         const morphAttributes = geometry.morphAttributes;
26635                         const keys = Object.keys( morphAttributes );
26636
26637                         if ( keys.length > 0 ) {
26638
26639                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
26640
26641                                 if ( morphAttribute !== undefined ) {
26642
26643                                         this.morphTargetInfluences = [];
26644                                         this.morphTargetDictionary = {};
26645
26646                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
26647
26648                                                 const name = morphAttribute[ m ].name || String( m );
26649
26650                                                 this.morphTargetInfluences.push( 0 );
26651                                                 this.morphTargetDictionary[ name ] = m;
26652
26653                                         }
26654
26655                                 }
26656
26657                         }
26658
26659                 } else {
26660
26661                         const morphTargets = geometry.morphTargets;
26662
26663                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
26664
26665                                 console.error( 'THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
26666
26667                         }
26668
26669                 }
26670
26671         }
26672
26673 } );
26674
26675 const _start$1 = new Vector3();
26676 const _end$1 = new Vector3();
26677
26678 function LineSegments( geometry, material ) {
26679
26680         Line.call( this, geometry, material );
26681
26682         this.type = 'LineSegments';
26683
26684 }
26685
26686 LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
26687
26688         constructor: LineSegments,
26689
26690         isLineSegments: true,
26691
26692         computeLineDistances: function () {
26693
26694                 const geometry = this.geometry;
26695
26696                 if ( geometry.isBufferGeometry ) {
26697
26698                         // we assume non-indexed geometry
26699
26700                         if ( geometry.index === null ) {
26701
26702                                 const positionAttribute = geometry.attributes.position;
26703                                 const lineDistances = [];
26704
26705                                 for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
26706
26707                                         _start$1.fromBufferAttribute( positionAttribute, i );
26708                                         _end$1.fromBufferAttribute( positionAttribute, i + 1 );
26709
26710                                         lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
26711                                         lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
26712
26713                                 }
26714
26715                                 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
26716
26717                         } else {
26718
26719                                 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
26720
26721                         }
26722
26723                 } else if ( geometry.isGeometry ) {
26724
26725                         console.error( 'THREE.LineSegments.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
26726
26727                 }
26728
26729                 return this;
26730
26731         }
26732
26733 } );
26734
26735 function LineLoop( geometry, material ) {
26736
26737         Line.call( this, geometry, material );
26738
26739         this.type = 'LineLoop';
26740
26741 }
26742
26743 LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
26744
26745         constructor: LineLoop,
26746
26747         isLineLoop: true,
26748
26749 } );
26750
26751 /**
26752  * parameters = {
26753  *  color: <hex>,
26754  *  opacity: <float>,
26755  *  map: new THREE.Texture( <Image> ),
26756  *  alphaMap: new THREE.Texture( <Image> ),
26757  *
26758  *  size: <float>,
26759  *  sizeAttenuation: <bool>
26760  *
26761  *  morphTargets: <bool>
26762  * }
26763  */
26764
26765 function PointsMaterial( parameters ) {
26766
26767         Material.call( this );
26768
26769         this.type = 'PointsMaterial';
26770
26771         this.color = new Color( 0xffffff );
26772
26773         this.map = null;
26774
26775         this.alphaMap = null;
26776
26777         this.size = 1;
26778         this.sizeAttenuation = true;
26779
26780         this.morphTargets = false;
26781
26782         this.setValues( parameters );
26783
26784 }
26785
26786 PointsMaterial.prototype = Object.create( Material.prototype );
26787 PointsMaterial.prototype.constructor = PointsMaterial;
26788
26789 PointsMaterial.prototype.isPointsMaterial = true;
26790
26791 PointsMaterial.prototype.copy = function ( source ) {
26792
26793         Material.prototype.copy.call( this, source );
26794
26795         this.color.copy( source.color );
26796
26797         this.map = source.map;
26798
26799         this.alphaMap = source.alphaMap;
26800
26801         this.size = source.size;
26802         this.sizeAttenuation = source.sizeAttenuation;
26803
26804         this.morphTargets = source.morphTargets;
26805
26806         return this;
26807
26808 };
26809
26810 const _inverseMatrix$2 = new Matrix4();
26811 const _ray$2 = new Ray();
26812 const _sphere$3 = new Sphere();
26813 const _position$1 = new Vector3();
26814
26815 function Points( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
26816
26817         Object3D.call( this );
26818
26819         this.type = 'Points';
26820
26821         this.geometry = geometry;
26822         this.material = material;
26823
26824         this.updateMorphTargets();
26825
26826 }
26827
26828 Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
26829
26830         constructor: Points,
26831
26832         isPoints: true,
26833
26834         copy: function ( source ) {
26835
26836                 Object3D.prototype.copy.call( this, source );
26837
26838                 this.material = source.material;
26839                 this.geometry = source.geometry;
26840
26841                 return this;
26842
26843         },
26844
26845         raycast: function ( raycaster, intersects ) {
26846
26847                 const geometry = this.geometry;
26848                 const matrixWorld = this.matrixWorld;
26849                 const threshold = raycaster.params.Points.threshold;
26850
26851                 // Checking boundingSphere distance to ray
26852
26853                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
26854
26855                 _sphere$3.copy( geometry.boundingSphere );
26856                 _sphere$3.applyMatrix4( matrixWorld );
26857                 _sphere$3.radius += threshold;
26858
26859                 if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
26860
26861                 //
26862
26863                 _inverseMatrix$2.copy( matrixWorld ).invert();
26864                 _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
26865
26866                 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
26867                 const localThresholdSq = localThreshold * localThreshold;
26868
26869                 if ( geometry.isBufferGeometry ) {
26870
26871                         const index = geometry.index;
26872                         const attributes = geometry.attributes;
26873                         const positionAttribute = attributes.position;
26874
26875                         if ( index !== null ) {
26876
26877                                 const indices = index.array;
26878
26879                                 for ( let i = 0, il = indices.length; i < il; i ++ ) {
26880
26881                                         const a = indices[ i ];
26882
26883                                         _position$1.fromBufferAttribute( positionAttribute, a );
26884
26885                                         testPoint( _position$1, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
26886
26887                                 }
26888
26889                         } else {
26890
26891                                 for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
26892
26893                                         _position$1.fromBufferAttribute( positionAttribute, i );
26894
26895                                         testPoint( _position$1, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
26896
26897                                 }
26898
26899                         }
26900
26901                 } else {
26902
26903                         console.error( 'THREE.Points.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
26904
26905                 }
26906
26907         },
26908
26909         updateMorphTargets: function () {
26910
26911                 const geometry = this.geometry;
26912
26913                 if ( geometry.isBufferGeometry ) {
26914
26915                         const morphAttributes = geometry.morphAttributes;
26916                         const keys = Object.keys( morphAttributes );
26917
26918                         if ( keys.length > 0 ) {
26919
26920                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
26921
26922                                 if ( morphAttribute !== undefined ) {
26923
26924                                         this.morphTargetInfluences = [];
26925                                         this.morphTargetDictionary = {};
26926
26927                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
26928
26929                                                 const name = morphAttribute[ m ].name || String( m );
26930
26931                                                 this.morphTargetInfluences.push( 0 );
26932                                                 this.morphTargetDictionary[ name ] = m;
26933
26934                                         }
26935
26936                                 }
26937
26938                         }
26939
26940                 } else {
26941
26942                         const morphTargets = geometry.morphTargets;
26943
26944                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
26945
26946                                 console.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
26947
26948                         }
26949
26950                 }
26951
26952         }
26953
26954 } );
26955
26956 function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
26957
26958         const rayPointDistanceSq = _ray$2.distanceSqToPoint( point );
26959
26960         if ( rayPointDistanceSq < localThresholdSq ) {
26961
26962                 const intersectPoint = new Vector3();
26963
26964                 _ray$2.closestPointToPoint( point, intersectPoint );
26965                 intersectPoint.applyMatrix4( matrixWorld );
26966
26967                 const distance = raycaster.ray.origin.distanceTo( intersectPoint );
26968
26969                 if ( distance < raycaster.near || distance > raycaster.far ) return;
26970
26971                 intersects.push( {
26972
26973                         distance: distance,
26974                         distanceToRay: Math.sqrt( rayPointDistanceSq ),
26975                         point: intersectPoint,
26976                         index: index,
26977                         face: null,
26978                         object: object
26979
26980                 } );
26981
26982         }
26983
26984 }
26985
26986 function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
26987
26988         Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
26989
26990         this.format = format !== undefined ? format : RGBFormat;
26991
26992         this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
26993         this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
26994
26995         this.generateMipmaps = false;
26996
26997         const scope = this;
26998
26999         function updateVideo() {
27000
27001                 scope.needsUpdate = true;
27002                 video.requestVideoFrameCallback( updateVideo );
27003
27004         }
27005
27006         if ( 'requestVideoFrameCallback' in video ) {
27007
27008                 video.requestVideoFrameCallback( updateVideo );
27009
27010         }
27011
27012 }
27013
27014 VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
27015
27016         constructor: VideoTexture,
27017
27018         clone: function () {
27019
27020                 return new this.constructor( this.image ).copy( this );
27021
27022         },
27023
27024         isVideoTexture: true,
27025
27026         update: function () {
27027
27028                 const video = this.image;
27029                 const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
27030
27031                 if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
27032
27033                         this.needsUpdate = true;
27034
27035                 }
27036
27037         }
27038
27039 } );
27040
27041 function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
27042
27043         Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
27044
27045         this.image = { width: width, height: height };
27046         this.mipmaps = mipmaps;
27047
27048         // no flipping for cube textures
27049         // (also flipping doesn't work for compressed textures )
27050
27051         this.flipY = false;
27052
27053         // can't generate mipmaps for compressed textures
27054         // mips must be embedded in DDS files
27055
27056         this.generateMipmaps = false;
27057
27058 }
27059
27060 CompressedTexture.prototype = Object.create( Texture.prototype );
27061 CompressedTexture.prototype.constructor = CompressedTexture;
27062
27063 CompressedTexture.prototype.isCompressedTexture = true;
27064
27065 function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
27066
27067         Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
27068
27069         this.needsUpdate = true;
27070
27071 }
27072
27073 CanvasTexture.prototype = Object.create( Texture.prototype );
27074 CanvasTexture.prototype.constructor = CanvasTexture;
27075 CanvasTexture.prototype.isCanvasTexture = true;
27076
27077 function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
27078
27079         format = format !== undefined ? format : DepthFormat;
27080
27081         if ( format !== DepthFormat && format !== DepthStencilFormat ) {
27082
27083                 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
27084
27085         }
27086
27087         if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
27088         if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
27089
27090         Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
27091
27092         this.image = { width: width, height: height };
27093
27094         this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
27095         this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
27096
27097         this.flipY = false;
27098         this.generateMipmaps = false;
27099
27100 }
27101
27102 DepthTexture.prototype = Object.create( Texture.prototype );
27103 DepthTexture.prototype.constructor = DepthTexture;
27104 DepthTexture.prototype.isDepthTexture = true;
27105
27106 class CircleGeometry extends BufferGeometry {
27107
27108         constructor( radius = 1, segments = 8, thetaStart = 0, thetaLength = Math.PI * 2 ) {
27109
27110                 super();
27111
27112                 this.type = 'CircleGeometry';
27113
27114                 this.parameters = {
27115                         radius: radius,
27116                         segments: segments,
27117                         thetaStart: thetaStart,
27118                         thetaLength: thetaLength
27119                 };
27120
27121                 segments = Math.max( 3, segments );
27122
27123                 // buffers
27124
27125                 const indices = [];
27126                 const vertices = [];
27127                 const normals = [];
27128                 const uvs = [];
27129
27130                 // helper variables
27131
27132                 const vertex = new Vector3();
27133                 const uv = new Vector2();
27134
27135                 // center point
27136
27137                 vertices.push( 0, 0, 0 );
27138                 normals.push( 0, 0, 1 );
27139                 uvs.push( 0.5, 0.5 );
27140
27141                 for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
27142
27143                         const segment = thetaStart + s / segments * thetaLength;
27144
27145                         // vertex
27146
27147                         vertex.x = radius * Math.cos( segment );
27148                         vertex.y = radius * Math.sin( segment );
27149
27150                         vertices.push( vertex.x, vertex.y, vertex.z );
27151
27152                         // normal
27153
27154                         normals.push( 0, 0, 1 );
27155
27156                         // uvs
27157
27158                         uv.x = ( vertices[ i ] / radius + 1 ) / 2;
27159                         uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
27160
27161                         uvs.push( uv.x, uv.y );
27162
27163                 }
27164
27165                 // indices
27166
27167                 for ( let i = 1; i <= segments; i ++ ) {
27168
27169                         indices.push( i, i + 1, 0 );
27170
27171                 }
27172
27173                 // build geometry
27174
27175                 this.setIndex( indices );
27176                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
27177                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
27178                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
27179
27180         }
27181
27182 }
27183
27184 class CylinderGeometry extends BufferGeometry {
27185
27186         constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
27187
27188                 super();
27189                 this.type = 'CylinderGeometry';
27190
27191                 this.parameters = {
27192                         radiusTop: radiusTop,
27193                         radiusBottom: radiusBottom,
27194                         height: height,
27195                         radialSegments: radialSegments,
27196                         heightSegments: heightSegments,
27197                         openEnded: openEnded,
27198                         thetaStart: thetaStart,
27199                         thetaLength: thetaLength
27200                 };
27201
27202                 const scope = this;
27203
27204                 radialSegments = Math.floor( radialSegments );
27205                 heightSegments = Math.floor( heightSegments );
27206
27207                 // buffers
27208
27209                 const indices = [];
27210                 const vertices = [];
27211                 const normals = [];
27212                 const uvs = [];
27213
27214                 // helper variables
27215
27216                 let index = 0;
27217                 const indexArray = [];
27218                 const halfHeight = height / 2;
27219                 let groupStart = 0;
27220
27221                 // generate geometry
27222
27223                 generateTorso();
27224
27225                 if ( openEnded === false ) {
27226
27227                         if ( radiusTop > 0 ) generateCap( true );
27228                         if ( radiusBottom > 0 ) generateCap( false );
27229
27230                 }
27231
27232                 // build geometry
27233
27234                 this.setIndex( indices );
27235                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
27236                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
27237                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
27238
27239                 function generateTorso() {
27240
27241                         const normal = new Vector3();
27242                         const vertex = new Vector3();
27243
27244                         let groupCount = 0;
27245
27246                         // this will be used to calculate the normal
27247                         const slope = ( radiusBottom - radiusTop ) / height;
27248
27249                         // generate vertices, normals and uvs
27250
27251                         for ( let y = 0; y <= heightSegments; y ++ ) {
27252
27253                                 const indexRow = [];
27254
27255                                 const v = y / heightSegments;
27256
27257                                 // calculate the radius of the current row
27258
27259                                 const radius = v * ( radiusBottom - radiusTop ) + radiusTop;
27260
27261                                 for ( let x = 0; x <= radialSegments; x ++ ) {
27262
27263                                         const u = x / radialSegments;
27264
27265                                         const theta = u * thetaLength + thetaStart;
27266
27267                                         const sinTheta = Math.sin( theta );
27268                                         const cosTheta = Math.cos( theta );
27269
27270                                         // vertex
27271
27272                                         vertex.x = radius * sinTheta;
27273                                         vertex.y = - v * height + halfHeight;
27274                                         vertex.z = radius * cosTheta;
27275                                         vertices.push( vertex.x, vertex.y, vertex.z );
27276
27277                                         // normal
27278
27279                                         normal.set( sinTheta, slope, cosTheta ).normalize();
27280                                         normals.push( normal.x, normal.y, normal.z );
27281
27282                                         // uv
27283
27284                                         uvs.push( u, 1 - v );
27285
27286                                         // save index of vertex in respective row
27287
27288                                         indexRow.push( index ++ );
27289
27290                                 }
27291
27292                                 // now save vertices of the row in our index array
27293
27294                                 indexArray.push( indexRow );
27295
27296                         }
27297
27298                         // generate indices
27299
27300                         for ( let x = 0; x < radialSegments; x ++ ) {
27301
27302                                 for ( let y = 0; y < heightSegments; y ++ ) {
27303
27304                                         // we use the index array to access the correct indices
27305
27306                                         const a = indexArray[ y ][ x ];
27307                                         const b = indexArray[ y + 1 ][ x ];
27308                                         const c = indexArray[ y + 1 ][ x + 1 ];
27309                                         const d = indexArray[ y ][ x + 1 ];
27310
27311                                         // faces
27312
27313                                         indices.push( a, b, d );
27314                                         indices.push( b, c, d );
27315
27316                                         // update group counter
27317
27318                                         groupCount += 6;
27319
27320                                 }
27321
27322                         }
27323
27324                         // add a group to the geometry. this will ensure multi material support
27325
27326                         scope.addGroup( groupStart, groupCount, 0 );
27327
27328                         // calculate new start value for groups
27329
27330                         groupStart += groupCount;
27331
27332                 }
27333
27334                 function generateCap( top ) {
27335
27336                         // save the index of the first center vertex
27337                         const centerIndexStart = index;
27338
27339                         const uv = new Vector2();
27340                         const vertex = new Vector3();
27341
27342                         let groupCount = 0;
27343
27344                         const radius = ( top === true ) ? radiusTop : radiusBottom;
27345                         const sign = ( top === true ) ? 1 : - 1;
27346
27347                         // first we generate the center vertex data of the cap.
27348                         // because the geometry needs one set of uvs per face,
27349                         // we must generate a center vertex per face/segment
27350
27351                         for ( let x = 1; x <= radialSegments; x ++ ) {
27352
27353                                 // vertex
27354
27355                                 vertices.push( 0, halfHeight * sign, 0 );
27356
27357                                 // normal
27358
27359                                 normals.push( 0, sign, 0 );
27360
27361                                 // uv
27362
27363                                 uvs.push( 0.5, 0.5 );
27364
27365                                 // increase index
27366
27367                                 index ++;
27368
27369                         }
27370
27371                         // save the index of the last center vertex
27372                         const centerIndexEnd = index;
27373
27374                         // now we generate the surrounding vertices, normals and uvs
27375
27376                         for ( let x = 0; x <= radialSegments; x ++ ) {
27377
27378                                 const u = x / radialSegments;
27379                                 const theta = u * thetaLength + thetaStart;
27380
27381                                 const cosTheta = Math.cos( theta );
27382                                 const sinTheta = Math.sin( theta );
27383
27384                                 // vertex
27385
27386                                 vertex.x = radius * sinTheta;
27387                                 vertex.y = halfHeight * sign;
27388                                 vertex.z = radius * cosTheta;
27389                                 vertices.push( vertex.x, vertex.y, vertex.z );
27390
27391                                 // normal
27392
27393                                 normals.push( 0, sign, 0 );
27394
27395                                 // uv
27396
27397                                 uv.x = ( cosTheta * 0.5 ) + 0.5;
27398                                 uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
27399                                 uvs.push( uv.x, uv.y );
27400
27401                                 // increase index
27402
27403                                 index ++;
27404
27405                         }
27406
27407                         // generate indices
27408
27409                         for ( let x = 0; x < radialSegments; x ++ ) {
27410
27411                                 const c = centerIndexStart + x;
27412                                 const i = centerIndexEnd + x;
27413
27414                                 if ( top === true ) {
27415
27416                                         // face top
27417
27418                                         indices.push( i, i + 1, c );
27419
27420                                 } else {
27421
27422                                         // face bottom
27423
27424                                         indices.push( i + 1, i, c );
27425
27426                                 }
27427
27428                                 groupCount += 3;
27429
27430                         }
27431
27432                         // add a group to the geometry. this will ensure multi material support
27433
27434                         scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
27435
27436                         // calculate new start value for groups
27437
27438                         groupStart += groupCount;
27439
27440                 }
27441
27442         }
27443
27444 }
27445
27446 class ConeGeometry extends CylinderGeometry {
27447
27448         constructor( radius = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
27449
27450                 super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
27451
27452                 this.type = 'ConeGeometry';
27453
27454                 this.parameters = {
27455                         radius: radius,
27456                         height: height,
27457                         radialSegments: radialSegments,
27458                         heightSegments: heightSegments,
27459                         openEnded: openEnded,
27460                         thetaStart: thetaStart,
27461                         thetaLength: thetaLength
27462                 };
27463
27464         }
27465
27466 }
27467
27468 class PolyhedronGeometry extends BufferGeometry {
27469
27470         constructor( vertices, indices, radius = 1, detail = 0 ) {
27471
27472                 super();
27473
27474                 this.type = 'PolyhedronGeometry';
27475
27476                 this.parameters = {
27477                         vertices: vertices,
27478                         indices: indices,
27479                         radius: radius,
27480                         detail: detail
27481                 };
27482
27483                 // default buffer data
27484
27485                 const vertexBuffer = [];
27486                 const uvBuffer = [];
27487
27488                 // the subdivision creates the vertex buffer data
27489
27490                 subdivide( detail );
27491
27492                 // all vertices should lie on a conceptual sphere with a given radius
27493
27494                 applyRadius( radius );
27495
27496                 // finally, create the uv data
27497
27498                 generateUVs();
27499
27500                 // build non-indexed geometry
27501
27502                 this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
27503                 this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
27504                 this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
27505
27506                 if ( detail === 0 ) {
27507
27508                         this.computeVertexNormals(); // flat normals
27509
27510                 } else {
27511
27512                         this.normalizeNormals(); // smooth normals
27513
27514                 }
27515
27516                 // helper functions
27517
27518                 function subdivide( detail ) {
27519
27520                         const a = new Vector3();
27521                         const b = new Vector3();
27522                         const c = new Vector3();
27523
27524                         // iterate over all faces and apply a subdivison with the given detail value
27525
27526                         for ( let i = 0; i < indices.length; i += 3 ) {
27527
27528                                 // get the vertices of the face
27529
27530                                 getVertexByIndex( indices[ i + 0 ], a );
27531                                 getVertexByIndex( indices[ i + 1 ], b );
27532                                 getVertexByIndex( indices[ i + 2 ], c );
27533
27534                                 // perform subdivision
27535
27536                                 subdivideFace( a, b, c, detail );
27537
27538                         }
27539
27540                 }
27541
27542                 function subdivideFace( a, b, c, detail ) {
27543
27544                         const cols = detail + 1;
27545
27546                         // we use this multidimensional array as a data structure for creating the subdivision
27547
27548                         const v = [];
27549
27550                         // construct all of the vertices for this subdivision
27551
27552                         for ( let i = 0; i <= cols; i ++ ) {
27553
27554                                 v[ i ] = [];
27555
27556                                 const aj = a.clone().lerp( c, i / cols );
27557                                 const bj = b.clone().lerp( c, i / cols );
27558
27559                                 const rows = cols - i;
27560
27561                                 for ( let j = 0; j <= rows; j ++ ) {
27562
27563                                         if ( j === 0 && i === cols ) {
27564
27565                                                 v[ i ][ j ] = aj;
27566
27567                                         } else {
27568
27569                                                 v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
27570
27571                                         }
27572
27573                                 }
27574
27575                         }
27576
27577                         // construct all of the faces
27578
27579                         for ( let i = 0; i < cols; i ++ ) {
27580
27581                                 for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
27582
27583                                         const k = Math.floor( j / 2 );
27584
27585                                         if ( j % 2 === 0 ) {
27586
27587                                                 pushVertex( v[ i ][ k + 1 ] );
27588                                                 pushVertex( v[ i + 1 ][ k ] );
27589                                                 pushVertex( v[ i ][ k ] );
27590
27591                                         } else {
27592
27593                                                 pushVertex( v[ i ][ k + 1 ] );
27594                                                 pushVertex( v[ i + 1 ][ k + 1 ] );
27595                                                 pushVertex( v[ i + 1 ][ k ] );
27596
27597                                         }
27598
27599                                 }
27600
27601                         }
27602
27603                 }
27604
27605                 function applyRadius( radius ) {
27606
27607                         const vertex = new Vector3();
27608
27609                         // iterate over the entire buffer and apply the radius to each vertex
27610
27611                         for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
27612
27613                                 vertex.x = vertexBuffer[ i + 0 ];
27614                                 vertex.y = vertexBuffer[ i + 1 ];
27615                                 vertex.z = vertexBuffer[ i + 2 ];
27616
27617                                 vertex.normalize().multiplyScalar( radius );
27618
27619                                 vertexBuffer[ i + 0 ] = vertex.x;
27620                                 vertexBuffer[ i + 1 ] = vertex.y;
27621                                 vertexBuffer[ i + 2 ] = vertex.z;
27622
27623                         }
27624
27625                 }
27626
27627                 function generateUVs() {
27628
27629                         const vertex = new Vector3();
27630
27631                         for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
27632
27633                                 vertex.x = vertexBuffer[ i + 0 ];
27634                                 vertex.y = vertexBuffer[ i + 1 ];
27635                                 vertex.z = vertexBuffer[ i + 2 ];
27636
27637                                 const u = azimuth( vertex ) / 2 / Math.PI + 0.5;
27638                                 const v = inclination( vertex ) / Math.PI + 0.5;
27639                                 uvBuffer.push( u, 1 - v );
27640
27641                         }
27642
27643                         correctUVs();
27644
27645                         correctSeam();
27646
27647                 }
27648
27649                 function correctSeam() {
27650
27651                         // handle case when face straddles the seam, see #3269
27652
27653                         for ( let i = 0; i < uvBuffer.length; i += 6 ) {
27654
27655                                 // uv data of a single face
27656
27657                                 const x0 = uvBuffer[ i + 0 ];
27658                                 const x1 = uvBuffer[ i + 2 ];
27659                                 const x2 = uvBuffer[ i + 4 ];
27660
27661                                 const max = Math.max( x0, x1, x2 );
27662                                 const min = Math.min( x0, x1, x2 );
27663
27664                                 // 0.9 is somewhat arbitrary
27665
27666                                 if ( max > 0.9 && min < 0.1 ) {
27667
27668                                         if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
27669                                         if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
27670                                         if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
27671
27672                                 }
27673
27674                         }
27675
27676                 }
27677
27678                 function pushVertex( vertex ) {
27679
27680                         vertexBuffer.push( vertex.x, vertex.y, vertex.z );
27681
27682                 }
27683
27684                 function getVertexByIndex( index, vertex ) {
27685
27686                         const stride = index * 3;
27687
27688                         vertex.x = vertices[ stride + 0 ];
27689                         vertex.y = vertices[ stride + 1 ];
27690                         vertex.z = vertices[ stride + 2 ];
27691
27692                 }
27693
27694                 function correctUVs() {
27695
27696                         const a = new Vector3();
27697                         const b = new Vector3();
27698                         const c = new Vector3();
27699
27700                         const centroid = new Vector3();
27701
27702                         const uvA = new Vector2();
27703                         const uvB = new Vector2();
27704                         const uvC = new Vector2();
27705
27706                         for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
27707
27708                                 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
27709                                 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
27710                                 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
27711
27712                                 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
27713                                 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
27714                                 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
27715
27716                                 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
27717
27718                                 const azi = azimuth( centroid );
27719
27720                                 correctUV( uvA, j + 0, a, azi );
27721                                 correctUV( uvB, j + 2, b, azi );
27722                                 correctUV( uvC, j + 4, c, azi );
27723
27724                         }
27725
27726                 }
27727
27728                 function correctUV( uv, stride, vector, azimuth ) {
27729
27730                         if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
27731
27732                                 uvBuffer[ stride ] = uv.x - 1;
27733
27734                         }
27735
27736                         if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
27737
27738                                 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
27739
27740                         }
27741
27742                 }
27743
27744                 // Angle around the Y axis, counter-clockwise when looking from above.
27745
27746                 function azimuth( vector ) {
27747
27748                         return Math.atan2( vector.z, - vector.x );
27749
27750                 }
27751
27752
27753                 // Angle above the XZ plane.
27754
27755                 function inclination( vector ) {
27756
27757                         return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
27758
27759                 }
27760
27761         }
27762
27763 }
27764
27765 class DodecahedronGeometry extends PolyhedronGeometry {
27766
27767         constructor( radius = 1, detail = 0 ) {
27768
27769                 const t = ( 1 + Math.sqrt( 5 ) ) / 2;
27770                 const r = 1 / t;
27771
27772                 const vertices = [
27773
27774                         // (±1, Â±1, Â±1)
27775                         - 1, - 1, - 1,  - 1, - 1, 1,
27776                         - 1, 1, - 1, - 1, 1, 1,
27777                         1, - 1, - 1, 1, - 1, 1,
27778                         1, 1, - 1, 1, 1, 1,
27779
27780                         // (0, Â±1/φ, Â±Ï†)
27781                         0, - r, - t, 0, - r, t,
27782                         0, r, - t, 0, r, t,
27783
27784                         // (±1/φ, Â±Ï†, 0)
27785                         - r, - t, 0, - r, t, 0,
27786                         r, - t, 0, r, t, 0,
27787
27788                         // (±φ, 0, Â±1/φ)
27789                         - t, 0, - r, t, 0, - r,
27790                         - t, 0, r, t, 0, r
27791                 ];
27792
27793                 const indices = [
27794                         3, 11, 7,       3, 7, 15,       3, 15, 13,
27795                         7, 19, 17,      7, 17, 6,       7, 6, 15,
27796                         17, 4, 8,       17, 8, 10,      17, 10, 6,
27797                         8, 0, 16,       8, 16, 2,       8, 2, 10,
27798                         0, 12, 1,       0, 1, 18,       0, 18, 16,
27799                         6, 10, 2,       6, 2, 13,       6, 13, 15,
27800                         2, 16, 18,      2, 18, 3,       2, 3, 13,
27801                         18, 1, 9,       18, 9, 11,      18, 11, 3,
27802                         4, 14, 12,      4, 12, 0,       4, 0, 8,
27803                         11, 9, 5,       11, 5, 19,      11, 19, 7,
27804                         19, 5, 14,      19, 14, 4,      19, 4, 17,
27805                         1, 12, 14,      1, 14, 5,       1, 5, 9
27806                 ];
27807
27808                 super( vertices, indices, radius, detail );
27809
27810                 this.type = 'DodecahedronGeometry';
27811
27812                 this.parameters = {
27813                         radius: radius,
27814                         detail: detail
27815                 };
27816
27817         }
27818
27819 }
27820
27821 const _v0$2 = new Vector3();
27822 const _v1$5 = new Vector3();
27823 const _normal$1 = new Vector3();
27824 const _triangle = new Triangle();
27825
27826 class EdgesGeometry extends BufferGeometry {
27827
27828         constructor( geometry, thresholdAngle ) {
27829
27830                 super();
27831
27832                 this.type = 'EdgesGeometry';
27833
27834                 this.parameters = {
27835                         thresholdAngle: thresholdAngle
27836                 };
27837
27838                 thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
27839
27840                 if ( geometry.isGeometry === true ) {
27841
27842                         console.error( 'THREE.EdgesGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
27843                         return;
27844
27845                 }
27846
27847                 const precisionPoints = 4;
27848                 const precision = Math.pow( 10, precisionPoints );
27849                 const thresholdDot = Math.cos( MathUtils.DEG2RAD * thresholdAngle );
27850
27851                 const indexAttr = geometry.getIndex();
27852                 const positionAttr = geometry.getAttribute( 'position' );
27853                 const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
27854
27855                 const indexArr = [ 0, 0, 0 ];
27856                 const vertKeys = [ 'a', 'b', 'c' ];
27857                 const hashes = new Array( 3 );
27858
27859                 const edgeData = {};
27860                 const vertices = [];
27861                 for ( let i = 0; i < indexCount; i += 3 ) {
27862
27863                         if ( indexAttr ) {
27864
27865                                 indexArr[ 0 ] = indexAttr.getX( i );
27866                                 indexArr[ 1 ] = indexAttr.getX( i + 1 );
27867                                 indexArr[ 2 ] = indexAttr.getX( i + 2 );
27868
27869                         } else {
27870
27871                                 indexArr[ 0 ] = i;
27872                                 indexArr[ 1 ] = i + 1;
27873                                 indexArr[ 2 ] = i + 2;
27874
27875                         }
27876
27877                         const { a, b, c } = _triangle;
27878                         a.fromBufferAttribute( positionAttr, indexArr[ 0 ] );
27879                         b.fromBufferAttribute( positionAttr, indexArr[ 1 ] );
27880                         c.fromBufferAttribute( positionAttr, indexArr[ 2 ] );
27881                         _triangle.getNormal( _normal$1 );
27882
27883                         // create hashes for the edge from the vertices
27884                         hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`;
27885                         hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`;
27886                         hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`;
27887
27888                         // skip degenerate triangles
27889                         if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) {
27890
27891                                 continue;
27892
27893                         }
27894
27895                         // iterate over every edge
27896                         for ( let j = 0; j < 3; j ++ ) {
27897
27898                                 // get the first and next vertex making up the edge
27899                                 const jNext = ( j + 1 ) % 3;
27900                                 const vecHash0 = hashes[ j ];
27901                                 const vecHash1 = hashes[ jNext ];
27902                                 const v0 = _triangle[ vertKeys[ j ] ];
27903                                 const v1 = _triangle[ vertKeys[ jNext ] ];
27904
27905                                 const hash = `${ vecHash0 }_${ vecHash1 }`;
27906                                 const reverseHash = `${ vecHash1 }_${ vecHash0 }`;
27907
27908                                 if ( reverseHash in edgeData && edgeData[ reverseHash ] ) {
27909
27910                                         // if we found a sibling edge add it into the vertex array if
27911                                         // it meets the angle threshold and delete the edge from the map.
27912                                         if ( _normal$1.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) {
27913
27914                                                 vertices.push( v0.x, v0.y, v0.z );
27915                                                 vertices.push( v1.x, v1.y, v1.z );
27916
27917                                         }
27918
27919                                         edgeData[ reverseHash ] = null;
27920
27921                                 } else if ( ! ( hash in edgeData ) ) {
27922
27923                                         // if we've already got an edge here then skip adding a new one
27924                                         edgeData[ hash ] = {
27925
27926                                                 index0: indexArr[ j ],
27927                                                 index1: indexArr[ jNext ],
27928                                                 normal: _normal$1.clone(),
27929
27930                                         };
27931
27932                                 }
27933
27934                         }
27935
27936                 }
27937
27938                 // iterate over all remaining, unmatched edges and add them to the vertex array
27939                 for ( const key in edgeData ) {
27940
27941                         if ( edgeData[ key ] ) {
27942
27943                                 const { index0, index1 } = edgeData[ key ];
27944                                 _v0$2.fromBufferAttribute( positionAttr, index0 );
27945                                 _v1$5.fromBufferAttribute( positionAttr, index1 );
27946
27947                                 vertices.push( _v0$2.x, _v0$2.y, _v0$2.z );
27948                                 vertices.push( _v1$5.x, _v1$5.y, _v1$5.z );
27949
27950                         }
27951
27952                 }
27953
27954                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
27955
27956         }
27957
27958 }
27959
27960 /**
27961  * Port from https://github.com/mapbox/earcut (v2.2.2)
27962  */
27963
27964 const Earcut = {
27965
27966         triangulate: function ( data, holeIndices, dim ) {
27967
27968                 dim = dim || 2;
27969
27970                 const hasHoles = holeIndices && holeIndices.length;
27971                 const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
27972                 let outerNode = linkedList( data, 0, outerLen, dim, true );
27973                 const triangles = [];
27974
27975                 if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
27976
27977                 let minX, minY, maxX, maxY, x, y, invSize;
27978
27979                 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
27980
27981                 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
27982                 if ( data.length > 80 * dim ) {
27983
27984                         minX = maxX = data[ 0 ];
27985                         minY = maxY = data[ 1 ];
27986
27987                         for ( let i = dim; i < outerLen; i += dim ) {
27988
27989                                 x = data[ i ];
27990                                 y = data[ i + 1 ];
27991                                 if ( x < minX ) minX = x;
27992                                 if ( y < minY ) minY = y;
27993                                 if ( x > maxX ) maxX = x;
27994                                 if ( y > maxY ) maxY = y;
27995
27996                         }
27997
27998                         // minX, minY and invSize are later used to transform coords into integers for z-order calculation
27999                         invSize = Math.max( maxX - minX, maxY - minY );
28000                         invSize = invSize !== 0 ? 1 / invSize : 0;
28001
28002                 }
28003
28004                 earcutLinked( outerNode, triangles, dim, minX, minY, invSize );
28005
28006                 return triangles;
28007
28008         }
28009
28010 };
28011
28012 // create a circular doubly linked list from polygon points in the specified winding order
28013 function linkedList( data, start, end, dim, clockwise ) {
28014
28015         let i, last;
28016
28017         if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
28018
28019                 for ( i = start; i < end; i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
28020
28021         } else {
28022
28023                 for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
28024
28025         }
28026
28027         if ( last && equals( last, last.next ) ) {
28028
28029                 removeNode( last );
28030                 last = last.next;
28031
28032         }
28033
28034         return last;
28035
28036 }
28037
28038 // eliminate colinear or duplicate points
28039 function filterPoints( start, end ) {
28040
28041         if ( ! start ) return start;
28042         if ( ! end ) end = start;
28043
28044         let p = start,
28045                 again;
28046         do {
28047
28048                 again = false;
28049
28050                 if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
28051
28052                         removeNode( p );
28053                         p = end = p.prev;
28054                         if ( p === p.next ) break;
28055                         again = true;
28056
28057                 } else {
28058
28059                         p = p.next;
28060
28061                 }
28062
28063         } while ( again || p !== end );
28064
28065         return end;
28066
28067 }
28068
28069 // main ear slicing loop which triangulates a polygon (given as a linked list)
28070 function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
28071
28072         if ( ! ear ) return;
28073
28074         // interlink polygon nodes in z-order
28075         if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
28076
28077         let stop = ear,
28078                 prev, next;
28079
28080         // iterate through ears, slicing them one by one
28081         while ( ear.prev !== ear.next ) {
28082
28083                 prev = ear.prev;
28084                 next = ear.next;
28085
28086                 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
28087
28088                         // cut off the triangle
28089                         triangles.push( prev.i / dim );
28090                         triangles.push( ear.i / dim );
28091                         triangles.push( next.i / dim );
28092
28093                         removeNode( ear );
28094
28095                         // skipping the next vertex leads to less sliver triangles
28096                         ear = next.next;
28097                         stop = next.next;
28098
28099                         continue;
28100
28101                 }
28102
28103                 ear = next;
28104
28105                 // if we looped through the whole remaining polygon and can't find any more ears
28106                 if ( ear === stop ) {
28107
28108                         // try filtering points and slicing again
28109                         if ( ! pass ) {
28110
28111                                 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
28112
28113                                 // if this didn't work, try curing all small self-intersections locally
28114
28115                         } else if ( pass === 1 ) {
28116
28117                                 ear = cureLocalIntersections( filterPoints( ear ), triangles, dim );
28118                                 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
28119
28120                                 // as a last resort, try splitting the remaining polygon into two
28121
28122                         } else if ( pass === 2 ) {
28123
28124                                 splitEarcut( ear, triangles, dim, minX, minY, invSize );
28125
28126                         }
28127
28128                         break;
28129
28130                 }
28131
28132         }
28133
28134 }
28135
28136 // check whether a polygon node forms a valid ear with adjacent nodes
28137 function isEar( ear ) {
28138
28139         const a = ear.prev,
28140                 b = ear,
28141                 c = ear.next;
28142
28143         if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
28144
28145         // now make sure we don't have other points inside the potential ear
28146         let p = ear.next.next;
28147
28148         while ( p !== ear.prev ) {
28149
28150                 if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
28151                         area( p.prev, p, p.next ) >= 0 ) return false;
28152                 p = p.next;
28153
28154         }
28155
28156         return true;
28157
28158 }
28159
28160 function isEarHashed( ear, minX, minY, invSize ) {
28161
28162         const a = ear.prev,
28163                 b = ear,
28164                 c = ear.next;
28165
28166         if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
28167
28168         // triangle bbox; min & max are calculated like this for speed
28169         const minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
28170                 minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
28171                 maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
28172                 maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
28173
28174         // z-order range for the current triangle bbox;
28175         const minZ = zOrder( minTX, minTY, minX, minY, invSize ),
28176                 maxZ = zOrder( maxTX, maxTY, minX, minY, invSize );
28177
28178         let p = ear.prevZ,
28179                 n = ear.nextZ;
28180
28181         // look for points inside the triangle in both directions
28182         while ( p && p.z >= minZ && n && n.z <= maxZ ) {
28183
28184                 if ( p !== ear.prev && p !== ear.next &&
28185                         pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
28186                         area( p.prev, p, p.next ) >= 0 ) return false;
28187                 p = p.prevZ;
28188
28189                 if ( n !== ear.prev && n !== ear.next &&
28190                         pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
28191                         area( n.prev, n, n.next ) >= 0 ) return false;
28192                 n = n.nextZ;
28193
28194         }
28195
28196         // look for remaining points in decreasing z-order
28197         while ( p && p.z >= minZ ) {
28198
28199                 if ( p !== ear.prev && p !== ear.next &&
28200                         pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
28201                         area( p.prev, p, p.next ) >= 0 ) return false;
28202                 p = p.prevZ;
28203
28204         }
28205
28206         // look for remaining points in increasing z-order
28207         while ( n && n.z <= maxZ ) {
28208
28209                 if ( n !== ear.prev && n !== ear.next &&
28210                         pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
28211                         area( n.prev, n, n.next ) >= 0 ) return false;
28212                 n = n.nextZ;
28213
28214         }
28215
28216         return true;
28217
28218 }
28219
28220 // go through all polygon nodes and cure small local self-intersections
28221 function cureLocalIntersections( start, triangles, dim ) {
28222
28223         let p = start;
28224         do {
28225
28226                 const a = p.prev,
28227                         b = p.next.next;
28228
28229                 if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
28230
28231                         triangles.push( a.i / dim );
28232                         triangles.push( p.i / dim );
28233                         triangles.push( b.i / dim );
28234
28235                         // remove two nodes involved
28236                         removeNode( p );
28237                         removeNode( p.next );
28238
28239                         p = start = b;
28240
28241                 }
28242
28243                 p = p.next;
28244
28245         } while ( p !== start );
28246
28247         return filterPoints( p );
28248
28249 }
28250
28251 // try splitting polygon into two and triangulate them independently
28252 function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
28253
28254         // look for a valid diagonal that divides the polygon into two
28255         let a = start;
28256         do {
28257
28258                 let b = a.next.next;
28259                 while ( b !== a.prev ) {
28260
28261                         if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
28262
28263                                 // split the polygon in two by the diagonal
28264                                 let c = splitPolygon( a, b );
28265
28266                                 // filter colinear points around the cuts
28267                                 a = filterPoints( a, a.next );
28268                                 c = filterPoints( c, c.next );
28269
28270                                 // run earcut on each half
28271                                 earcutLinked( a, triangles, dim, minX, minY, invSize );
28272                                 earcutLinked( c, triangles, dim, minX, minY, invSize );
28273                                 return;
28274
28275                         }
28276
28277                         b = b.next;
28278
28279                 }
28280
28281                 a = a.next;
28282
28283         } while ( a !== start );
28284
28285 }
28286
28287 // link every hole into the outer loop, producing a single-ring polygon without holes
28288 function eliminateHoles( data, holeIndices, outerNode, dim ) {
28289
28290         const queue = [];
28291         let i, len, start, end, list;
28292
28293         for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
28294
28295                 start = holeIndices[ i ] * dim;
28296                 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
28297                 list = linkedList( data, start, end, dim, false );
28298                 if ( list === list.next ) list.steiner = true;
28299                 queue.push( getLeftmost( list ) );
28300
28301         }
28302
28303         queue.sort( compareX );
28304
28305         // process holes from left to right
28306         for ( i = 0; i < queue.length; i ++ ) {
28307
28308                 eliminateHole( queue[ i ], outerNode );
28309                 outerNode = filterPoints( outerNode, outerNode.next );
28310
28311         }
28312
28313         return outerNode;
28314
28315 }
28316
28317 function compareX( a, b ) {
28318
28319         return a.x - b.x;
28320
28321 }
28322
28323 // find a bridge between vertices that connects hole with an outer ring and and link it
28324 function eliminateHole( hole, outerNode ) {
28325
28326         outerNode = findHoleBridge( hole, outerNode );
28327         if ( outerNode ) {
28328
28329                 const b = splitPolygon( outerNode, hole );
28330
28331                 // filter collinear points around the cuts
28332                 filterPoints( outerNode, outerNode.next );
28333                 filterPoints( b, b.next );
28334
28335         }
28336
28337 }
28338
28339 // David Eberly's algorithm for finding a bridge between hole and outer polygon
28340 function findHoleBridge( hole, outerNode ) {
28341
28342         let p = outerNode;
28343         const hx = hole.x;
28344         const hy = hole.y;
28345         let qx = - Infinity, m;
28346
28347         // find a segment intersected by a ray from the hole's leftmost point to the left;
28348         // segment's endpoint with lesser x will be potential connection point
28349         do {
28350
28351                 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
28352
28353                         const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
28354                         if ( x <= hx && x > qx ) {
28355
28356                                 qx = x;
28357                                 if ( x === hx ) {
28358
28359                                         if ( hy === p.y ) return p;
28360                                         if ( hy === p.next.y ) return p.next;
28361
28362                                 }
28363
28364                                 m = p.x < p.next.x ? p : p.next;
28365
28366                         }
28367
28368                 }
28369
28370                 p = p.next;
28371
28372         } while ( p !== outerNode );
28373
28374         if ( ! m ) return null;
28375
28376         if ( hx === qx ) return m; // hole touches outer segment; pick leftmost endpoint
28377
28378         // look for points inside the triangle of hole point, segment intersection and endpoint;
28379         // if there are no points found, we have a valid connection;
28380         // otherwise choose the point of the minimum angle with the ray as connection point
28381
28382         const stop = m,
28383                 mx = m.x,
28384                 my = m.y;
28385         let tanMin = Infinity, tan;
28386
28387         p = m;
28388
28389         do {
28390
28391                 if ( hx >= p.x && p.x >= mx && hx !== p.x &&
28392                                 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
28393
28394                         tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
28395
28396                         if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) {
28397
28398                                 m = p;
28399                                 tanMin = tan;
28400
28401                         }
28402
28403                 }
28404
28405                 p = p.next;
28406
28407         } while ( p !== stop );
28408
28409         return m;
28410
28411 }
28412
28413 // whether sector in vertex m contains sector in vertex p in the same coordinates
28414 function sectorContainsSector( m, p ) {
28415
28416         return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0;
28417
28418 }
28419
28420 // interlink polygon nodes in z-order
28421 function indexCurve( start, minX, minY, invSize ) {
28422
28423         let p = start;
28424         do {
28425
28426                 if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
28427                 p.prevZ = p.prev;
28428                 p.nextZ = p.next;
28429                 p = p.next;
28430
28431         } while ( p !== start );
28432
28433         p.prevZ.nextZ = null;
28434         p.prevZ = null;
28435
28436         sortLinked( p );
28437
28438 }
28439
28440 // Simon Tatham's linked list merge sort algorithm
28441 // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
28442 function sortLinked( list ) {
28443
28444         let i, p, q, e, tail, numMerges, pSize, qSize,
28445                 inSize = 1;
28446
28447         do {
28448
28449                 p = list;
28450                 list = null;
28451                 tail = null;
28452                 numMerges = 0;
28453
28454                 while ( p ) {
28455
28456                         numMerges ++;
28457                         q = p;
28458                         pSize = 0;
28459                         for ( i = 0; i < inSize; i ++ ) {
28460
28461                                 pSize ++;
28462                                 q = q.nextZ;
28463                                 if ( ! q ) break;
28464
28465                         }
28466
28467                         qSize = inSize;
28468
28469                         while ( pSize > 0 || ( qSize > 0 && q ) ) {
28470
28471                                 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
28472
28473                                         e = p;
28474                                         p = p.nextZ;
28475                                         pSize --;
28476
28477                                 } else {
28478
28479                                         e = q;
28480                                         q = q.nextZ;
28481                                         qSize --;
28482
28483                                 }
28484
28485                                 if ( tail ) tail.nextZ = e;
28486                                 else list = e;
28487
28488                                 e.prevZ = tail;
28489                                 tail = e;
28490
28491                         }
28492
28493                         p = q;
28494
28495                 }
28496
28497                 tail.nextZ = null;
28498                 inSize *= 2;
28499
28500         } while ( numMerges > 1 );
28501
28502         return list;
28503
28504 }
28505
28506 // z-order of a point given coords and inverse of the longer side of data bbox
28507 function zOrder( x, y, minX, minY, invSize ) {
28508
28509         // coords are transformed into non-negative 15-bit integer range
28510         x = 32767 * ( x - minX ) * invSize;
28511         y = 32767 * ( y - minY ) * invSize;
28512
28513         x = ( x | ( x << 8 ) ) & 0x00FF00FF;
28514         x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
28515         x = ( x | ( x << 2 ) ) & 0x33333333;
28516         x = ( x | ( x << 1 ) ) & 0x55555555;
28517
28518         y = ( y | ( y << 8 ) ) & 0x00FF00FF;
28519         y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
28520         y = ( y | ( y << 2 ) ) & 0x33333333;
28521         y = ( y | ( y << 1 ) ) & 0x55555555;
28522
28523         return x | ( y << 1 );
28524
28525 }
28526
28527 // find the leftmost node of a polygon ring
28528 function getLeftmost( start ) {
28529
28530         let p = start,
28531                 leftmost = start;
28532         do {
28533
28534                 if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
28535                 p = p.next;
28536
28537         } while ( p !== start );
28538
28539         return leftmost;
28540
28541 }
28542
28543 // check if a point lies within a convex triangle
28544 function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
28545
28546         return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
28547                         ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
28548                         ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
28549
28550 }
28551
28552 // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
28553 function isValidDiagonal( a, b ) {
28554
28555         return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges
28556                 ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible
28557                 ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors
28558                 equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case
28559
28560 }
28561
28562 // signed area of a triangle
28563 function area( p, q, r ) {
28564
28565         return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
28566
28567 }
28568
28569 // check if two points are equal
28570 function equals( p1, p2 ) {
28571
28572         return p1.x === p2.x && p1.y === p2.y;
28573
28574 }
28575
28576 // check if two segments intersect
28577 function intersects( p1, q1, p2, q2 ) {
28578
28579         const o1 = sign( area( p1, q1, p2 ) );
28580         const o2 = sign( area( p1, q1, q2 ) );
28581         const o3 = sign( area( p2, q2, p1 ) );
28582         const o4 = sign( area( p2, q2, q1 ) );
28583
28584         if ( o1 !== o2 && o3 !== o4 ) return true; // general case
28585
28586         if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
28587         if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
28588         if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
28589         if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
28590
28591         return false;
28592
28593 }
28594
28595 // for collinear points p, q, r, check if point q lies on segment pr
28596 function onSegment( p, q, r ) {
28597
28598         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 );
28599
28600 }
28601
28602 function sign( num ) {
28603
28604         return num > 0 ? 1 : num < 0 ? - 1 : 0;
28605
28606 }
28607
28608 // check if a polygon diagonal intersects any polygon segments
28609 function intersectsPolygon( a, b ) {
28610
28611         let p = a;
28612         do {
28613
28614                 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
28615                                 intersects( p, p.next, a, b ) ) return true;
28616                 p = p.next;
28617
28618         } while ( p !== a );
28619
28620         return false;
28621
28622 }
28623
28624 // check if a polygon diagonal is locally inside the polygon
28625 function locallyInside( a, b ) {
28626
28627         return area( a.prev, a, a.next ) < 0 ?
28628                 area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
28629                 area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
28630
28631 }
28632
28633 // check if the middle point of a polygon diagonal is inside the polygon
28634 function middleInside( a, b ) {
28635
28636         let p = a,
28637                 inside = false;
28638         const px = ( a.x + b.x ) / 2,
28639                 py = ( a.y + b.y ) / 2;
28640         do {
28641
28642                 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
28643                                 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
28644                         inside = ! inside;
28645                 p = p.next;
28646
28647         } while ( p !== a );
28648
28649         return inside;
28650
28651 }
28652
28653 // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
28654 // if one belongs to the outer ring and another to a hole, it merges it into a single ring
28655 function splitPolygon( a, b ) {
28656
28657         const a2 = new Node( a.i, a.x, a.y ),
28658                 b2 = new Node( b.i, b.x, b.y ),
28659                 an = a.next,
28660                 bp = b.prev;
28661
28662         a.next = b;
28663         b.prev = a;
28664
28665         a2.next = an;
28666         an.prev = a2;
28667
28668         b2.next = a2;
28669         a2.prev = b2;
28670
28671         bp.next = b2;
28672         b2.prev = bp;
28673
28674         return b2;
28675
28676 }
28677
28678 // create a node and optionally link it with previous one (in a circular doubly linked list)
28679 function insertNode( i, x, y, last ) {
28680
28681         const p = new Node( i, x, y );
28682
28683         if ( ! last ) {
28684
28685                 p.prev = p;
28686                 p.next = p;
28687
28688         } else {
28689
28690                 p.next = last.next;
28691                 p.prev = last;
28692                 last.next.prev = p;
28693                 last.next = p;
28694
28695         }
28696
28697         return p;
28698
28699 }
28700
28701 function removeNode( p ) {
28702
28703         p.next.prev = p.prev;
28704         p.prev.next = p.next;
28705
28706         if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
28707         if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
28708
28709 }
28710
28711 function Node( i, x, y ) {
28712
28713         // vertex index in coordinates array
28714         this.i = i;
28715
28716         // vertex coordinates
28717         this.x = x;
28718         this.y = y;
28719
28720         // previous and next vertex nodes in a polygon ring
28721         this.prev = null;
28722         this.next = null;
28723
28724         // z-order curve value
28725         this.z = null;
28726
28727         // previous and next nodes in z-order
28728         this.prevZ = null;
28729         this.nextZ = null;
28730
28731         // indicates whether this is a steiner point
28732         this.steiner = false;
28733
28734 }
28735
28736 function signedArea( data, start, end, dim ) {
28737
28738         let sum = 0;
28739         for ( let i = start, j = end - dim; i < end; i += dim ) {
28740
28741                 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
28742                 j = i;
28743
28744         }
28745
28746         return sum;
28747
28748 }
28749
28750 const ShapeUtils = {
28751
28752         // calculate area of the contour polygon
28753
28754         area: function ( contour ) {
28755
28756                 const n = contour.length;
28757                 let a = 0.0;
28758
28759                 for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
28760
28761                         a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
28762
28763                 }
28764
28765                 return a * 0.5;
28766
28767         },
28768
28769         isClockWise: function ( pts ) {
28770
28771                 return ShapeUtils.area( pts ) < 0;
28772
28773         },
28774
28775         triangulateShape: function ( contour, holes ) {
28776
28777                 const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
28778                 const holeIndices = []; // array of hole indices
28779                 const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
28780
28781                 removeDupEndPts( contour );
28782                 addContour( vertices, contour );
28783
28784                 //
28785
28786                 let holeIndex = contour.length;
28787
28788                 holes.forEach( removeDupEndPts );
28789
28790                 for ( let i = 0; i < holes.length; i ++ ) {
28791
28792                         holeIndices.push( holeIndex );
28793                         holeIndex += holes[ i ].length;
28794                         addContour( vertices, holes[ i ] );
28795
28796                 }
28797
28798                 //
28799
28800                 const triangles = Earcut.triangulate( vertices, holeIndices );
28801
28802                 //
28803
28804                 for ( let i = 0; i < triangles.length; i += 3 ) {
28805
28806                         faces.push( triangles.slice( i, i + 3 ) );
28807
28808                 }
28809
28810                 return faces;
28811
28812         }
28813
28814 };
28815
28816 function removeDupEndPts( points ) {
28817
28818         const l = points.length;
28819
28820         if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
28821
28822                 points.pop();
28823
28824         }
28825
28826 }
28827
28828 function addContour( vertices, contour ) {
28829
28830         for ( let i = 0; i < contour.length; i ++ ) {
28831
28832                 vertices.push( contour[ i ].x );
28833                 vertices.push( contour[ i ].y );
28834
28835         }
28836
28837 }
28838
28839 /**
28840  * Creates extruded geometry from a path shape.
28841  *
28842  * parameters = {
28843  *
28844  *  curveSegments: <int>, // number of points on the curves
28845  *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
28846  *  depth: <float>, // Depth to extrude the shape
28847  *
28848  *  bevelEnabled: <bool>, // turn on bevel
28849  *  bevelThickness: <float>, // how deep into the original shape bevel goes
28850  *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
28851  *  bevelOffset: <float>, // how far from shape outline does bevel start
28852  *  bevelSegments: <int>, // number of bevel layers
28853  *
28854  *  extrudePath: <THREE.Curve> // curve to extrude shape along
28855  *
28856  *  UVGenerator: <Object> // object that provides UV generator functions
28857  *
28858  * }
28859  */
28860
28861 class ExtrudeGeometry extends BufferGeometry {
28862
28863         constructor( shapes, options ) {
28864
28865                 super();
28866
28867                 this.type = 'ExtrudeGeometry';
28868
28869                 this.parameters = {
28870                         shapes: shapes,
28871                         options: options
28872                 };
28873
28874                 shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
28875
28876                 const scope = this;
28877
28878                 const verticesArray = [];
28879                 const uvArray = [];
28880
28881                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
28882
28883                         const shape = shapes[ i ];
28884                         addShape( shape );
28885
28886                 }
28887
28888                 // build geometry
28889
28890                 this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
28891                 this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
28892
28893                 this.computeVertexNormals();
28894
28895                 // functions
28896
28897                 function addShape( shape ) {
28898
28899                         const placeholder = [];
28900
28901                         // options
28902
28903                         const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
28904                         const steps = options.steps !== undefined ? options.steps : 1;
28905                         let depth = options.depth !== undefined ? options.depth : 100;
28906
28907                         let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
28908                         let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
28909                         let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
28910                         let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
28911                         let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
28912
28913                         const extrudePath = options.extrudePath;
28914
28915                         const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
28916
28917                         // deprecated options
28918
28919                         if ( options.amount !== undefined ) {
28920
28921                                 console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );
28922                                 depth = options.amount;
28923
28924                         }
28925
28926                         //
28927
28928                         let extrudePts, extrudeByPath = false;
28929                         let splineTube, binormal, normal, position2;
28930
28931                         if ( extrudePath ) {
28932
28933                                 extrudePts = extrudePath.getSpacedPoints( steps );
28934
28935                                 extrudeByPath = true;
28936                                 bevelEnabled = false; // bevels not supported for path extrusion
28937
28938                                 // SETUP TNB variables
28939
28940                                 // TODO1 - have a .isClosed in spline?
28941
28942                                 splineTube = extrudePath.computeFrenetFrames( steps, false );
28943
28944                                 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
28945
28946                                 binormal = new Vector3();
28947                                 normal = new Vector3();
28948                                 position2 = new Vector3();
28949
28950                         }
28951
28952                         // Safeguards if bevels are not enabled
28953
28954                         if ( ! bevelEnabled ) {
28955
28956                                 bevelSegments = 0;
28957                                 bevelThickness = 0;
28958                                 bevelSize = 0;
28959                                 bevelOffset = 0;
28960
28961                         }
28962
28963                         // Variables initialization
28964
28965                         const shapePoints = shape.extractPoints( curveSegments );
28966
28967                         let vertices = shapePoints.shape;
28968                         const holes = shapePoints.holes;
28969
28970                         const reverse = ! ShapeUtils.isClockWise( vertices );
28971
28972                         if ( reverse ) {
28973
28974                                 vertices = vertices.reverse();
28975
28976                                 // Maybe we should also check if holes are in the opposite direction, just to be safe ...
28977
28978                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
28979
28980                                         const ahole = holes[ h ];
28981
28982                                         if ( ShapeUtils.isClockWise( ahole ) ) {
28983
28984                                                 holes[ h ] = ahole.reverse();
28985
28986                                         }
28987
28988                                 }
28989
28990                         }
28991
28992
28993                         const faces = ShapeUtils.triangulateShape( vertices, holes );
28994
28995                         /* Vertices */
28996
28997                         const contour = vertices; // vertices has all points but contour has only points of circumference
28998
28999                         for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
29000
29001                                 const ahole = holes[ h ];
29002
29003                                 vertices = vertices.concat( ahole );
29004
29005                         }
29006
29007
29008                         function scalePt2( pt, vec, size ) {
29009
29010                                 if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' );
29011
29012                                 return vec.clone().multiplyScalar( size ).add( pt );
29013
29014                         }
29015
29016                         const vlen = vertices.length, flen = faces.length;
29017
29018
29019                         // Find directions for point movement
29020
29021
29022                         function getBevelVec( inPt, inPrev, inNext ) {
29023
29024                                 // computes for inPt the corresponding point inPt' on a new contour
29025                                 //   shifted by 1 unit (length of normalized vector) to the left
29026                                 // if we walk along contour clockwise, this new contour is outside the old one
29027                                 //
29028                                 // inPt' is the intersection of the two lines parallel to the two
29029                                 //  adjacent edges of inPt at a distance of 1 unit on the left side.
29030
29031                                 let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
29032
29033                                 // good reading for geometry algorithms (here: line-line intersection)
29034                                 // http://geomalgorithms.com/a05-_intersect-1.html
29035
29036                                 const v_prev_x = inPt.x - inPrev.x,
29037                                         v_prev_y = inPt.y - inPrev.y;
29038                                 const v_next_x = inNext.x - inPt.x,
29039                                         v_next_y = inNext.y - inPt.y;
29040
29041                                 const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
29042
29043                                 // check for collinear edges
29044                                 const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
29045
29046                                 if ( Math.abs( collinear0 ) > Number.EPSILON ) {
29047
29048                                         // not collinear
29049
29050                                         // length of vectors for normalizing
29051
29052                                         const v_prev_len = Math.sqrt( v_prev_lensq );
29053                                         const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
29054
29055                                         // shift adjacent points by unit vectors to the left
29056
29057                                         const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
29058                                         const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
29059
29060                                         const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
29061                                         const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
29062
29063                                         // scaling factor for v_prev to intersection point
29064
29065                                         const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
29066                                                         ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
29067                                                 ( v_prev_x * v_next_y - v_prev_y * v_next_x );
29068
29069                                         // vector from inPt to intersection point
29070
29071                                         v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
29072                                         v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
29073
29074                                         // Don't normalize!, otherwise sharp corners become ugly
29075                                         //  but prevent crazy spikes
29076                                         const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
29077                                         if ( v_trans_lensq <= 2 ) {
29078
29079                                                 return new Vector2( v_trans_x, v_trans_y );
29080
29081                                         } else {
29082
29083                                                 shrink_by = Math.sqrt( v_trans_lensq / 2 );
29084
29085                                         }
29086
29087                                 } else {
29088
29089                                         // handle special case of collinear edges
29090
29091                                         let direction_eq = false; // assumes: opposite
29092
29093                                         if ( v_prev_x > Number.EPSILON ) {
29094
29095                                                 if ( v_next_x > Number.EPSILON ) {
29096
29097                                                         direction_eq = true;
29098
29099                                                 }
29100
29101                                         } else {
29102
29103                                                 if ( v_prev_x < - Number.EPSILON ) {
29104
29105                                                         if ( v_next_x < - Number.EPSILON ) {
29106
29107                                                                 direction_eq = true;
29108
29109                                                         }
29110
29111                                                 } else {
29112
29113                                                         if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
29114
29115                                                                 direction_eq = true;
29116
29117                                                         }
29118
29119                                                 }
29120
29121                                         }
29122
29123                                         if ( direction_eq ) {
29124
29125                                                 // console.log("Warning: lines are a straight sequence");
29126                                                 v_trans_x = - v_prev_y;
29127                                                 v_trans_y = v_prev_x;
29128                                                 shrink_by = Math.sqrt( v_prev_lensq );
29129
29130                                         } else {
29131
29132                                                 // console.log("Warning: lines are a straight spike");
29133                                                 v_trans_x = v_prev_x;
29134                                                 v_trans_y = v_prev_y;
29135                                                 shrink_by = Math.sqrt( v_prev_lensq / 2 );
29136
29137                                         }
29138
29139                                 }
29140
29141                                 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
29142
29143                         }
29144
29145
29146                         const contourMovements = [];
29147
29148                         for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
29149
29150                                 if ( j === il ) j = 0;
29151                                 if ( k === il ) k = 0;
29152
29153                                 //  (j)---(i)---(k)
29154                                 // console.log('i,j,k', i, j , k)
29155
29156                                 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
29157
29158                         }
29159
29160                         const holesMovements = [];
29161                         let oneHoleMovements, verticesMovements = contourMovements.concat();
29162
29163                         for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
29164
29165                                 const ahole = holes[ h ];
29166
29167                                 oneHoleMovements = [];
29168
29169                                 for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
29170
29171                                         if ( j === il ) j = 0;
29172                                         if ( k === il ) k = 0;
29173
29174                                         //  (j)---(i)---(k)
29175                                         oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
29176
29177                                 }
29178
29179                                 holesMovements.push( oneHoleMovements );
29180                                 verticesMovements = verticesMovements.concat( oneHoleMovements );
29181
29182                         }
29183
29184
29185                         // Loop bevelSegments, 1 for the front, 1 for the back
29186
29187                         for ( let b = 0; b < bevelSegments; b ++ ) {
29188
29189                                 //for ( b = bevelSegments; b > 0; b -- ) {
29190
29191                                 const t = b / bevelSegments;
29192                                 const z = bevelThickness * Math.cos( t * Math.PI / 2 );
29193                                 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
29194
29195                                 // contract shape
29196
29197                                 for ( let i = 0, il = contour.length; i < il; i ++ ) {
29198
29199                                         const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
29200
29201                                         v( vert.x, vert.y, - z );
29202
29203                                 }
29204
29205                                 // expand holes
29206
29207                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
29208
29209                                         const ahole = holes[ h ];
29210                                         oneHoleMovements = holesMovements[ h ];
29211
29212                                         for ( let i = 0, il = ahole.length; i < il; i ++ ) {
29213
29214                                                 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
29215
29216                                                 v( vert.x, vert.y, - z );
29217
29218                                         }
29219
29220                                 }
29221
29222                         }
29223
29224                         const bs = bevelSize + bevelOffset;
29225
29226                         // Back facing vertices
29227
29228                         for ( let i = 0; i < vlen; i ++ ) {
29229
29230                                 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
29231
29232                                 if ( ! extrudeByPath ) {
29233
29234                                         v( vert.x, vert.y, 0 );
29235
29236                                 } else {
29237
29238                                         // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
29239
29240                                         normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
29241                                         binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
29242
29243                                         position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
29244
29245                                         v( position2.x, position2.y, position2.z );
29246
29247                                 }
29248
29249                         }
29250
29251                         // Add stepped vertices...
29252                         // Including front facing vertices
29253
29254                         for ( let s = 1; s <= steps; s ++ ) {
29255
29256                                 for ( let i = 0; i < vlen; i ++ ) {
29257
29258                                         const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
29259
29260                                         if ( ! extrudeByPath ) {
29261
29262                                                 v( vert.x, vert.y, depth / steps * s );
29263
29264                                         } else {
29265
29266                                                 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
29267
29268                                                 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
29269                                                 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
29270
29271                                                 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
29272
29273                                                 v( position2.x, position2.y, position2.z );
29274
29275                                         }
29276
29277                                 }
29278
29279                         }
29280
29281
29282                         // Add bevel segments planes
29283
29284                         //for ( b = 1; b <= bevelSegments; b ++ ) {
29285                         for ( let b = bevelSegments - 1; b >= 0; b -- ) {
29286
29287                                 const t = b / bevelSegments;
29288                                 const z = bevelThickness * Math.cos( t * Math.PI / 2 );
29289                                 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
29290
29291                                 // contract shape
29292
29293                                 for ( let i = 0, il = contour.length; i < il; i ++ ) {
29294
29295                                         const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
29296                                         v( vert.x, vert.y, depth + z );
29297
29298                                 }
29299
29300                                 // expand holes
29301
29302                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
29303
29304                                         const ahole = holes[ h ];
29305                                         oneHoleMovements = holesMovements[ h ];
29306
29307                                         for ( let i = 0, il = ahole.length; i < il; i ++ ) {
29308
29309                                                 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
29310
29311                                                 if ( ! extrudeByPath ) {
29312
29313                                                         v( vert.x, vert.y, depth + z );
29314
29315                                                 } else {
29316
29317                                                         v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
29318
29319                                                 }
29320
29321                                         }
29322
29323                                 }
29324
29325                         }
29326
29327                         /* Faces */
29328
29329                         // Top and bottom faces
29330
29331                         buildLidFaces();
29332
29333                         // Sides faces
29334
29335                         buildSideFaces();
29336
29337
29338                         /////  Internal functions
29339
29340                         function buildLidFaces() {
29341
29342                                 const start = verticesArray.length / 3;
29343
29344                                 if ( bevelEnabled ) {
29345
29346                                         let layer = 0; // steps + 1
29347                                         let offset = vlen * layer;
29348
29349                                         // Bottom faces
29350
29351                                         for ( let i = 0; i < flen; i ++ ) {
29352
29353                                                 const face = faces[ i ];
29354                                                 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
29355
29356                                         }
29357
29358                                         layer = steps + bevelSegments * 2;
29359                                         offset = vlen * layer;
29360
29361                                         // Top faces
29362
29363                                         for ( let i = 0; i < flen; i ++ ) {
29364
29365                                                 const face = faces[ i ];
29366                                                 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
29367
29368                                         }
29369
29370                                 } else {
29371
29372                                         // Bottom faces
29373
29374                                         for ( let i = 0; i < flen; i ++ ) {
29375
29376                                                 const face = faces[ i ];
29377                                                 f3( face[ 2 ], face[ 1 ], face[ 0 ] );
29378
29379                                         }
29380
29381                                         // Top faces
29382
29383                                         for ( let i = 0; i < flen; i ++ ) {
29384
29385                                                 const face = faces[ i ];
29386                                                 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
29387
29388                                         }
29389
29390                                 }
29391
29392                                 scope.addGroup( start, verticesArray.length / 3 - start, 0 );
29393
29394                         }
29395
29396                         // Create faces for the z-sides of the shape
29397
29398                         function buildSideFaces() {
29399
29400                                 const start = verticesArray.length / 3;
29401                                 let layeroffset = 0;
29402                                 sidewalls( contour, layeroffset );
29403                                 layeroffset += contour.length;
29404
29405                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
29406
29407                                         const ahole = holes[ h ];
29408                                         sidewalls( ahole, layeroffset );
29409
29410                                         //, true
29411                                         layeroffset += ahole.length;
29412
29413                                 }
29414
29415
29416                                 scope.addGroup( start, verticesArray.length / 3 - start, 1 );
29417
29418
29419                         }
29420
29421                         function sidewalls( contour, layeroffset ) {
29422
29423                                 let i = contour.length;
29424
29425                                 while ( -- i >= 0 ) {
29426
29427                                         const j = i;
29428                                         let k = i - 1;
29429                                         if ( k < 0 ) k = contour.length - 1;
29430
29431                                         //console.log('b', i,j, i-1, k,vertices.length);
29432
29433                                         for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
29434
29435                                                 const slen1 = vlen * s;
29436                                                 const slen2 = vlen * ( s + 1 );
29437
29438                                                 const a = layeroffset + j + slen1,
29439                                                         b = layeroffset + k + slen1,
29440                                                         c = layeroffset + k + slen2,
29441                                                         d = layeroffset + j + slen2;
29442
29443                                                 f4( a, b, c, d );
29444
29445                                         }
29446
29447                                 }
29448
29449                         }
29450
29451                         function v( x, y, z ) {
29452
29453                                 placeholder.push( x );
29454                                 placeholder.push( y );
29455                                 placeholder.push( z );
29456
29457                         }
29458
29459
29460                         function f3( a, b, c ) {
29461
29462                                 addVertex( a );
29463                                 addVertex( b );
29464                                 addVertex( c );
29465
29466                                 const nextIndex = verticesArray.length / 3;
29467                                 const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
29468
29469                                 addUV( uvs[ 0 ] );
29470                                 addUV( uvs[ 1 ] );
29471                                 addUV( uvs[ 2 ] );
29472
29473                         }
29474
29475                         function f4( a, b, c, d ) {
29476
29477                                 addVertex( a );
29478                                 addVertex( b );
29479                                 addVertex( d );
29480
29481                                 addVertex( b );
29482                                 addVertex( c );
29483                                 addVertex( d );
29484
29485
29486                                 const nextIndex = verticesArray.length / 3;
29487                                 const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
29488
29489                                 addUV( uvs[ 0 ] );
29490                                 addUV( uvs[ 1 ] );
29491                                 addUV( uvs[ 3 ] );
29492
29493                                 addUV( uvs[ 1 ] );
29494                                 addUV( uvs[ 2 ] );
29495                                 addUV( uvs[ 3 ] );
29496
29497                         }
29498
29499                         function addVertex( index ) {
29500
29501                                 verticesArray.push( placeholder[ index * 3 + 0 ] );
29502                                 verticesArray.push( placeholder[ index * 3 + 1 ] );
29503                                 verticesArray.push( placeholder[ index * 3 + 2 ] );
29504
29505                         }
29506
29507
29508                         function addUV( vector2 ) {
29509
29510                                 uvArray.push( vector2.x );
29511                                 uvArray.push( vector2.y );
29512
29513                         }
29514
29515                 }
29516
29517         }
29518
29519         toJSON() {
29520
29521                 const data = BufferGeometry.prototype.toJSON.call( this );
29522
29523                 const shapes = this.parameters.shapes;
29524                 const options = this.parameters.options;
29525
29526                 return toJSON( shapes, options, data );
29527
29528         }
29529
29530 }
29531
29532 const WorldUVGenerator = {
29533
29534         generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
29535
29536                 const a_x = vertices[ indexA * 3 ];
29537                 const a_y = vertices[ indexA * 3 + 1 ];
29538                 const b_x = vertices[ indexB * 3 ];
29539                 const b_y = vertices[ indexB * 3 + 1 ];
29540                 const c_x = vertices[ indexC * 3 ];
29541                 const c_y = vertices[ indexC * 3 + 1 ];
29542
29543                 return [
29544                         new Vector2( a_x, a_y ),
29545                         new Vector2( b_x, b_y ),
29546                         new Vector2( c_x, c_y )
29547                 ];
29548
29549         },
29550
29551         generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
29552
29553                 const a_x = vertices[ indexA * 3 ];
29554                 const a_y = vertices[ indexA * 3 + 1 ];
29555                 const a_z = vertices[ indexA * 3 + 2 ];
29556                 const b_x = vertices[ indexB * 3 ];
29557                 const b_y = vertices[ indexB * 3 + 1 ];
29558                 const b_z = vertices[ indexB * 3 + 2 ];
29559                 const c_x = vertices[ indexC * 3 ];
29560                 const c_y = vertices[ indexC * 3 + 1 ];
29561                 const c_z = vertices[ indexC * 3 + 2 ];
29562                 const d_x = vertices[ indexD * 3 ];
29563                 const d_y = vertices[ indexD * 3 + 1 ];
29564                 const d_z = vertices[ indexD * 3 + 2 ];
29565
29566                 if ( Math.abs( a_y - b_y ) < 0.01 ) {
29567
29568                         return [
29569                                 new Vector2( a_x, 1 - a_z ),
29570                                 new Vector2( b_x, 1 - b_z ),
29571                                 new Vector2( c_x, 1 - c_z ),
29572                                 new Vector2( d_x, 1 - d_z )
29573                         ];
29574
29575                 } else {
29576
29577                         return [
29578                                 new Vector2( a_y, 1 - a_z ),
29579                                 new Vector2( b_y, 1 - b_z ),
29580                                 new Vector2( c_y, 1 - c_z ),
29581                                 new Vector2( d_y, 1 - d_z )
29582                         ];
29583
29584                 }
29585
29586         }
29587
29588 };
29589
29590 function toJSON( shapes, options, data ) {
29591
29592         data.shapes = [];
29593
29594         if ( Array.isArray( shapes ) ) {
29595
29596                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
29597
29598                         const shape = shapes[ i ];
29599
29600                         data.shapes.push( shape.uuid );
29601
29602                 }
29603
29604         } else {
29605
29606                 data.shapes.push( shapes.uuid );
29607
29608         }
29609
29610         if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
29611
29612         return data;
29613
29614 }
29615
29616 class IcosahedronGeometry extends PolyhedronGeometry {
29617
29618         constructor( radius = 1, detail = 0 ) {
29619
29620                 const t = ( 1 + Math.sqrt( 5 ) ) / 2;
29621
29622                 const vertices = [
29623                         - 1, t, 0,      1, t, 0,        - 1, - t, 0,    1, - t, 0,
29624                         0, - 1, t,      0, 1, t,        0, - 1, - t,    0, 1, - t,
29625                         t, 0, - 1,      t, 0, 1,        - t, 0, - 1,    - t, 0, 1
29626                 ];
29627
29628                 const indices = [
29629                         0, 11, 5,       0, 5, 1,        0, 1, 7,        0, 7, 10,       0, 10, 11,
29630                         1, 5, 9,        5, 11, 4,       11, 10, 2,      10, 7, 6,       7, 1, 8,
29631                         3, 9, 4,        3, 4, 2,        3, 2, 6,        3, 6, 8,        3, 8, 9,
29632                         4, 9, 5,        2, 4, 11,       6, 2, 10,       8, 6, 7,        9, 8, 1
29633                 ];
29634
29635                 super( vertices, indices, radius, detail );
29636
29637                 this.type = 'IcosahedronGeometry';
29638
29639                 this.parameters = {
29640                         radius: radius,
29641                         detail: detail
29642                 };
29643
29644         }
29645
29646 }
29647
29648 class LatheGeometry extends BufferGeometry {
29649
29650         constructor( points, segments = 12, phiStart = 0, phiLength = Math.PI * 2 ) {
29651
29652                 super();
29653
29654                 this.type = 'LatheGeometry';
29655
29656                 this.parameters = {
29657                         points: points,
29658                         segments: segments,
29659                         phiStart: phiStart,
29660                         phiLength: phiLength
29661                 };
29662
29663                 segments = Math.floor( segments );
29664
29665                 // clamp phiLength so it's in range of [ 0, 2PI ]
29666
29667                 phiLength = MathUtils.clamp( phiLength, 0, Math.PI * 2 );
29668
29669                 // buffers
29670
29671                 const indices = [];
29672                 const vertices = [];
29673                 const uvs = [];
29674
29675                 // helper variables
29676
29677                 const inverseSegments = 1.0 / segments;
29678                 const vertex = new Vector3();
29679                 const uv = new Vector2();
29680
29681                 // generate vertices and uvs
29682
29683                 for ( let i = 0; i <= segments; i ++ ) {
29684
29685                         const phi = phiStart + i * inverseSegments * phiLength;
29686
29687                         const sin = Math.sin( phi );
29688                         const cos = Math.cos( phi );
29689
29690                         for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
29691
29692                                 // vertex
29693
29694                                 vertex.x = points[ j ].x * sin;
29695                                 vertex.y = points[ j ].y;
29696                                 vertex.z = points[ j ].x * cos;
29697
29698                                 vertices.push( vertex.x, vertex.y, vertex.z );
29699
29700                                 // uv
29701
29702                                 uv.x = i / segments;
29703                                 uv.y = j / ( points.length - 1 );
29704
29705                                 uvs.push( uv.x, uv.y );
29706
29707
29708                         }
29709
29710                 }
29711
29712                 // indices
29713
29714                 for ( let i = 0; i < segments; i ++ ) {
29715
29716                         for ( let j = 0; j < ( points.length - 1 ); j ++ ) {
29717
29718                                 const base = j + i * points.length;
29719
29720                                 const a = base;
29721                                 const b = base + points.length;
29722                                 const c = base + points.length + 1;
29723                                 const d = base + 1;
29724
29725                                 // faces
29726
29727                                 indices.push( a, b, d );
29728                                 indices.push( b, c, d );
29729
29730                         }
29731
29732                 }
29733
29734                 // build geometry
29735
29736                 this.setIndex( indices );
29737                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29738                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29739
29740                 // generate normals
29741
29742                 this.computeVertexNormals();
29743
29744                 // if the geometry is closed, we need to average the normals along the seam.
29745                 // because the corresponding vertices are identical (but still have different UVs).
29746
29747                 if ( phiLength === Math.PI * 2 ) {
29748
29749                         const normals = this.attributes.normal.array;
29750                         const n1 = new Vector3();
29751                         const n2 = new Vector3();
29752                         const n = new Vector3();
29753
29754                         // this is the buffer offset for the last line of vertices
29755
29756                         const base = segments * points.length * 3;
29757
29758                         for ( let i = 0, j = 0; i < points.length; i ++, j += 3 ) {
29759
29760                                 // select the normal of the vertex in the first line
29761
29762                                 n1.x = normals[ j + 0 ];
29763                                 n1.y = normals[ j + 1 ];
29764                                 n1.z = normals[ j + 2 ];
29765
29766                                 // select the normal of the vertex in the last line
29767
29768                                 n2.x = normals[ base + j + 0 ];
29769                                 n2.y = normals[ base + j + 1 ];
29770                                 n2.z = normals[ base + j + 2 ];
29771
29772                                 // average normals
29773
29774                                 n.addVectors( n1, n2 ).normalize();
29775
29776                                 // assign the new values to both normals
29777
29778                                 normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
29779                                 normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
29780                                 normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
29781
29782                         }
29783
29784                 }
29785
29786         }
29787
29788 }
29789
29790 class OctahedronGeometry extends PolyhedronGeometry {
29791
29792         constructor( radius = 1, detail = 0 ) {
29793
29794                 const vertices = [
29795                         1, 0, 0,        - 1, 0, 0,      0, 1, 0,
29796                         0, - 1, 0,      0, 0, 1,        0, 0, - 1
29797                 ];
29798
29799                 const indices = [
29800                         0, 2, 4,        0, 4, 3,        0, 3, 5,
29801                         0, 5, 2,        1, 2, 5,        1, 5, 3,
29802                         1, 3, 4,        1, 4, 2
29803                 ];
29804
29805                 super( vertices, indices, radius, detail );
29806
29807                 this.type = 'OctahedronGeometry';
29808
29809                 this.parameters = {
29810                         radius: radius,
29811                         detail: detail
29812                 };
29813
29814         }
29815
29816 }
29817
29818 /**
29819  * Parametric Surfaces Geometry
29820  * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
29821  */
29822
29823 function ParametricGeometry( func, slices, stacks ) {
29824
29825         BufferGeometry.call( this );
29826
29827         this.type = 'ParametricGeometry';
29828
29829         this.parameters = {
29830                 func: func,
29831                 slices: slices,
29832                 stacks: stacks
29833         };
29834
29835         // buffers
29836
29837         const indices = [];
29838         const vertices = [];
29839         const normals = [];
29840         const uvs = [];
29841
29842         const EPS = 0.00001;
29843
29844         const normal = new Vector3();
29845
29846         const p0 = new Vector3(), p1 = new Vector3();
29847         const pu = new Vector3(), pv = new Vector3();
29848
29849         if ( func.length < 3 ) {
29850
29851                 console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );
29852
29853         }
29854
29855         // generate vertices, normals and uvs
29856
29857         const sliceCount = slices + 1;
29858
29859         for ( let i = 0; i <= stacks; i ++ ) {
29860
29861                 const v = i / stacks;
29862
29863                 for ( let j = 0; j <= slices; j ++ ) {
29864
29865                         const u = j / slices;
29866
29867                         // vertex
29868
29869                         func( u, v, p0 );
29870                         vertices.push( p0.x, p0.y, p0.z );
29871
29872                         // normal
29873
29874                         // approximate tangent vectors via finite differences
29875
29876                         if ( u - EPS >= 0 ) {
29877
29878                                 func( u - EPS, v, p1 );
29879                                 pu.subVectors( p0, p1 );
29880
29881                         } else {
29882
29883                                 func( u + EPS, v, p1 );
29884                                 pu.subVectors( p1, p0 );
29885
29886                         }
29887
29888                         if ( v - EPS >= 0 ) {
29889
29890                                 func( u, v - EPS, p1 );
29891                                 pv.subVectors( p0, p1 );
29892
29893                         } else {
29894
29895                                 func( u, v + EPS, p1 );
29896                                 pv.subVectors( p1, p0 );
29897
29898                         }
29899
29900                         // cross product of tangent vectors returns surface normal
29901
29902                         normal.crossVectors( pu, pv ).normalize();
29903                         normals.push( normal.x, normal.y, normal.z );
29904
29905                         // uv
29906
29907                         uvs.push( u, v );
29908
29909                 }
29910
29911         }
29912
29913         // generate indices
29914
29915         for ( let i = 0; i < stacks; i ++ ) {
29916
29917                 for ( let j = 0; j < slices; j ++ ) {
29918
29919                         const a = i * sliceCount + j;
29920                         const b = i * sliceCount + j + 1;
29921                         const c = ( i + 1 ) * sliceCount + j + 1;
29922                         const d = ( i + 1 ) * sliceCount + j;
29923
29924                         // faces one and two
29925
29926                         indices.push( a, b, d );
29927                         indices.push( b, c, d );
29928
29929                 }
29930
29931         }
29932
29933         // build geometry
29934
29935         this.setIndex( indices );
29936         this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29937         this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29938         this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29939
29940 }
29941
29942 ParametricGeometry.prototype = Object.create( BufferGeometry.prototype );
29943 ParametricGeometry.prototype.constructor = ParametricGeometry;
29944
29945 class RingGeometry extends BufferGeometry {
29946
29947         constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 8, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) {
29948
29949                 super();
29950
29951                 this.type = 'RingGeometry';
29952
29953                 this.parameters = {
29954                         innerRadius: innerRadius,
29955                         outerRadius: outerRadius,
29956                         thetaSegments: thetaSegments,
29957                         phiSegments: phiSegments,
29958                         thetaStart: thetaStart,
29959                         thetaLength: thetaLength
29960                 };
29961
29962                 thetaSegments = Math.max( 3, thetaSegments );
29963                 phiSegments = Math.max( 1, phiSegments );
29964
29965                 // buffers
29966
29967                 const indices = [];
29968                 const vertices = [];
29969                 const normals = [];
29970                 const uvs = [];
29971
29972                 // some helper variables
29973
29974                 let radius = innerRadius;
29975                 const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
29976                 const vertex = new Vector3();
29977                 const uv = new Vector2();
29978
29979                 // generate vertices, normals and uvs
29980
29981                 for ( let j = 0; j <= phiSegments; j ++ ) {
29982
29983                         for ( let i = 0; i <= thetaSegments; i ++ ) {
29984
29985                                 // values are generate from the inside of the ring to the outside
29986
29987                                 const segment = thetaStart + i / thetaSegments * thetaLength;
29988
29989                                 // vertex
29990
29991                                 vertex.x = radius * Math.cos( segment );
29992                                 vertex.y = radius * Math.sin( segment );
29993
29994                                 vertices.push( vertex.x, vertex.y, vertex.z );
29995
29996                                 // normal
29997
29998                                 normals.push( 0, 0, 1 );
29999
30000                                 // uv
30001
30002                                 uv.x = ( vertex.x / outerRadius + 1 ) / 2;
30003                                 uv.y = ( vertex.y / outerRadius + 1 ) / 2;
30004
30005                                 uvs.push( uv.x, uv.y );
30006
30007                         }
30008
30009                         // increase the radius for next row of vertices
30010
30011                         radius += radiusStep;
30012
30013                 }
30014
30015                 // indices
30016
30017                 for ( let j = 0; j < phiSegments; j ++ ) {
30018
30019                         const thetaSegmentLevel = j * ( thetaSegments + 1 );
30020
30021                         for ( let i = 0; i < thetaSegments; i ++ ) {
30022
30023                                 const segment = i + thetaSegmentLevel;
30024
30025                                 const a = segment;
30026                                 const b = segment + thetaSegments + 1;
30027                                 const c = segment + thetaSegments + 2;
30028                                 const d = segment + 1;
30029
30030                                 // faces
30031
30032                                 indices.push( a, b, d );
30033                                 indices.push( b, c, d );
30034
30035                         }
30036
30037                 }
30038
30039                 // build geometry
30040
30041                 this.setIndex( indices );
30042                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30043                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30044                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30045
30046         }
30047
30048 }
30049
30050 class ShapeGeometry extends BufferGeometry {
30051
30052         constructor( shapes, curveSegments = 12 ) {
30053
30054                 super();
30055                 this.type = 'ShapeGeometry';
30056
30057                 this.parameters = {
30058                         shapes: shapes,
30059                         curveSegments: curveSegments
30060                 };
30061
30062                 // buffers
30063
30064                 const indices = [];
30065                 const vertices = [];
30066                 const normals = [];
30067                 const uvs = [];
30068
30069                 // helper variables
30070
30071                 let groupStart = 0;
30072                 let groupCount = 0;
30073
30074                 // allow single and array values for "shapes" parameter
30075
30076                 if ( Array.isArray( shapes ) === false ) {
30077
30078                         addShape( shapes );
30079
30080                 } else {
30081
30082                         for ( let i = 0; i < shapes.length; i ++ ) {
30083
30084                                 addShape( shapes[ i ] );
30085
30086                                 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
30087
30088                                 groupStart += groupCount;
30089                                 groupCount = 0;
30090
30091                         }
30092
30093                 }
30094
30095                 // build geometry
30096
30097                 this.setIndex( indices );
30098                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30099                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30100                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30101
30102
30103                 // helper functions
30104
30105                 function addShape( shape ) {
30106
30107                         const indexOffset = vertices.length / 3;
30108                         const points = shape.extractPoints( curveSegments );
30109
30110                         let shapeVertices = points.shape;
30111                         const shapeHoles = points.holes;
30112
30113                         // check direction of vertices
30114
30115                         if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
30116
30117                                 shapeVertices = shapeVertices.reverse();
30118
30119                         }
30120
30121                         for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
30122
30123                                 const shapeHole = shapeHoles[ i ];
30124
30125                                 if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
30126
30127                                         shapeHoles[ i ] = shapeHole.reverse();
30128
30129                                 }
30130
30131                         }
30132
30133                         const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
30134
30135                         // join vertices of inner and outer paths to a single array
30136
30137                         for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
30138
30139                                 const shapeHole = shapeHoles[ i ];
30140                                 shapeVertices = shapeVertices.concat( shapeHole );
30141
30142                         }
30143
30144                         // vertices, normals, uvs
30145
30146                         for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
30147
30148                                 const vertex = shapeVertices[ i ];
30149
30150                                 vertices.push( vertex.x, vertex.y, 0 );
30151                                 normals.push( 0, 0, 1 );
30152                                 uvs.push( vertex.x, vertex.y ); // world uvs
30153
30154                         }
30155
30156                         // incides
30157
30158                         for ( let i = 0, l = faces.length; i < l; i ++ ) {
30159
30160                                 const face = faces[ i ];
30161
30162                                 const a = face[ 0 ] + indexOffset;
30163                                 const b = face[ 1 ] + indexOffset;
30164                                 const c = face[ 2 ] + indexOffset;
30165
30166                                 indices.push( a, b, c );
30167                                 groupCount += 3;
30168
30169                         }
30170
30171                 }
30172
30173         }
30174
30175         toJSON() {
30176
30177                 const data = BufferGeometry.prototype.toJSON.call( this );
30178
30179                 const shapes = this.parameters.shapes;
30180
30181                 return toJSON$1( shapes, data );
30182
30183         }
30184
30185 }
30186
30187 function toJSON$1( shapes, data ) {
30188
30189         data.shapes = [];
30190
30191         if ( Array.isArray( shapes ) ) {
30192
30193                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
30194
30195                         const shape = shapes[ i ];
30196
30197                         data.shapes.push( shape.uuid );
30198
30199                 }
30200
30201         } else {
30202
30203                 data.shapes.push( shapes.uuid );
30204
30205         }
30206
30207         return data;
30208
30209 }
30210
30211 class SphereGeometry extends BufferGeometry {
30212
30213         constructor( radius = 1, widthSegments = 8, heightSegments = 6, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
30214
30215                 super();
30216                 this.type = 'SphereGeometry';
30217
30218                 this.parameters = {
30219                         radius: radius,
30220                         widthSegments: widthSegments,
30221                         heightSegments: heightSegments,
30222                         phiStart: phiStart,
30223                         phiLength: phiLength,
30224                         thetaStart: thetaStart,
30225                         thetaLength: thetaLength
30226                 };
30227
30228                 widthSegments = Math.max( 3, Math.floor( widthSegments ) );
30229                 heightSegments = Math.max( 2, Math.floor( heightSegments ) );
30230
30231                 const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
30232
30233                 let index = 0;
30234                 const grid = [];
30235
30236                 const vertex = new Vector3();
30237                 const normal = new Vector3();
30238
30239                 // buffers
30240
30241                 const indices = [];
30242                 const vertices = [];
30243                 const normals = [];
30244                 const uvs = [];
30245
30246                 // generate vertices, normals and uvs
30247
30248                 for ( let iy = 0; iy <= heightSegments; iy ++ ) {
30249
30250                         const verticesRow = [];
30251
30252                         const v = iy / heightSegments;
30253
30254                         // special case for the poles
30255
30256                         let uOffset = 0;
30257
30258                         if ( iy == 0 && thetaStart == 0 ) {
30259
30260                                 uOffset = 0.5 / widthSegments;
30261
30262                         } else if ( iy == heightSegments && thetaEnd == Math.PI ) {
30263
30264                                 uOffset = - 0.5 / widthSegments;
30265
30266                         }
30267
30268                         for ( let ix = 0; ix <= widthSegments; ix ++ ) {
30269
30270                                 const u = ix / widthSegments;
30271
30272                                 // vertex
30273
30274                                 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
30275                                 vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
30276                                 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
30277
30278                                 vertices.push( vertex.x, vertex.y, vertex.z );
30279
30280                                 // normal
30281
30282                                 normal.copy( vertex ).normalize();
30283                                 normals.push( normal.x, normal.y, normal.z );
30284
30285                                 // uv
30286
30287                                 uvs.push( u + uOffset, 1 - v );
30288
30289                                 verticesRow.push( index ++ );
30290
30291                         }
30292
30293                         grid.push( verticesRow );
30294
30295                 }
30296
30297                 // indices
30298
30299                 for ( let iy = 0; iy < heightSegments; iy ++ ) {
30300
30301                         for ( let ix = 0; ix < widthSegments; ix ++ ) {
30302
30303                                 const a = grid[ iy ][ ix + 1 ];
30304                                 const b = grid[ iy ][ ix ];
30305                                 const c = grid[ iy + 1 ][ ix ];
30306                                 const d = grid[ iy + 1 ][ ix + 1 ];
30307
30308                                 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
30309                                 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
30310
30311                         }
30312
30313                 }
30314
30315                 // build geometry
30316
30317                 this.setIndex( indices );
30318                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30319                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30320                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30321
30322         }
30323
30324 }
30325
30326 class TetrahedronGeometry extends PolyhedronGeometry {
30327
30328         constructor( radius = 1, detail = 0 ) {
30329
30330                 const vertices = [
30331                         1, 1, 1,        - 1, - 1, 1,    - 1, 1, - 1,    1, - 1, - 1
30332                 ];
30333
30334                 const indices = [
30335                         2, 1, 0,        0, 3, 2,        1, 3, 0,        2, 3, 1
30336                 ];
30337
30338                 super( vertices, indices, radius, detail );
30339
30340                 this.type = 'TetrahedronGeometry';
30341
30342                 this.parameters = {
30343                         radius: radius,
30344                         detail: detail
30345                 };
30346
30347         }
30348
30349 }
30350
30351 /**
30352  * Text = 3D Text
30353  *
30354  * parameters = {
30355  *  font: <THREE.Font>, // font
30356  *
30357  *  size: <float>, // size of the text
30358  *  height: <float>, // thickness to extrude text
30359  *  curveSegments: <int>, // number of points on the curves
30360  *
30361  *  bevelEnabled: <bool>, // turn on bevel
30362  *  bevelThickness: <float>, // how deep into text bevel goes
30363  *  bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
30364  *  bevelOffset: <float> // how far from text outline does bevel start
30365  * }
30366  */
30367
30368 class TextGeometry extends ExtrudeGeometry {
30369
30370         constructor( text, parameters = {} ) {
30371
30372                 const font = parameters.font;
30373
30374                 if ( ! ( font && font.isFont ) ) {
30375
30376                         console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
30377                         return new BufferGeometry();
30378
30379                 }
30380
30381                 const shapes = font.generateShapes( text, parameters.size );
30382
30383                 // translate parameters to ExtrudeGeometry API
30384
30385                 parameters.depth = parameters.height !== undefined ? parameters.height : 50;
30386
30387                 // defaults
30388
30389                 if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
30390                 if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
30391                 if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
30392
30393                 super( shapes, parameters );
30394
30395                 this.type = 'TextGeometry';
30396
30397         }
30398
30399 }
30400
30401 class TorusGeometry extends BufferGeometry {
30402
30403         constructor( radius = 1, tube = 0.4, radialSegments = 8, tubularSegments = 6, arc = Math.PI * 2 ) {
30404
30405                 super();
30406                 this.type = 'TorusGeometry';
30407
30408                 this.parameters = {
30409                         radius: radius,
30410                         tube: tube,
30411                         radialSegments: radialSegments,
30412                         tubularSegments: tubularSegments,
30413                         arc: arc
30414                 };
30415
30416                 radialSegments = Math.floor( radialSegments );
30417                 tubularSegments = Math.floor( tubularSegments );
30418
30419                 // buffers
30420
30421                 const indices = [];
30422                 const vertices = [];
30423                 const normals = [];
30424                 const uvs = [];
30425
30426                 // helper variables
30427
30428                 const center = new Vector3();
30429                 const vertex = new Vector3();
30430                 const normal = new Vector3();
30431
30432                 // generate vertices, normals and uvs
30433
30434                 for ( let j = 0; j <= radialSegments; j ++ ) {
30435
30436                         for ( let i = 0; i <= tubularSegments; i ++ ) {
30437
30438                                 const u = i / tubularSegments * arc;
30439                                 const v = j / radialSegments * Math.PI * 2;
30440
30441                                 // vertex
30442
30443                                 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
30444                                 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
30445                                 vertex.z = tube * Math.sin( v );
30446
30447                                 vertices.push( vertex.x, vertex.y, vertex.z );
30448
30449                                 // normal
30450
30451                                 center.x = radius * Math.cos( u );
30452                                 center.y = radius * Math.sin( u );
30453                                 normal.subVectors( vertex, center ).normalize();
30454
30455                                 normals.push( normal.x, normal.y, normal.z );
30456
30457                                 // uv
30458
30459                                 uvs.push( i / tubularSegments );
30460                                 uvs.push( j / radialSegments );
30461
30462                         }
30463
30464                 }
30465
30466                 // generate indices
30467
30468                 for ( let j = 1; j <= radialSegments; j ++ ) {
30469
30470                         for ( let i = 1; i <= tubularSegments; i ++ ) {
30471
30472                                 // indices
30473
30474                                 const a = ( tubularSegments + 1 ) * j + i - 1;
30475                                 const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
30476                                 const c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
30477                                 const d = ( tubularSegments + 1 ) * j + i;
30478
30479                                 // faces
30480
30481                                 indices.push( a, b, d );
30482                                 indices.push( b, c, d );
30483
30484                         }
30485
30486                 }
30487
30488                 // build geometry
30489
30490                 this.setIndex( indices );
30491                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30492                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30493                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30494
30495         }
30496
30497 }
30498
30499 class TorusKnotGeometry extends BufferGeometry {
30500
30501         constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) {
30502
30503                 super();
30504                 this.type = 'TorusKnotGeometry';
30505
30506                 this.parameters = {
30507                         radius: radius,
30508                         tube: tube,
30509                         tubularSegments: tubularSegments,
30510                         radialSegments: radialSegments,
30511                         p: p,
30512                         q: q
30513                 };
30514
30515                 tubularSegments = Math.floor( tubularSegments );
30516                 radialSegments = Math.floor( radialSegments );
30517
30518                 // buffers
30519
30520                 const indices = [];
30521                 const vertices = [];
30522                 const normals = [];
30523                 const uvs = [];
30524
30525                 // helper variables
30526
30527                 const vertex = new Vector3();
30528                 const normal = new Vector3();
30529
30530                 const P1 = new Vector3();
30531                 const P2 = new Vector3();
30532
30533                 const B = new Vector3();
30534                 const T = new Vector3();
30535                 const N = new Vector3();
30536
30537                 // generate vertices, normals and uvs
30538
30539                 for ( let i = 0; i <= tubularSegments; ++ i ) {
30540
30541                         // the radian "u" is used to calculate the position on the torus curve of the current tubular segement
30542
30543                         const u = i / tubularSegments * p * Math.PI * 2;
30544
30545                         // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
30546                         // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
30547
30548                         calculatePositionOnCurve( u, p, q, radius, P1 );
30549                         calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
30550
30551                         // calculate orthonormal basis
30552
30553                         T.subVectors( P2, P1 );
30554                         N.addVectors( P2, P1 );
30555                         B.crossVectors( T, N );
30556                         N.crossVectors( B, T );
30557
30558                         // normalize B, N. T can be ignored, we don't use it
30559
30560                         B.normalize();
30561                         N.normalize();
30562
30563                         for ( let j = 0; j <= radialSegments; ++ j ) {
30564
30565                                 // now calculate the vertices. they are nothing more than an extrusion of the torus curve.
30566                                 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
30567
30568                                 const v = j / radialSegments * Math.PI * 2;
30569                                 const cx = - tube * Math.cos( v );
30570                                 const cy = tube * Math.sin( v );
30571
30572                                 // now calculate the final vertex position.
30573                                 // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
30574
30575                                 vertex.x = P1.x + ( cx * N.x + cy * B.x );
30576                                 vertex.y = P1.y + ( cx * N.y + cy * B.y );
30577                                 vertex.z = P1.z + ( cx * N.z + cy * B.z );
30578
30579                                 vertices.push( vertex.x, vertex.y, vertex.z );
30580
30581                                 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
30582
30583                                 normal.subVectors( vertex, P1 ).normalize();
30584
30585                                 normals.push( normal.x, normal.y, normal.z );
30586
30587                                 // uv
30588
30589                                 uvs.push( i / tubularSegments );
30590                                 uvs.push( j / radialSegments );
30591
30592                         }
30593
30594                 }
30595
30596                 // generate indices
30597
30598                 for ( let j = 1; j <= tubularSegments; j ++ ) {
30599
30600                         for ( let i = 1; i <= radialSegments; i ++ ) {
30601
30602                                 // indices
30603
30604                                 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
30605                                 const b = ( radialSegments + 1 ) * j + ( i - 1 );
30606                                 const c = ( radialSegments + 1 ) * j + i;
30607                                 const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
30608
30609                                 // faces
30610
30611                                 indices.push( a, b, d );
30612                                 indices.push( b, c, d );
30613
30614                         }
30615
30616                 }
30617
30618                 // build geometry
30619
30620                 this.setIndex( indices );
30621                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30622                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30623                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30624
30625                 // this function calculates the current position on the torus curve
30626
30627                 function calculatePositionOnCurve( u, p, q, radius, position ) {
30628
30629                         const cu = Math.cos( u );
30630                         const su = Math.sin( u );
30631                         const quOverP = q / p * u;
30632                         const cs = Math.cos( quOverP );
30633
30634                         position.x = radius * ( 2 + cs ) * 0.5 * cu;
30635                         position.y = radius * ( 2 + cs ) * su * 0.5;
30636                         position.z = radius * Math.sin( quOverP ) * 0.5;
30637
30638                 }
30639
30640         }
30641
30642 }
30643
30644 class TubeGeometry extends BufferGeometry {
30645
30646         constructor( path, tubularSegments = 64, radius = 1, radialSegments = 8, closed = false ) {
30647
30648                 super();
30649                 this.type = 'TubeGeometry';
30650
30651                 this.parameters = {
30652                         path: path,
30653                         tubularSegments: tubularSegments,
30654                         radius: radius,
30655                         radialSegments: radialSegments,
30656                         closed: closed
30657                 };
30658
30659                 const frames = path.computeFrenetFrames( tubularSegments, closed );
30660
30661                 // expose internals
30662
30663                 this.tangents = frames.tangents;
30664                 this.normals = frames.normals;
30665                 this.binormals = frames.binormals;
30666
30667                 // helper variables
30668
30669                 const vertex = new Vector3();
30670                 const normal = new Vector3();
30671                 const uv = new Vector2();
30672                 let P = new Vector3();
30673
30674                 // buffer
30675
30676                 const vertices = [];
30677                 const normals = [];
30678                 const uvs = [];
30679                 const indices = [];
30680
30681                 // create buffer data
30682
30683                 generateBufferData();
30684
30685                 // build geometry
30686
30687                 this.setIndex( indices );
30688                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30689                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30690                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30691
30692                 // functions
30693
30694                 function generateBufferData() {
30695
30696                         for ( let i = 0; i < tubularSegments; i ++ ) {
30697
30698                                 generateSegment( i );
30699
30700                         }
30701
30702                         // if the geometry is not closed, generate the last row of vertices and normals
30703                         // at the regular position on the given path
30704                         //
30705                         // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
30706
30707                         generateSegment( ( closed === false ) ? tubularSegments : 0 );
30708
30709                         // uvs are generated in a separate function.
30710                         // this makes it easy compute correct values for closed geometries
30711
30712                         generateUVs();
30713
30714                         // finally create faces
30715
30716                         generateIndices();
30717
30718                 }
30719
30720                 function generateSegment( i ) {
30721
30722                         // we use getPointAt to sample evenly distributed points from the given path
30723
30724                         P = path.getPointAt( i / tubularSegments, P );
30725
30726                         // retrieve corresponding normal and binormal
30727
30728                         const N = frames.normals[ i ];
30729                         const B = frames.binormals[ i ];
30730
30731                         // generate normals and vertices for the current segment
30732
30733                         for ( let j = 0; j <= radialSegments; j ++ ) {
30734
30735                                 const v = j / radialSegments * Math.PI * 2;
30736
30737                                 const sin = Math.sin( v );
30738                                 const cos = - Math.cos( v );
30739
30740                                 // normal
30741
30742                                 normal.x = ( cos * N.x + sin * B.x );
30743                                 normal.y = ( cos * N.y + sin * B.y );
30744                                 normal.z = ( cos * N.z + sin * B.z );
30745                                 normal.normalize();
30746
30747                                 normals.push( normal.x, normal.y, normal.z );
30748
30749                                 // vertex
30750
30751                                 vertex.x = P.x + radius * normal.x;
30752                                 vertex.y = P.y + radius * normal.y;
30753                                 vertex.z = P.z + radius * normal.z;
30754
30755                                 vertices.push( vertex.x, vertex.y, vertex.z );
30756
30757                         }
30758
30759                 }
30760
30761                 function generateIndices() {
30762
30763                         for ( let j = 1; j <= tubularSegments; j ++ ) {
30764
30765                                 for ( let i = 1; i <= radialSegments; i ++ ) {
30766
30767                                         const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
30768                                         const b = ( radialSegments + 1 ) * j + ( i - 1 );
30769                                         const c = ( radialSegments + 1 ) * j + i;
30770                                         const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
30771
30772                                         // faces
30773
30774                                         indices.push( a, b, d );
30775                                         indices.push( b, c, d );
30776
30777                                 }
30778
30779                         }
30780
30781                 }
30782
30783                 function generateUVs() {
30784
30785                         for ( let i = 0; i <= tubularSegments; i ++ ) {
30786
30787                                 for ( let j = 0; j <= radialSegments; j ++ ) {
30788
30789                                         uv.x = i / tubularSegments;
30790                                         uv.y = j / radialSegments;
30791
30792                                         uvs.push( uv.x, uv.y );
30793
30794                                 }
30795
30796                         }
30797
30798                 }
30799
30800         }
30801         toJSON() {
30802
30803                 const data = BufferGeometry.prototype.toJSON.call( this );
30804
30805                 data.path = this.parameters.path.toJSON();
30806
30807                 return data;
30808
30809         }
30810
30811 }
30812
30813 class WireframeGeometry extends BufferGeometry {
30814
30815         constructor( geometry ) {
30816
30817                 super();
30818                 this.type = 'WireframeGeometry';
30819
30820                 if ( geometry.isGeometry === true ) {
30821
30822                         console.error( 'THREE.WireframeGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
30823                         return;
30824
30825                 }
30826
30827                 // buffer
30828
30829                 const vertices = [];
30830
30831                 // helper variables
30832
30833                 const edge = [ 0, 0 ], edges = {};
30834
30835                 const vertex = new Vector3();
30836
30837                 if ( geometry.index !== null ) {
30838
30839                         // indexed BufferGeometry
30840
30841                         const position = geometry.attributes.position;
30842                         const indices = geometry.index;
30843                         let groups = geometry.groups;
30844
30845                         if ( groups.length === 0 ) {
30846
30847                                 groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
30848
30849                         }
30850
30851                         // create a data structure that contains all eges without duplicates
30852
30853                         for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
30854
30855                                 const group = groups[ o ];
30856
30857                                 const start = group.start;
30858                                 const count = group.count;
30859
30860                                 for ( let i = start, l = ( start + count ); i < l; i += 3 ) {
30861
30862                                         for ( let j = 0; j < 3; j ++ ) {
30863
30864                                                 const edge1 = indices.getX( i + j );
30865                                                 const edge2 = indices.getX( i + ( j + 1 ) % 3 );
30866                                                 edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
30867                                                 edge[ 1 ] = Math.max( edge1, edge2 );
30868
30869                                                 const key = edge[ 0 ] + ',' + edge[ 1 ];
30870
30871                                                 if ( edges[ key ] === undefined ) {
30872
30873                                                         edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
30874
30875                                                 }
30876
30877                                         }
30878
30879                                 }
30880
30881                         }
30882
30883                         // generate vertices
30884
30885                         for ( const key in edges ) {
30886
30887                                 const e = edges[ key ];
30888
30889                                 vertex.fromBufferAttribute( position, e.index1 );
30890                                 vertices.push( vertex.x, vertex.y, vertex.z );
30891
30892                                 vertex.fromBufferAttribute( position, e.index2 );
30893                                 vertices.push( vertex.x, vertex.y, vertex.z );
30894
30895                         }
30896
30897                 } else {
30898
30899                         // non-indexed BufferGeometry
30900
30901                         const position = geometry.attributes.position;
30902
30903                         for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
30904
30905                                 for ( let j = 0; j < 3; j ++ ) {
30906
30907                                         // three edges per triangle, an edge is represented as (index1, index2)
30908                                         // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
30909
30910                                         const index1 = 3 * i + j;
30911                                         vertex.fromBufferAttribute( position, index1 );
30912                                         vertices.push( vertex.x, vertex.y, vertex.z );
30913
30914                                         const index2 = 3 * i + ( ( j + 1 ) % 3 );
30915                                         vertex.fromBufferAttribute( position, index2 );
30916                                         vertices.push( vertex.x, vertex.y, vertex.z );
30917
30918                                 }
30919
30920                         }
30921
30922                 }
30923
30924                 // build geometry
30925
30926                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30927
30928         }
30929
30930 }
30931
30932 var Geometries = /*#__PURE__*/Object.freeze({
30933         __proto__: null,
30934         BoxGeometry: BoxGeometry,
30935         BoxBufferGeometry: BoxGeometry,
30936         CircleGeometry: CircleGeometry,
30937         CircleBufferGeometry: CircleGeometry,
30938         ConeGeometry: ConeGeometry,
30939         ConeBufferGeometry: ConeGeometry,
30940         CylinderGeometry: CylinderGeometry,
30941         CylinderBufferGeometry: CylinderGeometry,
30942         DodecahedronGeometry: DodecahedronGeometry,
30943         DodecahedronBufferGeometry: DodecahedronGeometry,
30944         EdgesGeometry: EdgesGeometry,
30945         ExtrudeGeometry: ExtrudeGeometry,
30946         ExtrudeBufferGeometry: ExtrudeGeometry,
30947         IcosahedronGeometry: IcosahedronGeometry,
30948         IcosahedronBufferGeometry: IcosahedronGeometry,
30949         LatheGeometry: LatheGeometry,
30950         LatheBufferGeometry: LatheGeometry,
30951         OctahedronGeometry: OctahedronGeometry,
30952         OctahedronBufferGeometry: OctahedronGeometry,
30953         ParametricGeometry: ParametricGeometry,
30954         ParametricBufferGeometry: ParametricGeometry,
30955         PlaneGeometry: PlaneGeometry,
30956         PlaneBufferGeometry: PlaneGeometry,
30957         PolyhedronGeometry: PolyhedronGeometry,
30958         PolyhedronBufferGeometry: PolyhedronGeometry,
30959         RingGeometry: RingGeometry,
30960         RingBufferGeometry: RingGeometry,
30961         ShapeGeometry: ShapeGeometry,
30962         ShapeBufferGeometry: ShapeGeometry,
30963         SphereGeometry: SphereGeometry,
30964         SphereBufferGeometry: SphereGeometry,
30965         TetrahedronGeometry: TetrahedronGeometry,
30966         TetrahedronBufferGeometry: TetrahedronGeometry,
30967         TextGeometry: TextGeometry,
30968         TextBufferGeometry: TextGeometry,
30969         TorusGeometry: TorusGeometry,
30970         TorusBufferGeometry: TorusGeometry,
30971         TorusKnotGeometry: TorusKnotGeometry,
30972         TorusKnotBufferGeometry: TorusKnotGeometry,
30973         TubeGeometry: TubeGeometry,
30974         TubeBufferGeometry: TubeGeometry,
30975         WireframeGeometry: WireframeGeometry
30976 });
30977
30978 /**
30979  * parameters = {
30980  *  color: <THREE.Color>
30981  * }
30982  */
30983
30984 function ShadowMaterial( parameters ) {
30985
30986         Material.call( this );
30987
30988         this.type = 'ShadowMaterial';
30989
30990         this.color = new Color( 0x000000 );
30991         this.transparent = true;
30992
30993         this.setValues( parameters );
30994
30995 }
30996
30997 ShadowMaterial.prototype = Object.create( Material.prototype );
30998 ShadowMaterial.prototype.constructor = ShadowMaterial;
30999
31000 ShadowMaterial.prototype.isShadowMaterial = true;
31001
31002 ShadowMaterial.prototype.copy = function ( source ) {
31003
31004         Material.prototype.copy.call( this, source );
31005
31006         this.color.copy( source.color );
31007
31008         return this;
31009
31010 };
31011
31012 function RawShaderMaterial( parameters ) {
31013
31014         ShaderMaterial.call( this, parameters );
31015
31016         this.type = 'RawShaderMaterial';
31017
31018 }
31019
31020 RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
31021 RawShaderMaterial.prototype.constructor = RawShaderMaterial;
31022
31023 RawShaderMaterial.prototype.isRawShaderMaterial = true;
31024
31025 /**
31026  * parameters = {
31027  *  color: <hex>,
31028  *  roughness: <float>,
31029  *  metalness: <float>,
31030  *  opacity: <float>,
31031  *
31032  *  map: new THREE.Texture( <Image> ),
31033  *
31034  *  lightMap: new THREE.Texture( <Image> ),
31035  *  lightMapIntensity: <float>
31036  *
31037  *  aoMap: new THREE.Texture( <Image> ),
31038  *  aoMapIntensity: <float>
31039  *
31040  *  emissive: <hex>,
31041  *  emissiveIntensity: <float>
31042  *  emissiveMap: new THREE.Texture( <Image> ),
31043  *
31044  *  bumpMap: new THREE.Texture( <Image> ),
31045  *  bumpScale: <float>,
31046  *
31047  *  normalMap: new THREE.Texture( <Image> ),
31048  *  normalMapType: THREE.TangentSpaceNormalMap,
31049  *  normalScale: <Vector2>,
31050  *
31051  *  displacementMap: new THREE.Texture( <Image> ),
31052  *  displacementScale: <float>,
31053  *  displacementBias: <float>,
31054  *
31055  *  roughnessMap: new THREE.Texture( <Image> ),
31056  *
31057  *  metalnessMap: new THREE.Texture( <Image> ),
31058  *
31059  *  alphaMap: new THREE.Texture( <Image> ),
31060  *
31061  *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
31062  *  envMapIntensity: <float>
31063  *
31064  *  refractionRatio: <float>,
31065  *
31066  *  wireframe: <boolean>,
31067  *  wireframeLinewidth: <float>,
31068  *
31069  *  skinning: <bool>,
31070  *  morphTargets: <bool>,
31071  *  morphNormals: <bool>
31072  * }
31073  */
31074
31075 function MeshStandardMaterial( parameters ) {
31076
31077         Material.call( this );
31078
31079         this.defines = { 'STANDARD': '' };
31080
31081         this.type = 'MeshStandardMaterial';
31082
31083         this.color = new Color( 0xffffff ); // diffuse
31084         this.roughness = 1.0;
31085         this.metalness = 0.0;
31086
31087         this.map = null;
31088
31089         this.lightMap = null;
31090         this.lightMapIntensity = 1.0;
31091
31092         this.aoMap = null;
31093         this.aoMapIntensity = 1.0;
31094
31095         this.emissive = new Color( 0x000000 );
31096         this.emissiveIntensity = 1.0;
31097         this.emissiveMap = null;
31098
31099         this.bumpMap = null;
31100         this.bumpScale = 1;
31101
31102         this.normalMap = null;
31103         this.normalMapType = TangentSpaceNormalMap;
31104         this.normalScale = new Vector2( 1, 1 );
31105
31106         this.displacementMap = null;
31107         this.displacementScale = 1;
31108         this.displacementBias = 0;
31109
31110         this.roughnessMap = null;
31111
31112         this.metalnessMap = null;
31113
31114         this.alphaMap = null;
31115
31116         this.envMap = null;
31117         this.envMapIntensity = 1.0;
31118
31119         this.refractionRatio = 0.98;
31120
31121         this.wireframe = false;
31122         this.wireframeLinewidth = 1;
31123         this.wireframeLinecap = 'round';
31124         this.wireframeLinejoin = 'round';
31125
31126         this.skinning = false;
31127         this.morphTargets = false;
31128         this.morphNormals = false;
31129
31130         this.vertexTangents = false;
31131
31132         this.setValues( parameters );
31133
31134 }
31135
31136 MeshStandardMaterial.prototype = Object.create( Material.prototype );
31137 MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
31138
31139 MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
31140
31141 MeshStandardMaterial.prototype.copy = function ( source ) {
31142
31143         Material.prototype.copy.call( this, source );
31144
31145         this.defines = { 'STANDARD': '' };
31146
31147         this.color.copy( source.color );
31148         this.roughness = source.roughness;
31149         this.metalness = source.metalness;
31150
31151         this.map = source.map;
31152
31153         this.lightMap = source.lightMap;
31154         this.lightMapIntensity = source.lightMapIntensity;
31155
31156         this.aoMap = source.aoMap;
31157         this.aoMapIntensity = source.aoMapIntensity;
31158
31159         this.emissive.copy( source.emissive );
31160         this.emissiveMap = source.emissiveMap;
31161         this.emissiveIntensity = source.emissiveIntensity;
31162
31163         this.bumpMap = source.bumpMap;
31164         this.bumpScale = source.bumpScale;
31165
31166         this.normalMap = source.normalMap;
31167         this.normalMapType = source.normalMapType;
31168         this.normalScale.copy( source.normalScale );
31169
31170         this.displacementMap = source.displacementMap;
31171         this.displacementScale = source.displacementScale;
31172         this.displacementBias = source.displacementBias;
31173
31174         this.roughnessMap = source.roughnessMap;
31175
31176         this.metalnessMap = source.metalnessMap;
31177
31178         this.alphaMap = source.alphaMap;
31179
31180         this.envMap = source.envMap;
31181         this.envMapIntensity = source.envMapIntensity;
31182
31183         this.refractionRatio = source.refractionRatio;
31184
31185         this.wireframe = source.wireframe;
31186         this.wireframeLinewidth = source.wireframeLinewidth;
31187         this.wireframeLinecap = source.wireframeLinecap;
31188         this.wireframeLinejoin = source.wireframeLinejoin;
31189
31190         this.skinning = source.skinning;
31191         this.morphTargets = source.morphTargets;
31192         this.morphNormals = source.morphNormals;
31193
31194         this.vertexTangents = source.vertexTangents;
31195
31196         return this;
31197
31198 };
31199
31200 /**
31201  * parameters = {
31202  *  clearcoat: <float>,
31203  *  clearcoatMap: new THREE.Texture( <Image> ),
31204  *  clearcoatRoughness: <float>,
31205  *  clearcoatRoughnessMap: new THREE.Texture( <Image> ),
31206  *  clearcoatNormalScale: <Vector2>,
31207  *  clearcoatNormalMap: new THREE.Texture( <Image> ),
31208  *
31209  *  reflectivity: <float>,
31210  *  ior: <float>,
31211  *
31212  *  sheen: <Color>,
31213  *
31214  *  transmission: <float>,
31215  *  transmissionMap: new THREE.Texture( <Image> )
31216  * }
31217  */
31218
31219 function MeshPhysicalMaterial( parameters ) {
31220
31221         MeshStandardMaterial.call( this );
31222
31223         this.defines = {
31224
31225                 'STANDARD': '',
31226                 'PHYSICAL': ''
31227
31228         };
31229
31230         this.type = 'MeshPhysicalMaterial';
31231
31232         this.clearcoat = 0.0;
31233         this.clearcoatMap = null;
31234         this.clearcoatRoughness = 0.0;
31235         this.clearcoatRoughnessMap = null;
31236         this.clearcoatNormalScale = new Vector2( 1, 1 );
31237         this.clearcoatNormalMap = null;
31238
31239         this.reflectivity = 0.5; // maps to F0 = 0.04
31240
31241         Object.defineProperty( this, 'ior', {
31242                 get: function () {
31243
31244                         return ( 1 + 0.4 * this.reflectivity ) / ( 1 - 0.4 * this.reflectivity );
31245
31246                 },
31247                 set: function ( ior ) {
31248
31249                         this.reflectivity = MathUtils.clamp( 2.5 * ( ior - 1 ) / ( ior + 1 ), 0, 1 );
31250
31251                 }
31252         } );
31253
31254         this.sheen = null; // null will disable sheen bsdf
31255
31256         this.transmission = 0.0;
31257         this.transmissionMap = null;
31258
31259         this.setValues( parameters );
31260
31261 }
31262
31263 MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
31264 MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
31265
31266 MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
31267
31268 MeshPhysicalMaterial.prototype.copy = function ( source ) {
31269
31270         MeshStandardMaterial.prototype.copy.call( this, source );
31271
31272         this.defines = {
31273
31274                 'STANDARD': '',
31275                 'PHYSICAL': ''
31276
31277         };
31278
31279         this.clearcoat = source.clearcoat;
31280         this.clearcoatMap = source.clearcoatMap;
31281         this.clearcoatRoughness = source.clearcoatRoughness;
31282         this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
31283         this.clearcoatNormalMap = source.clearcoatNormalMap;
31284         this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
31285
31286         this.reflectivity = source.reflectivity;
31287
31288         if ( source.sheen ) {
31289
31290                 this.sheen = ( this.sheen || new Color() ).copy( source.sheen );
31291
31292         } else {
31293
31294                 this.sheen = null;
31295
31296         }
31297
31298         this.transmission = source.transmission;
31299         this.transmissionMap = source.transmissionMap;
31300
31301         return this;
31302
31303 };
31304
31305 /**
31306  * parameters = {
31307  *  color: <hex>,
31308  *  specular: <hex>,
31309  *  shininess: <float>,
31310  *  opacity: <float>,
31311  *
31312  *  map: new THREE.Texture( <Image> ),
31313  *
31314  *  lightMap: new THREE.Texture( <Image> ),
31315  *  lightMapIntensity: <float>
31316  *
31317  *  aoMap: new THREE.Texture( <Image> ),
31318  *  aoMapIntensity: <float>
31319  *
31320  *  emissive: <hex>,
31321  *  emissiveIntensity: <float>
31322  *  emissiveMap: new THREE.Texture( <Image> ),
31323  *
31324  *  bumpMap: new THREE.Texture( <Image> ),
31325  *  bumpScale: <float>,
31326  *
31327  *  normalMap: new THREE.Texture( <Image> ),
31328  *  normalMapType: THREE.TangentSpaceNormalMap,
31329  *  normalScale: <Vector2>,
31330  *
31331  *  displacementMap: new THREE.Texture( <Image> ),
31332  *  displacementScale: <float>,
31333  *  displacementBias: <float>,
31334  *
31335  *  specularMap: new THREE.Texture( <Image> ),
31336  *
31337  *  alphaMap: new THREE.Texture( <Image> ),
31338  *
31339  *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
31340  *  combine: THREE.MultiplyOperation,
31341  *  reflectivity: <float>,
31342  *  refractionRatio: <float>,
31343  *
31344  *  wireframe: <boolean>,
31345  *  wireframeLinewidth: <float>,
31346  *
31347  *  skinning: <bool>,
31348  *  morphTargets: <bool>,
31349  *  morphNormals: <bool>
31350  * }
31351  */
31352
31353 function MeshPhongMaterial( parameters ) {
31354
31355         Material.call( this );
31356
31357         this.type = 'MeshPhongMaterial';
31358
31359         this.color = new Color( 0xffffff ); // diffuse
31360         this.specular = new Color( 0x111111 );
31361         this.shininess = 30;
31362
31363         this.map = null;
31364
31365         this.lightMap = null;
31366         this.lightMapIntensity = 1.0;
31367
31368         this.aoMap = null;
31369         this.aoMapIntensity = 1.0;
31370
31371         this.emissive = new Color( 0x000000 );
31372         this.emissiveIntensity = 1.0;
31373         this.emissiveMap = null;
31374
31375         this.bumpMap = null;
31376         this.bumpScale = 1;
31377
31378         this.normalMap = null;
31379         this.normalMapType = TangentSpaceNormalMap;
31380         this.normalScale = new Vector2( 1, 1 );
31381
31382         this.displacementMap = null;
31383         this.displacementScale = 1;
31384         this.displacementBias = 0;
31385
31386         this.specularMap = null;
31387
31388         this.alphaMap = null;
31389
31390         this.envMap = null;
31391         this.combine = MultiplyOperation;
31392         this.reflectivity = 1;
31393         this.refractionRatio = 0.98;
31394
31395         this.wireframe = false;
31396         this.wireframeLinewidth = 1;
31397         this.wireframeLinecap = 'round';
31398         this.wireframeLinejoin = 'round';
31399
31400         this.skinning = false;
31401         this.morphTargets = false;
31402         this.morphNormals = false;
31403
31404         this.setValues( parameters );
31405
31406 }
31407
31408 MeshPhongMaterial.prototype = Object.create( Material.prototype );
31409 MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
31410
31411 MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
31412
31413 MeshPhongMaterial.prototype.copy = function ( source ) {
31414
31415         Material.prototype.copy.call( this, source );
31416
31417         this.color.copy( source.color );
31418         this.specular.copy( source.specular );
31419         this.shininess = source.shininess;
31420
31421         this.map = source.map;
31422
31423         this.lightMap = source.lightMap;
31424         this.lightMapIntensity = source.lightMapIntensity;
31425
31426         this.aoMap = source.aoMap;
31427         this.aoMapIntensity = source.aoMapIntensity;
31428
31429         this.emissive.copy( source.emissive );
31430         this.emissiveMap = source.emissiveMap;
31431         this.emissiveIntensity = source.emissiveIntensity;
31432
31433         this.bumpMap = source.bumpMap;
31434         this.bumpScale = source.bumpScale;
31435
31436         this.normalMap = source.normalMap;
31437         this.normalMapType = source.normalMapType;
31438         this.normalScale.copy( source.normalScale );
31439
31440         this.displacementMap = source.displacementMap;
31441         this.displacementScale = source.displacementScale;
31442         this.displacementBias = source.displacementBias;
31443
31444         this.specularMap = source.specularMap;
31445
31446         this.alphaMap = source.alphaMap;
31447
31448         this.envMap = source.envMap;
31449         this.combine = source.combine;
31450         this.reflectivity = source.reflectivity;
31451         this.refractionRatio = source.refractionRatio;
31452
31453         this.wireframe = source.wireframe;
31454         this.wireframeLinewidth = source.wireframeLinewidth;
31455         this.wireframeLinecap = source.wireframeLinecap;
31456         this.wireframeLinejoin = source.wireframeLinejoin;
31457
31458         this.skinning = source.skinning;
31459         this.morphTargets = source.morphTargets;
31460         this.morphNormals = source.morphNormals;
31461
31462         return this;
31463
31464 };
31465
31466 /**
31467  * parameters = {
31468  *  color: <hex>,
31469  *
31470  *  map: new THREE.Texture( <Image> ),
31471  *  gradientMap: new THREE.Texture( <Image> ),
31472  *
31473  *  lightMap: new THREE.Texture( <Image> ),
31474  *  lightMapIntensity: <float>
31475  *
31476  *  aoMap: new THREE.Texture( <Image> ),
31477  *  aoMapIntensity: <float>
31478  *
31479  *  emissive: <hex>,
31480  *  emissiveIntensity: <float>
31481  *  emissiveMap: new THREE.Texture( <Image> ),
31482  *
31483  *  bumpMap: new THREE.Texture( <Image> ),
31484  *  bumpScale: <float>,
31485  *
31486  *  normalMap: new THREE.Texture( <Image> ),
31487  *  normalMapType: THREE.TangentSpaceNormalMap,
31488  *  normalScale: <Vector2>,
31489  *
31490  *  displacementMap: new THREE.Texture( <Image> ),
31491  *  displacementScale: <float>,
31492  *  displacementBias: <float>,
31493  *
31494  *  alphaMap: new THREE.Texture( <Image> ),
31495  *
31496  *  wireframe: <boolean>,
31497  *  wireframeLinewidth: <float>,
31498  *
31499  *  skinning: <bool>,
31500  *  morphTargets: <bool>,
31501  *  morphNormals: <bool>
31502  * }
31503  */
31504
31505 function MeshToonMaterial( parameters ) {
31506
31507         Material.call( this );
31508
31509         this.defines = { 'TOON': '' };
31510
31511         this.type = 'MeshToonMaterial';
31512
31513         this.color = new Color( 0xffffff );
31514
31515         this.map = null;
31516         this.gradientMap = null;
31517
31518         this.lightMap = null;
31519         this.lightMapIntensity = 1.0;
31520
31521         this.aoMap = null;
31522         this.aoMapIntensity = 1.0;
31523
31524         this.emissive = new Color( 0x000000 );
31525         this.emissiveIntensity = 1.0;
31526         this.emissiveMap = null;
31527
31528         this.bumpMap = null;
31529         this.bumpScale = 1;
31530
31531         this.normalMap = null;
31532         this.normalMapType = TangentSpaceNormalMap;
31533         this.normalScale = new Vector2( 1, 1 );
31534
31535         this.displacementMap = null;
31536         this.displacementScale = 1;
31537         this.displacementBias = 0;
31538
31539         this.alphaMap = null;
31540
31541         this.wireframe = false;
31542         this.wireframeLinewidth = 1;
31543         this.wireframeLinecap = 'round';
31544         this.wireframeLinejoin = 'round';
31545
31546         this.skinning = false;
31547         this.morphTargets = false;
31548         this.morphNormals = false;
31549
31550         this.setValues( parameters );
31551
31552 }
31553
31554 MeshToonMaterial.prototype = Object.create( Material.prototype );
31555 MeshToonMaterial.prototype.constructor = MeshToonMaterial;
31556
31557 MeshToonMaterial.prototype.isMeshToonMaterial = true;
31558
31559 MeshToonMaterial.prototype.copy = function ( source ) {
31560
31561         Material.prototype.copy.call( this, source );
31562
31563         this.color.copy( source.color );
31564
31565         this.map = source.map;
31566         this.gradientMap = source.gradientMap;
31567
31568         this.lightMap = source.lightMap;
31569         this.lightMapIntensity = source.lightMapIntensity;
31570
31571         this.aoMap = source.aoMap;
31572         this.aoMapIntensity = source.aoMapIntensity;
31573
31574         this.emissive.copy( source.emissive );
31575         this.emissiveMap = source.emissiveMap;
31576         this.emissiveIntensity = source.emissiveIntensity;
31577
31578         this.bumpMap = source.bumpMap;
31579         this.bumpScale = source.bumpScale;
31580
31581         this.normalMap = source.normalMap;
31582         this.normalMapType = source.normalMapType;
31583         this.normalScale.copy( source.normalScale );
31584
31585         this.displacementMap = source.displacementMap;
31586         this.displacementScale = source.displacementScale;
31587         this.displacementBias = source.displacementBias;
31588
31589         this.alphaMap = source.alphaMap;
31590
31591         this.wireframe = source.wireframe;
31592         this.wireframeLinewidth = source.wireframeLinewidth;
31593         this.wireframeLinecap = source.wireframeLinecap;
31594         this.wireframeLinejoin = source.wireframeLinejoin;
31595
31596         this.skinning = source.skinning;
31597         this.morphTargets = source.morphTargets;
31598         this.morphNormals = source.morphNormals;
31599
31600         return this;
31601
31602 };
31603
31604 /**
31605  * parameters = {
31606  *  opacity: <float>,
31607  *
31608  *  bumpMap: new THREE.Texture( <Image> ),
31609  *  bumpScale: <float>,
31610  *
31611  *  normalMap: new THREE.Texture( <Image> ),
31612  *  normalMapType: THREE.TangentSpaceNormalMap,
31613  *  normalScale: <Vector2>,
31614  *
31615  *  displacementMap: new THREE.Texture( <Image> ),
31616  *  displacementScale: <float>,
31617  *  displacementBias: <float>,
31618  *
31619  *  wireframe: <boolean>,
31620  *  wireframeLinewidth: <float>
31621  *
31622  *  skinning: <bool>,
31623  *  morphTargets: <bool>,
31624  *  morphNormals: <bool>
31625  * }
31626  */
31627
31628 function MeshNormalMaterial( parameters ) {
31629
31630         Material.call( this );
31631
31632         this.type = 'MeshNormalMaterial';
31633
31634         this.bumpMap = null;
31635         this.bumpScale = 1;
31636
31637         this.normalMap = null;
31638         this.normalMapType = TangentSpaceNormalMap;
31639         this.normalScale = new Vector2( 1, 1 );
31640
31641         this.displacementMap = null;
31642         this.displacementScale = 1;
31643         this.displacementBias = 0;
31644
31645         this.wireframe = false;
31646         this.wireframeLinewidth = 1;
31647
31648         this.fog = false;
31649
31650         this.skinning = false;
31651         this.morphTargets = false;
31652         this.morphNormals = false;
31653
31654         this.setValues( parameters );
31655
31656 }
31657
31658 MeshNormalMaterial.prototype = Object.create( Material.prototype );
31659 MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
31660
31661 MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
31662
31663 MeshNormalMaterial.prototype.copy = function ( source ) {
31664
31665         Material.prototype.copy.call( this, source );
31666
31667         this.bumpMap = source.bumpMap;
31668         this.bumpScale = source.bumpScale;
31669
31670         this.normalMap = source.normalMap;
31671         this.normalMapType = source.normalMapType;
31672         this.normalScale.copy( source.normalScale );
31673
31674         this.displacementMap = source.displacementMap;
31675         this.displacementScale = source.displacementScale;
31676         this.displacementBias = source.displacementBias;
31677
31678         this.wireframe = source.wireframe;
31679         this.wireframeLinewidth = source.wireframeLinewidth;
31680
31681         this.skinning = source.skinning;
31682         this.morphTargets = source.morphTargets;
31683         this.morphNormals = source.morphNormals;
31684
31685         return this;
31686
31687 };
31688
31689 /**
31690  * parameters = {
31691  *  color: <hex>,
31692  *  opacity: <float>,
31693  *
31694  *  map: new THREE.Texture( <Image> ),
31695  *
31696  *  lightMap: new THREE.Texture( <Image> ),
31697  *  lightMapIntensity: <float>
31698  *
31699  *  aoMap: new THREE.Texture( <Image> ),
31700  *  aoMapIntensity: <float>
31701  *
31702  *  emissive: <hex>,
31703  *  emissiveIntensity: <float>
31704  *  emissiveMap: new THREE.Texture( <Image> ),
31705  *
31706  *  specularMap: new THREE.Texture( <Image> ),
31707  *
31708  *  alphaMap: new THREE.Texture( <Image> ),
31709  *
31710  *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
31711  *  combine: THREE.Multiply,
31712  *  reflectivity: <float>,
31713  *  refractionRatio: <float>,
31714  *
31715  *  wireframe: <boolean>,
31716  *  wireframeLinewidth: <float>,
31717  *
31718  *  skinning: <bool>,
31719  *  morphTargets: <bool>,
31720  *  morphNormals: <bool>
31721  * }
31722  */
31723
31724 function MeshLambertMaterial( parameters ) {
31725
31726         Material.call( this );
31727
31728         this.type = 'MeshLambertMaterial';
31729
31730         this.color = new Color( 0xffffff ); // diffuse
31731
31732         this.map = null;
31733
31734         this.lightMap = null;
31735         this.lightMapIntensity = 1.0;
31736
31737         this.aoMap = null;
31738         this.aoMapIntensity = 1.0;
31739
31740         this.emissive = new Color( 0x000000 );
31741         this.emissiveIntensity = 1.0;
31742         this.emissiveMap = null;
31743
31744         this.specularMap = null;
31745
31746         this.alphaMap = null;
31747
31748         this.envMap = null;
31749         this.combine = MultiplyOperation;
31750         this.reflectivity = 1;
31751         this.refractionRatio = 0.98;
31752
31753         this.wireframe = false;
31754         this.wireframeLinewidth = 1;
31755         this.wireframeLinecap = 'round';
31756         this.wireframeLinejoin = 'round';
31757
31758         this.skinning = false;
31759         this.morphTargets = false;
31760         this.morphNormals = false;
31761
31762         this.setValues( parameters );
31763
31764 }
31765
31766 MeshLambertMaterial.prototype = Object.create( Material.prototype );
31767 MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
31768
31769 MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
31770
31771 MeshLambertMaterial.prototype.copy = function ( source ) {
31772
31773         Material.prototype.copy.call( this, source );
31774
31775         this.color.copy( source.color );
31776
31777         this.map = source.map;
31778
31779         this.lightMap = source.lightMap;
31780         this.lightMapIntensity = source.lightMapIntensity;
31781
31782         this.aoMap = source.aoMap;
31783         this.aoMapIntensity = source.aoMapIntensity;
31784
31785         this.emissive.copy( source.emissive );
31786         this.emissiveMap = source.emissiveMap;
31787         this.emissiveIntensity = source.emissiveIntensity;
31788
31789         this.specularMap = source.specularMap;
31790
31791         this.alphaMap = source.alphaMap;
31792
31793         this.envMap = source.envMap;
31794         this.combine = source.combine;
31795         this.reflectivity = source.reflectivity;
31796         this.refractionRatio = source.refractionRatio;
31797
31798         this.wireframe = source.wireframe;
31799         this.wireframeLinewidth = source.wireframeLinewidth;
31800         this.wireframeLinecap = source.wireframeLinecap;
31801         this.wireframeLinejoin = source.wireframeLinejoin;
31802
31803         this.skinning = source.skinning;
31804         this.morphTargets = source.morphTargets;
31805         this.morphNormals = source.morphNormals;
31806
31807         return this;
31808
31809 };
31810
31811 /**
31812  * parameters = {
31813  *  color: <hex>,
31814  *  opacity: <float>,
31815  *
31816  *  matcap: new THREE.Texture( <Image> ),
31817  *
31818  *  map: new THREE.Texture( <Image> ),
31819  *
31820  *  bumpMap: new THREE.Texture( <Image> ),
31821  *  bumpScale: <float>,
31822  *
31823  *  normalMap: new THREE.Texture( <Image> ),
31824  *  normalMapType: THREE.TangentSpaceNormalMap,
31825  *  normalScale: <Vector2>,
31826  *
31827  *  displacementMap: new THREE.Texture( <Image> ),
31828  *  displacementScale: <float>,
31829  *  displacementBias: <float>,
31830  *
31831  *  alphaMap: new THREE.Texture( <Image> ),
31832  *
31833  *  skinning: <bool>,
31834  *  morphTargets: <bool>,
31835  *  morphNormals: <bool>
31836  * }
31837  */
31838
31839 function MeshMatcapMaterial( parameters ) {
31840
31841         Material.call( this );
31842
31843         this.defines = { 'MATCAP': '' };
31844
31845         this.type = 'MeshMatcapMaterial';
31846
31847         this.color = new Color( 0xffffff ); // diffuse
31848
31849         this.matcap = null;
31850
31851         this.map = null;
31852
31853         this.bumpMap = null;
31854         this.bumpScale = 1;
31855
31856         this.normalMap = null;
31857         this.normalMapType = TangentSpaceNormalMap;
31858         this.normalScale = new Vector2( 1, 1 );
31859
31860         this.displacementMap = null;
31861         this.displacementScale = 1;
31862         this.displacementBias = 0;
31863
31864         this.alphaMap = null;
31865
31866         this.skinning = false;
31867         this.morphTargets = false;
31868         this.morphNormals = false;
31869
31870         this.setValues( parameters );
31871
31872 }
31873
31874 MeshMatcapMaterial.prototype = Object.create( Material.prototype );
31875 MeshMatcapMaterial.prototype.constructor = MeshMatcapMaterial;
31876
31877 MeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;
31878
31879 MeshMatcapMaterial.prototype.copy = function ( source ) {
31880
31881         Material.prototype.copy.call( this, source );
31882
31883         this.defines = { 'MATCAP': '' };
31884
31885         this.color.copy( source.color );
31886
31887         this.matcap = source.matcap;
31888
31889         this.map = source.map;
31890
31891         this.bumpMap = source.bumpMap;
31892         this.bumpScale = source.bumpScale;
31893
31894         this.normalMap = source.normalMap;
31895         this.normalMapType = source.normalMapType;
31896         this.normalScale.copy( source.normalScale );
31897
31898         this.displacementMap = source.displacementMap;
31899         this.displacementScale = source.displacementScale;
31900         this.displacementBias = source.displacementBias;
31901
31902         this.alphaMap = source.alphaMap;
31903
31904         this.skinning = source.skinning;
31905         this.morphTargets = source.morphTargets;
31906         this.morphNormals = source.morphNormals;
31907
31908         return this;
31909
31910 };
31911
31912 /**
31913  * parameters = {
31914  *  color: <hex>,
31915  *  opacity: <float>,
31916  *
31917  *  linewidth: <float>,
31918  *
31919  *  scale: <float>,
31920  *  dashSize: <float>,
31921  *  gapSize: <float>
31922  * }
31923  */
31924
31925 function LineDashedMaterial( parameters ) {
31926
31927         LineBasicMaterial.call( this );
31928
31929         this.type = 'LineDashedMaterial';
31930
31931         this.scale = 1;
31932         this.dashSize = 3;
31933         this.gapSize = 1;
31934
31935         this.setValues( parameters );
31936
31937 }
31938
31939 LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
31940 LineDashedMaterial.prototype.constructor = LineDashedMaterial;
31941
31942 LineDashedMaterial.prototype.isLineDashedMaterial = true;
31943
31944 LineDashedMaterial.prototype.copy = function ( source ) {
31945
31946         LineBasicMaterial.prototype.copy.call( this, source );
31947
31948         this.scale = source.scale;
31949         this.dashSize = source.dashSize;
31950         this.gapSize = source.gapSize;
31951
31952         return this;
31953
31954 };
31955
31956 var Materials = /*#__PURE__*/Object.freeze({
31957         __proto__: null,
31958         ShadowMaterial: ShadowMaterial,
31959         SpriteMaterial: SpriteMaterial,
31960         RawShaderMaterial: RawShaderMaterial,
31961         ShaderMaterial: ShaderMaterial,
31962         PointsMaterial: PointsMaterial,
31963         MeshPhysicalMaterial: MeshPhysicalMaterial,
31964         MeshStandardMaterial: MeshStandardMaterial,
31965         MeshPhongMaterial: MeshPhongMaterial,
31966         MeshToonMaterial: MeshToonMaterial,
31967         MeshNormalMaterial: MeshNormalMaterial,
31968         MeshLambertMaterial: MeshLambertMaterial,
31969         MeshDepthMaterial: MeshDepthMaterial,
31970         MeshDistanceMaterial: MeshDistanceMaterial,
31971         MeshBasicMaterial: MeshBasicMaterial,
31972         MeshMatcapMaterial: MeshMatcapMaterial,
31973         LineDashedMaterial: LineDashedMaterial,
31974         LineBasicMaterial: LineBasicMaterial,
31975         Material: Material
31976 });
31977
31978 const AnimationUtils = {
31979
31980         // same as Array.prototype.slice, but also works on typed arrays
31981         arraySlice: function ( array, from, to ) {
31982
31983                 if ( AnimationUtils.isTypedArray( array ) ) {
31984
31985                         // in ios9 array.subarray(from, undefined) will return empty array
31986                         // but array.subarray(from) or array.subarray(from, len) is correct
31987                         return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
31988
31989                 }
31990
31991                 return array.slice( from, to );
31992
31993         },
31994
31995         // converts an array to a specific type
31996         convertArray: function ( array, type, forceClone ) {
31997
31998                 if ( ! array || // let 'undefined' and 'null' pass
31999                         ! forceClone && array.constructor === type ) return array;
32000
32001                 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
32002
32003                         return new type( array ); // create typed array
32004
32005                 }
32006
32007                 return Array.prototype.slice.call( array ); // create Array
32008
32009         },
32010
32011         isTypedArray: function ( object ) {
32012
32013                 return ArrayBuffer.isView( object ) &&
32014                         ! ( object instanceof DataView );
32015
32016         },
32017
32018         // returns an array by which times and values can be sorted
32019         getKeyframeOrder: function ( times ) {
32020
32021                 function compareTime( i, j ) {
32022
32023                         return times[ i ] - times[ j ];
32024
32025                 }
32026
32027                 const n = times.length;
32028                 const result = new Array( n );
32029                 for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
32030
32031                 result.sort( compareTime );
32032
32033                 return result;
32034
32035         },
32036
32037         // uses the array previously returned by 'getKeyframeOrder' to sort data
32038         sortedArray: function ( values, stride, order ) {
32039
32040                 const nValues = values.length;
32041                 const result = new values.constructor( nValues );
32042
32043                 for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
32044
32045                         const srcOffset = order[ i ] * stride;
32046
32047                         for ( let j = 0; j !== stride; ++ j ) {
32048
32049                                 result[ dstOffset ++ ] = values[ srcOffset + j ];
32050
32051                         }
32052
32053                 }
32054
32055                 return result;
32056
32057         },
32058
32059         // function for parsing AOS keyframe formats
32060         flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
32061
32062                 let i = 1, key = jsonKeys[ 0 ];
32063
32064                 while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
32065
32066                         key = jsonKeys[ i ++ ];
32067
32068                 }
32069
32070                 if ( key === undefined ) return; // no data
32071
32072                 let value = key[ valuePropertyName ];
32073                 if ( value === undefined ) return; // no data
32074
32075                 if ( Array.isArray( value ) ) {
32076
32077                         do {
32078
32079                                 value = key[ valuePropertyName ];
32080
32081                                 if ( value !== undefined ) {
32082
32083                                         times.push( key.time );
32084                                         values.push.apply( values, value ); // push all elements
32085
32086                                 }
32087
32088                                 key = jsonKeys[ i ++ ];
32089
32090                         } while ( key !== undefined );
32091
32092                 } else if ( value.toArray !== undefined ) {
32093
32094                         // ...assume THREE.Math-ish
32095
32096                         do {
32097
32098                                 value = key[ valuePropertyName ];
32099
32100                                 if ( value !== undefined ) {
32101
32102                                         times.push( key.time );
32103                                         value.toArray( values, values.length );
32104
32105                                 }
32106
32107                                 key = jsonKeys[ i ++ ];
32108
32109                         } while ( key !== undefined );
32110
32111                 } else {
32112
32113                         // otherwise push as-is
32114
32115                         do {
32116
32117                                 value = key[ valuePropertyName ];
32118
32119                                 if ( value !== undefined ) {
32120
32121                                         times.push( key.time );
32122                                         values.push( value );
32123
32124                                 }
32125
32126                                 key = jsonKeys[ i ++ ];
32127
32128                         } while ( key !== undefined );
32129
32130                 }
32131
32132         },
32133
32134         subclip: function ( sourceClip, name, startFrame, endFrame, fps = 30 ) {
32135
32136                 const clip = sourceClip.clone();
32137
32138                 clip.name = name;
32139
32140                 const tracks = [];
32141
32142                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
32143
32144                         const track = clip.tracks[ i ];
32145                         const valueSize = track.getValueSize();
32146
32147                         const times = [];
32148                         const values = [];
32149
32150                         for ( let j = 0; j < track.times.length; ++ j ) {
32151
32152                                 const frame = track.times[ j ] * fps;
32153
32154                                 if ( frame < startFrame || frame >= endFrame ) continue;
32155
32156                                 times.push( track.times[ j ] );
32157
32158                                 for ( let k = 0; k < valueSize; ++ k ) {
32159
32160                                         values.push( track.values[ j * valueSize + k ] );
32161
32162                                 }
32163
32164                         }
32165
32166                         if ( times.length === 0 ) continue;
32167
32168                         track.times = AnimationUtils.convertArray( times, track.times.constructor );
32169                         track.values = AnimationUtils.convertArray( values, track.values.constructor );
32170
32171                         tracks.push( track );
32172
32173                 }
32174
32175                 clip.tracks = tracks;
32176
32177                 // find minimum .times value across all tracks in the trimmed clip
32178
32179                 let minStartTime = Infinity;
32180
32181                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
32182
32183                         if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
32184
32185                                 minStartTime = clip.tracks[ i ].times[ 0 ];
32186
32187                         }
32188
32189                 }
32190
32191                 // shift all tracks such that clip begins at t=0
32192
32193                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
32194
32195                         clip.tracks[ i ].shift( - 1 * minStartTime );
32196
32197                 }
32198
32199                 clip.resetDuration();
32200
32201                 return clip;
32202
32203         },
32204
32205         makeClipAdditive: function ( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
32206
32207                 if ( fps <= 0 ) fps = 30;
32208
32209                 const numTracks = referenceClip.tracks.length;
32210                 const referenceTime = referenceFrame / fps;
32211
32212                 // Make each track's values relative to the values at the reference frame
32213                 for ( let i = 0; i < numTracks; ++ i ) {
32214
32215                         const referenceTrack = referenceClip.tracks[ i ];
32216                         const referenceTrackType = referenceTrack.ValueTypeName;
32217
32218                         // Skip this track if it's non-numeric
32219                         if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
32220
32221                         // Find the track in the target clip whose name and type matches the reference track
32222                         const targetTrack = targetClip.tracks.find( function ( track ) {
32223
32224                                 return track.name === referenceTrack.name
32225                                         && track.ValueTypeName === referenceTrackType;
32226
32227                         } );
32228
32229                         if ( targetTrack === undefined ) continue;
32230
32231                         let referenceOffset = 0;
32232                         const referenceValueSize = referenceTrack.getValueSize();
32233
32234                         if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
32235
32236                                 referenceOffset = referenceValueSize / 3;
32237
32238                         }
32239
32240                         let targetOffset = 0;
32241                         const targetValueSize = targetTrack.getValueSize();
32242
32243                         if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
32244
32245                                 targetOffset = targetValueSize / 3;
32246
32247                         }
32248
32249                         const lastIndex = referenceTrack.times.length - 1;
32250                         let referenceValue;
32251
32252                         // Find the value to subtract out of the track
32253                         if ( referenceTime <= referenceTrack.times[ 0 ] ) {
32254
32255                                 // Reference frame is earlier than the first keyframe, so just use the first keyframe
32256                                 const startIndex = referenceOffset;
32257                                 const endIndex = referenceValueSize - referenceOffset;
32258                                 referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
32259
32260                         } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
32261
32262                                 // Reference frame is after the last keyframe, so just use the last keyframe
32263                                 const startIndex = lastIndex * referenceValueSize + referenceOffset;
32264                                 const endIndex = startIndex + referenceValueSize - referenceOffset;
32265                                 referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
32266
32267                         } else {
32268
32269                                 // Interpolate to the reference value
32270                                 const interpolant = referenceTrack.createInterpolant();
32271                                 const startIndex = referenceOffset;
32272                                 const endIndex = referenceValueSize - referenceOffset;
32273                                 interpolant.evaluate( referenceTime );
32274                                 referenceValue = AnimationUtils.arraySlice( interpolant.resultBuffer, startIndex, endIndex );
32275
32276                         }
32277
32278                         // Conjugate the quaternion
32279                         if ( referenceTrackType === 'quaternion' ) {
32280
32281                                 const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
32282                                 referenceQuat.toArray( referenceValue );
32283
32284                         }
32285
32286                         // Subtract the reference value from all of the track values
32287
32288                         const numTimes = targetTrack.times.length;
32289                         for ( let j = 0; j < numTimes; ++ j ) {
32290
32291                                 const valueStart = j * targetValueSize + targetOffset;
32292
32293                                 if ( referenceTrackType === 'quaternion' ) {
32294
32295                                         // Multiply the conjugate for quaternion track types
32296                                         Quaternion.multiplyQuaternionsFlat(
32297                                                 targetTrack.values,
32298                                                 valueStart,
32299                                                 referenceValue,
32300                                                 0,
32301                                                 targetTrack.values,
32302                                                 valueStart
32303                                         );
32304
32305                                 } else {
32306
32307                                         const valueEnd = targetValueSize - targetOffset * 2;
32308
32309                                         // Subtract each value for all other numeric track types
32310                                         for ( let k = 0; k < valueEnd; ++ k ) {
32311
32312                                                 targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
32313
32314                                         }
32315
32316                                 }
32317
32318                         }
32319
32320                 }
32321
32322                 targetClip.blendMode = AdditiveAnimationBlendMode;
32323
32324                 return targetClip;
32325
32326         }
32327
32328 };
32329
32330 /**
32331  * Abstract base class of interpolants over parametric samples.
32332  *
32333  * The parameter domain is one dimensional, typically the time or a path
32334  * along a curve defined by the data.
32335  *
32336  * The sample values can have any dimensionality and derived classes may
32337  * apply special interpretations to the data.
32338  *
32339  * This class provides the interval seek in a Template Method, deferring
32340  * the actual interpolation to derived classes.
32341  *
32342  * Time complexity is O(1) for linear access crossing at most two points
32343  * and O(log N) for random access, where N is the number of positions.
32344  *
32345  * References:
32346  *
32347  *              http://www.oodesign.com/template-method-pattern.html
32348  *
32349  */
32350
32351 function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
32352
32353         this.parameterPositions = parameterPositions;
32354         this._cachedIndex = 0;
32355
32356         this.resultBuffer = resultBuffer !== undefined ?
32357                 resultBuffer : new sampleValues.constructor( sampleSize );
32358         this.sampleValues = sampleValues;
32359         this.valueSize = sampleSize;
32360
32361 }
32362
32363 Object.assign( Interpolant.prototype, {
32364
32365         evaluate: function ( t ) {
32366
32367                 const pp = this.parameterPositions;
32368                 let i1 = this._cachedIndex,
32369                         t1 = pp[ i1 ],
32370                         t0 = pp[ i1 - 1 ];
32371
32372                 validate_interval: {
32373
32374                         seek: {
32375
32376                                 let right;
32377
32378                                 linear_scan: {
32379
32380                                         //- See http://jsperf.com/comparison-to-undefined/3
32381                                         //- slower code:
32382                                         //-
32383                                         //-                             if ( t >= t1 || t1 === undefined ) {
32384                                         forward_scan: if ( ! ( t < t1 ) ) {
32385
32386                                                 for ( let giveUpAt = i1 + 2; ; ) {
32387
32388                                                         if ( t1 === undefined ) {
32389
32390                                                                 if ( t < t0 ) break forward_scan;
32391
32392                                                                 // after end
32393
32394                                                                 i1 = pp.length;
32395                                                                 this._cachedIndex = i1;
32396                                                                 return this.afterEnd_( i1 - 1, t, t0 );
32397
32398                                                         }
32399
32400                                                         if ( i1 === giveUpAt ) break; // this loop
32401
32402                                                         t0 = t1;
32403                                                         t1 = pp[ ++ i1 ];
32404
32405                                                         if ( t < t1 ) {
32406
32407                                                                 // we have arrived at the sought interval
32408                                                                 break seek;
32409
32410                                                         }
32411
32412                                                 }
32413
32414                                                 // prepare binary search on the right side of the index
32415                                                 right = pp.length;
32416                                                 break linear_scan;
32417
32418                                         }
32419
32420                                         //- slower code:
32421                                         //-                                     if ( t < t0 || t0 === undefined ) {
32422                                         if ( ! ( t >= t0 ) ) {
32423
32424                                                 // looping?
32425
32426                                                 const t1global = pp[ 1 ];
32427
32428                                                 if ( t < t1global ) {
32429
32430                                                         i1 = 2; // + 1, using the scan for the details
32431                                                         t0 = t1global;
32432
32433                                                 }
32434
32435                                                 // linear reverse scan
32436
32437                                                 for ( let giveUpAt = i1 - 2; ; ) {
32438
32439                                                         if ( t0 === undefined ) {
32440
32441                                                                 // before start
32442
32443                                                                 this._cachedIndex = 0;
32444                                                                 return this.beforeStart_( 0, t, t1 );
32445
32446                                                         }
32447
32448                                                         if ( i1 === giveUpAt ) break; // this loop
32449
32450                                                         t1 = t0;
32451                                                         t0 = pp[ -- i1 - 1 ];
32452
32453                                                         if ( t >= t0 ) {
32454
32455                                                                 // we have arrived at the sought interval
32456                                                                 break seek;
32457
32458                                                         }
32459
32460                                                 }
32461
32462                                                 // prepare binary search on the left side of the index
32463                                                 right = i1;
32464                                                 i1 = 0;
32465                                                 break linear_scan;
32466
32467                                         }
32468
32469                                         // the interval is valid
32470
32471                                         break validate_interval;
32472
32473                                 } // linear scan
32474
32475                                 // binary search
32476
32477                                 while ( i1 < right ) {
32478
32479                                         const mid = ( i1 + right ) >>> 1;
32480
32481                                         if ( t < pp[ mid ] ) {
32482
32483                                                 right = mid;
32484
32485                                         } else {
32486
32487                                                 i1 = mid + 1;
32488
32489                                         }
32490
32491                                 }
32492
32493                                 t1 = pp[ i1 ];
32494                                 t0 = pp[ i1 - 1 ];
32495
32496                                 // check boundary cases, again
32497
32498                                 if ( t0 === undefined ) {
32499
32500                                         this._cachedIndex = 0;
32501                                         return this.beforeStart_( 0, t, t1 );
32502
32503                                 }
32504
32505                                 if ( t1 === undefined ) {
32506
32507                                         i1 = pp.length;
32508                                         this._cachedIndex = i1;
32509                                         return this.afterEnd_( i1 - 1, t0, t );
32510
32511                                 }
32512
32513                         } // seek
32514
32515                         this._cachedIndex = i1;
32516
32517                         this.intervalChanged_( i1, t0, t1 );
32518
32519                 } // validate_interval
32520
32521                 return this.interpolate_( i1, t0, t, t1 );
32522
32523         },
32524
32525         settings: null, // optional, subclass-specific settings structure
32526         // Note: The indirection allows central control of many interpolants.
32527
32528         // --- Protected interface
32529
32530         DefaultSettings_: {},
32531
32532         getSettings_: function () {
32533
32534                 return this.settings || this.DefaultSettings_;
32535
32536         },
32537
32538         copySampleValue_: function ( index ) {
32539
32540                 // copies a sample value to the result buffer
32541
32542                 const result = this.resultBuffer,
32543                         values = this.sampleValues,
32544                         stride = this.valueSize,
32545                         offset = index * stride;
32546
32547                 for ( let i = 0; i !== stride; ++ i ) {
32548
32549                         result[ i ] = values[ offset + i ];
32550
32551                 }
32552
32553                 return result;
32554
32555         },
32556
32557         // Template methods for derived classes:
32558
32559         interpolate_: function ( /* i1, t0, t, t1 */ ) {
32560
32561                 throw new Error( 'call to abstract method' );
32562                 // implementations shall return this.resultBuffer
32563
32564         },
32565
32566         intervalChanged_: function ( /* i1, t0, t1 */ ) {
32567
32568                 // empty
32569
32570         }
32571
32572 } );
32573
32574 // DECLARE ALIAS AFTER assign prototype
32575 Object.assign( Interpolant.prototype, {
32576
32577         //( 0, t, t0 ), returns this.resultBuffer
32578         beforeStart_: Interpolant.prototype.copySampleValue_,
32579
32580         //( N-1, tN-1, t ), returns this.resultBuffer
32581         afterEnd_: Interpolant.prototype.copySampleValue_,
32582
32583 } );
32584
32585 /**
32586  * Fast and simple cubic spline interpolant.
32587  *
32588  * It was derived from a Hermitian construction setting the first derivative
32589  * at each sample position to the linear slope between neighboring positions
32590  * over their parameter interval.
32591  */
32592
32593 function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
32594
32595         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
32596
32597         this._weightPrev = - 0;
32598         this._offsetPrev = - 0;
32599         this._weightNext = - 0;
32600         this._offsetNext = - 0;
32601
32602 }
32603
32604 CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
32605
32606         constructor: CubicInterpolant,
32607
32608         DefaultSettings_: {
32609
32610                 endingStart: ZeroCurvatureEnding,
32611                 endingEnd: ZeroCurvatureEnding
32612
32613         },
32614
32615         intervalChanged_: function ( i1, t0, t1 ) {
32616
32617                 const pp = this.parameterPositions;
32618                 let iPrev = i1 - 2,
32619                         iNext = i1 + 1,
32620
32621                         tPrev = pp[ iPrev ],
32622                         tNext = pp[ iNext ];
32623
32624                 if ( tPrev === undefined ) {
32625
32626                         switch ( this.getSettings_().endingStart ) {
32627
32628                                 case ZeroSlopeEnding:
32629
32630                                         // f'(t0) = 0
32631                                         iPrev = i1;
32632                                         tPrev = 2 * t0 - t1;
32633
32634                                         break;
32635
32636                                 case WrapAroundEnding:
32637
32638                                         // use the other end of the curve
32639                                         iPrev = pp.length - 2;
32640                                         tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
32641
32642                                         break;
32643
32644                                 default: // ZeroCurvatureEnding
32645
32646                                         // f''(t0) = 0 a.k.a. Natural Spline
32647                                         iPrev = i1;
32648                                         tPrev = t1;
32649
32650                         }
32651
32652                 }
32653
32654                 if ( tNext === undefined ) {
32655
32656                         switch ( this.getSettings_().endingEnd ) {
32657
32658                                 case ZeroSlopeEnding:
32659
32660                                         // f'(tN) = 0
32661                                         iNext = i1;
32662                                         tNext = 2 * t1 - t0;
32663
32664                                         break;
32665
32666                                 case WrapAroundEnding:
32667
32668                                         // use the other end of the curve
32669                                         iNext = 1;
32670                                         tNext = t1 + pp[ 1 ] - pp[ 0 ];
32671
32672                                         break;
32673
32674                                 default: // ZeroCurvatureEnding
32675
32676                                         // f''(tN) = 0, a.k.a. Natural Spline
32677                                         iNext = i1 - 1;
32678                                         tNext = t0;
32679
32680                         }
32681
32682                 }
32683
32684                 const halfDt = ( t1 - t0 ) * 0.5,
32685                         stride = this.valueSize;
32686
32687                 this._weightPrev = halfDt / ( t0 - tPrev );
32688                 this._weightNext = halfDt / ( tNext - t1 );
32689                 this._offsetPrev = iPrev * stride;
32690                 this._offsetNext = iNext * stride;
32691
32692         },
32693
32694         interpolate_: function ( i1, t0, t, t1 ) {
32695
32696                 const result = this.resultBuffer,
32697                         values = this.sampleValues,
32698                         stride = this.valueSize,
32699
32700                         o1 = i1 * stride,               o0 = o1 - stride,
32701                         oP = this._offsetPrev,  oN = this._offsetNext,
32702                         wP = this._weightPrev,  wN = this._weightNext,
32703
32704                         p = ( t - t0 ) / ( t1 - t0 ),
32705                         pp = p * p,
32706                         ppp = pp * p;
32707
32708                 // evaluate polynomials
32709
32710                 const sP = - wP * ppp + 2 * wP * pp - wP * p;
32711                 const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
32712                 const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
32713                 const sN = wN * ppp - wN * pp;
32714
32715                 // combine data linearly
32716
32717                 for ( let i = 0; i !== stride; ++ i ) {
32718
32719                         result[ i ] =
32720                                         sP * values[ oP + i ] +
32721                                         s0 * values[ o0 + i ] +
32722                                         s1 * values[ o1 + i ] +
32723                                         sN * values[ oN + i ];
32724
32725                 }
32726
32727                 return result;
32728
32729         }
32730
32731 } );
32732
32733 function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
32734
32735         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
32736
32737 }
32738
32739 LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
32740
32741         constructor: LinearInterpolant,
32742
32743         interpolate_: function ( i1, t0, t, t1 ) {
32744
32745                 const result = this.resultBuffer,
32746                         values = this.sampleValues,
32747                         stride = this.valueSize,
32748
32749                         offset1 = i1 * stride,
32750                         offset0 = offset1 - stride,
32751
32752                         weight1 = ( t - t0 ) / ( t1 - t0 ),
32753                         weight0 = 1 - weight1;
32754
32755                 for ( let i = 0; i !== stride; ++ i ) {
32756
32757                         result[ i ] =
32758                                         values[ offset0 + i ] * weight0 +
32759                                         values[ offset1 + i ] * weight1;
32760
32761                 }
32762
32763                 return result;
32764
32765         }
32766
32767 } );
32768
32769 /**
32770  *
32771  * Interpolant that evaluates to the sample value at the position preceeding
32772  * the parameter.
32773  */
32774
32775 function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
32776
32777         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
32778
32779 }
32780
32781 DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
32782
32783         constructor: DiscreteInterpolant,
32784
32785         interpolate_: function ( i1 /*, t0, t, t1 */ ) {
32786
32787                 return this.copySampleValue_( i1 - 1 );
32788
32789         }
32790
32791 } );
32792
32793 function KeyframeTrack( name, times, values, interpolation ) {
32794
32795         if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
32796         if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
32797
32798         this.name = name;
32799
32800         this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
32801         this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
32802
32803         this.setInterpolation( interpolation || this.DefaultInterpolation );
32804
32805 }
32806
32807 // Static methods
32808
32809 Object.assign( KeyframeTrack, {
32810
32811         // Serialization (in static context, because of constructor invocation
32812         // and automatic invocation of .toJSON):
32813
32814         toJSON: function ( track ) {
32815
32816                 const trackType = track.constructor;
32817
32818                 let json;
32819
32820                 // derived classes can define a static toJSON method
32821                 if ( trackType.toJSON !== undefined ) {
32822
32823                         json = trackType.toJSON( track );
32824
32825                 } else {
32826
32827                         // by default, we assume the data can be serialized as-is
32828                         json = {
32829
32830                                 'name': track.name,
32831                                 'times': AnimationUtils.convertArray( track.times, Array ),
32832                                 'values': AnimationUtils.convertArray( track.values, Array )
32833
32834                         };
32835
32836                         const interpolation = track.getInterpolation();
32837
32838                         if ( interpolation !== track.DefaultInterpolation ) {
32839
32840                                 json.interpolation = interpolation;
32841
32842                         }
32843
32844                 }
32845
32846                 json.type = track.ValueTypeName; // mandatory
32847
32848                 return json;
32849
32850         }
32851
32852 } );
32853
32854 Object.assign( KeyframeTrack.prototype, {
32855
32856         constructor: KeyframeTrack,
32857
32858         TimeBufferType: Float32Array,
32859
32860         ValueBufferType: Float32Array,
32861
32862         DefaultInterpolation: InterpolateLinear,
32863
32864         InterpolantFactoryMethodDiscrete: function ( result ) {
32865
32866                 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
32867
32868         },
32869
32870         InterpolantFactoryMethodLinear: function ( result ) {
32871
32872                 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
32873
32874         },
32875
32876         InterpolantFactoryMethodSmooth: function ( result ) {
32877
32878                 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
32879
32880         },
32881
32882         setInterpolation: function ( interpolation ) {
32883
32884                 let factoryMethod;
32885
32886                 switch ( interpolation ) {
32887
32888                         case InterpolateDiscrete:
32889
32890                                 factoryMethod = this.InterpolantFactoryMethodDiscrete;
32891
32892                                 break;
32893
32894                         case InterpolateLinear:
32895
32896                                 factoryMethod = this.InterpolantFactoryMethodLinear;
32897
32898                                 break;
32899
32900                         case InterpolateSmooth:
32901
32902                                 factoryMethod = this.InterpolantFactoryMethodSmooth;
32903
32904                                 break;
32905
32906                 }
32907
32908                 if ( factoryMethod === undefined ) {
32909
32910                         const message = 'unsupported interpolation for ' +
32911                                 this.ValueTypeName + ' keyframe track named ' + this.name;
32912
32913                         if ( this.createInterpolant === undefined ) {
32914
32915                                 // fall back to default, unless the default itself is messed up
32916                                 if ( interpolation !== this.DefaultInterpolation ) {
32917
32918                                         this.setInterpolation( this.DefaultInterpolation );
32919
32920                                 } else {
32921
32922                                         throw new Error( message ); // fatal, in this case
32923
32924                                 }
32925
32926                         }
32927
32928                         console.warn( 'THREE.KeyframeTrack:', message );
32929                         return this;
32930
32931                 }
32932
32933                 this.createInterpolant = factoryMethod;
32934
32935                 return this;
32936
32937         },
32938
32939         getInterpolation: function () {
32940
32941                 switch ( this.createInterpolant ) {
32942
32943                         case this.InterpolantFactoryMethodDiscrete:
32944
32945                                 return InterpolateDiscrete;
32946
32947                         case this.InterpolantFactoryMethodLinear:
32948
32949                                 return InterpolateLinear;
32950
32951                         case this.InterpolantFactoryMethodSmooth:
32952
32953                                 return InterpolateSmooth;
32954
32955                 }
32956
32957         },
32958
32959         getValueSize: function () {
32960
32961                 return this.values.length / this.times.length;
32962
32963         },
32964
32965         // move all keyframes either forwards or backwards in time
32966         shift: function ( timeOffset ) {
32967
32968                 if ( timeOffset !== 0.0 ) {
32969
32970                         const times = this.times;
32971
32972                         for ( let i = 0, n = times.length; i !== n; ++ i ) {
32973
32974                                 times[ i ] += timeOffset;
32975
32976                         }
32977
32978                 }
32979
32980                 return this;
32981
32982         },
32983
32984         // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
32985         scale: function ( timeScale ) {
32986
32987                 if ( timeScale !== 1.0 ) {
32988
32989                         const times = this.times;
32990
32991                         for ( let i = 0, n = times.length; i !== n; ++ i ) {
32992
32993                                 times[ i ] *= timeScale;
32994
32995                         }
32996
32997                 }
32998
32999                 return this;
33000
33001         },
33002
33003         // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
33004         // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
33005         trim: function ( startTime, endTime ) {
33006
33007                 const times = this.times,
33008                         nKeys = times.length;
33009
33010                 let from = 0,
33011                         to = nKeys - 1;
33012
33013                 while ( from !== nKeys && times[ from ] < startTime ) {
33014
33015                         ++ from;
33016
33017                 }
33018
33019                 while ( to !== - 1 && times[ to ] > endTime ) {
33020
33021                         -- to;
33022
33023                 }
33024
33025                 ++ to; // inclusive -> exclusive bound
33026
33027                 if ( from !== 0 || to !== nKeys ) {
33028
33029                         // empty tracks are forbidden, so keep at least one keyframe
33030                         if ( from >= to ) {
33031
33032                                 to = Math.max( to, 1 );
33033                                 from = to - 1;
33034
33035                         }
33036
33037                         const stride = this.getValueSize();
33038                         this.times = AnimationUtils.arraySlice( times, from, to );
33039                         this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
33040
33041                 }
33042
33043                 return this;
33044
33045         },
33046
33047         // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
33048         validate: function () {
33049
33050                 let valid = true;
33051
33052                 const valueSize = this.getValueSize();
33053                 if ( valueSize - Math.floor( valueSize ) !== 0 ) {
33054
33055                         console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
33056                         valid = false;
33057
33058                 }
33059
33060                 const times = this.times,
33061                         values = this.values,
33062
33063                         nKeys = times.length;
33064
33065                 if ( nKeys === 0 ) {
33066
33067                         console.error( 'THREE.KeyframeTrack: Track is empty.', this );
33068                         valid = false;
33069
33070                 }
33071
33072                 let prevTime = null;
33073
33074                 for ( let i = 0; i !== nKeys; i ++ ) {
33075
33076                         const currTime = times[ i ];
33077
33078                         if ( typeof currTime === 'number' && isNaN( currTime ) ) {
33079
33080                                 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
33081                                 valid = false;
33082                                 break;
33083
33084                         }
33085
33086                         if ( prevTime !== null && prevTime > currTime ) {
33087
33088                                 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
33089                                 valid = false;
33090                                 break;
33091
33092                         }
33093
33094                         prevTime = currTime;
33095
33096                 }
33097
33098                 if ( values !== undefined ) {
33099
33100                         if ( AnimationUtils.isTypedArray( values ) ) {
33101
33102                                 for ( let i = 0, n = values.length; i !== n; ++ i ) {
33103
33104                                         const value = values[ i ];
33105
33106                                         if ( isNaN( value ) ) {
33107
33108                                                 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
33109                                                 valid = false;
33110                                                 break;
33111
33112                                         }
33113
33114                                 }
33115
33116                         }
33117
33118                 }
33119
33120                 return valid;
33121
33122         },
33123
33124         // removes equivalent sequential keys as common in morph target sequences
33125         // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
33126         optimize: function () {
33127
33128                 // times or values may be shared with other tracks, so overwriting is unsafe
33129                 const times = AnimationUtils.arraySlice( this.times ),
33130                         values = AnimationUtils.arraySlice( this.values ),
33131                         stride = this.getValueSize(),
33132
33133                         smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
33134
33135                         lastIndex = times.length - 1;
33136
33137                 let writeIndex = 1;
33138
33139                 for ( let i = 1; i < lastIndex; ++ i ) {
33140
33141                         let keep = false;
33142
33143                         const time = times[ i ];
33144                         const timeNext = times[ i + 1 ];
33145
33146                         // remove adjacent keyframes scheduled at the same time
33147
33148                         if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {
33149
33150                                 if ( ! smoothInterpolation ) {
33151
33152                                         // remove unnecessary keyframes same as their neighbors
33153
33154                                         const offset = i * stride,
33155                                                 offsetP = offset - stride,
33156                                                 offsetN = offset + stride;
33157
33158                                         for ( let j = 0; j !== stride; ++ j ) {
33159
33160                                                 const value = values[ offset + j ];
33161
33162                                                 if ( value !== values[ offsetP + j ] ||
33163                                                         value !== values[ offsetN + j ] ) {
33164
33165                                                         keep = true;
33166                                                         break;
33167
33168                                                 }
33169
33170                                         }
33171
33172                                 } else {
33173
33174                                         keep = true;
33175
33176                                 }
33177
33178                         }
33179
33180                         // in-place compaction
33181
33182                         if ( keep ) {
33183
33184                                 if ( i !== writeIndex ) {
33185
33186                                         times[ writeIndex ] = times[ i ];
33187
33188                                         const readOffset = i * stride,
33189                                                 writeOffset = writeIndex * stride;
33190
33191                                         for ( let j = 0; j !== stride; ++ j ) {
33192
33193                                                 values[ writeOffset + j ] = values[ readOffset + j ];
33194
33195                                         }
33196
33197                                 }
33198
33199                                 ++ writeIndex;
33200
33201                         }
33202
33203                 }
33204
33205                 // flush last keyframe (compaction looks ahead)
33206
33207                 if ( lastIndex > 0 ) {
33208
33209                         times[ writeIndex ] = times[ lastIndex ];
33210
33211                         for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
33212
33213                                 values[ writeOffset + j ] = values[ readOffset + j ];
33214
33215                         }
33216
33217                         ++ writeIndex;
33218
33219                 }
33220
33221                 if ( writeIndex !== times.length ) {
33222
33223                         this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
33224                         this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
33225
33226                 } else {
33227
33228                         this.times = times;
33229                         this.values = values;
33230
33231                 }
33232
33233                 return this;
33234
33235         },
33236
33237         clone: function () {
33238
33239                 const times = AnimationUtils.arraySlice( this.times, 0 );
33240                 const values = AnimationUtils.arraySlice( this.values, 0 );
33241
33242                 const TypedKeyframeTrack = this.constructor;
33243                 const track = new TypedKeyframeTrack( this.name, times, values );
33244
33245                 // Interpolant argument to constructor is not saved, so copy the factory method directly.
33246                 track.createInterpolant = this.createInterpolant;
33247
33248                 return track;
33249
33250         }
33251
33252 } );
33253
33254 /**
33255  * A Track of Boolean keyframe values.
33256  */
33257
33258 function BooleanKeyframeTrack( name, times, values ) {
33259
33260         KeyframeTrack.call( this, name, times, values );
33261
33262 }
33263
33264 BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33265
33266         constructor: BooleanKeyframeTrack,
33267
33268         ValueTypeName: 'bool',
33269         ValueBufferType: Array,
33270
33271         DefaultInterpolation: InterpolateDiscrete,
33272
33273         InterpolantFactoryMethodLinear: undefined,
33274         InterpolantFactoryMethodSmooth: undefined
33275
33276         // Note: Actually this track could have a optimized / compressed
33277         // representation of a single value and a custom interpolant that
33278         // computes "firstValue ^ isOdd( index )".
33279
33280 } );
33281
33282 /**
33283  * A Track of keyframe values that represent color.
33284  */
33285
33286 function ColorKeyframeTrack( name, times, values, interpolation ) {
33287
33288         KeyframeTrack.call( this, name, times, values, interpolation );
33289
33290 }
33291
33292 ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33293
33294         constructor: ColorKeyframeTrack,
33295
33296         ValueTypeName: 'color'
33297
33298         // ValueBufferType is inherited
33299
33300         // DefaultInterpolation is inherited
33301
33302         // Note: Very basic implementation and nothing special yet.
33303         // However, this is the place for color space parameterization.
33304
33305 } );
33306
33307 /**
33308  * A Track of numeric keyframe values.
33309  */
33310
33311 function NumberKeyframeTrack( name, times, values, interpolation ) {
33312
33313         KeyframeTrack.call( this, name, times, values, interpolation );
33314
33315 }
33316
33317 NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33318
33319         constructor: NumberKeyframeTrack,
33320
33321         ValueTypeName: 'number'
33322
33323         // ValueBufferType is inherited
33324
33325         // DefaultInterpolation is inherited
33326
33327 } );
33328
33329 /**
33330  * Spherical linear unit quaternion interpolant.
33331  */
33332
33333 function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
33334
33335         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
33336
33337 }
33338
33339 QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
33340
33341         constructor: QuaternionLinearInterpolant,
33342
33343         interpolate_: function ( i1, t0, t, t1 ) {
33344
33345                 const result = this.resultBuffer,
33346                         values = this.sampleValues,
33347                         stride = this.valueSize,
33348
33349                         alpha = ( t - t0 ) / ( t1 - t0 );
33350
33351                 let offset = i1 * stride;
33352
33353                 for ( let end = offset + stride; offset !== end; offset += 4 ) {
33354
33355                         Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
33356
33357                 }
33358
33359                 return result;
33360
33361         }
33362
33363 } );
33364
33365 /**
33366  * A Track of quaternion keyframe values.
33367  */
33368
33369 function QuaternionKeyframeTrack( name, times, values, interpolation ) {
33370
33371         KeyframeTrack.call( this, name, times, values, interpolation );
33372
33373 }
33374
33375 QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33376
33377         constructor: QuaternionKeyframeTrack,
33378
33379         ValueTypeName: 'quaternion',
33380
33381         // ValueBufferType is inherited
33382
33383         DefaultInterpolation: InterpolateLinear,
33384
33385         InterpolantFactoryMethodLinear: function ( result ) {
33386
33387                 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
33388
33389         },
33390
33391         InterpolantFactoryMethodSmooth: undefined // not yet implemented
33392
33393 } );
33394
33395 /**
33396  * A Track that interpolates Strings
33397  */
33398
33399 function StringKeyframeTrack( name, times, values, interpolation ) {
33400
33401         KeyframeTrack.call( this, name, times, values, interpolation );
33402
33403 }
33404
33405 StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33406
33407         constructor: StringKeyframeTrack,
33408
33409         ValueTypeName: 'string',
33410         ValueBufferType: Array,
33411
33412         DefaultInterpolation: InterpolateDiscrete,
33413
33414         InterpolantFactoryMethodLinear: undefined,
33415
33416         InterpolantFactoryMethodSmooth: undefined
33417
33418 } );
33419
33420 /**
33421  * A Track of vectored keyframe values.
33422  */
33423
33424 function VectorKeyframeTrack( name, times, values, interpolation ) {
33425
33426         KeyframeTrack.call( this, name, times, values, interpolation );
33427
33428 }
33429
33430 VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33431
33432         constructor: VectorKeyframeTrack,
33433
33434         ValueTypeName: 'vector'
33435
33436         // ValueBufferType is inherited
33437
33438         // DefaultInterpolation is inherited
33439
33440 } );
33441
33442 function AnimationClip( name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode ) {
33443
33444         this.name = name;
33445         this.tracks = tracks;
33446         this.duration = duration;
33447         this.blendMode = blendMode;
33448
33449         this.uuid = MathUtils.generateUUID();
33450
33451         // this means it should figure out its duration by scanning the tracks
33452         if ( this.duration < 0 ) {
33453
33454                 this.resetDuration();
33455
33456         }
33457
33458 }
33459
33460 function getTrackTypeForValueTypeName( typeName ) {
33461
33462         switch ( typeName.toLowerCase() ) {
33463
33464                 case 'scalar':
33465                 case 'double':
33466                 case 'float':
33467                 case 'number':
33468                 case 'integer':
33469
33470                         return NumberKeyframeTrack;
33471
33472                 case 'vector':
33473                 case 'vector2':
33474                 case 'vector3':
33475                 case 'vector4':
33476
33477                         return VectorKeyframeTrack;
33478
33479                 case 'color':
33480
33481                         return ColorKeyframeTrack;
33482
33483                 case 'quaternion':
33484
33485                         return QuaternionKeyframeTrack;
33486
33487                 case 'bool':
33488                 case 'boolean':
33489
33490                         return BooleanKeyframeTrack;
33491
33492                 case 'string':
33493
33494                         return StringKeyframeTrack;
33495
33496         }
33497
33498         throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
33499
33500 }
33501
33502 function parseKeyframeTrack( json ) {
33503
33504         if ( json.type === undefined ) {
33505
33506                 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
33507
33508         }
33509
33510         const trackType = getTrackTypeForValueTypeName( json.type );
33511
33512         if ( json.times === undefined ) {
33513
33514                 const times = [], values = [];
33515
33516                 AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
33517
33518                 json.times = times;
33519                 json.values = values;
33520
33521         }
33522
33523         // derived classes can define a static parse method
33524         if ( trackType.parse !== undefined ) {
33525
33526                 return trackType.parse( json );
33527
33528         } else {
33529
33530                 // by default, we assume a constructor compatible with the base
33531                 return new trackType( json.name, json.times, json.values, json.interpolation );
33532
33533         }
33534
33535 }
33536
33537 Object.assign( AnimationClip, {
33538
33539         parse: function ( json ) {
33540
33541                 const tracks = [],
33542                         jsonTracks = json.tracks,
33543                         frameTime = 1.0 / ( json.fps || 1.0 );
33544
33545                 for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
33546
33547                         tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
33548
33549                 }
33550
33551                 const clip = new AnimationClip( json.name, json.duration, tracks, json.blendMode );
33552                 clip.uuid = json.uuid;
33553
33554                 return clip;
33555
33556         },
33557
33558         toJSON: function ( clip ) {
33559
33560                 const tracks = [],
33561                         clipTracks = clip.tracks;
33562
33563                 const json = {
33564
33565                         'name': clip.name,
33566                         'duration': clip.duration,
33567                         'tracks': tracks,
33568                         'uuid': clip.uuid,
33569                         'blendMode': clip.blendMode
33570
33571                 };
33572
33573                 for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
33574
33575                         tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
33576
33577                 }
33578
33579                 return json;
33580
33581         },
33582
33583         CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
33584
33585                 const numMorphTargets = morphTargetSequence.length;
33586                 const tracks = [];
33587
33588                 for ( let i = 0; i < numMorphTargets; i ++ ) {
33589
33590                         let times = [];
33591                         let values = [];
33592
33593                         times.push(
33594                                 ( i + numMorphTargets - 1 ) % numMorphTargets,
33595                                 i,
33596                                 ( i + 1 ) % numMorphTargets );
33597
33598                         values.push( 0, 1, 0 );
33599
33600                         const order = AnimationUtils.getKeyframeOrder( times );
33601                         times = AnimationUtils.sortedArray( times, 1, order );
33602                         values = AnimationUtils.sortedArray( values, 1, order );
33603
33604                         // if there is a key at the first frame, duplicate it as the
33605                         // last frame as well for perfect loop.
33606                         if ( ! noLoop && times[ 0 ] === 0 ) {
33607
33608                                 times.push( numMorphTargets );
33609                                 values.push( values[ 0 ] );
33610
33611                         }
33612
33613                         tracks.push(
33614                                 new NumberKeyframeTrack(
33615                                         '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
33616                                         times, values
33617                                 ).scale( 1.0 / fps ) );
33618
33619                 }
33620
33621                 return new AnimationClip( name, - 1, tracks );
33622
33623         },
33624
33625         findByName: function ( objectOrClipArray, name ) {
33626
33627                 let clipArray = objectOrClipArray;
33628
33629                 if ( ! Array.isArray( objectOrClipArray ) ) {
33630
33631                         const o = objectOrClipArray;
33632                         clipArray = o.geometry && o.geometry.animations || o.animations;
33633
33634                 }
33635
33636                 for ( let i = 0; i < clipArray.length; i ++ ) {
33637
33638                         if ( clipArray[ i ].name === name ) {
33639
33640                                 return clipArray[ i ];
33641
33642                         }
33643
33644                 }
33645
33646                 return null;
33647
33648         },
33649
33650         CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
33651
33652                 const animationToMorphTargets = {};
33653
33654                 // tested with https://regex101.com/ on trick sequences
33655                 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
33656                 const pattern = /^([\w-]*?)([\d]+)$/;
33657
33658                 // sort morph target names into animation groups based
33659                 // patterns like Walk_001, Walk_002, Run_001, Run_002
33660                 for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
33661
33662                         const morphTarget = morphTargets[ i ];
33663                         const parts = morphTarget.name.match( pattern );
33664
33665                         if ( parts && parts.length > 1 ) {
33666
33667                                 const name = parts[ 1 ];
33668
33669                                 let animationMorphTargets = animationToMorphTargets[ name ];
33670
33671                                 if ( ! animationMorphTargets ) {
33672
33673                                         animationToMorphTargets[ name ] = animationMorphTargets = [];
33674
33675                                 }
33676
33677                                 animationMorphTargets.push( morphTarget );
33678
33679                         }
33680
33681                 }
33682
33683                 const clips = [];
33684
33685                 for ( const name in animationToMorphTargets ) {
33686
33687                         clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
33688
33689                 }
33690
33691                 return clips;
33692
33693         },
33694
33695         // parse the animation.hierarchy format
33696         parseAnimation: function ( animation, bones ) {
33697
33698                 if ( ! animation ) {
33699
33700                         console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
33701                         return null;
33702
33703                 }
33704
33705                 const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
33706
33707                         // only return track if there are actually keys.
33708                         if ( animationKeys.length !== 0 ) {
33709
33710                                 const times = [];
33711                                 const values = [];
33712
33713                                 AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
33714
33715                                 // empty keys are filtered out, so check again
33716                                 if ( times.length !== 0 ) {
33717
33718                                         destTracks.push( new trackType( trackName, times, values ) );
33719
33720                                 }
33721
33722                         }
33723
33724                 };
33725
33726                 const tracks = [];
33727
33728                 const clipName = animation.name || 'default';
33729                 const fps = animation.fps || 30;
33730                 const blendMode = animation.blendMode;
33731
33732                 // automatic length determination in AnimationClip.
33733                 let duration = animation.length || - 1;
33734
33735                 const hierarchyTracks = animation.hierarchy || [];
33736
33737                 for ( let h = 0; h < hierarchyTracks.length; h ++ ) {
33738
33739                         const animationKeys = hierarchyTracks[ h ].keys;
33740
33741                         // skip empty tracks
33742                         if ( ! animationKeys || animationKeys.length === 0 ) continue;
33743
33744                         // process morph targets
33745                         if ( animationKeys[ 0 ].morphTargets ) {
33746
33747                                 // figure out all morph targets used in this track
33748                                 const morphTargetNames = {};
33749
33750                                 let k;
33751
33752                                 for ( k = 0; k < animationKeys.length; k ++ ) {
33753
33754                                         if ( animationKeys[ k ].morphTargets ) {
33755
33756                                                 for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
33757
33758                                                         morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
33759
33760                                                 }
33761
33762                                         }
33763
33764                                 }
33765
33766                                 // create a track for each morph target with all zero
33767                                 // morphTargetInfluences except for the keys in which
33768                                 // the morphTarget is named.
33769                                 for ( const morphTargetName in morphTargetNames ) {
33770
33771                                         const times = [];
33772                                         const values = [];
33773
33774                                         for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
33775
33776                                                 const animationKey = animationKeys[ k ];
33777
33778                                                 times.push( animationKey.time );
33779                                                 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
33780
33781                                         }
33782
33783                                         tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
33784
33785                                 }
33786
33787                                 duration = morphTargetNames.length * ( fps || 1.0 );
33788
33789                         } else {
33790
33791                                 // ...assume skeletal animation
33792
33793                                 const boneName = '.bones[' + bones[ h ].name + ']';
33794
33795                                 addNonemptyTrack(
33796                                         VectorKeyframeTrack, boneName + '.position',
33797                                         animationKeys, 'pos', tracks );
33798
33799                                 addNonemptyTrack(
33800                                         QuaternionKeyframeTrack, boneName + '.quaternion',
33801                                         animationKeys, 'rot', tracks );
33802
33803                                 addNonemptyTrack(
33804                                         VectorKeyframeTrack, boneName + '.scale',
33805                                         animationKeys, 'scl', tracks );
33806
33807                         }
33808
33809                 }
33810
33811                 if ( tracks.length === 0 ) {
33812
33813                         return null;
33814
33815                 }
33816
33817                 const clip = new AnimationClip( clipName, duration, tracks, blendMode );
33818
33819                 return clip;
33820
33821         }
33822
33823 } );
33824
33825 Object.assign( AnimationClip.prototype, {
33826
33827         resetDuration: function () {
33828
33829                 const tracks = this.tracks;
33830                 let duration = 0;
33831
33832                 for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
33833
33834                         const track = this.tracks[ i ];
33835
33836                         duration = Math.max( duration, track.times[ track.times.length - 1 ] );
33837
33838                 }
33839
33840                 this.duration = duration;
33841
33842                 return this;
33843
33844         },
33845
33846         trim: function () {
33847
33848                 for ( let i = 0; i < this.tracks.length; i ++ ) {
33849
33850                         this.tracks[ i ].trim( 0, this.duration );
33851
33852                 }
33853
33854                 return this;
33855
33856         },
33857
33858         validate: function () {
33859
33860                 let valid = true;
33861
33862                 for ( let i = 0; i < this.tracks.length; i ++ ) {
33863
33864                         valid = valid && this.tracks[ i ].validate();
33865
33866                 }
33867
33868                 return valid;
33869
33870         },
33871
33872         optimize: function () {
33873
33874                 for ( let i = 0; i < this.tracks.length; i ++ ) {
33875
33876                         this.tracks[ i ].optimize();
33877
33878                 }
33879
33880                 return this;
33881
33882         },
33883
33884         clone: function () {
33885
33886                 const tracks = [];
33887
33888                 for ( let i = 0; i < this.tracks.length; i ++ ) {
33889
33890                         tracks.push( this.tracks[ i ].clone() );
33891
33892                 }
33893
33894                 return new AnimationClip( this.name, this.duration, tracks, this.blendMode );
33895
33896         },
33897
33898         toJSON: function () {
33899
33900                 return AnimationClip.toJSON( this );
33901
33902         }
33903
33904 } );
33905
33906 const Cache = {
33907
33908         enabled: false,
33909
33910         files: {},
33911
33912         add: function ( key, file ) {
33913
33914                 if ( this.enabled === false ) return;
33915
33916                 // console.log( 'THREE.Cache', 'Adding key:', key );
33917
33918                 this.files[ key ] = file;
33919
33920         },
33921
33922         get: function ( key ) {
33923
33924                 if ( this.enabled === false ) return;
33925
33926                 // console.log( 'THREE.Cache', 'Checking key:', key );
33927
33928                 return this.files[ key ];
33929
33930         },
33931
33932         remove: function ( key ) {
33933
33934                 delete this.files[ key ];
33935
33936         },
33937
33938         clear: function () {
33939
33940                 this.files = {};
33941
33942         }
33943
33944 };
33945
33946 function LoadingManager( onLoad, onProgress, onError ) {
33947
33948         const scope = this;
33949
33950         let isLoading = false;
33951         let itemsLoaded = 0;
33952         let itemsTotal = 0;
33953         let urlModifier = undefined;
33954         const handlers = [];
33955
33956         // Refer to #5689 for the reason why we don't set .onStart
33957         // in the constructor
33958
33959         this.onStart = undefined;
33960         this.onLoad = onLoad;
33961         this.onProgress = onProgress;
33962         this.onError = onError;
33963
33964         this.itemStart = function ( url ) {
33965
33966                 itemsTotal ++;
33967
33968                 if ( isLoading === false ) {
33969
33970                         if ( scope.onStart !== undefined ) {
33971
33972                                 scope.onStart( url, itemsLoaded, itemsTotal );
33973
33974                         }
33975
33976                 }
33977
33978                 isLoading = true;
33979
33980         };
33981
33982         this.itemEnd = function ( url ) {
33983
33984                 itemsLoaded ++;
33985
33986                 if ( scope.onProgress !== undefined ) {
33987
33988                         scope.onProgress( url, itemsLoaded, itemsTotal );
33989
33990                 }
33991
33992                 if ( itemsLoaded === itemsTotal ) {
33993
33994                         isLoading = false;
33995
33996                         if ( scope.onLoad !== undefined ) {
33997
33998                                 scope.onLoad();
33999
34000                         }
34001
34002                 }
34003
34004         };
34005
34006         this.itemError = function ( url ) {
34007
34008                 if ( scope.onError !== undefined ) {
34009
34010                         scope.onError( url );
34011
34012                 }
34013
34014         };
34015
34016         this.resolveURL = function ( url ) {
34017
34018                 if ( urlModifier ) {
34019
34020                         return urlModifier( url );
34021
34022                 }
34023
34024                 return url;
34025
34026         };
34027
34028         this.setURLModifier = function ( transform ) {
34029
34030                 urlModifier = transform;
34031
34032                 return this;
34033
34034         };
34035
34036         this.addHandler = function ( regex, loader ) {
34037
34038                 handlers.push( regex, loader );
34039
34040                 return this;
34041
34042         };
34043
34044         this.removeHandler = function ( regex ) {
34045
34046                 const index = handlers.indexOf( regex );
34047
34048                 if ( index !== - 1 ) {
34049
34050                         handlers.splice( index, 2 );
34051
34052                 }
34053
34054                 return this;
34055
34056         };
34057
34058         this.getHandler = function ( file ) {
34059
34060                 for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
34061
34062                         const regex = handlers[ i ];
34063                         const loader = handlers[ i + 1 ];
34064
34065                         if ( regex.global ) regex.lastIndex = 0; // see #17920
34066
34067                         if ( regex.test( file ) ) {
34068
34069                                 return loader;
34070
34071                         }
34072
34073                 }
34074
34075                 return null;
34076
34077         };
34078
34079 }
34080
34081 const DefaultLoadingManager = new LoadingManager();
34082
34083 function Loader( manager ) {
34084
34085         this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
34086
34087         this.crossOrigin = 'anonymous';
34088         this.withCredentials = false;
34089         this.path = '';
34090         this.resourcePath = '';
34091         this.requestHeader = {};
34092
34093 }
34094
34095 Object.assign( Loader.prototype, {
34096
34097         load: function ( /* url, onLoad, onProgress, onError */ ) {},
34098
34099         loadAsync: function ( url, onProgress ) {
34100
34101                 const scope = this;
34102
34103                 return new Promise( function ( resolve, reject ) {
34104
34105                         scope.load( url, resolve, onProgress, reject );
34106
34107                 } );
34108
34109         },
34110
34111         parse: function ( /* data */ ) {},
34112
34113         setCrossOrigin: function ( crossOrigin ) {
34114
34115                 this.crossOrigin = crossOrigin;
34116                 return this;
34117
34118         },
34119
34120         setWithCredentials: function ( value ) {
34121
34122                 this.withCredentials = value;
34123                 return this;
34124
34125         },
34126
34127         setPath: function ( path ) {
34128
34129                 this.path = path;
34130                 return this;
34131
34132         },
34133
34134         setResourcePath: function ( resourcePath ) {
34135
34136                 this.resourcePath = resourcePath;
34137                 return this;
34138
34139         },
34140
34141         setRequestHeader: function ( requestHeader ) {
34142
34143                 this.requestHeader = requestHeader;
34144                 return this;
34145
34146         }
34147
34148 } );
34149
34150 const loading = {};
34151
34152 function FileLoader( manager ) {
34153
34154         Loader.call( this, manager );
34155
34156 }
34157
34158 FileLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
34159
34160         constructor: FileLoader,
34161
34162         load: function ( url, onLoad, onProgress, onError ) {
34163
34164                 if ( url === undefined ) url = '';
34165
34166                 if ( this.path !== undefined ) url = this.path + url;
34167
34168                 url = this.manager.resolveURL( url );
34169
34170                 const scope = this;
34171
34172                 const cached = Cache.get( url );
34173
34174                 if ( cached !== undefined ) {
34175
34176                         scope.manager.itemStart( url );
34177
34178                         setTimeout( function () {
34179
34180                                 if ( onLoad ) onLoad( cached );
34181
34182                                 scope.manager.itemEnd( url );
34183
34184                         }, 0 );
34185
34186                         return cached;
34187
34188                 }
34189
34190                 // Check if request is duplicate
34191
34192                 if ( loading[ url ] !== undefined ) {
34193
34194                         loading[ url ].push( {
34195
34196                                 onLoad: onLoad,
34197                                 onProgress: onProgress,
34198                                 onError: onError
34199
34200                         } );
34201
34202                         return;
34203
34204                 }
34205
34206                 // Check for data: URI
34207                 const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
34208                 const dataUriRegexResult = url.match( dataUriRegex );
34209                 let request;
34210
34211                 // Safari can not handle Data URIs through XMLHttpRequest so process manually
34212                 if ( dataUriRegexResult ) {
34213
34214                         const mimeType = dataUriRegexResult[ 1 ];
34215                         const isBase64 = !! dataUriRegexResult[ 2 ];
34216
34217                         let data = dataUriRegexResult[ 3 ];
34218                         data = decodeURIComponent( data );
34219
34220                         if ( isBase64 ) data = atob( data );
34221
34222                         try {
34223
34224                                 let response;
34225                                 const responseType = ( this.responseType || '' ).toLowerCase();
34226
34227                                 switch ( responseType ) {
34228
34229                                         case 'arraybuffer':
34230                                         case 'blob':
34231
34232                                                 const view = new Uint8Array( data.length );
34233
34234                                                 for ( let i = 0; i < data.length; i ++ ) {
34235
34236                                                         view[ i ] = data.charCodeAt( i );
34237
34238                                                 }
34239
34240                                                 if ( responseType === 'blob' ) {
34241
34242                                                         response = new Blob( [ view.buffer ], { type: mimeType } );
34243
34244                                                 } else {
34245
34246                                                         response = view.buffer;
34247
34248                                                 }
34249
34250                                                 break;
34251
34252                                         case 'document':
34253
34254                                                 const parser = new DOMParser();
34255                                                 response = parser.parseFromString( data, mimeType );
34256
34257                                                 break;
34258
34259                                         case 'json':
34260
34261                                                 response = JSON.parse( data );
34262
34263                                                 break;
34264
34265                                         default: // 'text' or other
34266
34267                                                 response = data;
34268
34269                                                 break;
34270
34271                                 }
34272
34273                                 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
34274                                 setTimeout( function () {
34275
34276                                         if ( onLoad ) onLoad( response );
34277
34278                                         scope.manager.itemEnd( url );
34279
34280                                 }, 0 );
34281
34282                         } catch ( error ) {
34283
34284                                 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
34285                                 setTimeout( function () {
34286
34287                                         if ( onError ) onError( error );
34288
34289                                         scope.manager.itemError( url );
34290                                         scope.manager.itemEnd( url );
34291
34292                                 }, 0 );
34293
34294                         }
34295
34296                 } else {
34297
34298                         // Initialise array for duplicate requests
34299
34300                         loading[ url ] = [];
34301
34302                         loading[ url ].push( {
34303
34304                                 onLoad: onLoad,
34305                                 onProgress: onProgress,
34306                                 onError: onError
34307
34308                         } );
34309
34310                         request = new XMLHttpRequest();
34311
34312                         request.open( 'GET', url, true );
34313
34314                         request.addEventListener( 'load', function ( event ) {
34315
34316                                 const response = this.response;
34317
34318                                 const callbacks = loading[ url ];
34319
34320                                 delete loading[ url ];
34321
34322                                 if ( this.status === 200 || this.status === 0 ) {
34323
34324                                         // Some browsers return HTTP Status 0 when using non-http protocol
34325                                         // e.g. 'file://' or 'data://'. Handle as success.
34326
34327                                         if ( this.status === 0 ) console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
34328
34329                                         // Add to cache only on HTTP success, so that we do not cache
34330                                         // error response bodies as proper responses to requests.
34331                                         Cache.add( url, response );
34332
34333                                         for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
34334
34335                                                 const callback = callbacks[ i ];
34336                                                 if ( callback.onLoad ) callback.onLoad( response );
34337
34338                                         }
34339
34340                                         scope.manager.itemEnd( url );
34341
34342                                 } else {
34343
34344                                         for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
34345
34346                                                 const callback = callbacks[ i ];
34347                                                 if ( callback.onError ) callback.onError( event );
34348
34349                                         }
34350
34351                                         scope.manager.itemError( url );
34352                                         scope.manager.itemEnd( url );
34353
34354                                 }
34355
34356                         }, false );
34357
34358                         request.addEventListener( 'progress', function ( event ) {
34359
34360                                 const callbacks = loading[ url ];
34361
34362                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
34363
34364                                         const callback = callbacks[ i ];
34365                                         if ( callback.onProgress ) callback.onProgress( event );
34366
34367                                 }
34368
34369                         }, false );
34370
34371                         request.addEventListener( 'error', function ( event ) {
34372
34373                                 const callbacks = loading[ url ];
34374
34375                                 delete loading[ url ];
34376
34377                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
34378
34379                                         const callback = callbacks[ i ];
34380                                         if ( callback.onError ) callback.onError( event );
34381
34382                                 }
34383
34384                                 scope.manager.itemError( url );
34385                                 scope.manager.itemEnd( url );
34386
34387                         }, false );
34388
34389                         request.addEventListener( 'abort', function ( event ) {
34390
34391                                 const callbacks = loading[ url ];
34392
34393                                 delete loading[ url ];
34394
34395                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
34396
34397                                         const callback = callbacks[ i ];
34398                                         if ( callback.onError ) callback.onError( event );
34399
34400                                 }
34401
34402                                 scope.manager.itemError( url );
34403                                 scope.manager.itemEnd( url );
34404
34405                         }, false );
34406
34407                         if ( this.responseType !== undefined ) request.responseType = this.responseType;
34408                         if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
34409
34410                         if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
34411
34412                         for ( const header in this.requestHeader ) {
34413
34414                                 request.setRequestHeader( header, this.requestHeader[ header ] );
34415
34416                         }
34417
34418                         request.send( null );
34419
34420                 }
34421
34422                 scope.manager.itemStart( url );
34423
34424                 return request;
34425
34426         },
34427
34428         setResponseType: function ( value ) {
34429
34430                 this.responseType = value;
34431                 return this;
34432
34433         },
34434
34435         setMimeType: function ( value ) {
34436
34437                 this.mimeType = value;
34438                 return this;
34439
34440         }
34441
34442 } );
34443
34444 function AnimationLoader( manager ) {
34445
34446         Loader.call( this, manager );
34447
34448 }
34449
34450 AnimationLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
34451
34452         constructor: AnimationLoader,
34453
34454         load: function ( url, onLoad, onProgress, onError ) {
34455
34456                 const scope = this;
34457
34458                 const loader = new FileLoader( scope.manager );
34459                 loader.setPath( scope.path );
34460                 loader.setRequestHeader( scope.requestHeader );
34461                 loader.setWithCredentials( scope.withCredentials );
34462                 loader.load( url, function ( text ) {
34463
34464                         try {
34465
34466                                 onLoad( scope.parse( JSON.parse( text ) ) );
34467
34468                         } catch ( e ) {
34469
34470                                 if ( onError ) {
34471
34472                                         onError( e );
34473
34474                                 } else {
34475
34476                                         console.error( e );
34477
34478                                 }
34479
34480                                 scope.manager.itemError( url );
34481
34482                         }
34483
34484                 }, onProgress, onError );
34485
34486         },
34487
34488         parse: function ( json ) {
34489
34490                 const animations = [];
34491
34492                 for ( let i = 0; i < json.length; i ++ ) {
34493
34494                         const clip = AnimationClip.parse( json[ i ] );
34495
34496                         animations.push( clip );
34497
34498                 }
34499
34500                 return animations;
34501
34502         }
34503
34504 } );
34505
34506 /**
34507  * Abstract Base class to block based textures loader (dds, pvr, ...)
34508  *
34509  * Sub classes have to implement the parse() method which will be used in load().
34510  */
34511
34512 function CompressedTextureLoader( manager ) {
34513
34514         Loader.call( this, manager );
34515
34516 }
34517
34518 CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
34519
34520         constructor: CompressedTextureLoader,
34521
34522         load: function ( url, onLoad, onProgress, onError ) {
34523
34524                 const scope = this;
34525
34526                 const images = [];
34527
34528                 const texture = new CompressedTexture();
34529
34530                 const loader = new FileLoader( this.manager );
34531                 loader.setPath( this.path );
34532                 loader.setResponseType( 'arraybuffer' );
34533                 loader.setRequestHeader( this.requestHeader );
34534                 loader.setWithCredentials( scope.withCredentials );
34535
34536                 let loaded = 0;
34537
34538                 function loadTexture( i ) {
34539
34540                         loader.load( url[ i ], function ( buffer ) {
34541
34542                                 const texDatas = scope.parse( buffer, true );
34543
34544                                 images[ i ] = {
34545                                         width: texDatas.width,
34546                                         height: texDatas.height,
34547                                         format: texDatas.format,
34548                                         mipmaps: texDatas.mipmaps
34549                                 };
34550
34551                                 loaded += 1;
34552
34553                                 if ( loaded === 6 ) {
34554
34555                                         if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
34556
34557                                         texture.image = images;
34558                                         texture.format = texDatas.format;
34559                                         texture.needsUpdate = true;
34560
34561                                         if ( onLoad ) onLoad( texture );
34562
34563                                 }
34564
34565                         }, onProgress, onError );
34566
34567                 }
34568
34569                 if ( Array.isArray( url ) ) {
34570
34571                         for ( let i = 0, il = url.length; i < il; ++ i ) {
34572
34573                                 loadTexture( i );
34574
34575                         }
34576
34577                 } else {
34578
34579                         // compressed cubemap texture stored in a single DDS file
34580
34581                         loader.load( url, function ( buffer ) {
34582
34583                                 const texDatas = scope.parse( buffer, true );
34584
34585                                 if ( texDatas.isCubemap ) {
34586
34587                                         const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
34588
34589                                         for ( let f = 0; f < faces; f ++ ) {
34590
34591                                                 images[ f ] = { mipmaps: [] };
34592
34593                                                 for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
34594
34595                                                         images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
34596                                                         images[ f ].format = texDatas.format;
34597                                                         images[ f ].width = texDatas.width;
34598                                                         images[ f ].height = texDatas.height;
34599
34600                                                 }
34601
34602                                         }
34603
34604                                         texture.image = images;
34605
34606                                 } else {
34607
34608                                         texture.image.width = texDatas.width;
34609                                         texture.image.height = texDatas.height;
34610                                         texture.mipmaps = texDatas.mipmaps;
34611
34612                                 }
34613
34614                                 if ( texDatas.mipmapCount === 1 ) {
34615
34616                                         texture.minFilter = LinearFilter;
34617
34618                                 }
34619
34620                                 texture.format = texDatas.format;
34621                                 texture.needsUpdate = true;
34622
34623                                 if ( onLoad ) onLoad( texture );
34624
34625                         }, onProgress, onError );
34626
34627                 }
34628
34629                 return texture;
34630
34631         }
34632
34633 } );
34634
34635 function ImageLoader( manager ) {
34636
34637         Loader.call( this, manager );
34638
34639 }
34640
34641 ImageLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
34642
34643         constructor: ImageLoader,
34644
34645         load: function ( url, onLoad, onProgress, onError ) {
34646
34647                 if ( this.path !== undefined ) url = this.path + url;
34648
34649                 url = this.manager.resolveURL( url );
34650
34651                 const scope = this;
34652
34653                 const cached = Cache.get( url );
34654
34655                 if ( cached !== undefined ) {
34656
34657                         scope.manager.itemStart( url );
34658
34659                         setTimeout( function () {
34660
34661                                 if ( onLoad ) onLoad( cached );
34662
34663                                 scope.manager.itemEnd( url );
34664
34665                         }, 0 );
34666
34667                         return cached;
34668
34669                 }
34670
34671                 const image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
34672
34673                 function onImageLoad() {
34674
34675                         image.removeEventListener( 'load', onImageLoad, false );
34676                         image.removeEventListener( 'error', onImageError, false );
34677
34678                         Cache.add( url, this );
34679
34680                         if ( onLoad ) onLoad( this );
34681
34682                         scope.manager.itemEnd( url );
34683
34684                 }
34685
34686                 function onImageError( event ) {
34687
34688                         image.removeEventListener( 'load', onImageLoad, false );
34689                         image.removeEventListener( 'error', onImageError, false );
34690
34691                         if ( onError ) onError( event );
34692
34693                         scope.manager.itemError( url );
34694                         scope.manager.itemEnd( url );
34695
34696                 }
34697
34698                 image.addEventListener( 'load', onImageLoad, false );
34699                 image.addEventListener( 'error', onImageError, false );
34700
34701                 if ( url.substr( 0, 5 ) !== 'data:' ) {
34702
34703                         if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
34704
34705                 }
34706
34707                 scope.manager.itemStart( url );
34708
34709                 image.src = url;
34710
34711                 return image;
34712
34713         }
34714
34715 } );
34716
34717 function CubeTextureLoader( manager ) {
34718
34719         Loader.call( this, manager );
34720
34721 }
34722
34723 CubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
34724
34725         constructor: CubeTextureLoader,
34726
34727         load: function ( urls, onLoad, onProgress, onError ) {
34728
34729                 const texture = new CubeTexture();
34730
34731                 const loader = new ImageLoader( this.manager );
34732                 loader.setCrossOrigin( this.crossOrigin );
34733                 loader.setPath( this.path );
34734
34735                 let loaded = 0;
34736
34737                 function loadTexture( i ) {
34738
34739                         loader.load( urls[ i ], function ( image ) {
34740
34741                                 texture.images[ i ] = image;
34742
34743                                 loaded ++;
34744
34745                                 if ( loaded === 6 ) {
34746
34747                                         texture.needsUpdate = true;
34748
34749                                         if ( onLoad ) onLoad( texture );
34750
34751                                 }
34752
34753                         }, undefined, onError );
34754
34755                 }
34756
34757                 for ( let i = 0; i < urls.length; ++ i ) {
34758
34759                         loadTexture( i );
34760
34761                 }
34762
34763                 return texture;
34764
34765         }
34766
34767 } );
34768
34769 /**
34770  * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
34771  *
34772  * Sub classes have to implement the parse() method which will be used in load().
34773  */
34774
34775 function DataTextureLoader( manager ) {
34776
34777         Loader.call( this, manager );
34778
34779 }
34780
34781 DataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
34782
34783         constructor: DataTextureLoader,
34784
34785         load: function ( url, onLoad, onProgress, onError ) {
34786
34787                 const scope = this;
34788
34789                 const texture = new DataTexture();
34790
34791                 const loader = new FileLoader( this.manager );
34792                 loader.setResponseType( 'arraybuffer' );
34793                 loader.setRequestHeader( this.requestHeader );
34794                 loader.setPath( this.path );
34795                 loader.setWithCredentials( scope.withCredentials );
34796                 loader.load( url, function ( buffer ) {
34797
34798                         const texData = scope.parse( buffer );
34799
34800                         if ( ! texData ) return;
34801
34802                         if ( texData.image !== undefined ) {
34803
34804                                 texture.image = texData.image;
34805
34806                         } else if ( texData.data !== undefined ) {
34807
34808                                 texture.image.width = texData.width;
34809                                 texture.image.height = texData.height;
34810                                 texture.image.data = texData.data;
34811
34812                         }
34813
34814                         texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
34815                         texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
34816
34817                         texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
34818                         texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
34819
34820                         texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
34821
34822                         if ( texData.encoding !== undefined ) {
34823
34824                                 texture.encoding = texData.encoding;
34825
34826                         }
34827
34828                         if ( texData.flipY !== undefined ) {
34829
34830                                 texture.flipY = texData.flipY;
34831
34832                         }
34833
34834                         if ( texData.format !== undefined ) {
34835
34836                                 texture.format = texData.format;
34837
34838                         }
34839
34840                         if ( texData.type !== undefined ) {
34841
34842                                 texture.type = texData.type;
34843
34844                         }
34845
34846                         if ( texData.mipmaps !== undefined ) {
34847
34848                                 texture.mipmaps = texData.mipmaps;
34849                                 texture.minFilter = LinearMipmapLinearFilter; // presumably...
34850
34851                         }
34852
34853                         if ( texData.mipmapCount === 1 ) {
34854
34855                                 texture.minFilter = LinearFilter;
34856
34857                         }
34858
34859                         texture.needsUpdate = true;
34860
34861                         if ( onLoad ) onLoad( texture, texData );
34862
34863                 }, onProgress, onError );
34864
34865
34866                 return texture;
34867
34868         }
34869
34870 } );
34871
34872 function TextureLoader( manager ) {
34873
34874         Loader.call( this, manager );
34875
34876 }
34877
34878 TextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
34879
34880         constructor: TextureLoader,
34881
34882         load: function ( url, onLoad, onProgress, onError ) {
34883
34884                 const texture = new Texture();
34885
34886                 const loader = new ImageLoader( this.manager );
34887                 loader.setCrossOrigin( this.crossOrigin );
34888                 loader.setPath( this.path );
34889
34890                 loader.load( url, function ( image ) {
34891
34892                         texture.image = image;
34893
34894                         // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
34895                         const isJPEG = url.search( /\.jpe?g($|\?)/i ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
34896
34897                         texture.format = isJPEG ? RGBFormat : RGBAFormat;
34898                         texture.needsUpdate = true;
34899
34900                         if ( onLoad !== undefined ) {
34901
34902                                 onLoad( texture );
34903
34904                         }
34905
34906                 }, onProgress, onError );
34907
34908                 return texture;
34909
34910         }
34911
34912 } );
34913
34914 /**
34915  * Extensible curve object.
34916  *
34917  * Some common of curve methods:
34918  * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
34919  * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
34920  * .getPoints(), .getSpacedPoints()
34921  * .getLength()
34922  * .updateArcLengths()
34923  *
34924  * This following curves inherit from THREE.Curve:
34925  *
34926  * -- 2D curves --
34927  * THREE.ArcCurve
34928  * THREE.CubicBezierCurve
34929  * THREE.EllipseCurve
34930  * THREE.LineCurve
34931  * THREE.QuadraticBezierCurve
34932  * THREE.SplineCurve
34933  *
34934  * -- 3D curves --
34935  * THREE.CatmullRomCurve3
34936  * THREE.CubicBezierCurve3
34937  * THREE.LineCurve3
34938  * THREE.QuadraticBezierCurve3
34939  *
34940  * A series of curves can be represented as a THREE.CurvePath.
34941  *
34942  **/
34943
34944 function Curve() {
34945
34946         this.type = 'Curve';
34947
34948         this.arcLengthDivisions = 200;
34949
34950 }
34951
34952 Object.assign( Curve.prototype, {
34953
34954         // Virtual base class method to overwrite and implement in subclasses
34955         //      - t [0 .. 1]
34956
34957         getPoint: function ( /* t, optionalTarget */ ) {
34958
34959                 console.warn( 'THREE.Curve: .getPoint() not implemented.' );
34960                 return null;
34961
34962         },
34963
34964         // Get point at relative position in curve according to arc length
34965         // - u [0 .. 1]
34966
34967         getPointAt: function ( u, optionalTarget ) {
34968
34969                 const t = this.getUtoTmapping( u );
34970                 return this.getPoint( t, optionalTarget );
34971
34972         },
34973
34974         // Get sequence of points using getPoint( t )
34975
34976         getPoints: function ( divisions = 5 ) {
34977
34978                 const points = [];
34979
34980                 for ( let d = 0; d <= divisions; d ++ ) {
34981
34982                         points.push( this.getPoint( d / divisions ) );
34983
34984                 }
34985
34986                 return points;
34987
34988         },
34989
34990         // Get sequence of points using getPointAt( u )
34991
34992         getSpacedPoints: function ( divisions = 5 ) {
34993
34994                 const points = [];
34995
34996                 for ( let d = 0; d <= divisions; d ++ ) {
34997
34998                         points.push( this.getPointAt( d / divisions ) );
34999
35000                 }
35001
35002                 return points;
35003
35004         },
35005
35006         // Get total curve arc length
35007
35008         getLength: function () {
35009
35010                 const lengths = this.getLengths();
35011                 return lengths[ lengths.length - 1 ];
35012
35013         },
35014
35015         // Get list of cumulative segment lengths
35016
35017         getLengths: function ( divisions ) {
35018
35019                 if ( divisions === undefined ) divisions = this.arcLengthDivisions;
35020
35021                 if ( this.cacheArcLengths &&
35022                         ( this.cacheArcLengths.length === divisions + 1 ) &&
35023                         ! this.needsUpdate ) {
35024
35025                         return this.cacheArcLengths;
35026
35027                 }
35028
35029                 this.needsUpdate = false;
35030
35031                 const cache = [];
35032                 let current, last = this.getPoint( 0 );
35033                 let sum = 0;
35034
35035                 cache.push( 0 );
35036
35037                 for ( let p = 1; p <= divisions; p ++ ) {
35038
35039                         current = this.getPoint( p / divisions );
35040                         sum += current.distanceTo( last );
35041                         cache.push( sum );
35042                         last = current;
35043
35044                 }
35045
35046                 this.cacheArcLengths = cache;
35047
35048                 return cache; // { sums: cache, sum: sum }; Sum is in the last element.
35049
35050         },
35051
35052         updateArcLengths: function () {
35053
35054                 this.needsUpdate = true;
35055                 this.getLengths();
35056
35057         },
35058
35059         // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
35060
35061         getUtoTmapping: function ( u, distance ) {
35062
35063                 const arcLengths = this.getLengths();
35064
35065                 let i = 0;
35066                 const il = arcLengths.length;
35067
35068                 let targetArcLength; // The targeted u distance value to get
35069
35070                 if ( distance ) {
35071
35072                         targetArcLength = distance;
35073
35074                 } else {
35075
35076                         targetArcLength = u * arcLengths[ il - 1 ];
35077
35078                 }
35079
35080                 // binary search for the index with largest value smaller than target u distance
35081
35082                 let low = 0, high = il - 1, comparison;
35083
35084                 while ( low <= high ) {
35085
35086                         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
35087
35088                         comparison = arcLengths[ i ] - targetArcLength;
35089
35090                         if ( comparison < 0 ) {
35091
35092                                 low = i + 1;
35093
35094                         } else if ( comparison > 0 ) {
35095
35096                                 high = i - 1;
35097
35098                         } else {
35099
35100                                 high = i;
35101                                 break;
35102
35103                                 // DONE
35104
35105                         }
35106
35107                 }
35108
35109                 i = high;
35110
35111                 if ( arcLengths[ i ] === targetArcLength ) {
35112
35113                         return i / ( il - 1 );
35114
35115                 }
35116
35117                 // we could get finer grain at lengths, or use simple interpolation between two points
35118
35119                 const lengthBefore = arcLengths[ i ];
35120                 const lengthAfter = arcLengths[ i + 1 ];
35121
35122                 const segmentLength = lengthAfter - lengthBefore;
35123
35124                 // determine where we are between the 'before' and 'after' points
35125
35126                 const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
35127
35128                 // add that fractional amount to t
35129
35130                 const t = ( i + segmentFraction ) / ( il - 1 );
35131
35132                 return t;
35133
35134         },
35135
35136         // Returns a unit vector tangent at t
35137         // In case any sub curve does not implement its tangent derivation,
35138         // 2 points a small delta apart will be used to find its gradient
35139         // which seems to give a reasonable approximation
35140
35141         getTangent: function ( t, optionalTarget ) {
35142
35143                 const delta = 0.0001;
35144                 let t1 = t - delta;
35145                 let t2 = t + delta;
35146
35147                 // Capping in case of danger
35148
35149                 if ( t1 < 0 ) t1 = 0;
35150                 if ( t2 > 1 ) t2 = 1;
35151
35152                 const pt1 = this.getPoint( t1 );
35153                 const pt2 = this.getPoint( t2 );
35154
35155                 const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
35156
35157                 tangent.copy( pt2 ).sub( pt1 ).normalize();
35158
35159                 return tangent;
35160
35161         },
35162
35163         getTangentAt: function ( u, optionalTarget ) {
35164
35165                 const t = this.getUtoTmapping( u );
35166                 return this.getTangent( t, optionalTarget );
35167
35168         },
35169
35170         computeFrenetFrames: function ( segments, closed ) {
35171
35172                 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
35173
35174                 const normal = new Vector3();
35175
35176                 const tangents = [];
35177                 const normals = [];
35178                 const binormals = [];
35179
35180                 const vec = new Vector3();
35181                 const mat = new Matrix4();
35182
35183                 // compute the tangent vectors for each segment on the curve
35184
35185                 for ( let i = 0; i <= segments; i ++ ) {
35186
35187                         const u = i / segments;
35188
35189                         tangents[ i ] = this.getTangentAt( u, new Vector3() );
35190                         tangents[ i ].normalize();
35191
35192                 }
35193
35194                 // select an initial normal vector perpendicular to the first tangent vector,
35195                 // and in the direction of the minimum tangent xyz component
35196
35197                 normals[ 0 ] = new Vector3();
35198                 binormals[ 0 ] = new Vector3();
35199                 let min = Number.MAX_VALUE;
35200                 const tx = Math.abs( tangents[ 0 ].x );
35201                 const ty = Math.abs( tangents[ 0 ].y );
35202                 const tz = Math.abs( tangents[ 0 ].z );
35203
35204                 if ( tx <= min ) {
35205
35206                         min = tx;
35207                         normal.set( 1, 0, 0 );
35208
35209                 }
35210
35211                 if ( ty <= min ) {
35212
35213                         min = ty;
35214                         normal.set( 0, 1, 0 );
35215
35216                 }
35217
35218                 if ( tz <= min ) {
35219
35220                         normal.set( 0, 0, 1 );
35221
35222                 }
35223
35224                 vec.crossVectors( tangents[ 0 ], normal ).normalize();
35225
35226                 normals[ 0 ].crossVectors( tangents[ 0 ], vec );
35227                 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
35228
35229
35230                 // compute the slowly-varying normal and binormal vectors for each segment on the curve
35231
35232                 for ( let i = 1; i <= segments; i ++ ) {
35233
35234                         normals[ i ] = normals[ i - 1 ].clone();
35235
35236                         binormals[ i ] = binormals[ i - 1 ].clone();
35237
35238                         vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
35239
35240                         if ( vec.length() > Number.EPSILON ) {
35241
35242                                 vec.normalize();
35243
35244                                 const theta = Math.acos( MathUtils.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
35245
35246                                 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
35247
35248                         }
35249
35250                         binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
35251
35252                 }
35253
35254                 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
35255
35256                 if ( closed === true ) {
35257
35258                         let theta = Math.acos( MathUtils.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
35259                         theta /= segments;
35260
35261                         if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
35262
35263                                 theta = - theta;
35264
35265                         }
35266
35267                         for ( let i = 1; i <= segments; i ++ ) {
35268
35269                                 // twist a little...
35270                                 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
35271                                 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
35272
35273                         }
35274
35275                 }
35276
35277                 return {
35278                         tangents: tangents,
35279                         normals: normals,
35280                         binormals: binormals
35281                 };
35282
35283         },
35284
35285         clone: function () {
35286
35287                 return new this.constructor().copy( this );
35288
35289         },
35290
35291         copy: function ( source ) {
35292
35293                 this.arcLengthDivisions = source.arcLengthDivisions;
35294
35295                 return this;
35296
35297         },
35298
35299         toJSON: function () {
35300
35301                 const data = {
35302                         metadata: {
35303                                 version: 4.5,
35304                                 type: 'Curve',
35305                                 generator: 'Curve.toJSON'
35306                         }
35307                 };
35308
35309                 data.arcLengthDivisions = this.arcLengthDivisions;
35310                 data.type = this.type;
35311
35312                 return data;
35313
35314         },
35315
35316         fromJSON: function ( json ) {
35317
35318                 this.arcLengthDivisions = json.arcLengthDivisions;
35319
35320                 return this;
35321
35322         }
35323
35324 } );
35325
35326 function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
35327
35328         Curve.call( this );
35329
35330         this.type = 'EllipseCurve';
35331
35332         this.aX = aX || 0;
35333         this.aY = aY || 0;
35334
35335         this.xRadius = xRadius || 1;
35336         this.yRadius = yRadius || 1;
35337
35338         this.aStartAngle = aStartAngle || 0;
35339         this.aEndAngle = aEndAngle || 2 * Math.PI;
35340
35341         this.aClockwise = aClockwise || false;
35342
35343         this.aRotation = aRotation || 0;
35344
35345 }
35346
35347 EllipseCurve.prototype = Object.create( Curve.prototype );
35348 EllipseCurve.prototype.constructor = EllipseCurve;
35349
35350 EllipseCurve.prototype.isEllipseCurve = true;
35351
35352 EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {
35353
35354         const point = optionalTarget || new Vector2();
35355
35356         const twoPi = Math.PI * 2;
35357         let deltaAngle = this.aEndAngle - this.aStartAngle;
35358         const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
35359
35360         // ensures that deltaAngle is 0 .. 2 PI
35361         while ( deltaAngle < 0 ) deltaAngle += twoPi;
35362         while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
35363
35364         if ( deltaAngle < Number.EPSILON ) {
35365
35366                 if ( samePoints ) {
35367
35368                         deltaAngle = 0;
35369
35370                 } else {
35371
35372                         deltaAngle = twoPi;
35373
35374                 }
35375
35376         }
35377
35378         if ( this.aClockwise === true && ! samePoints ) {
35379
35380                 if ( deltaAngle === twoPi ) {
35381
35382                         deltaAngle = - twoPi;
35383
35384                 } else {
35385
35386                         deltaAngle = deltaAngle - twoPi;
35387
35388                 }
35389
35390         }
35391
35392         const angle = this.aStartAngle + t * deltaAngle;
35393         let x = this.aX + this.xRadius * Math.cos( angle );
35394         let y = this.aY + this.yRadius * Math.sin( angle );
35395
35396         if ( this.aRotation !== 0 ) {
35397
35398                 const cos = Math.cos( this.aRotation );
35399                 const sin = Math.sin( this.aRotation );
35400
35401                 const tx = x - this.aX;
35402                 const ty = y - this.aY;
35403
35404                 // Rotate the point about the center of the ellipse.
35405                 x = tx * cos - ty * sin + this.aX;
35406                 y = tx * sin + ty * cos + this.aY;
35407
35408         }
35409
35410         return point.set( x, y );
35411
35412 };
35413
35414 EllipseCurve.prototype.copy = function ( source ) {
35415
35416         Curve.prototype.copy.call( this, source );
35417
35418         this.aX = source.aX;
35419         this.aY = source.aY;
35420
35421         this.xRadius = source.xRadius;
35422         this.yRadius = source.yRadius;
35423
35424         this.aStartAngle = source.aStartAngle;
35425         this.aEndAngle = source.aEndAngle;
35426
35427         this.aClockwise = source.aClockwise;
35428
35429         this.aRotation = source.aRotation;
35430
35431         return this;
35432
35433 };
35434
35435
35436 EllipseCurve.prototype.toJSON = function () {
35437
35438         const data = Curve.prototype.toJSON.call( this );
35439
35440         data.aX = this.aX;
35441         data.aY = this.aY;
35442
35443         data.xRadius = this.xRadius;
35444         data.yRadius = this.yRadius;
35445
35446         data.aStartAngle = this.aStartAngle;
35447         data.aEndAngle = this.aEndAngle;
35448
35449         data.aClockwise = this.aClockwise;
35450
35451         data.aRotation = this.aRotation;
35452
35453         return data;
35454
35455 };
35456
35457 EllipseCurve.prototype.fromJSON = function ( json ) {
35458
35459         Curve.prototype.fromJSON.call( this, json );
35460
35461         this.aX = json.aX;
35462         this.aY = json.aY;
35463
35464         this.xRadius = json.xRadius;
35465         this.yRadius = json.yRadius;
35466
35467         this.aStartAngle = json.aStartAngle;
35468         this.aEndAngle = json.aEndAngle;
35469
35470         this.aClockwise = json.aClockwise;
35471
35472         this.aRotation = json.aRotation;
35473
35474         return this;
35475
35476 };
35477
35478 function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
35479
35480         EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
35481
35482         this.type = 'ArcCurve';
35483
35484 }
35485
35486 ArcCurve.prototype = Object.create( EllipseCurve.prototype );
35487 ArcCurve.prototype.constructor = ArcCurve;
35488
35489 ArcCurve.prototype.isArcCurve = true;
35490
35491 /**
35492  * Centripetal CatmullRom Curve - which is useful for avoiding
35493  * cusps and self-intersections in non-uniform catmull rom curves.
35494  * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
35495  *
35496  * curve.type accepts centripetal(default), chordal and catmullrom
35497  * curve.tension is used for catmullrom which defaults to 0.5
35498  */
35499
35500
35501 /*
35502 Based on an optimized c++ solution in
35503  - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
35504  - http://ideone.com/NoEbVM
35505
35506 This CubicPoly class could be used for reusing some variables and calculations,
35507 but for three.js curve use, it could be possible inlined and flatten into a single function call
35508 which can be placed in CurveUtils.
35509 */
35510
35511 function CubicPoly() {
35512
35513         let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
35514
35515         /*
35516          * Compute coefficients for a cubic polynomial
35517          *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
35518          * such that
35519          *   p(0) = x0, p(1) = x1
35520          *  and
35521          *   p'(0) = t0, p'(1) = t1.
35522          */
35523         function init( x0, x1, t0, t1 ) {
35524
35525                 c0 = x0;
35526                 c1 = t0;
35527                 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
35528                 c3 = 2 * x0 - 2 * x1 + t0 + t1;
35529
35530         }
35531
35532         return {
35533
35534                 initCatmullRom: function ( x0, x1, x2, x3, tension ) {
35535
35536                         init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
35537
35538                 },
35539
35540                 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
35541
35542                         // compute tangents when parameterized in [t1,t2]
35543                         let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
35544                         let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
35545
35546                         // rescale tangents for parametrization in [0,1]
35547                         t1 *= dt1;
35548                         t2 *= dt1;
35549
35550                         init( x1, x2, t1, t2 );
35551
35552                 },
35553
35554                 calc: function ( t ) {
35555
35556                         const t2 = t * t;
35557                         const t3 = t2 * t;
35558                         return c0 + c1 * t + c2 * t2 + c3 * t3;
35559
35560                 }
35561
35562         };
35563
35564 }
35565
35566 //
35567
35568 const tmp = new Vector3();
35569 const px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();
35570
35571 function CatmullRomCurve3( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
35572
35573         Curve.call( this );
35574
35575         this.type = 'CatmullRomCurve3';
35576
35577         this.points = points;
35578         this.closed = closed;
35579         this.curveType = curveType;
35580         this.tension = tension;
35581
35582 }
35583
35584 CatmullRomCurve3.prototype = Object.create( Curve.prototype );
35585 CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
35586
35587 CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
35588
35589 CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
35590
35591         const point = optionalTarget;
35592
35593         const points = this.points;
35594         const l = points.length;
35595
35596         const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
35597         let intPoint = Math.floor( p );
35598         let weight = p - intPoint;
35599
35600         if ( this.closed ) {
35601
35602                 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
35603
35604         } else if ( weight === 0 && intPoint === l - 1 ) {
35605
35606                 intPoint = l - 2;
35607                 weight = 1;
35608
35609         }
35610
35611         let p0, p3; // 4 points (p1 & p2 defined below)
35612
35613         if ( this.closed || intPoint > 0 ) {
35614
35615                 p0 = points[ ( intPoint - 1 ) % l ];
35616
35617         } else {
35618
35619                 // extrapolate first point
35620                 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
35621                 p0 = tmp;
35622
35623         }
35624
35625         const p1 = points[ intPoint % l ];
35626         const p2 = points[ ( intPoint + 1 ) % l ];
35627
35628         if ( this.closed || intPoint + 2 < l ) {
35629
35630                 p3 = points[ ( intPoint + 2 ) % l ];
35631
35632         } else {
35633
35634                 // extrapolate last point
35635                 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
35636                 p3 = tmp;
35637
35638         }
35639
35640         if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
35641
35642                 // init Centripetal / Chordal Catmull-Rom
35643                 const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
35644                 let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
35645                 let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
35646                 let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
35647
35648                 // safety check for repeated points
35649                 if ( dt1 < 1e-4 ) dt1 = 1.0;
35650                 if ( dt0 < 1e-4 ) dt0 = dt1;
35651                 if ( dt2 < 1e-4 ) dt2 = dt1;
35652
35653                 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
35654                 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
35655                 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
35656
35657         } else if ( this.curveType === 'catmullrom' ) {
35658
35659                 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
35660                 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
35661                 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
35662
35663         }
35664
35665         point.set(
35666                 px.calc( weight ),
35667                 py.calc( weight ),
35668                 pz.calc( weight )
35669         );
35670
35671         return point;
35672
35673 };
35674
35675 CatmullRomCurve3.prototype.copy = function ( source ) {
35676
35677         Curve.prototype.copy.call( this, source );
35678
35679         this.points = [];
35680
35681         for ( let i = 0, l = source.points.length; i < l; i ++ ) {
35682
35683                 const point = source.points[ i ];
35684
35685                 this.points.push( point.clone() );
35686
35687         }
35688
35689         this.closed = source.closed;
35690         this.curveType = source.curveType;
35691         this.tension = source.tension;
35692
35693         return this;
35694
35695 };
35696
35697 CatmullRomCurve3.prototype.toJSON = function () {
35698
35699         const data = Curve.prototype.toJSON.call( this );
35700
35701         data.points = [];
35702
35703         for ( let i = 0, l = this.points.length; i < l; i ++ ) {
35704
35705                 const point = this.points[ i ];
35706                 data.points.push( point.toArray() );
35707
35708         }
35709
35710         data.closed = this.closed;
35711         data.curveType = this.curveType;
35712         data.tension = this.tension;
35713
35714         return data;
35715
35716 };
35717
35718 CatmullRomCurve3.prototype.fromJSON = function ( json ) {
35719
35720         Curve.prototype.fromJSON.call( this, json );
35721
35722         this.points = [];
35723
35724         for ( let i = 0, l = json.points.length; i < l; i ++ ) {
35725
35726                 const point = json.points[ i ];
35727                 this.points.push( new Vector3().fromArray( point ) );
35728
35729         }
35730
35731         this.closed = json.closed;
35732         this.curveType = json.curveType;
35733         this.tension = json.tension;
35734
35735         return this;
35736
35737 };
35738
35739 /**
35740  * Bezier Curves formulas obtained from
35741  * http://en.wikipedia.org/wiki/Bézier_curve
35742  */
35743
35744 function CatmullRom( t, p0, p1, p2, p3 ) {
35745
35746         const v0 = ( p2 - p0 ) * 0.5;
35747         const v1 = ( p3 - p1 ) * 0.5;
35748         const t2 = t * t;
35749         const t3 = t * t2;
35750         return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
35751
35752 }
35753
35754 //
35755
35756 function QuadraticBezierP0( t, p ) {
35757
35758         const k = 1 - t;
35759         return k * k * p;
35760
35761 }
35762
35763 function QuadraticBezierP1( t, p ) {
35764
35765         return 2 * ( 1 - t ) * t * p;
35766
35767 }
35768
35769 function QuadraticBezierP2( t, p ) {
35770
35771         return t * t * p;
35772
35773 }
35774
35775 function QuadraticBezier( t, p0, p1, p2 ) {
35776
35777         return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
35778                 QuadraticBezierP2( t, p2 );
35779
35780 }
35781
35782 //
35783
35784 function CubicBezierP0( t, p ) {
35785
35786         const k = 1 - t;
35787         return k * k * k * p;
35788
35789 }
35790
35791 function CubicBezierP1( t, p ) {
35792
35793         const k = 1 - t;
35794         return 3 * k * k * t * p;
35795
35796 }
35797
35798 function CubicBezierP2( t, p ) {
35799
35800         return 3 * ( 1 - t ) * t * t * p;
35801
35802 }
35803
35804 function CubicBezierP3( t, p ) {
35805
35806         return t * t * t * p;
35807
35808 }
35809
35810 function CubicBezier( t, p0, p1, p2, p3 ) {
35811
35812         return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
35813                 CubicBezierP3( t, p3 );
35814
35815 }
35816
35817 function CubicBezierCurve( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
35818
35819         Curve.call( this );
35820
35821         this.type = 'CubicBezierCurve';
35822
35823         this.v0 = v0;
35824         this.v1 = v1;
35825         this.v2 = v2;
35826         this.v3 = v3;
35827
35828 }
35829
35830 CubicBezierCurve.prototype = Object.create( Curve.prototype );
35831 CubicBezierCurve.prototype.constructor = CubicBezierCurve;
35832
35833 CubicBezierCurve.prototype.isCubicBezierCurve = true;
35834
35835 CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
35836
35837         const point = optionalTarget;
35838
35839         const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
35840
35841         point.set(
35842                 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
35843                 CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
35844         );
35845
35846         return point;
35847
35848 };
35849
35850 CubicBezierCurve.prototype.copy = function ( source ) {
35851
35852         Curve.prototype.copy.call( this, source );
35853
35854         this.v0.copy( source.v0 );
35855         this.v1.copy( source.v1 );
35856         this.v2.copy( source.v2 );
35857         this.v3.copy( source.v3 );
35858
35859         return this;
35860
35861 };
35862
35863 CubicBezierCurve.prototype.toJSON = function () {
35864
35865         const data = Curve.prototype.toJSON.call( this );
35866
35867         data.v0 = this.v0.toArray();
35868         data.v1 = this.v1.toArray();
35869         data.v2 = this.v2.toArray();
35870         data.v3 = this.v3.toArray();
35871
35872         return data;
35873
35874 };
35875
35876 CubicBezierCurve.prototype.fromJSON = function ( json ) {
35877
35878         Curve.prototype.fromJSON.call( this, json );
35879
35880         this.v0.fromArray( json.v0 );
35881         this.v1.fromArray( json.v1 );
35882         this.v2.fromArray( json.v2 );
35883         this.v3.fromArray( json.v3 );
35884
35885         return this;
35886
35887 };
35888
35889 function CubicBezierCurve3( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
35890
35891         Curve.call( this );
35892
35893         this.type = 'CubicBezierCurve3';
35894
35895         this.v0 = v0;
35896         this.v1 = v1;
35897         this.v2 = v2;
35898         this.v3 = v3;
35899
35900 }
35901
35902 CubicBezierCurve3.prototype = Object.create( Curve.prototype );
35903 CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
35904
35905 CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
35906
35907 CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
35908
35909         const point = optionalTarget;
35910
35911         const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
35912
35913         point.set(
35914                 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
35915                 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
35916                 CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
35917         );
35918
35919         return point;
35920
35921 };
35922
35923 CubicBezierCurve3.prototype.copy = function ( source ) {
35924
35925         Curve.prototype.copy.call( this, source );
35926
35927         this.v0.copy( source.v0 );
35928         this.v1.copy( source.v1 );
35929         this.v2.copy( source.v2 );
35930         this.v3.copy( source.v3 );
35931
35932         return this;
35933
35934 };
35935
35936 CubicBezierCurve3.prototype.toJSON = function () {
35937
35938         const data = Curve.prototype.toJSON.call( this );
35939
35940         data.v0 = this.v0.toArray();
35941         data.v1 = this.v1.toArray();
35942         data.v2 = this.v2.toArray();
35943         data.v3 = this.v3.toArray();
35944
35945         return data;
35946
35947 };
35948
35949 CubicBezierCurve3.prototype.fromJSON = function ( json ) {
35950
35951         Curve.prototype.fromJSON.call( this, json );
35952
35953         this.v0.fromArray( json.v0 );
35954         this.v1.fromArray( json.v1 );
35955         this.v2.fromArray( json.v2 );
35956         this.v3.fromArray( json.v3 );
35957
35958         return this;
35959
35960 };
35961
35962 function LineCurve( v1 = new Vector2(), v2 = new Vector2() ) {
35963
35964         Curve.call( this );
35965
35966         this.type = 'LineCurve';
35967
35968         this.v1 = v1;
35969         this.v2 = v2;
35970
35971 }
35972
35973 LineCurve.prototype = Object.create( Curve.prototype );
35974 LineCurve.prototype.constructor = LineCurve;
35975
35976 LineCurve.prototype.isLineCurve = true;
35977
35978 LineCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
35979
35980         const point = optionalTarget;
35981
35982         if ( t === 1 ) {
35983
35984                 point.copy( this.v2 );
35985
35986         } else {
35987
35988                 point.copy( this.v2 ).sub( this.v1 );
35989                 point.multiplyScalar( t ).add( this.v1 );
35990
35991         }
35992
35993         return point;
35994
35995 };
35996
35997 // Line curve is linear, so we can overwrite default getPointAt
35998
35999 LineCurve.prototype.getPointAt = function ( u, optionalTarget ) {
36000
36001         return this.getPoint( u, optionalTarget );
36002
36003 };
36004
36005 LineCurve.prototype.getTangent = function ( t, optionalTarget ) {
36006
36007         const tangent = optionalTarget || new Vector2();
36008
36009         tangent.copy( this.v2 ).sub( this.v1 ).normalize();
36010
36011         return tangent;
36012
36013 };
36014
36015 LineCurve.prototype.copy = function ( source ) {
36016
36017         Curve.prototype.copy.call( this, source );
36018
36019         this.v1.copy( source.v1 );
36020         this.v2.copy( source.v2 );
36021
36022         return this;
36023
36024 };
36025
36026 LineCurve.prototype.toJSON = function () {
36027
36028         const data = Curve.prototype.toJSON.call( this );
36029
36030         data.v1 = this.v1.toArray();
36031         data.v2 = this.v2.toArray();
36032
36033         return data;
36034
36035 };
36036
36037 LineCurve.prototype.fromJSON = function ( json ) {
36038
36039         Curve.prototype.fromJSON.call( this, json );
36040
36041         this.v1.fromArray( json.v1 );
36042         this.v2.fromArray( json.v2 );
36043
36044         return this;
36045
36046 };
36047
36048 function LineCurve3( v1 = new Vector3(), v2 = new Vector3() ) {
36049
36050         Curve.call( this );
36051
36052         this.type = 'LineCurve3';
36053
36054         this.v1 = v1;
36055         this.v2 = v2;
36056
36057 }
36058
36059 LineCurve3.prototype = Object.create( Curve.prototype );
36060 LineCurve3.prototype.constructor = LineCurve3;
36061
36062 LineCurve3.prototype.isLineCurve3 = true;
36063
36064 LineCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
36065
36066         const point = optionalTarget;
36067
36068         if ( t === 1 ) {
36069
36070                 point.copy( this.v2 );
36071
36072         } else {
36073
36074                 point.copy( this.v2 ).sub( this.v1 );
36075                 point.multiplyScalar( t ).add( this.v1 );
36076
36077         }
36078
36079         return point;
36080
36081 };
36082
36083 // Line curve is linear, so we can overwrite default getPointAt
36084
36085 LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {
36086
36087         return this.getPoint( u, optionalTarget );
36088
36089 };
36090
36091 LineCurve3.prototype.copy = function ( source ) {
36092
36093         Curve.prototype.copy.call( this, source );
36094
36095         this.v1.copy( source.v1 );
36096         this.v2.copy( source.v2 );
36097
36098         return this;
36099
36100 };
36101
36102 LineCurve3.prototype.toJSON = function () {
36103
36104         const data = Curve.prototype.toJSON.call( this );
36105
36106         data.v1 = this.v1.toArray();
36107         data.v2 = this.v2.toArray();
36108
36109         return data;
36110
36111 };
36112
36113 LineCurve3.prototype.fromJSON = function ( json ) {
36114
36115         Curve.prototype.fromJSON.call( this, json );
36116
36117         this.v1.fromArray( json.v1 );
36118         this.v2.fromArray( json.v2 );
36119
36120         return this;
36121
36122 };
36123
36124 function QuadraticBezierCurve( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
36125
36126         Curve.call( this );
36127
36128         this.type = 'QuadraticBezierCurve';
36129
36130         this.v0 = v0;
36131         this.v1 = v1;
36132         this.v2 = v2;
36133
36134 }
36135
36136 QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
36137 QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
36138
36139 QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
36140
36141 QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
36142
36143         const point = optionalTarget;
36144
36145         const v0 = this.v0, v1 = this.v1, v2 = this.v2;
36146
36147         point.set(
36148                 QuadraticBezier( t, v0.x, v1.x, v2.x ),
36149                 QuadraticBezier( t, v0.y, v1.y, v2.y )
36150         );
36151
36152         return point;
36153
36154 };
36155
36156 QuadraticBezierCurve.prototype.copy = function ( source ) {
36157
36158         Curve.prototype.copy.call( this, source );
36159
36160         this.v0.copy( source.v0 );
36161         this.v1.copy( source.v1 );
36162         this.v2.copy( source.v2 );
36163
36164         return this;
36165
36166 };
36167
36168 QuadraticBezierCurve.prototype.toJSON = function () {
36169
36170         const data = Curve.prototype.toJSON.call( this );
36171
36172         data.v0 = this.v0.toArray();
36173         data.v1 = this.v1.toArray();
36174         data.v2 = this.v2.toArray();
36175
36176         return data;
36177
36178 };
36179
36180 QuadraticBezierCurve.prototype.fromJSON = function ( json ) {
36181
36182         Curve.prototype.fromJSON.call( this, json );
36183
36184         this.v0.fromArray( json.v0 );
36185         this.v1.fromArray( json.v1 );
36186         this.v2.fromArray( json.v2 );
36187
36188         return this;
36189
36190 };
36191
36192 function QuadraticBezierCurve3( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
36193
36194         Curve.call( this );
36195
36196         this.type = 'QuadraticBezierCurve3';
36197
36198         this.v0 = v0;
36199         this.v1 = v1;
36200         this.v2 = v2;
36201
36202 }
36203
36204 QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
36205 QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
36206
36207 QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
36208
36209 QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
36210
36211         const point = optionalTarget;
36212
36213         const v0 = this.v0, v1 = this.v1, v2 = this.v2;
36214
36215         point.set(
36216                 QuadraticBezier( t, v0.x, v1.x, v2.x ),
36217                 QuadraticBezier( t, v0.y, v1.y, v2.y ),
36218                 QuadraticBezier( t, v0.z, v1.z, v2.z )
36219         );
36220
36221         return point;
36222
36223 };
36224
36225 QuadraticBezierCurve3.prototype.copy = function ( source ) {
36226
36227         Curve.prototype.copy.call( this, source );
36228
36229         this.v0.copy( source.v0 );
36230         this.v1.copy( source.v1 );
36231         this.v2.copy( source.v2 );
36232
36233         return this;
36234
36235 };
36236
36237 QuadraticBezierCurve3.prototype.toJSON = function () {
36238
36239         const data = Curve.prototype.toJSON.call( this );
36240
36241         data.v0 = this.v0.toArray();
36242         data.v1 = this.v1.toArray();
36243         data.v2 = this.v2.toArray();
36244
36245         return data;
36246
36247 };
36248
36249 QuadraticBezierCurve3.prototype.fromJSON = function ( json ) {
36250
36251         Curve.prototype.fromJSON.call( this, json );
36252
36253         this.v0.fromArray( json.v0 );
36254         this.v1.fromArray( json.v1 );
36255         this.v2.fromArray( json.v2 );
36256
36257         return this;
36258
36259 };
36260
36261 function SplineCurve( points = [] ) {
36262
36263         Curve.call( this );
36264
36265         this.type = 'SplineCurve';
36266
36267         this.points = points;
36268
36269 }
36270
36271 SplineCurve.prototype = Object.create( Curve.prototype );
36272 SplineCurve.prototype.constructor = SplineCurve;
36273
36274 SplineCurve.prototype.isSplineCurve = true;
36275
36276 SplineCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
36277
36278         const point = optionalTarget;
36279
36280         const points = this.points;
36281         const p = ( points.length - 1 ) * t;
36282
36283         const intPoint = Math.floor( p );
36284         const weight = p - intPoint;
36285
36286         const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
36287         const p1 = points[ intPoint ];
36288         const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
36289         const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
36290
36291         point.set(
36292                 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
36293                 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
36294         );
36295
36296         return point;
36297
36298 };
36299
36300 SplineCurve.prototype.copy = function ( source ) {
36301
36302         Curve.prototype.copy.call( this, source );
36303
36304         this.points = [];
36305
36306         for ( let i = 0, l = source.points.length; i < l; i ++ ) {
36307
36308                 const point = source.points[ i ];
36309
36310                 this.points.push( point.clone() );
36311
36312         }
36313
36314         return this;
36315
36316 };
36317
36318 SplineCurve.prototype.toJSON = function () {
36319
36320         const data = Curve.prototype.toJSON.call( this );
36321
36322         data.points = [];
36323
36324         for ( let i = 0, l = this.points.length; i < l; i ++ ) {
36325
36326                 const point = this.points[ i ];
36327                 data.points.push( point.toArray() );
36328
36329         }
36330
36331         return data;
36332
36333 };
36334
36335 SplineCurve.prototype.fromJSON = function ( json ) {
36336
36337         Curve.prototype.fromJSON.call( this, json );
36338
36339         this.points = [];
36340
36341         for ( let i = 0, l = json.points.length; i < l; i ++ ) {
36342
36343                 const point = json.points[ i ];
36344                 this.points.push( new Vector2().fromArray( point ) );
36345
36346         }
36347
36348         return this;
36349
36350 };
36351
36352 var Curves = /*#__PURE__*/Object.freeze({
36353         __proto__: null,
36354         ArcCurve: ArcCurve,
36355         CatmullRomCurve3: CatmullRomCurve3,
36356         CubicBezierCurve: CubicBezierCurve,
36357         CubicBezierCurve3: CubicBezierCurve3,
36358         EllipseCurve: EllipseCurve,
36359         LineCurve: LineCurve,
36360         LineCurve3: LineCurve3,
36361         QuadraticBezierCurve: QuadraticBezierCurve,
36362         QuadraticBezierCurve3: QuadraticBezierCurve3,
36363         SplineCurve: SplineCurve
36364 });
36365
36366 /**************************************************************
36367  *      Curved Path - a curve path is simply a array of connected
36368  *  curves, but retains the api of a curve
36369  **************************************************************/
36370
36371 function CurvePath() {
36372
36373         Curve.call( this );
36374
36375         this.type = 'CurvePath';
36376
36377         this.curves = [];
36378         this.autoClose = false; // Automatically closes the path
36379
36380 }
36381
36382 CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
36383
36384         constructor: CurvePath,
36385
36386         add: function ( curve ) {
36387
36388                 this.curves.push( curve );
36389
36390         },
36391
36392         closePath: function () {
36393
36394                 // Add a line curve if start and end of lines are not connected
36395                 const startPoint = this.curves[ 0 ].getPoint( 0 );
36396                 const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
36397
36398                 if ( ! startPoint.equals( endPoint ) ) {
36399
36400                         this.curves.push( new LineCurve( endPoint, startPoint ) );
36401
36402                 }
36403
36404         },
36405
36406         // To get accurate point with reference to
36407         // entire path distance at time t,
36408         // following has to be done:
36409
36410         // 1. Length of each sub path have to be known
36411         // 2. Locate and identify type of curve
36412         // 3. Get t for the curve
36413         // 4. Return curve.getPointAt(t')
36414
36415         getPoint: function ( t ) {
36416
36417                 const d = t * this.getLength();
36418                 const curveLengths = this.getCurveLengths();
36419                 let i = 0;
36420
36421                 // To think about boundaries points.
36422
36423                 while ( i < curveLengths.length ) {
36424
36425                         if ( curveLengths[ i ] >= d ) {
36426
36427                                 const diff = curveLengths[ i ] - d;
36428                                 const curve = this.curves[ i ];
36429
36430                                 const segmentLength = curve.getLength();
36431                                 const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
36432
36433                                 return curve.getPointAt( u );
36434
36435                         }
36436
36437                         i ++;
36438
36439                 }
36440
36441                 return null;
36442
36443                 // loop where sum != 0, sum > d , sum+1 <d
36444
36445         },
36446
36447         // We cannot use the default THREE.Curve getPoint() with getLength() because in
36448         // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
36449         // getPoint() depends on getLength
36450
36451         getLength: function () {
36452
36453                 const lens = this.getCurveLengths();
36454                 return lens[ lens.length - 1 ];
36455
36456         },
36457
36458         // cacheLengths must be recalculated.
36459         updateArcLengths: function () {
36460
36461                 this.needsUpdate = true;
36462                 this.cacheLengths = null;
36463                 this.getCurveLengths();
36464
36465         },
36466
36467         // Compute lengths and cache them
36468         // We cannot overwrite getLengths() because UtoT mapping uses it.
36469
36470         getCurveLengths: function () {
36471
36472                 // We use cache values if curves and cache array are same length
36473
36474                 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
36475
36476                         return this.cacheLengths;
36477
36478                 }
36479
36480                 // Get length of sub-curve
36481                 // Push sums into cached array
36482
36483                 const lengths = [];
36484                 let sums = 0;
36485
36486                 for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
36487
36488                         sums += this.curves[ i ].getLength();
36489                         lengths.push( sums );
36490
36491                 }
36492
36493                 this.cacheLengths = lengths;
36494
36495                 return lengths;
36496
36497         },
36498
36499         getSpacedPoints: function ( divisions = 40 ) {
36500
36501                 const points = [];
36502
36503                 for ( let i = 0; i <= divisions; i ++ ) {
36504
36505                         points.push( this.getPoint( i / divisions ) );
36506
36507                 }
36508
36509                 if ( this.autoClose ) {
36510
36511                         points.push( points[ 0 ] );
36512
36513                 }
36514
36515                 return points;
36516
36517         },
36518
36519         getPoints: function ( divisions = 12 ) {
36520
36521                 const points = [];
36522                 let last;
36523
36524                 for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
36525
36526                         const curve = curves[ i ];
36527                         const resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
36528                                 : ( curve && ( curve.isLineCurve || curve.isLineCurve3 ) ) ? 1
36529                                         : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
36530                                                 : divisions;
36531
36532                         const pts = curve.getPoints( resolution );
36533
36534                         for ( let j = 0; j < pts.length; j ++ ) {
36535
36536                                 const point = pts[ j ];
36537
36538                                 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
36539
36540                                 points.push( point );
36541                                 last = point;
36542
36543                         }
36544
36545                 }
36546
36547                 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
36548
36549                         points.push( points[ 0 ] );
36550
36551                 }
36552
36553                 return points;
36554
36555         },
36556
36557         copy: function ( source ) {
36558
36559                 Curve.prototype.copy.call( this, source );
36560
36561                 this.curves = [];
36562
36563                 for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
36564
36565                         const curve = source.curves[ i ];
36566
36567                         this.curves.push( curve.clone() );
36568
36569                 }
36570
36571                 this.autoClose = source.autoClose;
36572
36573                 return this;
36574
36575         },
36576
36577         toJSON: function () {
36578
36579                 const data = Curve.prototype.toJSON.call( this );
36580
36581                 data.autoClose = this.autoClose;
36582                 data.curves = [];
36583
36584                 for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
36585
36586                         const curve = this.curves[ i ];
36587                         data.curves.push( curve.toJSON() );
36588
36589                 }
36590
36591                 return data;
36592
36593         },
36594
36595         fromJSON: function ( json ) {
36596
36597                 Curve.prototype.fromJSON.call( this, json );
36598
36599                 this.autoClose = json.autoClose;
36600                 this.curves = [];
36601
36602                 for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
36603
36604                         const curve = json.curves[ i ];
36605                         this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
36606
36607                 }
36608
36609                 return this;
36610
36611         }
36612
36613 } );
36614
36615 function Path( points ) {
36616
36617         CurvePath.call( this );
36618
36619         this.type = 'Path';
36620
36621         this.currentPoint = new Vector2();
36622
36623         if ( points ) {
36624
36625                 this.setFromPoints( points );
36626
36627         }
36628
36629 }
36630
36631 Path.prototype = Object.assign( Object.create( CurvePath.prototype ), {
36632
36633         constructor: Path,
36634
36635         setFromPoints: function ( points ) {
36636
36637                 this.moveTo( points[ 0 ].x, points[ 0 ].y );
36638
36639                 for ( let i = 1, l = points.length; i < l; i ++ ) {
36640
36641                         this.lineTo( points[ i ].x, points[ i ].y );
36642
36643                 }
36644
36645                 return this;
36646
36647         },
36648
36649         moveTo: function ( x, y ) {
36650
36651                 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
36652
36653                 return this;
36654
36655         },
36656
36657         lineTo: function ( x, y ) {
36658
36659                 const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
36660                 this.curves.push( curve );
36661
36662                 this.currentPoint.set( x, y );
36663
36664                 return this;
36665
36666         },
36667
36668         quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
36669
36670                 const curve = new QuadraticBezierCurve(
36671                         this.currentPoint.clone(),
36672                         new Vector2( aCPx, aCPy ),
36673                         new Vector2( aX, aY )
36674                 );
36675
36676                 this.curves.push( curve );
36677
36678                 this.currentPoint.set( aX, aY );
36679
36680                 return this;
36681
36682         },
36683
36684         bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
36685
36686                 const curve = new CubicBezierCurve(
36687                         this.currentPoint.clone(),
36688                         new Vector2( aCP1x, aCP1y ),
36689                         new Vector2( aCP2x, aCP2y ),
36690                         new Vector2( aX, aY )
36691                 );
36692
36693                 this.curves.push( curve );
36694
36695                 this.currentPoint.set( aX, aY );
36696
36697                 return this;
36698
36699         },
36700
36701         splineThru: function ( pts /*Array of Vector*/ ) {
36702
36703                 const npts = [ this.currentPoint.clone() ].concat( pts );
36704
36705                 const curve = new SplineCurve( npts );
36706                 this.curves.push( curve );
36707
36708                 this.currentPoint.copy( pts[ pts.length - 1 ] );
36709
36710                 return this;
36711
36712         },
36713
36714         arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36715
36716                 const x0 = this.currentPoint.x;
36717                 const y0 = this.currentPoint.y;
36718
36719                 this.absarc( aX + x0, aY + y0, aRadius,
36720                         aStartAngle, aEndAngle, aClockwise );
36721
36722                 return this;
36723
36724         },
36725
36726         absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36727
36728                 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
36729
36730                 return this;
36731
36732         },
36733
36734         ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36735
36736                 const x0 = this.currentPoint.x;
36737                 const y0 = this.currentPoint.y;
36738
36739                 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36740
36741                 return this;
36742
36743         },
36744
36745         absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36746
36747                 const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36748
36749                 if ( this.curves.length > 0 ) {
36750
36751                         // if a previous curve is present, attempt to join
36752                         const firstPoint = curve.getPoint( 0 );
36753
36754                         if ( ! firstPoint.equals( this.currentPoint ) ) {
36755
36756                                 this.lineTo( firstPoint.x, firstPoint.y );
36757
36758                         }
36759
36760                 }
36761
36762                 this.curves.push( curve );
36763
36764                 const lastPoint = curve.getPoint( 1 );
36765                 this.currentPoint.copy( lastPoint );
36766
36767                 return this;
36768
36769         },
36770
36771         copy: function ( source ) {
36772
36773                 CurvePath.prototype.copy.call( this, source );
36774
36775                 this.currentPoint.copy( source.currentPoint );
36776
36777                 return this;
36778
36779         },
36780
36781         toJSON: function () {
36782
36783                 const data = CurvePath.prototype.toJSON.call( this );
36784
36785                 data.currentPoint = this.currentPoint.toArray();
36786
36787                 return data;
36788
36789         },
36790
36791         fromJSON: function ( json ) {
36792
36793                 CurvePath.prototype.fromJSON.call( this, json );
36794
36795                 this.currentPoint.fromArray( json.currentPoint );
36796
36797                 return this;
36798
36799         }
36800
36801 } );
36802
36803 function Shape( points ) {
36804
36805         Path.call( this, points );
36806
36807         this.uuid = MathUtils.generateUUID();
36808
36809         this.type = 'Shape';
36810
36811         this.holes = [];
36812
36813 }
36814
36815 Shape.prototype = Object.assign( Object.create( Path.prototype ), {
36816
36817         constructor: Shape,
36818
36819         getPointsHoles: function ( divisions ) {
36820
36821                 const holesPts = [];
36822
36823                 for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
36824
36825                         holesPts[ i ] = this.holes[ i ].getPoints( divisions );
36826
36827                 }
36828
36829                 return holesPts;
36830
36831         },
36832
36833         // get points of shape and holes (keypoints based on segments parameter)
36834
36835         extractPoints: function ( divisions ) {
36836
36837                 return {
36838
36839                         shape: this.getPoints( divisions ),
36840                         holes: this.getPointsHoles( divisions )
36841
36842                 };
36843
36844         },
36845
36846         copy: function ( source ) {
36847
36848                 Path.prototype.copy.call( this, source );
36849
36850                 this.holes = [];
36851
36852                 for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
36853
36854                         const hole = source.holes[ i ];
36855
36856                         this.holes.push( hole.clone() );
36857
36858                 }
36859
36860                 return this;
36861
36862         },
36863
36864         toJSON: function () {
36865
36866                 const data = Path.prototype.toJSON.call( this );
36867
36868                 data.uuid = this.uuid;
36869                 data.holes = [];
36870
36871                 for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
36872
36873                         const hole = this.holes[ i ];
36874                         data.holes.push( hole.toJSON() );
36875
36876                 }
36877
36878                 return data;
36879
36880         },
36881
36882         fromJSON: function ( json ) {
36883
36884                 Path.prototype.fromJSON.call( this, json );
36885
36886                 this.uuid = json.uuid;
36887                 this.holes = [];
36888
36889                 for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
36890
36891                         const hole = json.holes[ i ];
36892                         this.holes.push( new Path().fromJSON( hole ) );
36893
36894                 }
36895
36896                 return this;
36897
36898         }
36899
36900 } );
36901
36902 function Light( color, intensity = 1 ) {
36903
36904         Object3D.call( this );
36905
36906         this.type = 'Light';
36907
36908         this.color = new Color( color );
36909         this.intensity = intensity;
36910
36911 }
36912
36913 Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
36914
36915         constructor: Light,
36916
36917         isLight: true,
36918
36919         copy: function ( source ) {
36920
36921                 Object3D.prototype.copy.call( this, source );
36922
36923                 this.color.copy( source.color );
36924                 this.intensity = source.intensity;
36925
36926                 return this;
36927
36928         },
36929
36930         toJSON: function ( meta ) {
36931
36932                 const data = Object3D.prototype.toJSON.call( this, meta );
36933
36934                 data.object.color = this.color.getHex();
36935                 data.object.intensity = this.intensity;
36936
36937                 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
36938
36939                 if ( this.distance !== undefined ) data.object.distance = this.distance;
36940                 if ( this.angle !== undefined ) data.object.angle = this.angle;
36941                 if ( this.decay !== undefined ) data.object.decay = this.decay;
36942                 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
36943
36944                 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
36945
36946                 return data;
36947
36948         }
36949
36950 } );
36951
36952 function HemisphereLight( skyColor, groundColor, intensity ) {
36953
36954         Light.call( this, skyColor, intensity );
36955
36956         this.type = 'HemisphereLight';
36957
36958         this.position.copy( Object3D.DefaultUp );
36959         this.updateMatrix();
36960
36961         this.groundColor = new Color( groundColor );
36962
36963 }
36964
36965 HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
36966
36967         constructor: HemisphereLight,
36968
36969         isHemisphereLight: true,
36970
36971         copy: function ( source ) {
36972
36973                 Light.prototype.copy.call( this, source );
36974
36975                 this.groundColor.copy( source.groundColor );
36976
36977                 return this;
36978
36979         }
36980
36981 } );
36982
36983 function LightShadow( camera ) {
36984
36985         this.camera = camera;
36986
36987         this.bias = 0;
36988         this.normalBias = 0;
36989         this.radius = 1;
36990
36991         this.mapSize = new Vector2( 512, 512 );
36992
36993         this.map = null;
36994         this.mapPass = null;
36995         this.matrix = new Matrix4();
36996
36997         this.autoUpdate = true;
36998         this.needsUpdate = false;
36999
37000         this._frustum = new Frustum();
37001         this._frameExtents = new Vector2( 1, 1 );
37002
37003         this._viewportCount = 1;
37004
37005         this._viewports = [
37006
37007                 new Vector4( 0, 0, 1, 1 )
37008
37009         ];
37010
37011 }
37012
37013 Object.assign( LightShadow.prototype, {
37014
37015         _projScreenMatrix: new Matrix4(),
37016
37017         _lightPositionWorld: new Vector3(),
37018
37019         _lookTarget: new Vector3(),
37020
37021         getViewportCount: function () {
37022
37023                 return this._viewportCount;
37024
37025         },
37026
37027         getFrustum: function () {
37028
37029                 return this._frustum;
37030
37031         },
37032
37033         updateMatrices: function ( light ) {
37034
37035                 const shadowCamera = this.camera,
37036                         shadowMatrix = this.matrix,
37037                         projScreenMatrix = this._projScreenMatrix,
37038                         lookTarget = this._lookTarget,
37039                         lightPositionWorld = this._lightPositionWorld;
37040
37041                 lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
37042                 shadowCamera.position.copy( lightPositionWorld );
37043
37044                 lookTarget.setFromMatrixPosition( light.target.matrixWorld );
37045                 shadowCamera.lookAt( lookTarget );
37046                 shadowCamera.updateMatrixWorld();
37047
37048                 projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
37049                 this._frustum.setFromProjectionMatrix( projScreenMatrix );
37050
37051                 shadowMatrix.set(
37052                         0.5, 0.0, 0.0, 0.5,
37053                         0.0, 0.5, 0.0, 0.5,
37054                         0.0, 0.0, 0.5, 0.5,
37055                         0.0, 0.0, 0.0, 1.0
37056                 );
37057
37058                 shadowMatrix.multiply( shadowCamera.projectionMatrix );
37059                 shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
37060
37061         },
37062
37063         getViewport: function ( viewportIndex ) {
37064
37065                 return this._viewports[ viewportIndex ];
37066
37067         },
37068
37069         getFrameExtents: function () {
37070
37071                 return this._frameExtents;
37072
37073         },
37074
37075         copy: function ( source ) {
37076
37077                 this.camera = source.camera.clone();
37078
37079                 this.bias = source.bias;
37080                 this.radius = source.radius;
37081
37082                 this.mapSize.copy( source.mapSize );
37083
37084                 return this;
37085
37086         },
37087
37088         clone: function () {
37089
37090                 return new this.constructor().copy( this );
37091
37092         },
37093
37094         toJSON: function () {
37095
37096                 const object = {};
37097
37098                 if ( this.bias !== 0 ) object.bias = this.bias;
37099                 if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
37100                 if ( this.radius !== 1 ) object.radius = this.radius;
37101                 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
37102
37103                 object.camera = this.camera.toJSON( false ).object;
37104                 delete object.camera.matrix;
37105
37106                 return object;
37107
37108         }
37109
37110 } );
37111
37112 function SpotLightShadow() {
37113
37114         LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
37115
37116         this.focus = 1;
37117
37118 }
37119
37120 SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
37121
37122         constructor: SpotLightShadow,
37123
37124         isSpotLightShadow: true,
37125
37126         updateMatrices: function ( light ) {
37127
37128                 const camera = this.camera;
37129
37130                 const fov = MathUtils.RAD2DEG * 2 * light.angle * this.focus;
37131                 const aspect = this.mapSize.width / this.mapSize.height;
37132                 const far = light.distance || camera.far;
37133
37134                 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
37135
37136                         camera.fov = fov;
37137                         camera.aspect = aspect;
37138                         camera.far = far;
37139                         camera.updateProjectionMatrix();
37140
37141                 }
37142
37143                 LightShadow.prototype.updateMatrices.call( this, light );
37144
37145         }
37146
37147 } );
37148
37149 function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
37150
37151         Light.call( this, color, intensity );
37152
37153         this.type = 'SpotLight';
37154
37155         this.position.copy( Object3D.DefaultUp );
37156         this.updateMatrix();
37157
37158         this.target = new Object3D();
37159
37160         Object.defineProperty( this, 'power', {
37161                 get: function () {
37162
37163                         // intensity = power per solid angle.
37164                         // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
37165                         return this.intensity * Math.PI;
37166
37167                 },
37168                 set: function ( power ) {
37169
37170                         // intensity = power per solid angle.
37171                         // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
37172                         this.intensity = power / Math.PI;
37173
37174                 }
37175         } );
37176
37177         this.distance = ( distance !== undefined ) ? distance : 0;
37178         this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
37179         this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
37180         this.decay = ( decay !== undefined ) ? decay : 1;       // for physically correct lights, should be 2.
37181
37182         this.shadow = new SpotLightShadow();
37183
37184 }
37185
37186 SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
37187
37188         constructor: SpotLight,
37189
37190         isSpotLight: true,
37191
37192         copy: function ( source ) {
37193
37194                 Light.prototype.copy.call( this, source );
37195
37196                 this.distance = source.distance;
37197                 this.angle = source.angle;
37198                 this.penumbra = source.penumbra;
37199                 this.decay = source.decay;
37200
37201                 this.target = source.target.clone();
37202
37203                 this.shadow = source.shadow.clone();
37204
37205                 return this;
37206
37207         }
37208
37209 } );
37210
37211 function PointLightShadow() {
37212
37213         LightShadow.call( this, new PerspectiveCamera( 90, 1, 0.5, 500 ) );
37214
37215         this._frameExtents = new Vector2( 4, 2 );
37216
37217         this._viewportCount = 6;
37218
37219         this._viewports = [
37220                 // These viewports map a cube-map onto a 2D texture with the
37221                 // following orientation:
37222                 //
37223                 //  xzXZ
37224                 //   y Y
37225                 //
37226                 // X - Positive x direction
37227                 // x - Negative x direction
37228                 // Y - Positive y direction
37229                 // y - Negative y direction
37230                 // Z - Positive z direction
37231                 // z - Negative z direction
37232
37233                 // positive X
37234                 new Vector4( 2, 1, 1, 1 ),
37235                 // negative X
37236                 new Vector4( 0, 1, 1, 1 ),
37237                 // positive Z
37238                 new Vector4( 3, 1, 1, 1 ),
37239                 // negative Z
37240                 new Vector4( 1, 1, 1, 1 ),
37241                 // positive Y
37242                 new Vector4( 3, 0, 1, 1 ),
37243                 // negative Y
37244                 new Vector4( 1, 0, 1, 1 )
37245         ];
37246
37247         this._cubeDirections = [
37248                 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
37249                 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
37250         ];
37251
37252         this._cubeUps = [
37253                 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
37254                 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
37255         ];
37256
37257 }
37258
37259 PointLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
37260
37261         constructor: PointLightShadow,
37262
37263         isPointLightShadow: true,
37264
37265         updateMatrices: function ( light, viewportIndex = 0 ) {
37266
37267                 const camera = this.camera,
37268                         shadowMatrix = this.matrix,
37269                         lightPositionWorld = this._lightPositionWorld,
37270                         lookTarget = this._lookTarget,
37271                         projScreenMatrix = this._projScreenMatrix;
37272
37273                 lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
37274                 camera.position.copy( lightPositionWorld );
37275
37276                 lookTarget.copy( camera.position );
37277                 lookTarget.add( this._cubeDirections[ viewportIndex ] );
37278                 camera.up.copy( this._cubeUps[ viewportIndex ] );
37279                 camera.lookAt( lookTarget );
37280                 camera.updateMatrixWorld();
37281
37282                 shadowMatrix.makeTranslation( - lightPositionWorld.x, - lightPositionWorld.y, - lightPositionWorld.z );
37283
37284                 projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
37285                 this._frustum.setFromProjectionMatrix( projScreenMatrix );
37286
37287         }
37288
37289 } );
37290
37291 function PointLight( color, intensity, distance, decay ) {
37292
37293         Light.call( this, color, intensity );
37294
37295         this.type = 'PointLight';
37296
37297         Object.defineProperty( this, 'power', {
37298                 get: function () {
37299
37300                         // intensity = power per solid angle.
37301                         // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
37302                         return this.intensity * 4 * Math.PI;
37303
37304                 },
37305                 set: function ( power ) {
37306
37307                         // intensity = power per solid angle.
37308                         // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
37309                         this.intensity = power / ( 4 * Math.PI );
37310
37311                 }
37312         } );
37313
37314         this.distance = ( distance !== undefined ) ? distance : 0;
37315         this.decay = ( decay !== undefined ) ? decay : 1;       // for physically correct lights, should be 2.
37316
37317         this.shadow = new PointLightShadow();
37318
37319 }
37320
37321 PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
37322
37323         constructor: PointLight,
37324
37325         isPointLight: true,
37326
37327         copy: function ( source ) {
37328
37329                 Light.prototype.copy.call( this, source );
37330
37331                 this.distance = source.distance;
37332                 this.decay = source.decay;
37333
37334                 this.shadow = source.shadow.clone();
37335
37336                 return this;
37337
37338         }
37339
37340 } );
37341
37342 function OrthographicCamera( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
37343
37344         Camera.call( this );
37345
37346         this.type = 'OrthographicCamera';
37347
37348         this.zoom = 1;
37349         this.view = null;
37350
37351         this.left = left;
37352         this.right = right;
37353         this.top = top;
37354         this.bottom = bottom;
37355
37356         this.near = near;
37357         this.far = far;
37358
37359         this.updateProjectionMatrix();
37360
37361 }
37362
37363 OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
37364
37365         constructor: OrthographicCamera,
37366
37367         isOrthographicCamera: true,
37368
37369         copy: function ( source, recursive ) {
37370
37371                 Camera.prototype.copy.call( this, source, recursive );
37372
37373                 this.left = source.left;
37374                 this.right = source.right;
37375                 this.top = source.top;
37376                 this.bottom = source.bottom;
37377                 this.near = source.near;
37378                 this.far = source.far;
37379
37380                 this.zoom = source.zoom;
37381                 this.view = source.view === null ? null : Object.assign( {}, source.view );
37382
37383                 return this;
37384
37385         },
37386
37387         setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
37388
37389                 if ( this.view === null ) {
37390
37391                         this.view = {
37392                                 enabled: true,
37393                                 fullWidth: 1,
37394                                 fullHeight: 1,
37395                                 offsetX: 0,
37396                                 offsetY: 0,
37397                                 width: 1,
37398                                 height: 1
37399                         };
37400
37401                 }
37402
37403                 this.view.enabled = true;
37404                 this.view.fullWidth = fullWidth;
37405                 this.view.fullHeight = fullHeight;
37406                 this.view.offsetX = x;
37407                 this.view.offsetY = y;
37408                 this.view.width = width;
37409                 this.view.height = height;
37410
37411                 this.updateProjectionMatrix();
37412
37413         },
37414
37415         clearViewOffset: function () {
37416
37417                 if ( this.view !== null ) {
37418
37419                         this.view.enabled = false;
37420
37421                 }
37422
37423                 this.updateProjectionMatrix();
37424
37425         },
37426
37427         updateProjectionMatrix: function () {
37428
37429                 const dx = ( this.right - this.left ) / ( 2 * this.zoom );
37430                 const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
37431                 const cx = ( this.right + this.left ) / 2;
37432                 const cy = ( this.top + this.bottom ) / 2;
37433
37434                 let left = cx - dx;
37435                 let right = cx + dx;
37436                 let top = cy + dy;
37437                 let bottom = cy - dy;
37438
37439                 if ( this.view !== null && this.view.enabled ) {
37440
37441                         const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
37442                         const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
37443
37444                         left += scaleW * this.view.offsetX;
37445                         right = left + scaleW * this.view.width;
37446                         top -= scaleH * this.view.offsetY;
37447                         bottom = top - scaleH * this.view.height;
37448
37449                 }
37450
37451                 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
37452
37453                 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
37454
37455         },
37456
37457         toJSON: function ( meta ) {
37458
37459                 const data = Object3D.prototype.toJSON.call( this, meta );
37460
37461                 data.object.zoom = this.zoom;
37462                 data.object.left = this.left;
37463                 data.object.right = this.right;
37464                 data.object.top = this.top;
37465                 data.object.bottom = this.bottom;
37466                 data.object.near = this.near;
37467                 data.object.far = this.far;
37468
37469                 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
37470
37471                 return data;
37472
37473         }
37474
37475 } );
37476
37477 function DirectionalLightShadow() {
37478
37479         LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
37480
37481 }
37482
37483 DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
37484
37485         constructor: DirectionalLightShadow,
37486
37487         isDirectionalLightShadow: true,
37488
37489         updateMatrices: function ( light ) {
37490
37491                 LightShadow.prototype.updateMatrices.call( this, light );
37492
37493         }
37494
37495 } );
37496
37497 function DirectionalLight( color, intensity ) {
37498
37499         Light.call( this, color, intensity );
37500
37501         this.type = 'DirectionalLight';
37502
37503         this.position.copy( Object3D.DefaultUp );
37504         this.updateMatrix();
37505
37506         this.target = new Object3D();
37507
37508         this.shadow = new DirectionalLightShadow();
37509
37510 }
37511
37512 DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
37513
37514         constructor: DirectionalLight,
37515
37516         isDirectionalLight: true,
37517
37518         copy: function ( source ) {
37519
37520                 Light.prototype.copy.call( this, source );
37521
37522                 this.target = source.target.clone();
37523
37524                 this.shadow = source.shadow.clone();
37525
37526                 return this;
37527
37528         }
37529
37530 } );
37531
37532 function AmbientLight( color, intensity ) {
37533
37534         Light.call( this, color, intensity );
37535
37536         this.type = 'AmbientLight';
37537
37538 }
37539
37540 AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
37541
37542         constructor: AmbientLight,
37543
37544         isAmbientLight: true
37545
37546 } );
37547
37548 function RectAreaLight( color, intensity, width, height ) {
37549
37550         Light.call( this, color, intensity );
37551
37552         this.type = 'RectAreaLight';
37553
37554         this.width = ( width !== undefined ) ? width : 10;
37555         this.height = ( height !== undefined ) ? height : 10;
37556
37557 }
37558
37559 RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
37560
37561         constructor: RectAreaLight,
37562
37563         isRectAreaLight: true,
37564
37565         copy: function ( source ) {
37566
37567                 Light.prototype.copy.call( this, source );
37568
37569                 this.width = source.width;
37570                 this.height = source.height;
37571
37572                 return this;
37573
37574         },
37575
37576         toJSON: function ( meta ) {
37577
37578                 const data = Light.prototype.toJSON.call( this, meta );
37579
37580                 data.object.width = this.width;
37581                 data.object.height = this.height;
37582
37583                 return data;
37584
37585         }
37586
37587 } );
37588
37589 /**
37590  * Primary reference:
37591  *   https://graphics.stanford.edu/papers/envmap/envmap.pdf
37592  *
37593  * Secondary reference:
37594  *   https://www.ppsloan.org/publications/StupidSH36.pdf
37595  */
37596
37597 // 3-band SH defined by 9 coefficients
37598
37599 class SphericalHarmonics3 {
37600
37601         constructor() {
37602
37603                 Object.defineProperty( this, 'isSphericalHarmonics3', { value: true } );
37604
37605                 this.coefficients = [];
37606
37607                 for ( let i = 0; i < 9; i ++ ) {
37608
37609                         this.coefficients.push( new Vector3() );
37610
37611                 }
37612
37613         }
37614
37615         set( coefficients ) {
37616
37617                 for ( let i = 0; i < 9; i ++ ) {
37618
37619                         this.coefficients[ i ].copy( coefficients[ i ] );
37620
37621                 }
37622
37623                 return this;
37624
37625         }
37626
37627         zero() {
37628
37629                 for ( let i = 0; i < 9; i ++ ) {
37630
37631                         this.coefficients[ i ].set( 0, 0, 0 );
37632
37633                 }
37634
37635                 return this;
37636
37637         }
37638
37639         // get the radiance in the direction of the normal
37640         // target is a Vector3
37641         getAt( normal, target ) {
37642
37643                 // normal is assumed to be unit length
37644
37645                 const x = normal.x, y = normal.y, z = normal.z;
37646
37647                 const coeff = this.coefficients;
37648
37649                 // band 0
37650                 target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
37651
37652                 // band 1
37653                 target.addScaledVector( coeff[ 1 ], 0.488603 * y );
37654                 target.addScaledVector( coeff[ 2 ], 0.488603 * z );
37655                 target.addScaledVector( coeff[ 3 ], 0.488603 * x );
37656
37657                 // band 2
37658                 target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
37659                 target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
37660                 target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
37661                 target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
37662                 target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
37663
37664                 return target;
37665
37666         }
37667
37668         // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
37669         // target is a Vector3
37670         // https://graphics.stanford.edu/papers/envmap/envmap.pdf
37671         getIrradianceAt( normal, target ) {
37672
37673                 // normal is assumed to be unit length
37674
37675                 const x = normal.x, y = normal.y, z = normal.z;
37676
37677                 const coeff = this.coefficients;
37678
37679                 // band 0
37680                 target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // Ï€ * 0.282095
37681
37682                 // band 1
37683                 target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * Ï€ / 3 ) * 0.488603
37684                 target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
37685                 target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
37686
37687                 // band 2
37688                 target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( Ï€ / 4 ) * 1.092548
37689                 target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
37690                 target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( Ï€ / 4 ) * 0.315392 * 3
37691                 target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
37692                 target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( Ï€ / 4 ) * 0.546274
37693
37694                 return target;
37695
37696         }
37697
37698         add( sh ) {
37699
37700                 for ( let i = 0; i < 9; i ++ ) {
37701
37702                         this.coefficients[ i ].add( sh.coefficients[ i ] );
37703
37704                 }
37705
37706                 return this;
37707
37708         }
37709
37710         addScaledSH( sh, s ) {
37711
37712                 for ( let i = 0; i < 9; i ++ ) {
37713
37714                         this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
37715
37716                 }
37717
37718                 return this;
37719
37720         }
37721
37722         scale( s ) {
37723
37724                 for ( let i = 0; i < 9; i ++ ) {
37725
37726                         this.coefficients[ i ].multiplyScalar( s );
37727
37728                 }
37729
37730                 return this;
37731
37732         }
37733
37734         lerp( sh, alpha ) {
37735
37736                 for ( let i = 0; i < 9; i ++ ) {
37737
37738                         this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
37739
37740                 }
37741
37742                 return this;
37743
37744         }
37745
37746         equals( sh ) {
37747
37748                 for ( let i = 0; i < 9; i ++ ) {
37749
37750                         if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
37751
37752                                 return false;
37753
37754                         }
37755
37756                 }
37757
37758                 return true;
37759
37760         }
37761
37762         copy( sh ) {
37763
37764                 return this.set( sh.coefficients );
37765
37766         }
37767
37768         clone() {
37769
37770                 return new this.constructor().copy( this );
37771
37772         }
37773
37774         fromArray( array, offset = 0 ) {
37775
37776                 const coefficients = this.coefficients;
37777
37778                 for ( let i = 0; i < 9; i ++ ) {
37779
37780                         coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
37781
37782                 }
37783
37784                 return this;
37785
37786         }
37787
37788         toArray( array = [], offset = 0 ) {
37789
37790                 const coefficients = this.coefficients;
37791
37792                 for ( let i = 0; i < 9; i ++ ) {
37793
37794                         coefficients[ i ].toArray( array, offset + ( i * 3 ) );
37795
37796                 }
37797
37798                 return array;
37799
37800         }
37801
37802         // evaluate the basis functions
37803         // shBasis is an Array[ 9 ]
37804         static getBasisAt( normal, shBasis ) {
37805
37806                 // normal is assumed to be unit length
37807
37808                 const x = normal.x, y = normal.y, z = normal.z;
37809
37810                 // band 0
37811                 shBasis[ 0 ] = 0.282095;
37812
37813                 // band 1
37814                 shBasis[ 1 ] = 0.488603 * y;
37815                 shBasis[ 2 ] = 0.488603 * z;
37816                 shBasis[ 3 ] = 0.488603 * x;
37817
37818                 // band 2
37819                 shBasis[ 4 ] = 1.092548 * x * y;
37820                 shBasis[ 5 ] = 1.092548 * y * z;
37821                 shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
37822                 shBasis[ 7 ] = 1.092548 * x * z;
37823                 shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
37824
37825         }
37826
37827 }
37828
37829 function LightProbe( sh, intensity ) {
37830
37831         Light.call( this, undefined, intensity );
37832
37833         this.type = 'LightProbe';
37834
37835         this.sh = ( sh !== undefined ) ? sh : new SphericalHarmonics3();
37836
37837 }
37838
37839 LightProbe.prototype = Object.assign( Object.create( Light.prototype ), {
37840
37841         constructor: LightProbe,
37842
37843         isLightProbe: true,
37844
37845         copy: function ( source ) {
37846
37847                 Light.prototype.copy.call( this, source );
37848
37849                 this.sh.copy( source.sh );
37850
37851                 return this;
37852
37853         },
37854
37855         fromJSON: function ( json ) {
37856
37857                 this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
37858                 this.sh.fromArray( json.sh );
37859
37860                 return this;
37861
37862         },
37863
37864         toJSON: function ( meta ) {
37865
37866                 const data = Light.prototype.toJSON.call( this, meta );
37867
37868                 data.object.sh = this.sh.toArray();
37869
37870                 return data;
37871
37872         }
37873
37874 } );
37875
37876 function MaterialLoader( manager ) {
37877
37878         Loader.call( this, manager );
37879
37880         this.textures = {};
37881
37882 }
37883
37884 MaterialLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
37885
37886         constructor: MaterialLoader,
37887
37888         load: function ( url, onLoad, onProgress, onError ) {
37889
37890                 const scope = this;
37891
37892                 const loader = new FileLoader( scope.manager );
37893                 loader.setPath( scope.path );
37894                 loader.setRequestHeader( scope.requestHeader );
37895                 loader.setWithCredentials( scope.withCredentials );
37896                 loader.load( url, function ( text ) {
37897
37898                         try {
37899
37900                                 onLoad( scope.parse( JSON.parse( text ) ) );
37901
37902                         } catch ( e ) {
37903
37904                                 if ( onError ) {
37905
37906                                         onError( e );
37907
37908                                 } else {
37909
37910                                         console.error( e );
37911
37912                                 }
37913
37914                                 scope.manager.itemError( url );
37915
37916                         }
37917
37918                 }, onProgress, onError );
37919
37920         },
37921
37922         parse: function ( json ) {
37923
37924                 const textures = this.textures;
37925
37926                 function getTexture( name ) {
37927
37928                         if ( textures[ name ] === undefined ) {
37929
37930                                 console.warn( 'THREE.MaterialLoader: Undefined texture', name );
37931
37932                         }
37933
37934                         return textures[ name ];
37935
37936                 }
37937
37938                 const material = new Materials[ json.type ]();
37939
37940                 if ( json.uuid !== undefined ) material.uuid = json.uuid;
37941                 if ( json.name !== undefined ) material.name = json.name;
37942                 if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color );
37943                 if ( json.roughness !== undefined ) material.roughness = json.roughness;
37944                 if ( json.metalness !== undefined ) material.metalness = json.metalness;
37945                 if ( json.sheen !== undefined ) material.sheen = new Color().setHex( json.sheen );
37946                 if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive );
37947                 if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular );
37948                 if ( json.shininess !== undefined ) material.shininess = json.shininess;
37949                 if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
37950                 if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
37951                 if ( json.fog !== undefined ) material.fog = json.fog;
37952                 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
37953                 if ( json.blending !== undefined ) material.blending = json.blending;
37954                 if ( json.combine !== undefined ) material.combine = json.combine;
37955                 if ( json.side !== undefined ) material.side = json.side;
37956                 if ( json.opacity !== undefined ) material.opacity = json.opacity;
37957                 if ( json.transparent !== undefined ) material.transparent = json.transparent;
37958                 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
37959                 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
37960                 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
37961                 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
37962
37963                 if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
37964                 if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
37965                 if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
37966                 if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
37967                 if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
37968                 if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
37969                 if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
37970                 if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
37971
37972                 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
37973                 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
37974                 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
37975                 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
37976
37977                 if ( json.rotation !== undefined ) material.rotation = json.rotation;
37978
37979                 if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
37980                 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
37981                 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
37982                 if ( json.scale !== undefined ) material.scale = json.scale;
37983
37984                 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
37985                 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
37986                 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
37987
37988                 if ( json.skinning !== undefined ) material.skinning = json.skinning;
37989                 if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
37990                 if ( json.morphNormals !== undefined ) material.morphNormals = json.morphNormals;
37991                 if ( json.dithering !== undefined ) material.dithering = json.dithering;
37992
37993                 if ( json.vertexTangents !== undefined ) material.vertexTangents = json.vertexTangents;
37994
37995                 if ( json.visible !== undefined ) material.visible = json.visible;
37996
37997                 if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
37998
37999                 if ( json.userData !== undefined ) material.userData = json.userData;
38000
38001                 if ( json.vertexColors !== undefined ) {
38002
38003                         if ( typeof json.vertexColors === 'number' ) {
38004
38005                                 material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
38006
38007                         } else {
38008
38009                                 material.vertexColors = json.vertexColors;
38010
38011                         }
38012
38013                 }
38014
38015                 // Shader Material
38016
38017                 if ( json.uniforms !== undefined ) {
38018
38019                         for ( const name in json.uniforms ) {
38020
38021                                 const uniform = json.uniforms[ name ];
38022
38023                                 material.uniforms[ name ] = {};
38024
38025                                 switch ( uniform.type ) {
38026
38027                                         case 't':
38028                                                 material.uniforms[ name ].value = getTexture( uniform.value );
38029                                                 break;
38030
38031                                         case 'c':
38032                                                 material.uniforms[ name ].value = new Color().setHex( uniform.value );
38033                                                 break;
38034
38035                                         case 'v2':
38036                                                 material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
38037                                                 break;
38038
38039                                         case 'v3':
38040                                                 material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
38041                                                 break;
38042
38043                                         case 'v4':
38044                                                 material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
38045                                                 break;
38046
38047                                         case 'm3':
38048                                                 material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
38049                                                 break;
38050
38051                                         case 'm4':
38052                                                 material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
38053                                                 break;
38054
38055                                         default:
38056                                                 material.uniforms[ name ].value = uniform.value;
38057
38058                                 }
38059
38060                         }
38061
38062                 }
38063
38064                 if ( json.defines !== undefined ) material.defines = json.defines;
38065                 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
38066                 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
38067
38068                 if ( json.extensions !== undefined ) {
38069
38070                         for ( const key in json.extensions ) {
38071
38072                                 material.extensions[ key ] = json.extensions[ key ];
38073
38074                         }
38075
38076                 }
38077
38078                 // Deprecated
38079
38080                 if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
38081
38082                 // for PointsMaterial
38083
38084                 if ( json.size !== undefined ) material.size = json.size;
38085                 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
38086
38087                 // maps
38088
38089                 if ( json.map !== undefined ) material.map = getTexture( json.map );
38090                 if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
38091
38092                 if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
38093
38094                 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
38095                 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
38096
38097                 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
38098                 if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
38099                 if ( json.normalScale !== undefined ) {
38100
38101                         let normalScale = json.normalScale;
38102
38103                         if ( Array.isArray( normalScale ) === false ) {
38104
38105                                 // Blender exporter used to export a scalar. See #7459
38106
38107                                 normalScale = [ normalScale, normalScale ];
38108
38109                         }
38110
38111                         material.normalScale = new Vector2().fromArray( normalScale );
38112
38113                 }
38114
38115                 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
38116                 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
38117                 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
38118
38119                 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
38120                 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
38121
38122                 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
38123                 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
38124
38125                 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
38126
38127                 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
38128                 if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
38129
38130                 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
38131                 if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
38132
38133                 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
38134                 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
38135
38136                 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
38137                 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
38138
38139                 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
38140
38141                 if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
38142                 if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
38143                 if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
38144                 if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
38145
38146                 if ( json.transmission !== undefined ) material.transmission = json.transmission;
38147                 if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
38148
38149                 return material;
38150
38151         },
38152
38153         setTextures: function ( value ) {
38154
38155                 this.textures = value;
38156                 return this;
38157
38158         }
38159
38160 } );
38161
38162 const LoaderUtils = {
38163
38164         decodeText: function ( array ) {
38165
38166                 if ( typeof TextDecoder !== 'undefined' ) {
38167
38168                         return new TextDecoder().decode( array );
38169
38170                 }
38171
38172                 // Avoid the String.fromCharCode.apply(null, array) shortcut, which
38173                 // throws a "maximum call stack size exceeded" error for large arrays.
38174
38175                 let s = '';
38176
38177                 for ( let i = 0, il = array.length; i < il; i ++ ) {
38178
38179                         // Implicitly assumes little-endian.
38180                         s += String.fromCharCode( array[ i ] );
38181
38182                 }
38183
38184                 try {
38185
38186                         // merges multi-byte utf-8 characters.
38187
38188                         return decodeURIComponent( escape( s ) );
38189
38190                 } catch ( e ) { // see #16358
38191
38192                         return s;
38193
38194                 }
38195
38196         },
38197
38198         extractUrlBase: function ( url ) {
38199
38200                 const index = url.lastIndexOf( '/' );
38201
38202                 if ( index === - 1 ) return './';
38203
38204                 return url.substr( 0, index + 1 );
38205
38206         }
38207
38208 };
38209
38210 function InstancedBufferGeometry() {
38211
38212         BufferGeometry.call( this );
38213
38214         this.type = 'InstancedBufferGeometry';
38215         this.instanceCount = Infinity;
38216
38217 }
38218
38219 InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
38220
38221         constructor: InstancedBufferGeometry,
38222
38223         isInstancedBufferGeometry: true,
38224
38225         copy: function ( source ) {
38226
38227                 BufferGeometry.prototype.copy.call( this, source );
38228
38229                 this.instanceCount = source.instanceCount;
38230
38231                 return this;
38232
38233         },
38234
38235         clone: function () {
38236
38237                 return new this.constructor().copy( this );
38238
38239         },
38240
38241         toJSON: function () {
38242
38243                 const data = BufferGeometry.prototype.toJSON.call( this );
38244
38245                 data.instanceCount = this.instanceCount;
38246
38247                 data.isInstancedBufferGeometry = true;
38248
38249                 return data;
38250
38251         }
38252
38253 } );
38254
38255 function InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) {
38256
38257         if ( typeof ( normalized ) === 'number' ) {
38258
38259                 meshPerAttribute = normalized;
38260
38261                 normalized = false;
38262
38263                 console.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );
38264
38265         }
38266
38267         BufferAttribute.call( this, array, itemSize, normalized );
38268
38269         this.meshPerAttribute = meshPerAttribute || 1;
38270
38271 }
38272
38273 InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
38274
38275         constructor: InstancedBufferAttribute,
38276
38277         isInstancedBufferAttribute: true,
38278
38279         copy: function ( source ) {
38280
38281                 BufferAttribute.prototype.copy.call( this, source );
38282
38283                 this.meshPerAttribute = source.meshPerAttribute;
38284
38285                 return this;
38286
38287         },
38288
38289         toJSON: function ()     {
38290
38291                 const data = BufferAttribute.prototype.toJSON.call( this );
38292
38293                 data.meshPerAttribute = this.meshPerAttribute;
38294
38295                 data.isInstancedBufferAttribute = true;
38296
38297                 return data;
38298
38299         }
38300
38301 } );
38302
38303 function BufferGeometryLoader( manager ) {
38304
38305         Loader.call( this, manager );
38306
38307 }
38308
38309 BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
38310
38311         constructor: BufferGeometryLoader,
38312
38313         load: function ( url, onLoad, onProgress, onError ) {
38314
38315                 const scope = this;
38316
38317                 const loader = new FileLoader( scope.manager );
38318                 loader.setPath( scope.path );
38319                 loader.setRequestHeader( scope.requestHeader );
38320                 loader.setWithCredentials( scope.withCredentials );
38321                 loader.load( url, function ( text ) {
38322
38323                         try {
38324
38325                                 onLoad( scope.parse( JSON.parse( text ) ) );
38326
38327                         } catch ( e ) {
38328
38329                                 if ( onError ) {
38330
38331                                         onError( e );
38332
38333                                 } else {
38334
38335                                         console.error( e );
38336
38337                                 }
38338
38339                                 scope.manager.itemError( url );
38340
38341                         }
38342
38343                 }, onProgress, onError );
38344
38345         },
38346
38347         parse: function ( json ) {
38348
38349                 const interleavedBufferMap = {};
38350                 const arrayBufferMap = {};
38351
38352                 function getInterleavedBuffer( json, uuid ) {
38353
38354                         if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
38355
38356                         const interleavedBuffers = json.interleavedBuffers;
38357                         const interleavedBuffer = interleavedBuffers[ uuid ];
38358
38359                         const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
38360
38361                         const array = getTypedArray( interleavedBuffer.type, buffer );
38362                         const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
38363                         ib.uuid = interleavedBuffer.uuid;
38364
38365                         interleavedBufferMap[ uuid ] = ib;
38366
38367                         return ib;
38368
38369                 }
38370
38371                 function getArrayBuffer( json, uuid ) {
38372
38373                         if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
38374
38375                         const arrayBuffers = json.arrayBuffers;
38376                         const arrayBuffer = arrayBuffers[ uuid ];
38377
38378                         const ab = new Uint32Array( arrayBuffer ).buffer;
38379
38380                         arrayBufferMap[ uuid ] = ab;
38381
38382                         return ab;
38383
38384                 }
38385
38386                 const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
38387
38388                 const index = json.data.index;
38389
38390                 if ( index !== undefined ) {
38391
38392                         const typedArray = getTypedArray( index.type, index.array );
38393                         geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
38394
38395                 }
38396
38397                 const attributes = json.data.attributes;
38398
38399                 for ( const key in attributes ) {
38400
38401                         const attribute = attributes[ key ];
38402                         let bufferAttribute;
38403
38404                         if ( attribute.isInterleavedBufferAttribute ) {
38405
38406                                 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
38407                                 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
38408
38409                         } else {
38410
38411                                 const typedArray = getTypedArray( attribute.type, attribute.array );
38412                                 const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
38413                                 bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
38414
38415                         }
38416
38417                         if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
38418                         geometry.setAttribute( key, bufferAttribute );
38419
38420                 }
38421
38422                 const morphAttributes = json.data.morphAttributes;
38423
38424                 if ( morphAttributes ) {
38425
38426                         for ( const key in morphAttributes ) {
38427
38428                                 const attributeArray = morphAttributes[ key ];
38429
38430                                 const array = [];
38431
38432                                 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
38433
38434                                         const attribute = attributeArray[ i ];
38435                                         let bufferAttribute;
38436
38437                                         if ( attribute.isInterleavedBufferAttribute ) {
38438
38439                                                 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
38440                                                 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
38441
38442                                         } else {
38443
38444                                                 const typedArray = getTypedArray( attribute.type, attribute.array );
38445                                                 bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
38446
38447                                         }
38448
38449                                         if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
38450                                         array.push( bufferAttribute );
38451
38452                                 }
38453
38454                                 geometry.morphAttributes[ key ] = array;
38455
38456                         }
38457
38458                 }
38459
38460                 const morphTargetsRelative = json.data.morphTargetsRelative;
38461
38462                 if ( morphTargetsRelative ) {
38463
38464                         geometry.morphTargetsRelative = true;
38465
38466                 }
38467
38468                 const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
38469
38470                 if ( groups !== undefined ) {
38471
38472                         for ( let i = 0, n = groups.length; i !== n; ++ i ) {
38473
38474                                 const group = groups[ i ];
38475
38476                                 geometry.addGroup( group.start, group.count, group.materialIndex );
38477
38478                         }
38479
38480                 }
38481
38482                 const boundingSphere = json.data.boundingSphere;
38483
38484                 if ( boundingSphere !== undefined ) {
38485
38486                         const center = new Vector3();
38487
38488                         if ( boundingSphere.center !== undefined ) {
38489
38490                                 center.fromArray( boundingSphere.center );
38491
38492                         }
38493
38494                         geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
38495
38496                 }
38497
38498                 if ( json.name ) geometry.name = json.name;
38499                 if ( json.userData ) geometry.userData = json.userData;
38500
38501                 return geometry;
38502
38503         }
38504
38505 } );
38506
38507 class ObjectLoader extends Loader {
38508
38509         constructor( manager ) {
38510
38511                 super( manager );
38512
38513         }
38514
38515         load( url, onLoad, onProgress, onError ) {
38516
38517                 const scope = this;
38518
38519                 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
38520                 this.resourcePath = this.resourcePath || path;
38521
38522                 const loader = new FileLoader( this.manager );
38523                 loader.setPath( this.path );
38524                 loader.setRequestHeader( this.requestHeader );
38525                 loader.setWithCredentials( this.withCredentials );
38526                 loader.load( url, function ( text ) {
38527
38528                         let json = null;
38529
38530                         try {
38531
38532                                 json = JSON.parse( text );
38533
38534                         } catch ( error ) {
38535
38536                                 if ( onError !== undefined ) onError( error );
38537
38538                                 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
38539
38540                                 return;
38541
38542                         }
38543
38544                         const metadata = json.metadata;
38545
38546                         if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
38547
38548                                 console.error( 'THREE.ObjectLoader: Can\'t load ' + url );
38549                                 return;
38550
38551                         }
38552
38553                         scope.parse( json, onLoad );
38554
38555                 }, onProgress, onError );
38556
38557         }
38558
38559         parse( json, onLoad ) {
38560
38561                 const animations = this.parseAnimations( json.animations );
38562                 const shapes = this.parseShapes( json.shapes );
38563                 const geometries = this.parseGeometries( json.geometries, shapes );
38564
38565                 const images = this.parseImages( json.images, function () {
38566
38567                         if ( onLoad !== undefined ) onLoad( object );
38568
38569                 } );
38570
38571                 const textures = this.parseTextures( json.textures, images );
38572                 const materials = this.parseMaterials( json.materials, textures );
38573
38574                 const object = this.parseObject( json.object, geometries, materials, animations );
38575                 const skeletons = this.parseSkeletons( json.skeletons, object );
38576
38577                 this.bindSkeletons( object, skeletons );
38578
38579                 //
38580
38581                 if ( onLoad !== undefined ) {
38582
38583                         let hasImages = false;
38584
38585                         for ( const uuid in images ) {
38586
38587                                 if ( images[ uuid ] instanceof HTMLImageElement ) {
38588
38589                                         hasImages = true;
38590                                         break;
38591
38592                                 }
38593
38594                         }
38595
38596                         if ( hasImages === false ) onLoad( object );
38597
38598                 }
38599
38600                 return object;
38601
38602         }
38603
38604         parseShapes( json ) {
38605
38606                 const shapes = {};
38607
38608                 if ( json !== undefined ) {
38609
38610                         for ( let i = 0, l = json.length; i < l; i ++ ) {
38611
38612                                 const shape = new Shape().fromJSON( json[ i ] );
38613
38614                                 shapes[ shape.uuid ] = shape;
38615
38616                         }
38617
38618                 }
38619
38620                 return shapes;
38621
38622         }
38623
38624         parseSkeletons( json, object ) {
38625
38626                 const skeletons = {};
38627                 const bones = {};
38628
38629                 // generate bone lookup table
38630
38631                 object.traverse( function ( child ) {
38632
38633                         if ( child.isBone ) bones[ child.uuid ] = child;
38634
38635                 } );
38636
38637                 // create skeletons
38638
38639                 if ( json !== undefined ) {
38640
38641                         for ( let i = 0, l = json.length; i < l; i ++ ) {
38642
38643                                 const skeleton = new Skeleton().fromJSON( json[ i ], bones );
38644
38645                                 skeletons[ skeleton.uuid ] = skeleton;
38646
38647                         }
38648
38649                 }
38650
38651                 return skeletons;
38652
38653         }
38654
38655         parseGeometries( json, shapes ) {
38656
38657                 const geometries = {};
38658                 let geometryShapes;
38659
38660                 if ( json !== undefined ) {
38661
38662                         const bufferGeometryLoader = new BufferGeometryLoader();
38663
38664                         for ( let i = 0, l = json.length; i < l; i ++ ) {
38665
38666                                 let geometry;
38667                                 const data = json[ i ];
38668
38669                                 switch ( data.type ) {
38670
38671                                         case 'PlaneGeometry':
38672                                         case 'PlaneBufferGeometry':
38673
38674                                                 geometry = new Geometries[ data.type ](
38675                                                         data.width,
38676                                                         data.height,
38677                                                         data.widthSegments,
38678                                                         data.heightSegments
38679                                                 );
38680
38681                                                 break;
38682
38683                                         case 'BoxGeometry':
38684                                         case 'BoxBufferGeometry':
38685
38686                                                 geometry = new Geometries[ data.type ](
38687                                                         data.width,
38688                                                         data.height,
38689                                                         data.depth,
38690                                                         data.widthSegments,
38691                                                         data.heightSegments,
38692                                                         data.depthSegments
38693                                                 );
38694
38695                                                 break;
38696
38697                                         case 'CircleGeometry':
38698                                         case 'CircleBufferGeometry':
38699
38700                                                 geometry = new Geometries[ data.type ](
38701                                                         data.radius,
38702                                                         data.segments,
38703                                                         data.thetaStart,
38704                                                         data.thetaLength
38705                                                 );
38706
38707                                                 break;
38708
38709                                         case 'CylinderGeometry':
38710                                         case 'CylinderBufferGeometry':
38711
38712                                                 geometry = new Geometries[ data.type ](
38713                                                         data.radiusTop,
38714                                                         data.radiusBottom,
38715                                                         data.height,
38716                                                         data.radialSegments,
38717                                                         data.heightSegments,
38718                                                         data.openEnded,
38719                                                         data.thetaStart,
38720                                                         data.thetaLength
38721                                                 );
38722
38723                                                 break;
38724
38725                                         case 'ConeGeometry':
38726                                         case 'ConeBufferGeometry':
38727
38728                                                 geometry = new Geometries[ data.type ](
38729                                                         data.radius,
38730                                                         data.height,
38731                                                         data.radialSegments,
38732                                                         data.heightSegments,
38733                                                         data.openEnded,
38734                                                         data.thetaStart,
38735                                                         data.thetaLength
38736                                                 );
38737
38738                                                 break;
38739
38740                                         case 'SphereGeometry':
38741                                         case 'SphereBufferGeometry':
38742
38743                                                 geometry = new Geometries[ data.type ](
38744                                                         data.radius,
38745                                                         data.widthSegments,
38746                                                         data.heightSegments,
38747                                                         data.phiStart,
38748                                                         data.phiLength,
38749                                                         data.thetaStart,
38750                                                         data.thetaLength
38751                                                 );
38752
38753                                                 break;
38754
38755                                         case 'DodecahedronGeometry':
38756                                         case 'DodecahedronBufferGeometry':
38757                                         case 'IcosahedronGeometry':
38758                                         case 'IcosahedronBufferGeometry':
38759                                         case 'OctahedronGeometry':
38760                                         case 'OctahedronBufferGeometry':
38761                                         case 'TetrahedronGeometry':
38762                                         case 'TetrahedronBufferGeometry':
38763
38764                                                 geometry = new Geometries[ data.type ](
38765                                                         data.radius,
38766                                                         data.detail
38767                                                 );
38768
38769                                                 break;
38770
38771                                         case 'RingGeometry':
38772                                         case 'RingBufferGeometry':
38773
38774                                                 geometry = new Geometries[ data.type ](
38775                                                         data.innerRadius,
38776                                                         data.outerRadius,
38777                                                         data.thetaSegments,
38778                                                         data.phiSegments,
38779                                                         data.thetaStart,
38780                                                         data.thetaLength
38781                                                 );
38782
38783                                                 break;
38784
38785                                         case 'TorusGeometry':
38786                                         case 'TorusBufferGeometry':
38787
38788                                                 geometry = new Geometries[ data.type ](
38789                                                         data.radius,
38790                                                         data.tube,
38791                                                         data.radialSegments,
38792                                                         data.tubularSegments,
38793                                                         data.arc
38794                                                 );
38795
38796                                                 break;
38797
38798                                         case 'TorusKnotGeometry':
38799                                         case 'TorusKnotBufferGeometry':
38800
38801                                                 geometry = new Geometries[ data.type ](
38802                                                         data.radius,
38803                                                         data.tube,
38804                                                         data.tubularSegments,
38805                                                         data.radialSegments,
38806                                                         data.p,
38807                                                         data.q
38808                                                 );
38809
38810                                                 break;
38811
38812                                         case 'TubeGeometry':
38813                                         case 'TubeBufferGeometry':
38814
38815                                                 // This only works for built-in curves (e.g. CatmullRomCurve3).
38816                                                 // User defined curves or instances of CurvePath will not be deserialized.
38817                                                 geometry = new Geometries[ data.type ](
38818                                                         new Curves[ data.path.type ]().fromJSON( data.path ),
38819                                                         data.tubularSegments,
38820                                                         data.radius,
38821                                                         data.radialSegments,
38822                                                         data.closed
38823                                                 );
38824
38825                                                 break;
38826
38827                                         case 'LatheGeometry':
38828                                         case 'LatheBufferGeometry':
38829
38830                                                 geometry = new Geometries[ data.type ](
38831                                                         data.points,
38832                                                         data.segments,
38833                                                         data.phiStart,
38834                                                         data.phiLength
38835                                                 );
38836
38837                                                 break;
38838
38839                                         case 'PolyhedronGeometry':
38840                                         case 'PolyhedronBufferGeometry':
38841
38842                                                 geometry = new Geometries[ data.type ](
38843                                                         data.vertices,
38844                                                         data.indices,
38845                                                         data.radius,
38846                                                         data.details
38847                                                 );
38848
38849                                                 break;
38850
38851                                         case 'ShapeGeometry':
38852                                         case 'ShapeBufferGeometry':
38853
38854                                                 geometryShapes = [];
38855
38856                                                 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
38857
38858                                                         const shape = shapes[ data.shapes[ j ] ];
38859
38860                                                         geometryShapes.push( shape );
38861
38862                                                 }
38863
38864                                                 geometry = new Geometries[ data.type ](
38865                                                         geometryShapes,
38866                                                         data.curveSegments
38867                                                 );
38868
38869                                                 break;
38870
38871
38872                                         case 'ExtrudeGeometry':
38873                                         case 'ExtrudeBufferGeometry':
38874
38875                                                 geometryShapes = [];
38876
38877                                                 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
38878
38879                                                         const shape = shapes[ data.shapes[ j ] ];
38880
38881                                                         geometryShapes.push( shape );
38882
38883                                                 }
38884
38885                                                 const extrudePath = data.options.extrudePath;
38886
38887                                                 if ( extrudePath !== undefined ) {
38888
38889                                                         data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
38890
38891                                                 }
38892
38893                                                 geometry = new Geometries[ data.type ](
38894                                                         geometryShapes,
38895                                                         data.options
38896                                                 );
38897
38898                                                 break;
38899
38900                                         case 'BufferGeometry':
38901                                         case 'InstancedBufferGeometry':
38902
38903                                                 geometry = bufferGeometryLoader.parse( data );
38904
38905                                                 break;
38906
38907                                         case 'Geometry':
38908
38909                                                 console.error( 'THREE.ObjectLoader: Loading "Geometry" is not supported anymore.' );
38910
38911                                                 break;
38912
38913                                         default:
38914
38915                                                 console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
38916
38917                                                 continue;
38918
38919                                 }
38920
38921                                 geometry.uuid = data.uuid;
38922
38923                                 if ( data.name !== undefined ) geometry.name = data.name;
38924                                 if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData;
38925
38926                                 geometries[ data.uuid ] = geometry;
38927
38928                         }
38929
38930                 }
38931
38932                 return geometries;
38933
38934         }
38935
38936         parseMaterials( json, textures ) {
38937
38938                 const cache = {}; // MultiMaterial
38939                 const materials = {};
38940
38941                 if ( json !== undefined ) {
38942
38943                         const loader = new MaterialLoader();
38944                         loader.setTextures( textures );
38945
38946                         for ( let i = 0, l = json.length; i < l; i ++ ) {
38947
38948                                 const data = json[ i ];
38949
38950                                 if ( data.type === 'MultiMaterial' ) {
38951
38952                                         // Deprecated
38953
38954                                         const array = [];
38955
38956                                         for ( let j = 0; j < data.materials.length; j ++ ) {
38957
38958                                                 const material = data.materials[ j ];
38959
38960                                                 if ( cache[ material.uuid ] === undefined ) {
38961
38962                                                         cache[ material.uuid ] = loader.parse( material );
38963
38964                                                 }
38965
38966                                                 array.push( cache[ material.uuid ] );
38967
38968                                         }
38969
38970                                         materials[ data.uuid ] = array;
38971
38972                                 } else {
38973
38974                                         if ( cache[ data.uuid ] === undefined ) {
38975
38976                                                 cache[ data.uuid ] = loader.parse( data );
38977
38978                                         }
38979
38980                                         materials[ data.uuid ] = cache[ data.uuid ];
38981
38982                                 }
38983
38984                         }
38985
38986                 }
38987
38988                 return materials;
38989
38990         }
38991
38992         parseAnimations( json ) {
38993
38994                 const animations = {};
38995
38996                 if ( json !== undefined ) {
38997
38998                         for ( let i = 0; i < json.length; i ++ ) {
38999
39000                                 const data = json[ i ];
39001
39002                                 const clip = AnimationClip.parse( data );
39003
39004                                 animations[ clip.uuid ] = clip;
39005
39006                         }
39007
39008                 }
39009
39010                 return animations;
39011
39012         }
39013
39014         parseImages( json, onLoad ) {
39015
39016                 const scope = this;
39017                 const images = {};
39018
39019                 let loader;
39020
39021                 function loadImage( url ) {
39022
39023                         scope.manager.itemStart( url );
39024
39025                         return loader.load( url, function () {
39026
39027                                 scope.manager.itemEnd( url );
39028
39029                         }, undefined, function () {
39030
39031                                 scope.manager.itemError( url );
39032                                 scope.manager.itemEnd( url );
39033
39034                         } );
39035
39036                 }
39037
39038                 function deserializeImage( image ) {
39039
39040                         if ( typeof image === 'string' ) {
39041
39042                                 const url = image;
39043
39044                                 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
39045
39046                                 return loadImage( path );
39047
39048                         } else {
39049
39050                                 if ( image.data ) {
39051
39052                                         return {
39053                                                 data: getTypedArray( image.type, image.data ),
39054                                                 width: image.width,
39055                                                 height: image.height
39056                                         };
39057
39058                                 } else {
39059
39060                                         return null;
39061
39062                                 }
39063
39064                         }
39065
39066                 }
39067
39068                 if ( json !== undefined && json.length > 0 ) {
39069
39070                         const manager = new LoadingManager( onLoad );
39071
39072                         loader = new ImageLoader( manager );
39073                         loader.setCrossOrigin( this.crossOrigin );
39074
39075                         for ( let i = 0, il = json.length; i < il; i ++ ) {
39076
39077                                 const image = json[ i ];
39078                                 const url = image.url;
39079
39080                                 if ( Array.isArray( url ) ) {
39081
39082                                         // load array of images e.g CubeTexture
39083
39084                                         images[ image.uuid ] = [];
39085
39086                                         for ( let j = 0, jl = url.length; j < jl; j ++ ) {
39087
39088                                                 const currentUrl = url[ j ];
39089
39090                                                 const deserializedImage = deserializeImage( currentUrl );
39091
39092                                                 if ( deserializedImage !== null ) {
39093
39094                                                         if ( deserializedImage instanceof HTMLImageElement ) {
39095
39096                                                                 images[ image.uuid ].push( deserializedImage );
39097
39098                                                         } else {
39099
39100                                                                 // special case: handle array of data textures for cube textures
39101
39102                                                                 images[ image.uuid ].push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
39103
39104                                                         }
39105
39106                                                 }
39107
39108                                         }
39109
39110                                 } else {
39111
39112                                         // load single image
39113
39114                                         const deserializedImage = deserializeImage( image.url );
39115
39116                                         if ( deserializedImage !== null ) {
39117
39118                                                 images[ image.uuid ] = deserializedImage;
39119
39120                                         }
39121
39122                                 }
39123
39124                         }
39125
39126                 }
39127
39128                 return images;
39129
39130         }
39131
39132         parseTextures( json, images ) {
39133
39134                 function parseConstant( value, type ) {
39135
39136                         if ( typeof value === 'number' ) return value;
39137
39138                         console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
39139
39140                         return type[ value ];
39141
39142                 }
39143
39144                 const textures = {};
39145
39146                 if ( json !== undefined ) {
39147
39148                         for ( let i = 0, l = json.length; i < l; i ++ ) {
39149
39150                                 const data = json[ i ];
39151
39152                                 if ( data.image === undefined ) {
39153
39154                                         console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
39155
39156                                 }
39157
39158                                 if ( images[ data.image ] === undefined ) {
39159
39160                                         console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
39161
39162                                 }
39163
39164                                 let texture;
39165                                 const image = images[ data.image ];
39166
39167                                 if ( Array.isArray( image ) ) {
39168
39169                                         texture = new CubeTexture( image );
39170
39171                                         if ( image.length === 6 ) texture.needsUpdate = true;
39172
39173                                 } else {
39174
39175                                         if ( image && image.data ) {
39176
39177                                                 texture = new DataTexture( image.data, image.width, image.height );
39178
39179                                         } else {
39180
39181                                                 texture = new Texture( image );
39182
39183                                         }
39184
39185                                         if ( image ) texture.needsUpdate = true; // textures can have undefined image data
39186
39187                                 }
39188
39189                                 texture.uuid = data.uuid;
39190
39191                                 if ( data.name !== undefined ) texture.name = data.name;
39192
39193                                 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
39194
39195                                 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
39196                                 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
39197                                 if ( data.center !== undefined ) texture.center.fromArray( data.center );
39198                                 if ( data.rotation !== undefined ) texture.rotation = data.rotation;
39199
39200                                 if ( data.wrap !== undefined ) {
39201
39202                                         texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
39203                                         texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
39204
39205                                 }
39206
39207                                 if ( data.format !== undefined ) texture.format = data.format;
39208                                 if ( data.type !== undefined ) texture.type = data.type;
39209                                 if ( data.encoding !== undefined ) texture.encoding = data.encoding;
39210
39211                                 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
39212                                 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
39213                                 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
39214
39215                                 if ( data.flipY !== undefined ) texture.flipY = data.flipY;
39216
39217                                 if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
39218                                 if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
39219
39220                                 textures[ data.uuid ] = texture;
39221
39222                         }
39223
39224                 }
39225
39226                 return textures;
39227
39228         }
39229
39230         parseObject( data, geometries, materials, animations ) {
39231
39232                 let object;
39233
39234                 function getGeometry( name ) {
39235
39236                         if ( geometries[ name ] === undefined ) {
39237
39238                                 console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
39239
39240                         }
39241
39242                         return geometries[ name ];
39243
39244                 }
39245
39246                 function getMaterial( name ) {
39247
39248                         if ( name === undefined ) return undefined;
39249
39250                         if ( Array.isArray( name ) ) {
39251
39252                                 const array = [];
39253
39254                                 for ( let i = 0, l = name.length; i < l; i ++ ) {
39255
39256                                         const uuid = name[ i ];
39257
39258                                         if ( materials[ uuid ] === undefined ) {
39259
39260                                                 console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
39261
39262                                         }
39263
39264                                         array.push( materials[ uuid ] );
39265
39266                                 }
39267
39268                                 return array;
39269
39270                         }
39271
39272                         if ( materials[ name ] === undefined ) {
39273
39274                                 console.warn( 'THREE.ObjectLoader: Undefined material', name );
39275
39276                         }
39277
39278                         return materials[ name ];
39279
39280                 }
39281
39282                 let geometry, material;
39283
39284                 switch ( data.type ) {
39285
39286                         case 'Scene':
39287
39288                                 object = new Scene();
39289
39290                                 if ( data.background !== undefined ) {
39291
39292                                         if ( Number.isInteger( data.background ) ) {
39293
39294                                                 object.background = new Color( data.background );
39295
39296                                         }
39297
39298                                 }
39299
39300                                 if ( data.fog !== undefined ) {
39301
39302                                         if ( data.fog.type === 'Fog' ) {
39303
39304                                                 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
39305
39306                                         } else if ( data.fog.type === 'FogExp2' ) {
39307
39308                                                 object.fog = new FogExp2( data.fog.color, data.fog.density );
39309
39310                                         }
39311
39312                                 }
39313
39314                                 break;
39315
39316                         case 'PerspectiveCamera':
39317
39318                                 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
39319
39320                                 if ( data.focus !== undefined ) object.focus = data.focus;
39321                                 if ( data.zoom !== undefined ) object.zoom = data.zoom;
39322                                 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
39323                                 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
39324                                 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
39325
39326                                 break;
39327
39328                         case 'OrthographicCamera':
39329
39330                                 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
39331
39332                                 if ( data.zoom !== undefined ) object.zoom = data.zoom;
39333                                 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
39334
39335                                 break;
39336
39337                         case 'AmbientLight':
39338
39339                                 object = new AmbientLight( data.color, data.intensity );
39340
39341                                 break;
39342
39343                         case 'DirectionalLight':
39344
39345                                 object = new DirectionalLight( data.color, data.intensity );
39346
39347                                 break;
39348
39349                         case 'PointLight':
39350
39351                                 object = new PointLight( data.color, data.intensity, data.distance, data.decay );
39352
39353                                 break;
39354
39355                         case 'RectAreaLight':
39356
39357                                 object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
39358
39359                                 break;
39360
39361                         case 'SpotLight':
39362
39363                                 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
39364
39365                                 break;
39366
39367                         case 'HemisphereLight':
39368
39369                                 object = new HemisphereLight( data.color, data.groundColor, data.intensity );
39370
39371                                 break;
39372
39373                         case 'LightProbe':
39374
39375                                 object = new LightProbe().fromJSON( data );
39376
39377                                 break;
39378
39379                         case 'SkinnedMesh':
39380
39381                                 geometry = getGeometry( data.geometry );
39382                                 material = getMaterial( data.material );
39383
39384                                 object = new SkinnedMesh( geometry, material );
39385
39386                                 if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
39387                                 if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix );
39388                                 if ( data.skeleton !== undefined ) object.skeleton = data.skeleton;
39389
39390                                 break;
39391
39392                         case 'Mesh':
39393
39394                                 geometry = getGeometry( data.geometry );
39395                                 material = getMaterial( data.material );
39396
39397                                 object = new Mesh( geometry, material );
39398
39399                                 break;
39400
39401                         case 'InstancedMesh':
39402
39403                                 geometry = getGeometry( data.geometry );
39404                                 material = getMaterial( data.material );
39405                                 const count = data.count;
39406                                 const instanceMatrix = data.instanceMatrix;
39407
39408                                 object = new InstancedMesh( geometry, material, count );
39409                                 object.instanceMatrix = new BufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
39410
39411                                 break;
39412
39413                         case 'LOD':
39414
39415                                 object = new LOD();
39416
39417                                 break;
39418
39419                         case 'Line':
39420
39421                                 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) );
39422
39423                                 break;
39424
39425                         case 'LineLoop':
39426
39427                                 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
39428
39429                                 break;
39430
39431                         case 'LineSegments':
39432
39433                                 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
39434
39435                                 break;
39436
39437                         case 'PointCloud':
39438                         case 'Points':
39439
39440                                 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
39441
39442                                 break;
39443
39444                         case 'Sprite':
39445
39446                                 object = new Sprite( getMaterial( data.material ) );
39447
39448                                 break;
39449
39450                         case 'Group':
39451
39452                                 object = new Group();
39453
39454                                 break;
39455
39456                         case 'Bone':
39457
39458                                 object = new Bone();
39459
39460                                 break;
39461
39462                         default:
39463
39464                                 object = new Object3D();
39465
39466                 }
39467
39468                 object.uuid = data.uuid;
39469
39470                 if ( data.name !== undefined ) object.name = data.name;
39471
39472                 if ( data.matrix !== undefined ) {
39473
39474                         object.matrix.fromArray( data.matrix );
39475
39476                         if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
39477                         if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
39478
39479                 } else {
39480
39481                         if ( data.position !== undefined ) object.position.fromArray( data.position );
39482                         if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
39483                         if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
39484                         if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
39485
39486                 }
39487
39488                 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
39489                 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
39490
39491                 if ( data.shadow ) {
39492
39493                         if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
39494                         if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias;
39495                         if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
39496                         if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
39497                         if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
39498
39499                 }
39500
39501                 if ( data.visible !== undefined ) object.visible = data.visible;
39502                 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
39503                 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
39504                 if ( data.userData !== undefined ) object.userData = data.userData;
39505                 if ( data.layers !== undefined ) object.layers.mask = data.layers;
39506
39507                 if ( data.children !== undefined ) {
39508
39509                         const children = data.children;
39510
39511                         for ( let i = 0; i < children.length; i ++ ) {
39512
39513                                 object.add( this.parseObject( children[ i ], geometries, materials, animations ) );
39514
39515                         }
39516
39517                 }
39518
39519                 if ( data.animations !== undefined ) {
39520
39521                         const objectAnimations = data.animations;
39522
39523                         for ( let i = 0; i < objectAnimations.length; i ++ ) {
39524
39525                                 const uuid = objectAnimations[ i ];
39526
39527                                 object.animations.push( animations[ uuid ] );
39528
39529                         }
39530
39531                 }
39532
39533                 if ( data.type === 'LOD' ) {
39534
39535                         if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
39536
39537                         const levels = data.levels;
39538
39539                         for ( let l = 0; l < levels.length; l ++ ) {
39540
39541                                 const level = levels[ l ];
39542                                 const child = object.getObjectByProperty( 'uuid', level.object );
39543
39544                                 if ( child !== undefined ) {
39545
39546                                         object.addLevel( child, level.distance );
39547
39548                                 }
39549
39550                         }
39551
39552                 }
39553
39554                 return object;
39555
39556         }
39557
39558         bindSkeletons( object, skeletons ) {
39559
39560                 if ( Object.keys( skeletons ).length === 0 ) return;
39561
39562                 object.traverse( function ( child ) {
39563
39564                         if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) {
39565
39566                                 const skeleton = skeletons[ child.skeleton ];
39567
39568                                 if ( skeleton === undefined ) {
39569
39570                                         console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton );
39571
39572                                 } else {
39573
39574                                         child.bind( skeleton, child.bindMatrix );
39575
39576                                 }
39577
39578                         }
39579
39580                 } );
39581
39582         }
39583
39584         /* DEPRECATED */
39585
39586         setTexturePath( value ) {
39587
39588                 console.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );
39589                 return this.setResourcePath( value );
39590
39591         }
39592
39593 }
39594
39595 const TEXTURE_MAPPING = {
39596         UVMapping: UVMapping,
39597         CubeReflectionMapping: CubeReflectionMapping,
39598         CubeRefractionMapping: CubeRefractionMapping,
39599         EquirectangularReflectionMapping: EquirectangularReflectionMapping,
39600         EquirectangularRefractionMapping: EquirectangularRefractionMapping,
39601         CubeUVReflectionMapping: CubeUVReflectionMapping,
39602         CubeUVRefractionMapping: CubeUVRefractionMapping
39603 };
39604
39605 const TEXTURE_WRAPPING = {
39606         RepeatWrapping: RepeatWrapping,
39607         ClampToEdgeWrapping: ClampToEdgeWrapping,
39608         MirroredRepeatWrapping: MirroredRepeatWrapping
39609 };
39610
39611 const TEXTURE_FILTER = {
39612         NearestFilter: NearestFilter,
39613         NearestMipmapNearestFilter: NearestMipmapNearestFilter,
39614         NearestMipmapLinearFilter: NearestMipmapLinearFilter,
39615         LinearFilter: LinearFilter,
39616         LinearMipmapNearestFilter: LinearMipmapNearestFilter,
39617         LinearMipmapLinearFilter: LinearMipmapLinearFilter
39618 };
39619
39620 function ImageBitmapLoader( manager ) {
39621
39622         if ( typeof createImageBitmap === 'undefined' ) {
39623
39624                 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
39625
39626         }
39627
39628         if ( typeof fetch === 'undefined' ) {
39629
39630                 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
39631
39632         }
39633
39634         Loader.call( this, manager );
39635
39636         this.options = { premultiplyAlpha: 'none' };
39637
39638 }
39639
39640 ImageBitmapLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
39641
39642         constructor: ImageBitmapLoader,
39643
39644         isImageBitmapLoader: true,
39645
39646         setOptions: function setOptions( options ) {
39647
39648                 this.options = options;
39649
39650                 return this;
39651
39652         },
39653
39654         load: function ( url, onLoad, onProgress, onError ) {
39655
39656                 if ( url === undefined ) url = '';
39657
39658                 if ( this.path !== undefined ) url = this.path + url;
39659
39660                 url = this.manager.resolveURL( url );
39661
39662                 const scope = this;
39663
39664                 const cached = Cache.get( url );
39665
39666                 if ( cached !== undefined ) {
39667
39668                         scope.manager.itemStart( url );
39669
39670                         setTimeout( function () {
39671
39672                                 if ( onLoad ) onLoad( cached );
39673
39674                                 scope.manager.itemEnd( url );
39675
39676                         }, 0 );
39677
39678                         return cached;
39679
39680                 }
39681
39682                 const fetchOptions = {};
39683                 fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
39684
39685                 fetch( url, fetchOptions ).then( function ( res ) {
39686
39687                         return res.blob();
39688
39689                 } ).then( function ( blob ) {
39690
39691                         return createImageBitmap( blob, scope.options );
39692
39693                 } ).then( function ( imageBitmap ) {
39694
39695                         Cache.add( url, imageBitmap );
39696
39697                         if ( onLoad ) onLoad( imageBitmap );
39698
39699                         scope.manager.itemEnd( url );
39700
39701                 } ).catch( function ( e ) {
39702
39703                         if ( onError ) onError( e );
39704
39705                         scope.manager.itemError( url );
39706                         scope.manager.itemEnd( url );
39707
39708                 } );
39709
39710                 scope.manager.itemStart( url );
39711
39712         }
39713
39714 } );
39715
39716 function ShapePath() {
39717
39718         this.type = 'ShapePath';
39719
39720         this.color = new Color();
39721
39722         this.subPaths = [];
39723         this.currentPath = null;
39724
39725 }
39726
39727 Object.assign( ShapePath.prototype, {
39728
39729         moveTo: function ( x, y ) {
39730
39731                 this.currentPath = new Path();
39732                 this.subPaths.push( this.currentPath );
39733                 this.currentPath.moveTo( x, y );
39734
39735                 return this;
39736
39737         },
39738
39739         lineTo: function ( x, y ) {
39740
39741                 this.currentPath.lineTo( x, y );
39742
39743                 return this;
39744
39745         },
39746
39747         quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
39748
39749                 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
39750
39751                 return this;
39752
39753         },
39754
39755         bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
39756
39757                 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
39758
39759                 return this;
39760
39761         },
39762
39763         splineThru: function ( pts ) {
39764
39765                 this.currentPath.splineThru( pts );
39766
39767                 return this;
39768
39769         },
39770
39771         toShapes: function ( isCCW, noHoles ) {
39772
39773                 function toShapesNoHoles( inSubpaths ) {
39774
39775                         const shapes = [];
39776
39777                         for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) {
39778
39779                                 const tmpPath = inSubpaths[ i ];
39780
39781                                 const tmpShape = new Shape();
39782                                 tmpShape.curves = tmpPath.curves;
39783
39784                                 shapes.push( tmpShape );
39785
39786                         }
39787
39788                         return shapes;
39789
39790                 }
39791
39792                 function isPointInsidePolygon( inPt, inPolygon ) {
39793
39794                         const polyLen = inPolygon.length;
39795
39796                         // inPt on polygon contour => immediate success    or
39797                         // toggling of inside/outside at every single! intersection point of an edge
39798                         //  with the horizontal line through inPt, left of inPt
39799                         //  not counting lowerY endpoints of edges and whole edges on that line
39800                         let inside = false;
39801                         for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
39802
39803                                 let edgeLowPt = inPolygon[ p ];
39804                                 let edgeHighPt = inPolygon[ q ];
39805
39806                                 let edgeDx = edgeHighPt.x - edgeLowPt.x;
39807                                 let edgeDy = edgeHighPt.y - edgeLowPt.y;
39808
39809                                 if ( Math.abs( edgeDy ) > Number.EPSILON ) {
39810
39811                                         // not parallel
39812                                         if ( edgeDy < 0 ) {
39813
39814                                                 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
39815                                                 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
39816
39817                                         }
39818
39819                                         if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) )            continue;
39820
39821                                         if ( inPt.y === edgeLowPt.y ) {
39822
39823                                                 if ( inPt.x === edgeLowPt.x )           return  true;           // inPt is on contour ?
39824                                                 // continue;                            // no intersection or edgeLowPt => doesn't count !!!
39825
39826                                         } else {
39827
39828                                                 const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
39829                                                 if ( perpEdge === 0 )                           return  true;           // inPt is on contour ?
39830                                                 if ( perpEdge < 0 )                             continue;
39831                                                 inside = ! inside;              // true intersection left of inPt
39832
39833                                         }
39834
39835                                 } else {
39836
39837                                         // parallel or collinear
39838                                         if ( inPt.y !== edgeLowPt.y )           continue;                       // parallel
39839                                         // edge lies on the same horizontal line as inPt
39840                                         if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
39841                                                  ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )          return  true;   // inPt: Point on contour !
39842                                         // continue;
39843
39844                                 }
39845
39846                         }
39847
39848                         return  inside;
39849
39850                 }
39851
39852                 const isClockWise = ShapeUtils.isClockWise;
39853
39854                 const subPaths = this.subPaths;
39855                 if ( subPaths.length === 0 ) return [];
39856
39857                 if ( noHoles === true ) return  toShapesNoHoles( subPaths );
39858
39859
39860                 let solid, tmpPath, tmpShape;
39861                 const shapes = [];
39862
39863                 if ( subPaths.length === 1 ) {
39864
39865                         tmpPath = subPaths[ 0 ];
39866                         tmpShape = new Shape();
39867                         tmpShape.curves = tmpPath.curves;
39868                         shapes.push( tmpShape );
39869                         return shapes;
39870
39871                 }
39872
39873                 let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
39874                 holesFirst = isCCW ? ! holesFirst : holesFirst;
39875
39876                 // console.log("Holes first", holesFirst);
39877
39878                 const betterShapeHoles = [];
39879                 const newShapes = [];
39880                 let newShapeHoles = [];
39881                 let mainIdx = 0;
39882                 let tmpPoints;
39883
39884                 newShapes[ mainIdx ] = undefined;
39885                 newShapeHoles[ mainIdx ] = [];
39886
39887                 for ( let i = 0, l = subPaths.length; i < l; i ++ ) {
39888
39889                         tmpPath = subPaths[ i ];
39890                         tmpPoints = tmpPath.getPoints();
39891                         solid = isClockWise( tmpPoints );
39892                         solid = isCCW ? ! solid : solid;
39893
39894                         if ( solid ) {
39895
39896                                 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )     mainIdx ++;
39897
39898                                 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
39899                                 newShapes[ mainIdx ].s.curves = tmpPath.curves;
39900
39901                                 if ( holesFirst )       mainIdx ++;
39902                                 newShapeHoles[ mainIdx ] = [];
39903
39904                                 //console.log('cw', i);
39905
39906                         } else {
39907
39908                                 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
39909
39910                                 //console.log('ccw', i);
39911
39912                         }
39913
39914                 }
39915
39916                 // only Holes? -> probably all Shapes with wrong orientation
39917                 if ( ! newShapes[ 0 ] ) return  toShapesNoHoles( subPaths );
39918
39919
39920                 if ( newShapes.length > 1 ) {
39921
39922                         let ambiguous = false;
39923                         const toChange = [];
39924
39925                         for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
39926
39927                                 betterShapeHoles[ sIdx ] = [];
39928
39929                         }
39930
39931                         for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
39932
39933                                 const sho = newShapeHoles[ sIdx ];
39934
39935                                 for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) {
39936
39937                                         const ho = sho[ hIdx ];
39938                                         let hole_unassigned = true;
39939
39940                                         for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
39941
39942                                                 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
39943
39944                                                         if ( sIdx !== s2Idx )   toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
39945                                                         if ( hole_unassigned ) {
39946
39947                                                                 hole_unassigned = false;
39948                                                                 betterShapeHoles[ s2Idx ].push( ho );
39949
39950                                                         } else {
39951
39952                                                                 ambiguous = true;
39953
39954                                                         }
39955
39956                                                 }
39957
39958                                         }
39959
39960                                         if ( hole_unassigned ) {
39961
39962                                                 betterShapeHoles[ sIdx ].push( ho );
39963
39964                                         }
39965
39966                                 }
39967
39968                         }
39969                         // console.log("ambiguous: ", ambiguous);
39970
39971                         if ( toChange.length > 0 ) {
39972
39973                                 // console.log("to change: ", toChange);
39974                                 if ( ! ambiguous )      newShapeHoles = betterShapeHoles;
39975
39976                         }
39977
39978                 }
39979
39980                 let tmpHoles;
39981
39982                 for ( let i = 0, il = newShapes.length; i < il; i ++ ) {
39983
39984                         tmpShape = newShapes[ i ].s;
39985                         shapes.push( tmpShape );
39986                         tmpHoles = newShapeHoles[ i ];
39987
39988                         for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
39989
39990                                 tmpShape.holes.push( tmpHoles[ j ].h );
39991
39992                         }
39993
39994                 }
39995
39996                 //console.log("shape", shapes);
39997
39998                 return shapes;
39999
40000         }
40001
40002 } );
40003
40004 class Font {
40005
40006         constructor( data ) {
40007
40008                 Object.defineProperty( this, 'isFont', { value: true } );
40009
40010                 this.type = 'Font';
40011
40012                 this.data = data;
40013
40014         }
40015
40016         generateShapes( text, size = 100 ) {
40017
40018                 const shapes = [];
40019                 const paths = createPaths( text, size, this.data );
40020
40021                 for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
40022
40023                         Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
40024
40025                 }
40026
40027                 return shapes;
40028
40029         }
40030
40031 }
40032
40033 function createPaths( text, size, data ) {
40034
40035         const chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // workaround for IE11, see #13988
40036         const scale = size / data.resolution;
40037         const line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
40038
40039         const paths = [];
40040
40041         let offsetX = 0, offsetY = 0;
40042
40043         for ( let i = 0; i < chars.length; i ++ ) {
40044
40045                 const char = chars[ i ];
40046
40047                 if ( char === '\n' ) {
40048
40049                         offsetX = 0;
40050                         offsetY -= line_height;
40051
40052                 } else {
40053
40054                         const ret = createPath( char, scale, offsetX, offsetY, data );
40055                         offsetX += ret.offsetX;
40056                         paths.push( ret.path );
40057
40058                 }
40059
40060         }
40061
40062         return paths;
40063
40064 }
40065
40066 function createPath( char, scale, offsetX, offsetY, data ) {
40067
40068         const glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
40069
40070         if ( ! glyph ) {
40071
40072                 console.error( 'THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + '.' );
40073
40074                 return;
40075
40076         }
40077
40078         const path = new ShapePath();
40079
40080         let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
40081
40082         if ( glyph.o ) {
40083
40084                 const outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
40085
40086                 for ( let i = 0, l = outline.length; i < l; ) {
40087
40088                         const action = outline[ i ++ ];
40089
40090                         switch ( action ) {
40091
40092                                 case 'm': // moveTo
40093
40094                                         x = outline[ i ++ ] * scale + offsetX;
40095                                         y = outline[ i ++ ] * scale + offsetY;
40096
40097                                         path.moveTo( x, y );
40098
40099                                         break;
40100
40101                                 case 'l': // lineTo
40102
40103                                         x = outline[ i ++ ] * scale + offsetX;
40104                                         y = outline[ i ++ ] * scale + offsetY;
40105
40106                                         path.lineTo( x, y );
40107
40108                                         break;
40109
40110                                 case 'q': // quadraticCurveTo
40111
40112                                         cpx = outline[ i ++ ] * scale + offsetX;
40113                                         cpy = outline[ i ++ ] * scale + offsetY;
40114                                         cpx1 = outline[ i ++ ] * scale + offsetX;
40115                                         cpy1 = outline[ i ++ ] * scale + offsetY;
40116
40117                                         path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
40118
40119                                         break;
40120
40121                                 case 'b': // bezierCurveTo
40122
40123                                         cpx = outline[ i ++ ] * scale + offsetX;
40124                                         cpy = outline[ i ++ ] * scale + offsetY;
40125                                         cpx1 = outline[ i ++ ] * scale + offsetX;
40126                                         cpy1 = outline[ i ++ ] * scale + offsetY;
40127                                         cpx2 = outline[ i ++ ] * scale + offsetX;
40128                                         cpy2 = outline[ i ++ ] * scale + offsetY;
40129
40130                                         path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
40131
40132                                         break;
40133
40134                         }
40135
40136                 }
40137
40138         }
40139
40140         return { offsetX: glyph.ha * scale, path: path };
40141
40142 }
40143
40144 function FontLoader( manager ) {
40145
40146         Loader.call( this, manager );
40147
40148 }
40149
40150 FontLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
40151
40152         constructor: FontLoader,
40153
40154         load: function ( url, onLoad, onProgress, onError ) {
40155
40156                 const scope = this;
40157
40158                 const loader = new FileLoader( this.manager );
40159                 loader.setPath( this.path );
40160                 loader.setRequestHeader( this.requestHeader );
40161                 loader.setWithCredentials( scope.withCredentials );
40162                 loader.load( url, function ( text ) {
40163
40164                         let json;
40165
40166                         try {
40167
40168                                 json = JSON.parse( text );
40169
40170                         } catch ( e ) {
40171
40172                                 console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
40173                                 json = JSON.parse( text.substring( 65, text.length - 2 ) );
40174
40175                         }
40176
40177                         const font = scope.parse( json );
40178
40179                         if ( onLoad ) onLoad( font );
40180
40181                 }, onProgress, onError );
40182
40183         },
40184
40185         parse: function ( json ) {
40186
40187                 return new Font( json );
40188
40189         }
40190
40191 } );
40192
40193 let _context;
40194
40195 const AudioContext = {
40196
40197         getContext: function () {
40198
40199                 if ( _context === undefined ) {
40200
40201                         _context = new ( window.AudioContext || window.webkitAudioContext )();
40202
40203                 }
40204
40205                 return _context;
40206
40207         },
40208
40209         setContext: function ( value ) {
40210
40211                 _context = value;
40212
40213         }
40214
40215 };
40216
40217 function AudioLoader( manager ) {
40218
40219         Loader.call( this, manager );
40220
40221 }
40222
40223 AudioLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
40224
40225         constructor: AudioLoader,
40226
40227         load: function ( url, onLoad, onProgress, onError ) {
40228
40229                 const scope = this;
40230
40231                 const loader = new FileLoader( scope.manager );
40232                 loader.setResponseType( 'arraybuffer' );
40233                 loader.setPath( scope.path );
40234                 loader.setRequestHeader( scope.requestHeader );
40235                 loader.setWithCredentials( scope.withCredentials );
40236                 loader.load( url, function ( buffer ) {
40237
40238                         try {
40239
40240                                 // Create a copy of the buffer. The `decodeAudioData` method
40241                                 // detaches the buffer when complete, preventing reuse.
40242                                 const bufferCopy = buffer.slice( 0 );
40243
40244                                 const context = AudioContext.getContext();
40245                                 context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
40246
40247                                         onLoad( audioBuffer );
40248
40249                                 } );
40250
40251                         } catch ( e ) {
40252
40253                                 if ( onError ) {
40254
40255                                         onError( e );
40256
40257                                 } else {
40258
40259                                         console.error( e );
40260
40261                                 }
40262
40263                                 scope.manager.itemError( url );
40264
40265                         }
40266
40267                 }, onProgress, onError );
40268
40269         }
40270
40271 } );
40272
40273 function HemisphereLightProbe( skyColor, groundColor, intensity ) {
40274
40275         LightProbe.call( this, undefined, intensity );
40276
40277         const color1 = new Color().set( skyColor );
40278         const color2 = new Color().set( groundColor );
40279
40280         const sky = new Vector3( color1.r, color1.g, color1.b );
40281         const ground = new Vector3( color2.r, color2.g, color2.b );
40282
40283         // without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
40284         const c0 = Math.sqrt( Math.PI );
40285         const c1 = c0 * Math.sqrt( 0.75 );
40286
40287         this.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
40288         this.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
40289
40290 }
40291
40292 HemisphereLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
40293
40294         constructor: HemisphereLightProbe,
40295
40296         isHemisphereLightProbe: true,
40297
40298         copy: function ( source ) { // modifying colors not currently supported
40299
40300                 LightProbe.prototype.copy.call( this, source );
40301
40302                 return this;
40303
40304         },
40305
40306         toJSON: function ( meta ) {
40307
40308                 const data = LightProbe.prototype.toJSON.call( this, meta );
40309
40310                 // data.sh = this.sh.toArray(); // todo
40311
40312                 return data;
40313
40314         }
40315
40316 } );
40317
40318 function AmbientLightProbe( color, intensity ) {
40319
40320         LightProbe.call( this, undefined, intensity );
40321
40322         const color1 = new Color().set( color );
40323
40324         // without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
40325         this.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );
40326
40327 }
40328
40329 AmbientLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
40330
40331         constructor: AmbientLightProbe,
40332
40333         isAmbientLightProbe: true,
40334
40335         copy: function ( source ) { // modifying color not currently supported
40336
40337                 LightProbe.prototype.copy.call( this, source );
40338
40339                 return this;
40340
40341         },
40342
40343         toJSON: function ( meta ) {
40344
40345                 const data = LightProbe.prototype.toJSON.call( this, meta );
40346
40347                 // data.sh = this.sh.toArray(); // todo
40348
40349                 return data;
40350
40351         }
40352
40353 } );
40354
40355 const _eyeRight = new Matrix4();
40356 const _eyeLeft = new Matrix4();
40357
40358 function StereoCamera() {
40359
40360         this.type = 'StereoCamera';
40361
40362         this.aspect = 1;
40363
40364         this.eyeSep = 0.064;
40365
40366         this.cameraL = new PerspectiveCamera();
40367         this.cameraL.layers.enable( 1 );
40368         this.cameraL.matrixAutoUpdate = false;
40369
40370         this.cameraR = new PerspectiveCamera();
40371         this.cameraR.layers.enable( 2 );
40372         this.cameraR.matrixAutoUpdate = false;
40373
40374         this._cache = {
40375                 focus: null,
40376                 fov: null,
40377                 aspect: null,
40378                 near: null,
40379                 far: null,
40380                 zoom: null,
40381                 eyeSep: null
40382         };
40383
40384 }
40385
40386 Object.assign( StereoCamera.prototype, {
40387
40388         update: function ( camera ) {
40389
40390                 const cache = this._cache;
40391
40392                 const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
40393                         cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
40394                         cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
40395
40396                 if ( needsUpdate ) {
40397
40398                         cache.focus = camera.focus;
40399                         cache.fov = camera.fov;
40400                         cache.aspect = camera.aspect * this.aspect;
40401                         cache.near = camera.near;
40402                         cache.far = camera.far;
40403                         cache.zoom = camera.zoom;
40404                         cache.eyeSep = this.eyeSep;
40405
40406                         // Off-axis stereoscopic effect based on
40407                         // http://paulbourke.net/stereographics/stereorender/
40408
40409                         const projectionMatrix = camera.projectionMatrix.clone();
40410                         const eyeSepHalf = cache.eyeSep / 2;
40411                         const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
40412                         const ymax = ( cache.near * Math.tan( MathUtils.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
40413                         let xmin, xmax;
40414
40415                         // translate xOffset
40416
40417                         _eyeLeft.elements[ 12 ] = - eyeSepHalf;
40418                         _eyeRight.elements[ 12 ] = eyeSepHalf;
40419
40420                         // for left eye
40421
40422                         xmin = - ymax * cache.aspect + eyeSepOnProjection;
40423                         xmax = ymax * cache.aspect + eyeSepOnProjection;
40424
40425                         projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
40426                         projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
40427
40428                         this.cameraL.projectionMatrix.copy( projectionMatrix );
40429
40430                         // for right eye
40431
40432                         xmin = - ymax * cache.aspect - eyeSepOnProjection;
40433                         xmax = ymax * cache.aspect - eyeSepOnProjection;
40434
40435                         projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
40436                         projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
40437
40438                         this.cameraR.projectionMatrix.copy( projectionMatrix );
40439
40440                 }
40441
40442                 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
40443                 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
40444
40445         }
40446
40447 } );
40448
40449 class Clock {
40450
40451         constructor( autoStart ) {
40452
40453                 this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
40454
40455                 this.startTime = 0;
40456                 this.oldTime = 0;
40457                 this.elapsedTime = 0;
40458
40459                 this.running = false;
40460
40461         }
40462
40463         start() {
40464
40465                 this.startTime = now();
40466
40467                 this.oldTime = this.startTime;
40468                 this.elapsedTime = 0;
40469                 this.running = true;
40470
40471         }
40472
40473         stop() {
40474
40475                 this.getElapsedTime();
40476                 this.running = false;
40477                 this.autoStart = false;
40478
40479         }
40480
40481         getElapsedTime() {
40482
40483                 this.getDelta();
40484                 return this.elapsedTime;
40485
40486         }
40487
40488         getDelta() {
40489
40490                 let diff = 0;
40491
40492                 if ( this.autoStart && ! this.running ) {
40493
40494                         this.start();
40495                         return 0;
40496
40497                 }
40498
40499                 if ( this.running ) {
40500
40501                         const newTime = now();
40502
40503                         diff = ( newTime - this.oldTime ) / 1000;
40504                         this.oldTime = newTime;
40505
40506                         this.elapsedTime += diff;
40507
40508                 }
40509
40510                 return diff;
40511
40512         }
40513
40514 }
40515
40516 function now() {
40517
40518         return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
40519
40520 }
40521
40522 const _position$2 = /*@__PURE__*/ new Vector3();
40523 const _quaternion$3 = /*@__PURE__*/ new Quaternion();
40524 const _scale$1 = /*@__PURE__*/ new Vector3();
40525 const _orientation = /*@__PURE__*/ new Vector3();
40526
40527 class AudioListener extends Object3D {
40528
40529         constructor() {
40530
40531                 super();
40532
40533                 this.type = 'AudioListener';
40534
40535                 this.context = AudioContext.getContext();
40536
40537                 this.gain = this.context.createGain();
40538                 this.gain.connect( this.context.destination );
40539
40540                 this.filter = null;
40541
40542                 this.timeDelta = 0;
40543
40544                 // private
40545
40546                 this._clock = new Clock();
40547
40548         }
40549
40550         getInput() {
40551
40552                 return this.gain;
40553
40554         }
40555
40556         removeFilter() {
40557
40558                 if ( this.filter !== null ) {
40559
40560                         this.gain.disconnect( this.filter );
40561                         this.filter.disconnect( this.context.destination );
40562                         this.gain.connect( this.context.destination );
40563                         this.filter = null;
40564
40565                 }
40566
40567                 return this;
40568
40569         }
40570
40571         getFilter() {
40572
40573                 return this.filter;
40574
40575         }
40576
40577         setFilter( value ) {
40578
40579                 if ( this.filter !== null ) {
40580
40581                         this.gain.disconnect( this.filter );
40582                         this.filter.disconnect( this.context.destination );
40583
40584                 } else {
40585
40586                         this.gain.disconnect( this.context.destination );
40587
40588                 }
40589
40590                 this.filter = value;
40591                 this.gain.connect( this.filter );
40592                 this.filter.connect( this.context.destination );
40593
40594                 return this;
40595
40596         }
40597
40598         getMasterVolume() {
40599
40600                 return this.gain.gain.value;
40601
40602         }
40603
40604         setMasterVolume( value ) {
40605
40606                 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
40607
40608                 return this;
40609
40610         }
40611
40612         updateMatrixWorld( force ) {
40613
40614                 super.updateMatrixWorld( force );
40615
40616                 const listener = this.context.listener;
40617                 const up = this.up;
40618
40619                 this.timeDelta = this._clock.getDelta();
40620
40621                 this.matrixWorld.decompose( _position$2, _quaternion$3, _scale$1 );
40622
40623                 _orientation.set( 0, 0, - 1 ).applyQuaternion( _quaternion$3 );
40624
40625                 if ( listener.positionX ) {
40626
40627                         // code path for Chrome (see #14393)
40628
40629                         const endTime = this.context.currentTime + this.timeDelta;
40630
40631                         listener.positionX.linearRampToValueAtTime( _position$2.x, endTime );
40632                         listener.positionY.linearRampToValueAtTime( _position$2.y, endTime );
40633                         listener.positionZ.linearRampToValueAtTime( _position$2.z, endTime );
40634                         listener.forwardX.linearRampToValueAtTime( _orientation.x, endTime );
40635                         listener.forwardY.linearRampToValueAtTime( _orientation.y, endTime );
40636                         listener.forwardZ.linearRampToValueAtTime( _orientation.z, endTime );
40637                         listener.upX.linearRampToValueAtTime( up.x, endTime );
40638                         listener.upY.linearRampToValueAtTime( up.y, endTime );
40639                         listener.upZ.linearRampToValueAtTime( up.z, endTime );
40640
40641                 } else {
40642
40643                         listener.setPosition( _position$2.x, _position$2.y, _position$2.z );
40644                         listener.setOrientation( _orientation.x, _orientation.y, _orientation.z, up.x, up.y, up.z );
40645
40646                 }
40647
40648         }
40649
40650 }
40651
40652 class Audio extends Object3D {
40653
40654         constructor( listener ) {
40655
40656                 super();
40657
40658                 this.type = 'Audio';
40659
40660                 this.listener = listener;
40661                 this.context = listener.context;
40662
40663                 this.gain = this.context.createGain();
40664                 this.gain.connect( listener.getInput() );
40665
40666                 this.autoplay = false;
40667
40668                 this.buffer = null;
40669                 this.detune = 0;
40670                 this.loop = false;
40671                 this.loopStart = 0;
40672                 this.loopEnd = 0;
40673                 this.offset = 0;
40674                 this.duration = undefined;
40675                 this.playbackRate = 1;
40676                 this.isPlaying = false;
40677                 this.hasPlaybackControl = true;
40678                 this.source = null;
40679                 this.sourceType = 'empty';
40680
40681                 this._startedAt = 0;
40682                 this._progress = 0;
40683                 this._connected = false;
40684
40685                 this.filters = [];
40686
40687         }
40688
40689         getOutput() {
40690
40691                 return this.gain;
40692
40693         }
40694
40695         setNodeSource( audioNode ) {
40696
40697                 this.hasPlaybackControl = false;
40698                 this.sourceType = 'audioNode';
40699                 this.source = audioNode;
40700                 this.connect();
40701
40702                 return this;
40703
40704         }
40705
40706         setMediaElementSource( mediaElement ) {
40707
40708                 this.hasPlaybackControl = false;
40709                 this.sourceType = 'mediaNode';
40710                 this.source = this.context.createMediaElementSource( mediaElement );
40711                 this.connect();
40712
40713                 return this;
40714
40715         }
40716
40717         setMediaStreamSource( mediaStream ) {
40718
40719                 this.hasPlaybackControl = false;
40720                 this.sourceType = 'mediaStreamNode';
40721                 this.source = this.context.createMediaStreamSource( mediaStream );
40722                 this.connect();
40723
40724                 return this;
40725
40726         }
40727
40728         setBuffer( audioBuffer ) {
40729
40730                 this.buffer = audioBuffer;
40731                 this.sourceType = 'buffer';
40732
40733                 if ( this.autoplay ) this.play();
40734
40735                 return this;
40736
40737         }
40738
40739         play( delay = 0 ) {
40740
40741                 if ( this.isPlaying === true ) {
40742
40743                         console.warn( 'THREE.Audio: Audio is already playing.' );
40744                         return;
40745
40746                 }
40747
40748                 if ( this.hasPlaybackControl === false ) {
40749
40750                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40751                         return;
40752
40753                 }
40754
40755                 this._startedAt = this.context.currentTime + delay;
40756
40757                 const source = this.context.createBufferSource();
40758                 source.buffer = this.buffer;
40759                 source.loop = this.loop;
40760                 source.loopStart = this.loopStart;
40761                 source.loopEnd = this.loopEnd;
40762                 source.onended = this.onEnded.bind( this );
40763                 source.start( this._startedAt, this._progress + this.offset, this.duration );
40764
40765                 this.isPlaying = true;
40766
40767                 this.source = source;
40768
40769                 this.setDetune( this.detune );
40770                 this.setPlaybackRate( this.playbackRate );
40771
40772                 return this.connect();
40773
40774         }
40775
40776         pause() {
40777
40778                 if ( this.hasPlaybackControl === false ) {
40779
40780                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40781                         return;
40782
40783                 }
40784
40785                 if ( this.isPlaying === true ) {
40786
40787                         // update current progress
40788
40789                         this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
40790
40791                         if ( this.loop === true ) {
40792
40793                                 // ensure _progress does not exceed duration with looped audios
40794
40795                                 this._progress = this._progress % ( this.duration || this.buffer.duration );
40796
40797                         }
40798
40799                         this.source.stop();
40800                         this.source.onended = null;
40801
40802                         this.isPlaying = false;
40803
40804                 }
40805
40806                 return this;
40807
40808         }
40809
40810         stop() {
40811
40812                 if ( this.hasPlaybackControl === false ) {
40813
40814                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40815                         return;
40816
40817                 }
40818
40819                 this._progress = 0;
40820
40821                 this.source.stop();
40822                 this.source.onended = null;
40823                 this.isPlaying = false;
40824
40825                 return this;
40826
40827         }
40828
40829         connect() {
40830
40831                 if ( this.filters.length > 0 ) {
40832
40833                         this.source.connect( this.filters[ 0 ] );
40834
40835                         for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
40836
40837                                 this.filters[ i - 1 ].connect( this.filters[ i ] );
40838
40839                         }
40840
40841                         this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
40842
40843                 } else {
40844
40845                         this.source.connect( this.getOutput() );
40846
40847                 }
40848
40849                 this._connected = true;
40850
40851                 return this;
40852
40853         }
40854
40855         disconnect() {
40856
40857                 if ( this.filters.length > 0 ) {
40858
40859                         this.source.disconnect( this.filters[ 0 ] );
40860
40861                         for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
40862
40863                                 this.filters[ i - 1 ].disconnect( this.filters[ i ] );
40864
40865                         }
40866
40867                         this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
40868
40869                 } else {
40870
40871                         this.source.disconnect( this.getOutput() );
40872
40873                 }
40874
40875                 this._connected = false;
40876
40877                 return this;
40878
40879         }
40880
40881         getFilters() {
40882
40883                 return this.filters;
40884
40885         }
40886
40887         setFilters( value ) {
40888
40889                 if ( ! value ) value = [];
40890
40891                 if ( this._connected === true ) {
40892
40893                         this.disconnect();
40894                         this.filters = value.slice();
40895                         this.connect();
40896
40897                 } else {
40898
40899                         this.filters = value.slice();
40900
40901                 }
40902
40903                 return this;
40904
40905         }
40906
40907         setDetune( value ) {
40908
40909                 this.detune = value;
40910
40911                 if ( this.source.detune === undefined ) return; // only set detune when available
40912
40913                 if ( this.isPlaying === true ) {
40914
40915                         this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
40916
40917                 }
40918
40919                 return this;
40920
40921         }
40922
40923         getDetune() {
40924
40925                 return this.detune;
40926
40927         }
40928
40929         getFilter() {
40930
40931                 return this.getFilters()[ 0 ];
40932
40933         }
40934
40935         setFilter( filter ) {
40936
40937                 return this.setFilters( filter ? [ filter ] : [] );
40938
40939         }
40940
40941         setPlaybackRate( value ) {
40942
40943                 if ( this.hasPlaybackControl === false ) {
40944
40945                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40946                         return;
40947
40948                 }
40949
40950                 this.playbackRate = value;
40951
40952                 if ( this.isPlaying === true ) {
40953
40954                         this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
40955
40956                 }
40957
40958                 return this;
40959
40960         }
40961
40962         getPlaybackRate() {
40963
40964                 return this.playbackRate;
40965
40966         }
40967
40968         onEnded() {
40969
40970                 this.isPlaying = false;
40971
40972         }
40973
40974         getLoop() {
40975
40976                 if ( this.hasPlaybackControl === false ) {
40977
40978                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40979                         return false;
40980
40981                 }
40982
40983                 return this.loop;
40984
40985         }
40986
40987         setLoop( value ) {
40988
40989                 if ( this.hasPlaybackControl === false ) {
40990
40991                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
40992                         return;
40993
40994                 }
40995
40996                 this.loop = value;
40997
40998                 if ( this.isPlaying === true ) {
40999
41000                         this.source.loop = this.loop;
41001
41002                 }
41003
41004                 return this;
41005
41006         }
41007
41008         setLoopStart( value ) {
41009
41010                 this.loopStart = value;
41011
41012                 return this;
41013
41014         }
41015
41016         setLoopEnd( value ) {
41017
41018                 this.loopEnd = value;
41019
41020                 return this;
41021
41022         }
41023
41024         getVolume() {
41025
41026                 return this.gain.gain.value;
41027
41028         }
41029
41030         setVolume( value ) {
41031
41032                 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
41033
41034                 return this;
41035
41036         }
41037
41038 }
41039
41040 const _position$3 = /*@__PURE__*/ new Vector3();
41041 const _quaternion$4 = /*@__PURE__*/ new Quaternion();
41042 const _scale$2 = /*@__PURE__*/ new Vector3();
41043 const _orientation$1 = /*@__PURE__*/ new Vector3();
41044
41045 class PositionalAudio extends Audio {
41046
41047         constructor( listener ) {
41048
41049                 super( listener );
41050
41051                 this.panner = this.context.createPanner();
41052                 this.panner.panningModel = 'HRTF';
41053                 this.panner.connect( this.gain );
41054
41055         }
41056
41057         getOutput() {
41058
41059                 return this.panner;
41060
41061         }
41062
41063         getRefDistance() {
41064
41065                 return this.panner.refDistance;
41066
41067         }
41068
41069         setRefDistance( value ) {
41070
41071                 this.panner.refDistance = value;
41072
41073                 return this;
41074
41075         }
41076
41077         getRolloffFactor() {
41078
41079                 return this.panner.rolloffFactor;
41080
41081         }
41082
41083         setRolloffFactor( value ) {
41084
41085                 this.panner.rolloffFactor = value;
41086
41087                 return this;
41088
41089         }
41090
41091         getDistanceModel() {
41092
41093                 return this.panner.distanceModel;
41094
41095         }
41096
41097         setDistanceModel( value ) {
41098
41099                 this.panner.distanceModel = value;
41100
41101                 return this;
41102
41103         }
41104
41105         getMaxDistance() {
41106
41107                 return this.panner.maxDistance;
41108
41109         }
41110
41111         setMaxDistance( value ) {
41112
41113                 this.panner.maxDistance = value;
41114
41115                 return this;
41116
41117         }
41118
41119         setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
41120
41121                 this.panner.coneInnerAngle = coneInnerAngle;
41122                 this.panner.coneOuterAngle = coneOuterAngle;
41123                 this.panner.coneOuterGain = coneOuterGain;
41124
41125                 return this;
41126
41127         }
41128
41129         updateMatrixWorld( force ) {
41130
41131                 super.updateMatrixWorld( force );
41132
41133                 if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
41134
41135                 this.matrixWorld.decompose( _position$3, _quaternion$4, _scale$2 );
41136
41137                 _orientation$1.set( 0, 0, 1 ).applyQuaternion( _quaternion$4 );
41138
41139                 const panner = this.panner;
41140
41141                 if ( panner.positionX ) {
41142
41143                         // code path for Chrome and Firefox (see #14393)
41144
41145                         const endTime = this.context.currentTime + this.listener.timeDelta;
41146
41147                         panner.positionX.linearRampToValueAtTime( _position$3.x, endTime );
41148                         panner.positionY.linearRampToValueAtTime( _position$3.y, endTime );
41149                         panner.positionZ.linearRampToValueAtTime( _position$3.z, endTime );
41150                         panner.orientationX.linearRampToValueAtTime( _orientation$1.x, endTime );
41151                         panner.orientationY.linearRampToValueAtTime( _orientation$1.y, endTime );
41152                         panner.orientationZ.linearRampToValueAtTime( _orientation$1.z, endTime );
41153
41154                 } else {
41155
41156                         panner.setPosition( _position$3.x, _position$3.y, _position$3.z );
41157                         panner.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z );
41158
41159                 }
41160
41161         }
41162
41163 }
41164
41165 class AudioAnalyser {
41166
41167         constructor( audio, fftSize = 2048 ) {
41168
41169                 this.analyser = audio.context.createAnalyser();
41170                 this.analyser.fftSize = fftSize;
41171
41172                 this.data = new Uint8Array( this.analyser.frequencyBinCount );
41173
41174                 audio.getOutput().connect( this.analyser );
41175
41176         }
41177
41178
41179         getFrequencyData() {
41180
41181                 this.analyser.getByteFrequencyData( this.data );
41182
41183                 return this.data;
41184
41185         }
41186
41187         getAverageFrequency() {
41188
41189                 let value = 0;
41190                 const data = this.getFrequencyData();
41191
41192                 for ( let i = 0; i < data.length; i ++ ) {
41193
41194                         value += data[ i ];
41195
41196                 }
41197
41198                 return value / data.length;
41199
41200         }
41201
41202 }
41203
41204 function PropertyMixer( binding, typeName, valueSize ) {
41205
41206         this.binding = binding;
41207         this.valueSize = valueSize;
41208
41209         let mixFunction,
41210                 mixFunctionAdditive,
41211                 setIdentity;
41212
41213         // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
41214         //
41215         // interpolators can use .buffer as their .result
41216         // the data then goes to 'incoming'
41217         //
41218         // 'accu0' and 'accu1' are used frame-interleaved for
41219         // the cumulative result and are compared to detect
41220         // changes
41221         //
41222         // 'orig' stores the original state of the property
41223         //
41224         // 'add' is used for additive cumulative results
41225         //
41226         // 'work' is optional and is only present for quaternion types. It is used
41227         // to store intermediate quaternion multiplication results
41228
41229         switch ( typeName ) {
41230
41231                 case 'quaternion':
41232                         mixFunction = this._slerp;
41233                         mixFunctionAdditive = this._slerpAdditive;
41234                         setIdentity = this._setAdditiveIdentityQuaternion;
41235
41236                         this.buffer = new Float64Array( valueSize * 6 );
41237                         this._workIndex = 5;
41238                         break;
41239
41240                 case 'string':
41241                 case 'bool':
41242                         mixFunction = this._select;
41243
41244                         // Use the regular mix function and for additive on these types,
41245                         // additive is not relevant for non-numeric types
41246                         mixFunctionAdditive = this._select;
41247
41248                         setIdentity = this._setAdditiveIdentityOther;
41249
41250                         this.buffer = new Array( valueSize * 5 );
41251                         break;
41252
41253                 default:
41254                         mixFunction = this._lerp;
41255                         mixFunctionAdditive = this._lerpAdditive;
41256                         setIdentity = this._setAdditiveIdentityNumeric;
41257
41258                         this.buffer = new Float64Array( valueSize * 5 );
41259
41260         }
41261
41262         this._mixBufferRegion = mixFunction;
41263         this._mixBufferRegionAdditive = mixFunctionAdditive;
41264         this._setIdentity = setIdentity;
41265         this._origIndex = 3;
41266         this._addIndex = 4;
41267
41268         this.cumulativeWeight = 0;
41269         this.cumulativeWeightAdditive = 0;
41270
41271         this.useCount = 0;
41272         this.referenceCount = 0;
41273
41274 }
41275
41276 Object.assign( PropertyMixer.prototype, {
41277
41278         // accumulate data in the 'incoming' region into 'accu<i>'
41279         accumulate: function ( accuIndex, weight ) {
41280
41281                 // note: happily accumulating nothing when weight = 0, the caller knows
41282                 // the weight and shouldn't have made the call in the first place
41283
41284                 const buffer = this.buffer,
41285                         stride = this.valueSize,
41286                         offset = accuIndex * stride + stride;
41287
41288                 let currentWeight = this.cumulativeWeight;
41289
41290                 if ( currentWeight === 0 ) {
41291
41292                         // accuN := incoming * weight
41293
41294                         for ( let i = 0; i !== stride; ++ i ) {
41295
41296                                 buffer[ offset + i ] = buffer[ i ];
41297
41298                         }
41299
41300                         currentWeight = weight;
41301
41302                 } else {
41303
41304                         // accuN := accuN + incoming * weight
41305
41306                         currentWeight += weight;
41307                         const mix = weight / currentWeight;
41308                         this._mixBufferRegion( buffer, offset, 0, mix, stride );
41309
41310                 }
41311
41312                 this.cumulativeWeight = currentWeight;
41313
41314         },
41315
41316         // accumulate data in the 'incoming' region into 'add'
41317         accumulateAdditive: function ( weight ) {
41318
41319                 const buffer = this.buffer,
41320                         stride = this.valueSize,
41321                         offset = stride * this._addIndex;
41322
41323                 if ( this.cumulativeWeightAdditive === 0 ) {
41324
41325                         // add = identity
41326
41327                         this._setIdentity();
41328
41329                 }
41330
41331                 // add := add + incoming * weight
41332
41333                 this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
41334                 this.cumulativeWeightAdditive += weight;
41335
41336         },
41337
41338         // apply the state of 'accu<i>' to the binding when accus differ
41339         apply: function ( accuIndex ) {
41340
41341                 const stride = this.valueSize,
41342                         buffer = this.buffer,
41343                         offset = accuIndex * stride + stride,
41344
41345                         weight = this.cumulativeWeight,
41346                         weightAdditive = this.cumulativeWeightAdditive,
41347
41348                         binding = this.binding;
41349
41350                 this.cumulativeWeight = 0;
41351                 this.cumulativeWeightAdditive = 0;
41352
41353                 if ( weight < 1 ) {
41354
41355                         // accuN := accuN + original * ( 1 - cumulativeWeight )
41356
41357                         const originalValueOffset = stride * this._origIndex;
41358
41359                         this._mixBufferRegion(
41360                                 buffer, offset, originalValueOffset, 1 - weight, stride );
41361
41362                 }
41363
41364                 if ( weightAdditive > 0 ) {
41365
41366                         // accuN := accuN + additive accuN
41367
41368                         this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
41369
41370                 }
41371
41372                 for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
41373
41374                         if ( buffer[ i ] !== buffer[ i + stride ] ) {
41375
41376                                 // value has changed -> update scene graph
41377
41378                                 binding.setValue( buffer, offset );
41379                                 break;
41380
41381                         }
41382
41383                 }
41384
41385         },
41386
41387         // remember the state of the bound property and copy it to both accus
41388         saveOriginalState: function () {
41389
41390                 const binding = this.binding;
41391
41392                 const buffer = this.buffer,
41393                         stride = this.valueSize,
41394
41395                         originalValueOffset = stride * this._origIndex;
41396
41397                 binding.getValue( buffer, originalValueOffset );
41398
41399                 // accu[0..1] := orig -- initially detect changes against the original
41400                 for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
41401
41402                         buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
41403
41404                 }
41405
41406                 // Add to identity for additive
41407                 this._setIdentity();
41408
41409                 this.cumulativeWeight = 0;
41410                 this.cumulativeWeightAdditive = 0;
41411
41412         },
41413
41414         // apply the state previously taken via 'saveOriginalState' to the binding
41415         restoreOriginalState: function () {
41416
41417                 const originalValueOffset = this.valueSize * 3;
41418                 this.binding.setValue( this.buffer, originalValueOffset );
41419
41420         },
41421
41422         _setAdditiveIdentityNumeric: function () {
41423
41424                 const startIndex = this._addIndex * this.valueSize;
41425                 const endIndex = startIndex + this.valueSize;
41426
41427                 for ( let i = startIndex; i < endIndex; i ++ ) {
41428
41429                         this.buffer[ i ] = 0;
41430
41431                 }
41432
41433         },
41434
41435         _setAdditiveIdentityQuaternion: function () {
41436
41437                 this._setAdditiveIdentityNumeric();
41438                 this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
41439
41440         },
41441
41442         _setAdditiveIdentityOther: function () {
41443
41444                 const startIndex = this._origIndex * this.valueSize;
41445                 const targetIndex = this._addIndex * this.valueSize;
41446
41447                 for ( let i = 0; i < this.valueSize; i ++ ) {
41448
41449                         this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
41450
41451                 }
41452
41453         },
41454
41455
41456         // mix functions
41457
41458         _select: function ( buffer, dstOffset, srcOffset, t, stride ) {
41459
41460                 if ( t >= 0.5 ) {
41461
41462                         for ( let i = 0; i !== stride; ++ i ) {
41463
41464                                 buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
41465
41466                         }
41467
41468                 }
41469
41470         },
41471
41472         _slerp: function ( buffer, dstOffset, srcOffset, t ) {
41473
41474                 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
41475
41476         },
41477
41478         _slerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
41479
41480                 const workOffset = this._workIndex * stride;
41481
41482                 // Store result in intermediate buffer offset
41483                 Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
41484
41485                 // Slerp to the intermediate result
41486                 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
41487
41488         },
41489
41490         _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
41491
41492                 const s = 1 - t;
41493
41494                 for ( let i = 0; i !== stride; ++ i ) {
41495
41496                         const j = dstOffset + i;
41497
41498                         buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
41499
41500                 }
41501
41502         },
41503
41504         _lerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
41505
41506                 for ( let i = 0; i !== stride; ++ i ) {
41507
41508                         const j = dstOffset + i;
41509
41510                         buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
41511
41512                 }
41513
41514         }
41515
41516 } );
41517
41518 // Characters [].:/ are reserved for track binding syntax.
41519 const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
41520 const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
41521
41522 // Attempts to allow node names from any language. ES5's `\w` regexp matches
41523 // only latin characters, and the unicode \p{L} is not yet supported. So
41524 // instead, we exclude reserved characters and match everything else.
41525 const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
41526 const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
41527
41528 // Parent directories, delimited by '/' or ':'. Currently unused, but must
41529 // be matched to parse the rest of the track name.
41530 const _directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
41531
41532 // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
41533 const _nodeRe = /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
41534
41535 // Object on target node, and accessor. May not contain reserved
41536 // characters. Accessor may contain any character except closing bracket.
41537 const _objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
41538
41539 // Property and accessor. May not contain reserved characters. Accessor may
41540 // contain any non-bracket characters.
41541 const _propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
41542
41543 const _trackRe = new RegExp( ''
41544         + '^'
41545         + _directoryRe
41546         + _nodeRe
41547         + _objectRe
41548         + _propertyRe
41549         + '$'
41550 );
41551
41552 const _supportedObjectNames = [ 'material', 'materials', 'bones' ];
41553
41554 function Composite( targetGroup, path, optionalParsedPath ) {
41555
41556         const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
41557
41558         this._targetGroup = targetGroup;
41559         this._bindings = targetGroup.subscribe_( path, parsedPath );
41560
41561 }
41562
41563 Object.assign( Composite.prototype, {
41564
41565         getValue: function ( array, offset ) {
41566
41567                 this.bind(); // bind all binding
41568
41569                 const firstValidIndex = this._targetGroup.nCachedObjects_,
41570                         binding = this._bindings[ firstValidIndex ];
41571
41572                 // and only call .getValue on the first
41573                 if ( binding !== undefined ) binding.getValue( array, offset );
41574
41575         },
41576
41577         setValue: function ( array, offset ) {
41578
41579                 const bindings = this._bindings;
41580
41581                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
41582
41583                         bindings[ i ].setValue( array, offset );
41584
41585                 }
41586
41587         },
41588
41589         bind: function () {
41590
41591                 const bindings = this._bindings;
41592
41593                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
41594
41595                         bindings[ i ].bind();
41596
41597                 }
41598
41599         },
41600
41601         unbind: function () {
41602
41603                 const bindings = this._bindings;
41604
41605                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
41606
41607                         bindings[ i ].unbind();
41608
41609                 }
41610
41611         }
41612
41613 } );
41614
41615
41616 function PropertyBinding( rootNode, path, parsedPath ) {
41617
41618         this.path = path;
41619         this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
41620
41621         this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
41622
41623         this.rootNode = rootNode;
41624
41625 }
41626
41627 Object.assign( PropertyBinding, {
41628
41629         Composite: Composite,
41630
41631         create: function ( root, path, parsedPath ) {
41632
41633                 if ( ! ( root && root.isAnimationObjectGroup ) ) {
41634
41635                         return new PropertyBinding( root, path, parsedPath );
41636
41637                 } else {
41638
41639                         return new PropertyBinding.Composite( root, path, parsedPath );
41640
41641                 }
41642
41643         },
41644
41645         /**
41646          * Replaces spaces with underscores and removes unsupported characters from
41647          * node names, to ensure compatibility with parseTrackName().
41648          *
41649          * @param {string} name Node name to be sanitized.
41650          * @return {string}
41651          */
41652         sanitizeNodeName: function ( name ) {
41653
41654                 return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
41655
41656         },
41657
41658         parseTrackName: function ( trackName ) {
41659
41660                 const matches = _trackRe.exec( trackName );
41661
41662                 if ( ! matches ) {
41663
41664                         throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
41665
41666                 }
41667
41668                 const results = {
41669                         // directoryName: matches[ 1 ], // (tschw) currently unused
41670                         nodeName: matches[ 2 ],
41671                         objectName: matches[ 3 ],
41672                         objectIndex: matches[ 4 ],
41673                         propertyName: matches[ 5 ], // required
41674                         propertyIndex: matches[ 6 ]
41675                 };
41676
41677                 const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
41678
41679                 if ( lastDot !== undefined && lastDot !== - 1 ) {
41680
41681                         const objectName = results.nodeName.substring( lastDot + 1 );
41682
41683                         // Object names must be checked against an allowlist. Otherwise, there
41684                         // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
41685                         // 'bar' could be the objectName, or part of a nodeName (which can
41686                         // include '.' characters).
41687                         if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
41688
41689                                 results.nodeName = results.nodeName.substring( 0, lastDot );
41690                                 results.objectName = objectName;
41691
41692                         }
41693
41694                 }
41695
41696                 if ( results.propertyName === null || results.propertyName.length === 0 ) {
41697
41698                         throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
41699
41700                 }
41701
41702                 return results;
41703
41704         },
41705
41706         findNode: function ( root, nodeName ) {
41707
41708                 if ( ! nodeName || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
41709
41710                         return root;
41711
41712                 }
41713
41714                 // search into skeleton bones.
41715                 if ( root.skeleton ) {
41716
41717                         const bone = root.skeleton.getBoneByName( nodeName );
41718
41719                         if ( bone !== undefined ) {
41720
41721                                 return bone;
41722
41723                         }
41724
41725                 }
41726
41727                 // search into node subtree.
41728                 if ( root.children ) {
41729
41730                         const searchNodeSubtree = function ( children ) {
41731
41732                                 for ( let i = 0; i < children.length; i ++ ) {
41733
41734                                         const childNode = children[ i ];
41735
41736                                         if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
41737
41738                                                 return childNode;
41739
41740                                         }
41741
41742                                         const result = searchNodeSubtree( childNode.children );
41743
41744                                         if ( result ) return result;
41745
41746                                 }
41747
41748                                 return null;
41749
41750                         };
41751
41752                         const subTreeNode = searchNodeSubtree( root.children );
41753
41754                         if ( subTreeNode ) {
41755
41756                                 return subTreeNode;
41757
41758                         }
41759
41760                 }
41761
41762                 return null;
41763
41764         }
41765
41766 } );
41767
41768 Object.assign( PropertyBinding.prototype, { // prototype, continued
41769
41770         // these are used to "bind" a nonexistent property
41771         _getValue_unavailable: function () {},
41772         _setValue_unavailable: function () {},
41773
41774         BindingType: {
41775                 Direct: 0,
41776                 EntireArray: 1,
41777                 ArrayElement: 2,
41778                 HasFromToArray: 3
41779         },
41780
41781         Versioning: {
41782                 None: 0,
41783                 NeedsUpdate: 1,
41784                 MatrixWorldNeedsUpdate: 2
41785         },
41786
41787         GetterByBindingType: [
41788
41789                 function getValue_direct( buffer, offset ) {
41790
41791                         buffer[ offset ] = this.node[ this.propertyName ];
41792
41793                 },
41794
41795                 function getValue_array( buffer, offset ) {
41796
41797                         const source = this.resolvedProperty;
41798
41799                         for ( let i = 0, n = source.length; i !== n; ++ i ) {
41800
41801                                 buffer[ offset ++ ] = source[ i ];
41802
41803                         }
41804
41805                 },
41806
41807                 function getValue_arrayElement( buffer, offset ) {
41808
41809                         buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
41810
41811                 },
41812
41813                 function getValue_toArray( buffer, offset ) {
41814
41815                         this.resolvedProperty.toArray( buffer, offset );
41816
41817                 }
41818
41819         ],
41820
41821         SetterByBindingTypeAndVersioning: [
41822
41823                 [
41824                         // Direct
41825
41826                         function setValue_direct( buffer, offset ) {
41827
41828                                 this.targetObject[ this.propertyName ] = buffer[ offset ];
41829
41830                         },
41831
41832                         function setValue_direct_setNeedsUpdate( buffer, offset ) {
41833
41834                                 this.targetObject[ this.propertyName ] = buffer[ offset ];
41835                                 this.targetObject.needsUpdate = true;
41836
41837                         },
41838
41839                         function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
41840
41841                                 this.targetObject[ this.propertyName ] = buffer[ offset ];
41842                                 this.targetObject.matrixWorldNeedsUpdate = true;
41843
41844                         }
41845
41846                 ], [
41847
41848                         // EntireArray
41849
41850                         function setValue_array( buffer, offset ) {
41851
41852                                 const dest = this.resolvedProperty;
41853
41854                                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
41855
41856                                         dest[ i ] = buffer[ offset ++ ];
41857
41858                                 }
41859
41860                         },
41861
41862                         function setValue_array_setNeedsUpdate( buffer, offset ) {
41863
41864                                 const dest = this.resolvedProperty;
41865
41866                                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
41867
41868                                         dest[ i ] = buffer[ offset ++ ];
41869
41870                                 }
41871
41872                                 this.targetObject.needsUpdate = true;
41873
41874                         },
41875
41876                         function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
41877
41878                                 const dest = this.resolvedProperty;
41879
41880                                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
41881
41882                                         dest[ i ] = buffer[ offset ++ ];
41883
41884                                 }
41885
41886                                 this.targetObject.matrixWorldNeedsUpdate = true;
41887
41888                         }
41889
41890                 ], [
41891
41892                         // ArrayElement
41893
41894                         function setValue_arrayElement( buffer, offset ) {
41895
41896                                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
41897
41898                         },
41899
41900                         function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
41901
41902                                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
41903                                 this.targetObject.needsUpdate = true;
41904
41905                         },
41906
41907                         function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
41908
41909                                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
41910                                 this.targetObject.matrixWorldNeedsUpdate = true;
41911
41912                         }
41913
41914                 ], [
41915
41916                         // HasToFromArray
41917
41918                         function setValue_fromArray( buffer, offset ) {
41919
41920                                 this.resolvedProperty.fromArray( buffer, offset );
41921
41922                         },
41923
41924                         function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
41925
41926                                 this.resolvedProperty.fromArray( buffer, offset );
41927                                 this.targetObject.needsUpdate = true;
41928
41929                         },
41930
41931                         function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
41932
41933                                 this.resolvedProperty.fromArray( buffer, offset );
41934                                 this.targetObject.matrixWorldNeedsUpdate = true;
41935
41936                         }
41937
41938                 ]
41939
41940         ],
41941
41942         getValue: function getValue_unbound( targetArray, offset ) {
41943
41944                 this.bind();
41945                 this.getValue( targetArray, offset );
41946
41947                 // Note: This class uses a State pattern on a per-method basis:
41948                 // 'bind' sets 'this.getValue' / 'setValue' and shadows the
41949                 // prototype version of these methods with one that represents
41950                 // the bound state. When the property is not found, the methods
41951                 // become no-ops.
41952
41953         },
41954
41955         setValue: function getValue_unbound( sourceArray, offset ) {
41956
41957                 this.bind();
41958                 this.setValue( sourceArray, offset );
41959
41960         },
41961
41962         // create getter / setter pair for a property in the scene graph
41963         bind: function () {
41964
41965                 let targetObject = this.node;
41966                 const parsedPath = this.parsedPath;
41967
41968                 const objectName = parsedPath.objectName;
41969                 const propertyName = parsedPath.propertyName;
41970                 let propertyIndex = parsedPath.propertyIndex;
41971
41972                 if ( ! targetObject ) {
41973
41974                         targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
41975
41976                         this.node = targetObject;
41977
41978                 }
41979
41980                 // set fail state so we can just 'return' on error
41981                 this.getValue = this._getValue_unavailable;
41982                 this.setValue = this._setValue_unavailable;
41983
41984                 // ensure there is a value node
41985                 if ( ! targetObject ) {
41986
41987                         console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
41988                         return;
41989
41990                 }
41991
41992                 if ( objectName ) {
41993
41994                         let objectIndex = parsedPath.objectIndex;
41995
41996                         // special cases were we need to reach deeper into the hierarchy to get the face materials....
41997                         switch ( objectName ) {
41998
41999                                 case 'materials':
42000
42001                                         if ( ! targetObject.material ) {
42002
42003                                                 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
42004                                                 return;
42005
42006                                         }
42007
42008                                         if ( ! targetObject.material.materials ) {
42009
42010                                                 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
42011                                                 return;
42012
42013                                         }
42014
42015                                         targetObject = targetObject.material.materials;
42016
42017                                         break;
42018
42019                                 case 'bones':
42020
42021                                         if ( ! targetObject.skeleton ) {
42022
42023                                                 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
42024                                                 return;
42025
42026                                         }
42027
42028                                         // potential future optimization: skip this if propertyIndex is already an integer
42029                                         // and convert the integer string to a true integer.
42030
42031                                         targetObject = targetObject.skeleton.bones;
42032
42033                                         // support resolving morphTarget names into indices.
42034                                         for ( let i = 0; i < targetObject.length; i ++ ) {
42035
42036                                                 if ( targetObject[ i ].name === objectIndex ) {
42037
42038                                                         objectIndex = i;
42039                                                         break;
42040
42041                                                 }
42042
42043                                         }
42044
42045                                         break;
42046
42047                                 default:
42048
42049                                         if ( targetObject[ objectName ] === undefined ) {
42050
42051                                                 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
42052                                                 return;
42053
42054                                         }
42055
42056                                         targetObject = targetObject[ objectName ];
42057
42058                         }
42059
42060
42061                         if ( objectIndex !== undefined ) {
42062
42063                                 if ( targetObject[ objectIndex ] === undefined ) {
42064
42065                                         console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
42066                                         return;
42067
42068                                 }
42069
42070                                 targetObject = targetObject[ objectIndex ];
42071
42072                         }
42073
42074                 }
42075
42076                 // resolve property
42077                 const nodeProperty = targetObject[ propertyName ];
42078
42079                 if ( nodeProperty === undefined ) {
42080
42081                         const nodeName = parsedPath.nodeName;
42082
42083                         console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
42084                                 '.' + propertyName + ' but it wasn\'t found.', targetObject );
42085                         return;
42086
42087                 }
42088
42089                 // determine versioning scheme
42090                 let versioning = this.Versioning.None;
42091
42092                 this.targetObject = targetObject;
42093
42094                 if ( targetObject.needsUpdate !== undefined ) { // material
42095
42096                         versioning = this.Versioning.NeedsUpdate;
42097
42098                 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
42099
42100                         versioning = this.Versioning.MatrixWorldNeedsUpdate;
42101
42102                 }
42103
42104                 // determine how the property gets bound
42105                 let bindingType = this.BindingType.Direct;
42106
42107                 if ( propertyIndex !== undefined ) {
42108
42109                         // access a sub element of the property array (only primitives are supported right now)
42110
42111                         if ( propertyName === 'morphTargetInfluences' ) {
42112
42113                                 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
42114
42115                                 // support resolving morphTarget names into indices.
42116                                 if ( ! targetObject.geometry ) {
42117
42118                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
42119                                         return;
42120
42121                                 }
42122
42123                                 if ( targetObject.geometry.isBufferGeometry ) {
42124
42125                                         if ( ! targetObject.geometry.morphAttributes ) {
42126
42127                                                 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
42128                                                 return;
42129
42130                                         }
42131
42132                                         if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
42133
42134                                                 propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
42135
42136                                         }
42137
42138
42139                                 } else {
42140
42141                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences on THREE.Geometry. Use THREE.BufferGeometry instead.', this );
42142                                         return;
42143
42144                                 }
42145
42146                         }
42147
42148                         bindingType = this.BindingType.ArrayElement;
42149
42150                         this.resolvedProperty = nodeProperty;
42151                         this.propertyIndex = propertyIndex;
42152
42153                 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
42154
42155                         // must use copy for Object3D.Euler/Quaternion
42156
42157                         bindingType = this.BindingType.HasFromToArray;
42158
42159                         this.resolvedProperty = nodeProperty;
42160
42161                 } else if ( Array.isArray( nodeProperty ) ) {
42162
42163                         bindingType = this.BindingType.EntireArray;
42164
42165                         this.resolvedProperty = nodeProperty;
42166
42167                 } else {
42168
42169                         this.propertyName = propertyName;
42170
42171                 }
42172
42173                 // select getter / setter
42174                 this.getValue = this.GetterByBindingType[ bindingType ];
42175                 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
42176
42177         },
42178
42179         unbind: function () {
42180
42181                 this.node = null;
42182
42183                 // back to the prototype version of getValue / setValue
42184                 // note: avoiding to mutate the shape of 'this' via 'delete'
42185                 this.getValue = this._getValue_unbound;
42186                 this.setValue = this._setValue_unbound;
42187
42188         }
42189
42190 } );
42191
42192 // DECLARE ALIAS AFTER assign prototype
42193 Object.assign( PropertyBinding.prototype, {
42194
42195         // initial state of these methods that calls 'bind'
42196         _getValue_unbound: PropertyBinding.prototype.getValue,
42197         _setValue_unbound: PropertyBinding.prototype.setValue,
42198
42199 } );
42200
42201 /**
42202  *
42203  * A group of objects that receives a shared animation state.
42204  *
42205  * Usage:
42206  *
42207  *  - Add objects you would otherwise pass as 'root' to the
42208  *    constructor or the .clipAction method of AnimationMixer.
42209  *
42210  *  - Instead pass this object as 'root'.
42211  *
42212  *  - You can also add and remove objects later when the mixer
42213  *    is running.
42214  *
42215  * Note:
42216  *
42217  *    Objects of this class appear as one object to the mixer,
42218  *    so cache control of the individual objects must be done
42219  *    on the group.
42220  *
42221  * Limitation:
42222  *
42223  *  - The animated properties must be compatible among the
42224  *    all objects in the group.
42225  *
42226  *  - A single property can either be controlled through a
42227  *    target group or directly, but not both.
42228  */
42229
42230 function AnimationObjectGroup() {
42231
42232         this.uuid = MathUtils.generateUUID();
42233
42234         // cached objects followed by the active ones
42235         this._objects = Array.prototype.slice.call( arguments );
42236
42237         this.nCachedObjects_ = 0; // threshold
42238         // note: read by PropertyBinding.Composite
42239
42240         const indices = {};
42241         this._indicesByUUID = indices; // for bookkeeping
42242
42243         for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
42244
42245                 indices[ arguments[ i ].uuid ] = i;
42246
42247         }
42248
42249         this._paths = []; // inside: string
42250         this._parsedPaths = []; // inside: { we don't care, here }
42251         this._bindings = []; // inside: Array< PropertyBinding >
42252         this._bindingsIndicesByPath = {}; // inside: indices in these arrays
42253
42254         const scope = this;
42255
42256         this.stats = {
42257
42258                 objects: {
42259                         get total() {
42260
42261                                 return scope._objects.length;
42262
42263                         },
42264                         get inUse() {
42265
42266                                 return this.total - scope.nCachedObjects_;
42267
42268                         }
42269                 },
42270                 get bindingsPerObject() {
42271
42272                         return scope._bindings.length;
42273
42274                 }
42275
42276         };
42277
42278 }
42279
42280 Object.assign( AnimationObjectGroup.prototype, {
42281
42282         isAnimationObjectGroup: true,
42283
42284         add: function () {
42285
42286                 const objects = this._objects,
42287                         indicesByUUID = this._indicesByUUID,
42288                         paths = this._paths,
42289                         parsedPaths = this._parsedPaths,
42290                         bindings = this._bindings,
42291                         nBindings = bindings.length;
42292
42293                 let knownObject = undefined,
42294                         nObjects = objects.length,
42295                         nCachedObjects = this.nCachedObjects_;
42296
42297                 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
42298
42299                         const object = arguments[ i ],
42300                                 uuid = object.uuid;
42301                         let index = indicesByUUID[ uuid ];
42302
42303                         if ( index === undefined ) {
42304
42305                                 // unknown object -> add it to the ACTIVE region
42306
42307                                 index = nObjects ++;
42308                                 indicesByUUID[ uuid ] = index;
42309                                 objects.push( object );
42310
42311                                 // accounting is done, now do the same for all bindings
42312
42313                                 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
42314
42315                                         bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
42316
42317                                 }
42318
42319                         } else if ( index < nCachedObjects ) {
42320
42321                                 knownObject = objects[ index ];
42322
42323                                 // move existing object to the ACTIVE region
42324
42325                                 const firstActiveIndex = -- nCachedObjects,
42326                                         lastCachedObject = objects[ firstActiveIndex ];
42327
42328                                 indicesByUUID[ lastCachedObject.uuid ] = index;
42329                                 objects[ index ] = lastCachedObject;
42330
42331                                 indicesByUUID[ uuid ] = firstActiveIndex;
42332                                 objects[ firstActiveIndex ] = object;
42333
42334                                 // accounting is done, now do the same for all bindings
42335
42336                                 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
42337
42338                                         const bindingsForPath = bindings[ j ],
42339                                                 lastCached = bindingsForPath[ firstActiveIndex ];
42340
42341                                         let binding = bindingsForPath[ index ];
42342
42343                                         bindingsForPath[ index ] = lastCached;
42344
42345                                         if ( binding === undefined ) {
42346
42347                                                 // since we do not bother to create new bindings
42348                                                 // for objects that are cached, the binding may
42349                                                 // or may not exist
42350
42351                                                 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
42352
42353                                         }
42354
42355                                         bindingsForPath[ firstActiveIndex ] = binding;
42356
42357                                 }
42358
42359                         } else if ( objects[ index ] !== knownObject ) {
42360
42361                                 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
42362                                         'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
42363
42364                         } // else the object is already where we want it to be
42365
42366                 } // for arguments
42367
42368                 this.nCachedObjects_ = nCachedObjects;
42369
42370         },
42371
42372         remove: function () {
42373
42374                 const objects = this._objects,
42375                         indicesByUUID = this._indicesByUUID,
42376                         bindings = this._bindings,
42377                         nBindings = bindings.length;
42378
42379                 let nCachedObjects = this.nCachedObjects_;
42380
42381                 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
42382
42383                         const object = arguments[ i ],
42384                                 uuid = object.uuid,
42385                                 index = indicesByUUID[ uuid ];
42386
42387                         if ( index !== undefined && index >= nCachedObjects ) {
42388
42389                                 // move existing object into the CACHED region
42390
42391                                 const lastCachedIndex = nCachedObjects ++,
42392                                         firstActiveObject = objects[ lastCachedIndex ];
42393
42394                                 indicesByUUID[ firstActiveObject.uuid ] = index;
42395                                 objects[ index ] = firstActiveObject;
42396
42397                                 indicesByUUID[ uuid ] = lastCachedIndex;
42398                                 objects[ lastCachedIndex ] = object;
42399
42400                                 // accounting is done, now do the same for all bindings
42401
42402                                 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
42403
42404                                         const bindingsForPath = bindings[ j ],
42405                                                 firstActive = bindingsForPath[ lastCachedIndex ],
42406                                                 binding = bindingsForPath[ index ];
42407
42408                                         bindingsForPath[ index ] = firstActive;
42409                                         bindingsForPath[ lastCachedIndex ] = binding;
42410
42411                                 }
42412
42413                         }
42414
42415                 } // for arguments
42416
42417                 this.nCachedObjects_ = nCachedObjects;
42418
42419         },
42420
42421         // remove & forget
42422         uncache: function () {
42423
42424                 const objects = this._objects,
42425                         indicesByUUID = this._indicesByUUID,
42426                         bindings = this._bindings,
42427                         nBindings = bindings.length;
42428
42429                 let nCachedObjects = this.nCachedObjects_,
42430                         nObjects = objects.length;
42431
42432                 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
42433
42434                         const object = arguments[ i ],
42435                                 uuid = object.uuid,
42436                                 index = indicesByUUID[ uuid ];
42437
42438                         if ( index !== undefined ) {
42439
42440                                 delete indicesByUUID[ uuid ];
42441
42442                                 if ( index < nCachedObjects ) {
42443
42444                                         // object is cached, shrink the CACHED region
42445
42446                                         const firstActiveIndex = -- nCachedObjects,
42447                                                 lastCachedObject = objects[ firstActiveIndex ],
42448                                                 lastIndex = -- nObjects,
42449                                                 lastObject = objects[ lastIndex ];
42450
42451                                         // last cached object takes this object's place
42452                                         indicesByUUID[ lastCachedObject.uuid ] = index;
42453                                         objects[ index ] = lastCachedObject;
42454
42455                                         // last object goes to the activated slot and pop
42456                                         indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
42457                                         objects[ firstActiveIndex ] = lastObject;
42458                                         objects.pop();
42459
42460                                         // accounting is done, now do the same for all bindings
42461
42462                                         for ( let j = 0, m = nBindings; j !== m; ++ j ) {
42463
42464                                                 const bindingsForPath = bindings[ j ],
42465                                                         lastCached = bindingsForPath[ firstActiveIndex ],
42466                                                         last = bindingsForPath[ lastIndex ];
42467
42468                                                 bindingsForPath[ index ] = lastCached;
42469                                                 bindingsForPath[ firstActiveIndex ] = last;
42470                                                 bindingsForPath.pop();
42471
42472                                         }
42473
42474                                 } else {
42475
42476                                         // object is active, just swap with the last and pop
42477
42478                                         const lastIndex = -- nObjects,
42479                                                 lastObject = objects[ lastIndex ];
42480
42481                                         if ( lastIndex > 0 ) {
42482
42483                                                 indicesByUUID[ lastObject.uuid ] = index;
42484
42485                                         }
42486
42487                                         objects[ index ] = lastObject;
42488                                         objects.pop();
42489
42490                                         // accounting is done, now do the same for all bindings
42491
42492                                         for ( let j = 0, m = nBindings; j !== m; ++ j ) {
42493
42494                                                 const bindingsForPath = bindings[ j ];
42495
42496                                                 bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
42497                                                 bindingsForPath.pop();
42498
42499                                         }
42500
42501                                 } // cached or active
42502
42503                         } // if object is known
42504
42505                 } // for arguments
42506
42507                 this.nCachedObjects_ = nCachedObjects;
42508
42509         },
42510
42511         // Internal interface used by befriended PropertyBinding.Composite:
42512
42513         subscribe_: function ( path, parsedPath ) {
42514
42515                 // returns an array of bindings for the given path that is changed
42516                 // according to the contained objects in the group
42517
42518                 const indicesByPath = this._bindingsIndicesByPath;
42519                 let index = indicesByPath[ path ];
42520                 const bindings = this._bindings;
42521
42522                 if ( index !== undefined ) return bindings[ index ];
42523
42524                 const paths = this._paths,
42525                         parsedPaths = this._parsedPaths,
42526                         objects = this._objects,
42527                         nObjects = objects.length,
42528                         nCachedObjects = this.nCachedObjects_,
42529                         bindingsForPath = new Array( nObjects );
42530
42531                 index = bindings.length;
42532
42533                 indicesByPath[ path ] = index;
42534
42535                 paths.push( path );
42536                 parsedPaths.push( parsedPath );
42537                 bindings.push( bindingsForPath );
42538
42539                 for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
42540
42541                         const object = objects[ i ];
42542                         bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
42543
42544                 }
42545
42546                 return bindingsForPath;
42547
42548         },
42549
42550         unsubscribe_: function ( path ) {
42551
42552                 // tells the group to forget about a property path and no longer
42553                 // update the array previously obtained with 'subscribe_'
42554
42555                 const indicesByPath = this._bindingsIndicesByPath,
42556                         index = indicesByPath[ path ];
42557
42558                 if ( index !== undefined ) {
42559
42560                         const paths = this._paths,
42561                                 parsedPaths = this._parsedPaths,
42562                                 bindings = this._bindings,
42563                                 lastBindingsIndex = bindings.length - 1,
42564                                 lastBindings = bindings[ lastBindingsIndex ],
42565                                 lastBindingsPath = path[ lastBindingsIndex ];
42566
42567                         indicesByPath[ lastBindingsPath ] = index;
42568
42569                         bindings[ index ] = lastBindings;
42570                         bindings.pop();
42571
42572                         parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
42573                         parsedPaths.pop();
42574
42575                         paths[ index ] = paths[ lastBindingsIndex ];
42576                         paths.pop();
42577
42578                 }
42579
42580         }
42581
42582 } );
42583
42584 class AnimationAction {
42585
42586         constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
42587
42588                 this._mixer = mixer;
42589                 this._clip = clip;
42590                 this._localRoot = localRoot;
42591                 this.blendMode = blendMode;
42592
42593                 const tracks = clip.tracks,
42594                         nTracks = tracks.length,
42595                         interpolants = new Array( nTracks );
42596
42597                 const interpolantSettings = {
42598                         endingStart: ZeroCurvatureEnding,
42599                         endingEnd: ZeroCurvatureEnding
42600                 };
42601
42602                 for ( let i = 0; i !== nTracks; ++ i ) {
42603
42604                         const interpolant = tracks[ i ].createInterpolant( null );
42605                         interpolants[ i ] = interpolant;
42606                         interpolant.settings = interpolantSettings;
42607
42608                 }
42609
42610                 this._interpolantSettings = interpolantSettings;
42611
42612                 this._interpolants = interpolants; // bound by the mixer
42613
42614                 // inside: PropertyMixer (managed by the mixer)
42615                 this._propertyBindings = new Array( nTracks );
42616
42617                 this._cacheIndex = null; // for the memory manager
42618                 this._byClipCacheIndex = null; // for the memory manager
42619
42620                 this._timeScaleInterpolant = null;
42621                 this._weightInterpolant = null;
42622
42623                 this.loop = LoopRepeat;
42624                 this._loopCount = - 1;
42625
42626                 // global mixer time when the action is to be started
42627                 // it's set back to 'null' upon start of the action
42628                 this._startTime = null;
42629
42630                 // scaled local time of the action
42631                 // gets clamped or wrapped to 0..clip.duration according to loop
42632                 this.time = 0;
42633
42634                 this.timeScale = 1;
42635                 this._effectiveTimeScale = 1;
42636
42637                 this.weight = 1;
42638                 this._effectiveWeight = 1;
42639
42640                 this.repetitions = Infinity; // no. of repetitions when looping
42641
42642                 this.paused = false; // true -> zero effective time scale
42643                 this.enabled = true; // false -> zero effective weight
42644
42645                 this.clampWhenFinished = false;// keep feeding the last frame?
42646
42647                 this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
42648                 this.zeroSlopeAtEnd = true;// clips for start, loop and end
42649
42650         }
42651
42652         // State & Scheduling
42653
42654         play() {
42655
42656                 this._mixer._activateAction( this );
42657
42658                 return this;
42659
42660         }
42661
42662         stop() {
42663
42664                 this._mixer._deactivateAction( this );
42665
42666                 return this.reset();
42667
42668         }
42669
42670         reset() {
42671
42672                 this.paused = false;
42673                 this.enabled = true;
42674
42675                 this.time = 0; // restart clip
42676                 this._loopCount = - 1;// forget previous loops
42677                 this._startTime = null;// forget scheduling
42678
42679                 return this.stopFading().stopWarping();
42680
42681         }
42682
42683         isRunning() {
42684
42685                 return this.enabled && ! this.paused && this.timeScale !== 0 &&
42686                         this._startTime === null && this._mixer._isActiveAction( this );
42687
42688         }
42689
42690         // return true when play has been called
42691         isScheduled() {
42692
42693                 return this._mixer._isActiveAction( this );
42694
42695         }
42696
42697         startAt( time ) {
42698
42699                 this._startTime = time;
42700
42701                 return this;
42702
42703         }
42704
42705         setLoop( mode, repetitions ) {
42706
42707                 this.loop = mode;
42708                 this.repetitions = repetitions;
42709
42710                 return this;
42711
42712         }
42713
42714         // Weight
42715
42716         // set the weight stopping any scheduled fading
42717         // although .enabled = false yields an effective weight of zero, this
42718         // method does *not* change .enabled, because it would be confusing
42719         setEffectiveWeight( weight ) {
42720
42721                 this.weight = weight;
42722
42723                 // note: same logic as when updated at runtime
42724                 this._effectiveWeight = this.enabled ? weight : 0;
42725
42726                 return this.stopFading();
42727
42728         }
42729
42730         // return the weight considering fading and .enabled
42731         getEffectiveWeight() {
42732
42733                 return this._effectiveWeight;
42734
42735         }
42736
42737         fadeIn( duration ) {
42738
42739                 return this._scheduleFading( duration, 0, 1 );
42740
42741         }
42742
42743         fadeOut( duration ) {
42744
42745                 return this._scheduleFading( duration, 1, 0 );
42746
42747         }
42748
42749         crossFadeFrom( fadeOutAction, duration, warp ) {
42750
42751                 fadeOutAction.fadeOut( duration );
42752                 this.fadeIn( duration );
42753
42754                 if ( warp ) {
42755
42756                         const fadeInDuration = this._clip.duration,
42757                                 fadeOutDuration = fadeOutAction._clip.duration,
42758
42759                                 startEndRatio = fadeOutDuration / fadeInDuration,
42760                                 endStartRatio = fadeInDuration / fadeOutDuration;
42761
42762                         fadeOutAction.warp( 1.0, startEndRatio, duration );
42763                         this.warp( endStartRatio, 1.0, duration );
42764
42765                 }
42766
42767                 return this;
42768
42769         }
42770
42771         crossFadeTo( fadeInAction, duration, warp ) {
42772
42773                 return fadeInAction.crossFadeFrom( this, duration, warp );
42774
42775         }
42776
42777         stopFading() {
42778
42779                 const weightInterpolant = this._weightInterpolant;
42780
42781                 if ( weightInterpolant !== null ) {
42782
42783                         this._weightInterpolant = null;
42784                         this._mixer._takeBackControlInterpolant( weightInterpolant );
42785
42786                 }
42787
42788                 return this;
42789
42790         }
42791
42792         // Time Scale Control
42793
42794         // set the time scale stopping any scheduled warping
42795         // although .paused = true yields an effective time scale of zero, this
42796         // method does *not* change .paused, because it would be confusing
42797         setEffectiveTimeScale( timeScale ) {
42798
42799                 this.timeScale = timeScale;
42800                 this._effectiveTimeScale = this.paused ? 0 : timeScale;
42801
42802                 return this.stopWarping();
42803
42804         }
42805
42806         // return the time scale considering warping and .paused
42807         getEffectiveTimeScale() {
42808
42809                 return this._effectiveTimeScale;
42810
42811         }
42812
42813         setDuration( duration ) {
42814
42815                 this.timeScale = this._clip.duration / duration;
42816
42817                 return this.stopWarping();
42818
42819         }
42820
42821         syncWith( action ) {
42822
42823                 this.time = action.time;
42824                 this.timeScale = action.timeScale;
42825
42826                 return this.stopWarping();
42827
42828         }
42829
42830         halt( duration ) {
42831
42832                 return this.warp( this._effectiveTimeScale, 0, duration );
42833
42834         }
42835
42836         warp( startTimeScale, endTimeScale, duration ) {
42837
42838                 const mixer = this._mixer,
42839                         now = mixer.time,
42840                         timeScale = this.timeScale;
42841
42842                 let interpolant = this._timeScaleInterpolant;
42843
42844                 if ( interpolant === null ) {
42845
42846                         interpolant = mixer._lendControlInterpolant();
42847                         this._timeScaleInterpolant = interpolant;
42848
42849                 }
42850
42851                 const times = interpolant.parameterPositions,
42852                         values = interpolant.sampleValues;
42853
42854                 times[ 0 ] = now;
42855                 times[ 1 ] = now + duration;
42856
42857                 values[ 0 ] = startTimeScale / timeScale;
42858                 values[ 1 ] = endTimeScale / timeScale;
42859
42860                 return this;
42861
42862         }
42863
42864         stopWarping() {
42865
42866                 const timeScaleInterpolant = this._timeScaleInterpolant;
42867
42868                 if ( timeScaleInterpolant !== null ) {
42869
42870                         this._timeScaleInterpolant = null;
42871                         this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
42872
42873                 }
42874
42875                 return this;
42876
42877         }
42878
42879         // Object Accessors
42880
42881         getMixer() {
42882
42883                 return this._mixer;
42884
42885         }
42886
42887         getClip() {
42888
42889                 return this._clip;
42890
42891         }
42892
42893         getRoot() {
42894
42895                 return this._localRoot || this._mixer._root;
42896
42897         }
42898
42899         // Interna
42900
42901         _update( time, deltaTime, timeDirection, accuIndex ) {
42902
42903                 // called by the mixer
42904
42905                 if ( ! this.enabled ) {
42906
42907                         // call ._updateWeight() to update ._effectiveWeight
42908
42909                         this._updateWeight( time );
42910                         return;
42911
42912                 }
42913
42914                 const startTime = this._startTime;
42915
42916                 if ( startTime !== null ) {
42917
42918                         // check for scheduled start of action
42919
42920                         const timeRunning = ( time - startTime ) * timeDirection;
42921                         if ( timeRunning < 0 || timeDirection === 0 ) {
42922
42923                                 return; // yet to come / don't decide when delta = 0
42924
42925                         }
42926
42927                         // start
42928
42929                         this._startTime = null; // unschedule
42930                         deltaTime = timeDirection * timeRunning;
42931
42932                 }
42933
42934                 // apply time scale and advance time
42935
42936                 deltaTime *= this._updateTimeScale( time );
42937                 const clipTime = this._updateTime( deltaTime );
42938
42939                 // note: _updateTime may disable the action resulting in
42940                 // an effective weight of 0
42941
42942                 const weight = this._updateWeight( time );
42943
42944                 if ( weight > 0 ) {
42945
42946                         const interpolants = this._interpolants;
42947                         const propertyMixers = this._propertyBindings;
42948
42949                         switch ( this.blendMode ) {
42950
42951                                 case AdditiveAnimationBlendMode:
42952
42953                                         for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
42954
42955                                                 interpolants[ j ].evaluate( clipTime );
42956                                                 propertyMixers[ j ].accumulateAdditive( weight );
42957
42958                                         }
42959
42960                                         break;
42961
42962                                 case NormalAnimationBlendMode:
42963                                 default:
42964
42965                                         for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
42966
42967                                                 interpolants[ j ].evaluate( clipTime );
42968                                                 propertyMixers[ j ].accumulate( accuIndex, weight );
42969
42970                                         }
42971
42972                         }
42973
42974                 }
42975
42976         }
42977
42978         _updateWeight( time ) {
42979
42980                 let weight = 0;
42981
42982                 if ( this.enabled ) {
42983
42984                         weight = this.weight;
42985                         const interpolant = this._weightInterpolant;
42986
42987                         if ( interpolant !== null ) {
42988
42989                                 const interpolantValue = interpolant.evaluate( time )[ 0 ];
42990
42991                                 weight *= interpolantValue;
42992
42993                                 if ( time > interpolant.parameterPositions[ 1 ] ) {
42994
42995                                         this.stopFading();
42996
42997                                         if ( interpolantValue === 0 ) {
42998
42999                                                 // faded out, disable
43000                                                 this.enabled = false;
43001
43002                                         }
43003
43004                                 }
43005
43006                         }
43007
43008                 }
43009
43010                 this._effectiveWeight = weight;
43011                 return weight;
43012
43013         }
43014
43015         _updateTimeScale( time ) {
43016
43017                 let timeScale = 0;
43018
43019                 if ( ! this.paused ) {
43020
43021                         timeScale = this.timeScale;
43022
43023                         const interpolant = this._timeScaleInterpolant;
43024
43025                         if ( interpolant !== null ) {
43026
43027                                 const interpolantValue = interpolant.evaluate( time )[ 0 ];
43028
43029                                 timeScale *= interpolantValue;
43030
43031                                 if ( time > interpolant.parameterPositions[ 1 ] ) {
43032
43033                                         this.stopWarping();
43034
43035                                         if ( timeScale === 0 ) {
43036
43037                                                 // motion has halted, pause
43038                                                 this.paused = true;
43039
43040                                         } else {
43041
43042                                                 // warp done - apply final time scale
43043                                                 this.timeScale = timeScale;
43044
43045                                         }
43046
43047                                 }
43048
43049                         }
43050
43051                 }
43052
43053                 this._effectiveTimeScale = timeScale;
43054                 return timeScale;
43055
43056         }
43057
43058         _updateTime( deltaTime ) {
43059
43060                 const duration = this._clip.duration;
43061                 const loop = this.loop;
43062
43063                 let time = this.time + deltaTime;
43064                 let loopCount = this._loopCount;
43065
43066                 const pingPong = ( loop === LoopPingPong );
43067
43068                 if ( deltaTime === 0 ) {
43069
43070                         if ( loopCount === - 1 ) return time;
43071
43072                         return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
43073
43074                 }
43075
43076                 if ( loop === LoopOnce ) {
43077
43078                         if ( loopCount === - 1 ) {
43079
43080                                 // just started
43081
43082                                 this._loopCount = 0;
43083                                 this._setEndings( true, true, false );
43084
43085                         }
43086
43087                         handle_stop: {
43088
43089                                 if ( time >= duration ) {
43090
43091                                         time = duration;
43092
43093                                 } else if ( time < 0 ) {
43094
43095                                         time = 0;
43096
43097                                 } else {
43098
43099                                         this.time = time;
43100
43101                                         break handle_stop;
43102
43103                                 }
43104
43105                                 if ( this.clampWhenFinished ) this.paused = true;
43106                                 else this.enabled = false;
43107
43108                                 this.time = time;
43109
43110                                 this._mixer.dispatchEvent( {
43111                                         type: 'finished', action: this,
43112                                         direction: deltaTime < 0 ? - 1 : 1
43113                                 } );
43114
43115                         }
43116
43117                 } else { // repetitive Repeat or PingPong
43118
43119                         if ( loopCount === - 1 ) {
43120
43121                                 // just started
43122
43123                                 if ( deltaTime >= 0 ) {
43124
43125                                         loopCount = 0;
43126
43127                                         this._setEndings( true, this.repetitions === 0, pingPong );
43128
43129                                 } else {
43130
43131                                         // when looping in reverse direction, the initial
43132                                         // transition through zero counts as a repetition,
43133                                         // so leave loopCount at -1
43134
43135                                         this._setEndings( this.repetitions === 0, true, pingPong );
43136
43137                                 }
43138
43139                         }
43140
43141                         if ( time >= duration || time < 0 ) {
43142
43143                                 // wrap around
43144
43145                                 const loopDelta = Math.floor( time / duration ); // signed
43146                                 time -= duration * loopDelta;
43147
43148                                 loopCount += Math.abs( loopDelta );
43149
43150                                 const pending = this.repetitions - loopCount;
43151
43152                                 if ( pending <= 0 ) {
43153
43154                                         // have to stop (switch state, clamp time, fire event)
43155
43156                                         if ( this.clampWhenFinished ) this.paused = true;
43157                                         else this.enabled = false;
43158
43159                                         time = deltaTime > 0 ? duration : 0;
43160
43161                                         this.time = time;
43162
43163                                         this._mixer.dispatchEvent( {
43164                                                 type: 'finished', action: this,
43165                                                 direction: deltaTime > 0 ? 1 : - 1
43166                                         } );
43167
43168                                 } else {
43169
43170                                         // keep running
43171
43172                                         if ( pending === 1 ) {
43173
43174                                                 // entering the last round
43175
43176                                                 const atStart = deltaTime < 0;
43177                                                 this._setEndings( atStart, ! atStart, pingPong );
43178
43179                                         } else {
43180
43181                                                 this._setEndings( false, false, pingPong );
43182
43183                                         }
43184
43185                                         this._loopCount = loopCount;
43186
43187                                         this.time = time;
43188
43189                                         this._mixer.dispatchEvent( {
43190                                                 type: 'loop', action: this, loopDelta: loopDelta
43191                                         } );
43192
43193                                 }
43194
43195                         } else {
43196
43197                                 this.time = time;
43198
43199                         }
43200
43201                         if ( pingPong && ( loopCount & 1 ) === 1 ) {
43202
43203                                 // invert time for the "pong round"
43204
43205                                 return duration - time;
43206
43207                         }
43208
43209                 }
43210
43211                 return time;
43212
43213         }
43214
43215         _setEndings( atStart, atEnd, pingPong ) {
43216
43217                 const settings = this._interpolantSettings;
43218
43219                 if ( pingPong ) {
43220
43221                         settings.endingStart = ZeroSlopeEnding;
43222                         settings.endingEnd = ZeroSlopeEnding;
43223
43224                 } else {
43225
43226                         // assuming for LoopOnce atStart == atEnd == true
43227
43228                         if ( atStart ) {
43229
43230                                 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
43231
43232                         } else {
43233
43234                                 settings.endingStart = WrapAroundEnding;
43235
43236                         }
43237
43238                         if ( atEnd ) {
43239
43240                                 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
43241
43242                         } else {
43243
43244                                 settings.endingEnd       = WrapAroundEnding;
43245
43246                         }
43247
43248                 }
43249
43250         }
43251
43252         _scheduleFading( duration, weightNow, weightThen ) {
43253
43254                 const mixer = this._mixer, now = mixer.time;
43255                 let interpolant = this._weightInterpolant;
43256
43257                 if ( interpolant === null ) {
43258
43259                         interpolant = mixer._lendControlInterpolant();
43260                         this._weightInterpolant = interpolant;
43261
43262                 }
43263
43264                 const times = interpolant.parameterPositions,
43265                         values = interpolant.sampleValues;
43266
43267                 times[ 0 ] = now;
43268                 values[ 0 ] = weightNow;
43269                 times[ 1 ] = now + duration;
43270                 values[ 1 ] = weightThen;
43271
43272                 return this;
43273
43274         }
43275
43276 }
43277
43278 function AnimationMixer( root ) {
43279
43280         this._root = root;
43281         this._initMemoryManager();
43282         this._accuIndex = 0;
43283
43284         this.time = 0;
43285
43286         this.timeScale = 1.0;
43287
43288 }
43289
43290 AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
43291
43292         constructor: AnimationMixer,
43293
43294         _bindAction: function ( action, prototypeAction ) {
43295
43296                 const root = action._localRoot || this._root,
43297                         tracks = action._clip.tracks,
43298                         nTracks = tracks.length,
43299                         bindings = action._propertyBindings,
43300                         interpolants = action._interpolants,
43301                         rootUuid = root.uuid,
43302                         bindingsByRoot = this._bindingsByRootAndName;
43303
43304                 let bindingsByName = bindingsByRoot[ rootUuid ];
43305
43306                 if ( bindingsByName === undefined ) {
43307
43308                         bindingsByName = {};
43309                         bindingsByRoot[ rootUuid ] = bindingsByName;
43310
43311                 }
43312
43313                 for ( let i = 0; i !== nTracks; ++ i ) {
43314
43315                         const track = tracks[ i ],
43316                                 trackName = track.name;
43317
43318                         let binding = bindingsByName[ trackName ];
43319
43320                         if ( binding !== undefined ) {
43321
43322                                 bindings[ i ] = binding;
43323
43324                         } else {
43325
43326                                 binding = bindings[ i ];
43327
43328                                 if ( binding !== undefined ) {
43329
43330                                         // existing binding, make sure the cache knows
43331
43332                                         if ( binding._cacheIndex === null ) {
43333
43334                                                 ++ binding.referenceCount;
43335                                                 this._addInactiveBinding( binding, rootUuid, trackName );
43336
43337                                         }
43338
43339                                         continue;
43340
43341                                 }
43342
43343                                 const path = prototypeAction && prototypeAction.
43344                                         _propertyBindings[ i ].binding.parsedPath;
43345
43346                                 binding = new PropertyMixer(
43347                                         PropertyBinding.create( root, trackName, path ),
43348                                         track.ValueTypeName, track.getValueSize() );
43349
43350                                 ++ binding.referenceCount;
43351                                 this._addInactiveBinding( binding, rootUuid, trackName );
43352
43353                                 bindings[ i ] = binding;
43354
43355                         }
43356
43357                         interpolants[ i ].resultBuffer = binding.buffer;
43358
43359                 }
43360
43361         },
43362
43363         _activateAction: function ( action ) {
43364
43365                 if ( ! this._isActiveAction( action ) ) {
43366
43367                         if ( action._cacheIndex === null ) {
43368
43369                                 // this action has been forgotten by the cache, but the user
43370                                 // appears to be still using it -> rebind
43371
43372                                 const rootUuid = ( action._localRoot || this._root ).uuid,
43373                                         clipUuid = action._clip.uuid,
43374                                         actionsForClip = this._actionsByClip[ clipUuid ];
43375
43376                                 this._bindAction( action,
43377                                         actionsForClip && actionsForClip.knownActions[ 0 ] );
43378
43379                                 this._addInactiveAction( action, clipUuid, rootUuid );
43380
43381                         }
43382
43383                         const bindings = action._propertyBindings;
43384
43385                         // increment reference counts / sort out state
43386                         for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
43387
43388                                 const binding = bindings[ i ];
43389
43390                                 if ( binding.useCount ++ === 0 ) {
43391
43392                                         this._lendBinding( binding );
43393                                         binding.saveOriginalState();
43394
43395                                 }
43396
43397                         }
43398
43399                         this._lendAction( action );
43400
43401                 }
43402
43403         },
43404
43405         _deactivateAction: function ( action ) {
43406
43407                 if ( this._isActiveAction( action ) ) {
43408
43409                         const bindings = action._propertyBindings;
43410
43411                         // decrement reference counts / sort out state
43412                         for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
43413
43414                                 const binding = bindings[ i ];
43415
43416                                 if ( -- binding.useCount === 0 ) {
43417
43418                                         binding.restoreOriginalState();
43419                                         this._takeBackBinding( binding );
43420
43421                                 }
43422
43423                         }
43424
43425                         this._takeBackAction( action );
43426
43427                 }
43428
43429         },
43430
43431         // Memory manager
43432
43433         _initMemoryManager: function () {
43434
43435                 this._actions = []; // 'nActiveActions' followed by inactive ones
43436                 this._nActiveActions = 0;
43437
43438                 this._actionsByClip = {};
43439                 // inside:
43440                 // {
43441                 //      knownActions: Array< AnimationAction > - used as prototypes
43442                 //      actionByRoot: AnimationAction - lookup
43443                 // }
43444
43445
43446                 this._bindings = []; // 'nActiveBindings' followed by inactive ones
43447                 this._nActiveBindings = 0;
43448
43449                 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
43450
43451
43452                 this._controlInterpolants = []; // same game as above
43453                 this._nActiveControlInterpolants = 0;
43454
43455                 const scope = this;
43456
43457                 this.stats = {
43458
43459                         actions: {
43460                                 get total() {
43461
43462                                         return scope._actions.length;
43463
43464                                 },
43465                                 get inUse() {
43466
43467                                         return scope._nActiveActions;
43468
43469                                 }
43470                         },
43471                         bindings: {
43472                                 get total() {
43473
43474                                         return scope._bindings.length;
43475
43476                                 },
43477                                 get inUse() {
43478
43479                                         return scope._nActiveBindings;
43480
43481                                 }
43482                         },
43483                         controlInterpolants: {
43484                                 get total() {
43485
43486                                         return scope._controlInterpolants.length;
43487
43488                                 },
43489                                 get inUse() {
43490
43491                                         return scope._nActiveControlInterpolants;
43492
43493                                 }
43494                         }
43495
43496                 };
43497
43498         },
43499
43500         // Memory management for AnimationAction objects
43501
43502         _isActiveAction: function ( action ) {
43503
43504                 const index = action._cacheIndex;
43505                 return index !== null && index < this._nActiveActions;
43506
43507         },
43508
43509         _addInactiveAction: function ( action, clipUuid, rootUuid ) {
43510
43511                 const actions = this._actions,
43512                         actionsByClip = this._actionsByClip;
43513
43514                 let actionsForClip = actionsByClip[ clipUuid ];
43515
43516                 if ( actionsForClip === undefined ) {
43517
43518                         actionsForClip = {
43519
43520                                 knownActions: [ action ],
43521                                 actionByRoot: {}
43522
43523                         };
43524
43525                         action._byClipCacheIndex = 0;
43526
43527                         actionsByClip[ clipUuid ] = actionsForClip;
43528
43529                 } else {
43530
43531                         const knownActions = actionsForClip.knownActions;
43532
43533                         action._byClipCacheIndex = knownActions.length;
43534                         knownActions.push( action );
43535
43536                 }
43537
43538                 action._cacheIndex = actions.length;
43539                 actions.push( action );
43540
43541                 actionsForClip.actionByRoot[ rootUuid ] = action;
43542
43543         },
43544
43545         _removeInactiveAction: function ( action ) {
43546
43547                 const actions = this._actions,
43548                         lastInactiveAction = actions[ actions.length - 1 ],
43549                         cacheIndex = action._cacheIndex;
43550
43551                 lastInactiveAction._cacheIndex = cacheIndex;
43552                 actions[ cacheIndex ] = lastInactiveAction;
43553                 actions.pop();
43554
43555                 action._cacheIndex = null;
43556
43557
43558                 const clipUuid = action._clip.uuid,
43559                         actionsByClip = this._actionsByClip,
43560                         actionsForClip = actionsByClip[ clipUuid ],
43561                         knownActionsForClip = actionsForClip.knownActions,
43562
43563                         lastKnownAction =
43564                                 knownActionsForClip[ knownActionsForClip.length - 1 ],
43565
43566                         byClipCacheIndex = action._byClipCacheIndex;
43567
43568                 lastKnownAction._byClipCacheIndex = byClipCacheIndex;
43569                 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
43570                 knownActionsForClip.pop();
43571
43572                 action._byClipCacheIndex = null;
43573
43574
43575                 const actionByRoot = actionsForClip.actionByRoot,
43576                         rootUuid = ( action._localRoot || this._root ).uuid;
43577
43578                 delete actionByRoot[ rootUuid ];
43579
43580                 if ( knownActionsForClip.length === 0 ) {
43581
43582                         delete actionsByClip[ clipUuid ];
43583
43584                 }
43585
43586                 this._removeInactiveBindingsForAction( action );
43587
43588         },
43589
43590         _removeInactiveBindingsForAction: function ( action ) {
43591
43592                 const bindings = action._propertyBindings;
43593
43594                 for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
43595
43596                         const binding = bindings[ i ];
43597
43598                         if ( -- binding.referenceCount === 0 ) {
43599
43600                                 this._removeInactiveBinding( binding );
43601
43602                         }
43603
43604                 }
43605
43606         },
43607
43608         _lendAction: function ( action ) {
43609
43610                 // [ active actions |  inactive actions  ]
43611                 // [  active actions >| inactive actions ]
43612                 //                 s        a
43613                 //                  <-swap->
43614                 //                 a        s
43615
43616                 const actions = this._actions,
43617                         prevIndex = action._cacheIndex,
43618
43619                         lastActiveIndex = this._nActiveActions ++,
43620
43621                         firstInactiveAction = actions[ lastActiveIndex ];
43622
43623                 action._cacheIndex = lastActiveIndex;
43624                 actions[ lastActiveIndex ] = action;
43625
43626                 firstInactiveAction._cacheIndex = prevIndex;
43627                 actions[ prevIndex ] = firstInactiveAction;
43628
43629         },
43630
43631         _takeBackAction: function ( action ) {
43632
43633                 // [  active actions  | inactive actions ]
43634                 // [ active actions |< inactive actions  ]
43635                 //        a        s
43636                 //         <-swap->
43637                 //        s        a
43638
43639                 const actions = this._actions,
43640                         prevIndex = action._cacheIndex,
43641
43642                         firstInactiveIndex = -- this._nActiveActions,
43643
43644                         lastActiveAction = actions[ firstInactiveIndex ];
43645
43646                 action._cacheIndex = firstInactiveIndex;
43647                 actions[ firstInactiveIndex ] = action;
43648
43649                 lastActiveAction._cacheIndex = prevIndex;
43650                 actions[ prevIndex ] = lastActiveAction;
43651
43652         },
43653
43654         // Memory management for PropertyMixer objects
43655
43656         _addInactiveBinding: function ( binding, rootUuid, trackName ) {
43657
43658                 const bindingsByRoot = this._bindingsByRootAndName,
43659                         bindings = this._bindings;
43660
43661                 let bindingByName = bindingsByRoot[ rootUuid ];
43662
43663                 if ( bindingByName === undefined ) {
43664
43665                         bindingByName = {};
43666                         bindingsByRoot[ rootUuid ] = bindingByName;
43667
43668                 }
43669
43670                 bindingByName[ trackName ] = binding;
43671
43672                 binding._cacheIndex = bindings.length;
43673                 bindings.push( binding );
43674
43675         },
43676
43677         _removeInactiveBinding: function ( binding ) {
43678
43679                 const bindings = this._bindings,
43680                         propBinding = binding.binding,
43681                         rootUuid = propBinding.rootNode.uuid,
43682                         trackName = propBinding.path,
43683                         bindingsByRoot = this._bindingsByRootAndName,
43684                         bindingByName = bindingsByRoot[ rootUuid ],
43685
43686                         lastInactiveBinding = bindings[ bindings.length - 1 ],
43687                         cacheIndex = binding._cacheIndex;
43688
43689                 lastInactiveBinding._cacheIndex = cacheIndex;
43690                 bindings[ cacheIndex ] = lastInactiveBinding;
43691                 bindings.pop();
43692
43693                 delete bindingByName[ trackName ];
43694
43695                 if ( Object.keys( bindingByName ).length === 0 ) {
43696
43697                         delete bindingsByRoot[ rootUuid ];
43698
43699                 }
43700
43701         },
43702
43703         _lendBinding: function ( binding ) {
43704
43705                 const bindings = this._bindings,
43706                         prevIndex = binding._cacheIndex,
43707
43708                         lastActiveIndex = this._nActiveBindings ++,
43709
43710                         firstInactiveBinding = bindings[ lastActiveIndex ];
43711
43712                 binding._cacheIndex = lastActiveIndex;
43713                 bindings[ lastActiveIndex ] = binding;
43714
43715                 firstInactiveBinding._cacheIndex = prevIndex;
43716                 bindings[ prevIndex ] = firstInactiveBinding;
43717
43718         },
43719
43720         _takeBackBinding: function ( binding ) {
43721
43722                 const bindings = this._bindings,
43723                         prevIndex = binding._cacheIndex,
43724
43725                         firstInactiveIndex = -- this._nActiveBindings,
43726
43727                         lastActiveBinding = bindings[ firstInactiveIndex ];
43728
43729                 binding._cacheIndex = firstInactiveIndex;
43730                 bindings[ firstInactiveIndex ] = binding;
43731
43732                 lastActiveBinding._cacheIndex = prevIndex;
43733                 bindings[ prevIndex ] = lastActiveBinding;
43734
43735         },
43736
43737
43738         // Memory management of Interpolants for weight and time scale
43739
43740         _lendControlInterpolant: function () {
43741
43742                 const interpolants = this._controlInterpolants,
43743                         lastActiveIndex = this._nActiveControlInterpolants ++;
43744
43745                 let interpolant = interpolants[ lastActiveIndex ];
43746
43747                 if ( interpolant === undefined ) {
43748
43749                         interpolant = new LinearInterpolant(
43750                                 new Float32Array( 2 ), new Float32Array( 2 ),
43751                                 1, this._controlInterpolantsResultBuffer );
43752
43753                         interpolant.__cacheIndex = lastActiveIndex;
43754                         interpolants[ lastActiveIndex ] = interpolant;
43755
43756                 }
43757
43758                 return interpolant;
43759
43760         },
43761
43762         _takeBackControlInterpolant: function ( interpolant ) {
43763
43764                 const interpolants = this._controlInterpolants,
43765                         prevIndex = interpolant.__cacheIndex,
43766
43767                         firstInactiveIndex = -- this._nActiveControlInterpolants,
43768
43769                         lastActiveInterpolant = interpolants[ firstInactiveIndex ];
43770
43771                 interpolant.__cacheIndex = firstInactiveIndex;
43772                 interpolants[ firstInactiveIndex ] = interpolant;
43773
43774                 lastActiveInterpolant.__cacheIndex = prevIndex;
43775                 interpolants[ prevIndex ] = lastActiveInterpolant;
43776
43777         },
43778
43779         _controlInterpolantsResultBuffer: new Float32Array( 1 ),
43780
43781         // return an action for a clip optionally using a custom root target
43782         // object (this method allocates a lot of dynamic memory in case a
43783         // previously unknown clip/root combination is specified)
43784         clipAction: function ( clip, optionalRoot, blendMode ) {
43785
43786                 const root = optionalRoot || this._root,
43787                         rootUuid = root.uuid;
43788
43789                 let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
43790
43791                 const clipUuid = clipObject !== null ? clipObject.uuid : clip;
43792
43793                 const actionsForClip = this._actionsByClip[ clipUuid ];
43794                 let prototypeAction = null;
43795
43796                 if ( blendMode === undefined ) {
43797
43798                         if ( clipObject !== null ) {
43799
43800                                 blendMode = clipObject.blendMode;
43801
43802                         } else {
43803
43804                                 blendMode = NormalAnimationBlendMode;
43805
43806                         }
43807
43808                 }
43809
43810                 if ( actionsForClip !== undefined ) {
43811
43812                         const existingAction = actionsForClip.actionByRoot[ rootUuid ];
43813
43814                         if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
43815
43816                                 return existingAction;
43817
43818                         }
43819
43820                         // we know the clip, so we don't have to parse all
43821                         // the bindings again but can just copy
43822                         prototypeAction = actionsForClip.knownActions[ 0 ];
43823
43824                         // also, take the clip from the prototype action
43825                         if ( clipObject === null )
43826                                 clipObject = prototypeAction._clip;
43827
43828                 }
43829
43830                 // clip must be known when specified via string
43831                 if ( clipObject === null ) return null;
43832
43833                 // allocate all resources required to run it
43834                 const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
43835
43836                 this._bindAction( newAction, prototypeAction );
43837
43838                 // and make the action known to the memory manager
43839                 this._addInactiveAction( newAction, clipUuid, rootUuid );
43840
43841                 return newAction;
43842
43843         },
43844
43845         // get an existing action
43846         existingAction: function ( clip, optionalRoot ) {
43847
43848                 const root = optionalRoot || this._root,
43849                         rootUuid = root.uuid,
43850
43851                         clipObject = typeof clip === 'string' ?
43852                                 AnimationClip.findByName( root, clip ) : clip,
43853
43854                         clipUuid = clipObject ? clipObject.uuid : clip,
43855
43856                         actionsForClip = this._actionsByClip[ clipUuid ];
43857
43858                 if ( actionsForClip !== undefined ) {
43859
43860                         return actionsForClip.actionByRoot[ rootUuid ] || null;
43861
43862                 }
43863
43864                 return null;
43865
43866         },
43867
43868         // deactivates all previously scheduled actions
43869         stopAllAction: function () {
43870
43871                 const actions = this._actions,
43872                         nActions = this._nActiveActions;
43873
43874                 for ( let i = nActions - 1; i >= 0; -- i ) {
43875
43876                         actions[ i ].stop();
43877
43878                 }
43879
43880                 return this;
43881
43882         },
43883
43884         // advance the time and update apply the animation
43885         update: function ( deltaTime ) {
43886
43887                 deltaTime *= this.timeScale;
43888
43889                 const actions = this._actions,
43890                         nActions = this._nActiveActions,
43891
43892                         time = this.time += deltaTime,
43893                         timeDirection = Math.sign( deltaTime ),
43894
43895                         accuIndex = this._accuIndex ^= 1;
43896
43897                 // run active actions
43898
43899                 for ( let i = 0; i !== nActions; ++ i ) {
43900
43901                         const action = actions[ i ];
43902
43903                         action._update( time, deltaTime, timeDirection, accuIndex );
43904
43905                 }
43906
43907                 // update scene graph
43908
43909                 const bindings = this._bindings,
43910                         nBindings = this._nActiveBindings;
43911
43912                 for ( let i = 0; i !== nBindings; ++ i ) {
43913
43914                         bindings[ i ].apply( accuIndex );
43915
43916                 }
43917
43918                 return this;
43919
43920         },
43921
43922         // Allows you to seek to a specific time in an animation.
43923         setTime: function ( timeInSeconds ) {
43924
43925                 this.time = 0; // Zero out time attribute for AnimationMixer object;
43926                 for ( let i = 0; i < this._actions.length; i ++ ) {
43927
43928                         this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
43929
43930                 }
43931
43932                 return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
43933
43934         },
43935
43936         // return this mixer's root target object
43937         getRoot: function () {
43938
43939                 return this._root;
43940
43941         },
43942
43943         // free all resources specific to a particular clip
43944         uncacheClip: function ( clip ) {
43945
43946                 const actions = this._actions,
43947                         clipUuid = clip.uuid,
43948                         actionsByClip = this._actionsByClip,
43949                         actionsForClip = actionsByClip[ clipUuid ];
43950
43951                 if ( actionsForClip !== undefined ) {
43952
43953                         // note: just calling _removeInactiveAction would mess up the
43954                         // iteration state and also require updating the state we can
43955                         // just throw away
43956
43957                         const actionsToRemove = actionsForClip.knownActions;
43958
43959                         for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
43960
43961                                 const action = actionsToRemove[ i ];
43962
43963                                 this._deactivateAction( action );
43964
43965                                 const cacheIndex = action._cacheIndex,
43966                                         lastInactiveAction = actions[ actions.length - 1 ];
43967
43968                                 action._cacheIndex = null;
43969                                 action._byClipCacheIndex = null;
43970
43971                                 lastInactiveAction._cacheIndex = cacheIndex;
43972                                 actions[ cacheIndex ] = lastInactiveAction;
43973                                 actions.pop();
43974
43975                                 this._removeInactiveBindingsForAction( action );
43976
43977                         }
43978
43979                         delete actionsByClip[ clipUuid ];
43980
43981                 }
43982
43983         },
43984
43985         // free all resources specific to a particular root target object
43986         uncacheRoot: function ( root ) {
43987
43988                 const rootUuid = root.uuid,
43989                         actionsByClip = this._actionsByClip;
43990
43991                 for ( const clipUuid in actionsByClip ) {
43992
43993                         const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
43994                                 action = actionByRoot[ rootUuid ];
43995
43996                         if ( action !== undefined ) {
43997
43998                                 this._deactivateAction( action );
43999                                 this._removeInactiveAction( action );
44000
44001                         }
44002
44003                 }
44004
44005                 const bindingsByRoot = this._bindingsByRootAndName,
44006                         bindingByName = bindingsByRoot[ rootUuid ];
44007
44008                 if ( bindingByName !== undefined ) {
44009
44010                         for ( const trackName in bindingByName ) {
44011
44012                                 const binding = bindingByName[ trackName ];
44013                                 binding.restoreOriginalState();
44014                                 this._removeInactiveBinding( binding );
44015
44016                         }
44017
44018                 }
44019
44020         },
44021
44022         // remove a targeted clip from the cache
44023         uncacheAction: function ( clip, optionalRoot ) {
44024
44025                 const action = this.existingAction( clip, optionalRoot );
44026
44027                 if ( action !== null ) {
44028
44029                         this._deactivateAction( action );
44030                         this._removeInactiveAction( action );
44031
44032                 }
44033
44034         }
44035
44036 } );
44037
44038 class Uniform {
44039
44040         constructor( value ) {
44041
44042                 if ( typeof value === 'string' ) {
44043
44044                         console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
44045                         value = arguments[ 1 ];
44046
44047                 }
44048
44049                 this.value = value;
44050
44051         }
44052
44053         clone() {
44054
44055                 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
44056
44057         }
44058
44059 }
44060
44061 function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
44062
44063         InterleavedBuffer.call( this, array, stride );
44064
44065         this.meshPerAttribute = meshPerAttribute || 1;
44066
44067 }
44068
44069 InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
44070
44071         constructor: InstancedInterleavedBuffer,
44072
44073         isInstancedInterleavedBuffer: true,
44074
44075         copy: function ( source ) {
44076
44077                 InterleavedBuffer.prototype.copy.call( this, source );
44078
44079                 this.meshPerAttribute = source.meshPerAttribute;
44080
44081                 return this;
44082
44083         },
44084
44085         clone: function ( data ) {
44086
44087                 const ib = InterleavedBuffer.prototype.clone.call( this, data );
44088
44089                 ib.meshPerAttribute = this.meshPerAttribute;
44090
44091                 return ib;
44092
44093         },
44094
44095         toJSON: function ( data ) {
44096
44097                 const json = InterleavedBuffer.prototype.toJSON.call( this, data );
44098
44099                 json.isInstancedInterleavedBuffer = true;
44100                 json.meshPerAttribute = this.meshPerAttribute;
44101
44102                 return json;
44103
44104         }
44105
44106 } );
44107
44108 function GLBufferAttribute( buffer, type, itemSize, elementSize, count ) {
44109
44110         this.buffer = buffer;
44111         this.type = type;
44112         this.itemSize = itemSize;
44113         this.elementSize = elementSize;
44114         this.count = count;
44115
44116         this.version = 0;
44117
44118 }
44119
44120 Object.defineProperty( GLBufferAttribute.prototype, 'needsUpdate', {
44121
44122         set: function ( value ) {
44123
44124                 if ( value === true ) this.version ++;
44125
44126         }
44127
44128 } );
44129
44130 Object.assign( GLBufferAttribute.prototype, {
44131
44132         isGLBufferAttribute: true,
44133
44134         setBuffer: function ( buffer ) {
44135
44136                 this.buffer = buffer;
44137
44138                 return this;
44139
44140         },
44141
44142         setType: function ( type, elementSize ) {
44143
44144                 this.type = type;
44145                 this.elementSize = elementSize;
44146
44147                 return this;
44148
44149         },
44150
44151         setItemSize: function ( itemSize ) {
44152
44153                 this.itemSize = itemSize;
44154
44155                 return this;
44156
44157         },
44158
44159         setCount: function ( count ) {
44160
44161                 this.count = count;
44162
44163                 return this;
44164
44165         },
44166
44167 } );
44168
44169 function Raycaster( origin, direction, near, far ) {
44170
44171         this.ray = new Ray( origin, direction );
44172         // direction is assumed to be normalized (for accurate distance calculations)
44173
44174         this.near = near || 0;
44175         this.far = far || Infinity;
44176         this.camera = null;
44177         this.layers = new Layers();
44178
44179         this.params = {
44180                 Mesh: {},
44181                 Line: { threshold: 1 },
44182                 LOD: {},
44183                 Points: { threshold: 1 },
44184                 Sprite: {}
44185         };
44186
44187         Object.defineProperties( this.params, {
44188                 PointCloud: {
44189                         get: function () {
44190
44191                                 console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
44192                                 return this.Points;
44193
44194                         }
44195                 }
44196         } );
44197
44198 }
44199
44200 function ascSort( a, b ) {
44201
44202         return a.distance - b.distance;
44203
44204 }
44205
44206 function intersectObject( object, raycaster, intersects, recursive ) {
44207
44208         if ( object.layers.test( raycaster.layers ) ) {
44209
44210                 object.raycast( raycaster, intersects );
44211
44212         }
44213
44214         if ( recursive === true ) {
44215
44216                 const children = object.children;
44217
44218                 for ( let i = 0, l = children.length; i < l; i ++ ) {
44219
44220                         intersectObject( children[ i ], raycaster, intersects, true );
44221
44222                 }
44223
44224         }
44225
44226 }
44227
44228 Object.assign( Raycaster.prototype, {
44229
44230         set: function ( origin, direction ) {
44231
44232                 // direction is assumed to be normalized (for accurate distance calculations)
44233
44234                 this.ray.set( origin, direction );
44235
44236         },
44237
44238         setFromCamera: function ( coords, camera ) {
44239
44240                 if ( camera && camera.isPerspectiveCamera ) {
44241
44242                         this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
44243                         this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
44244                         this.camera = camera;
44245
44246                 } else if ( camera && camera.isOrthographicCamera ) {
44247
44248                         this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
44249                         this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
44250                         this.camera = camera;
44251
44252                 } else {
44253
44254                         console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type );
44255
44256                 }
44257
44258         },
44259
44260         intersectObject: function ( object, recursive, optionalTarget ) {
44261
44262                 const intersects = optionalTarget || [];
44263
44264                 intersectObject( object, this, intersects, recursive );
44265
44266                 intersects.sort( ascSort );
44267
44268                 return intersects;
44269
44270         },
44271
44272         intersectObjects: function ( objects, recursive, optionalTarget ) {
44273
44274                 const intersects = optionalTarget || [];
44275
44276                 if ( Array.isArray( objects ) === false ) {
44277
44278                         console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
44279                         return intersects;
44280
44281                 }
44282
44283                 for ( let i = 0, l = objects.length; i < l; i ++ ) {
44284
44285                         intersectObject( objects[ i ], this, intersects, recursive );
44286
44287                 }
44288
44289                 intersects.sort( ascSort );
44290
44291                 return intersects;
44292
44293         }
44294
44295 } );
44296
44297 /**
44298  * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
44299  *
44300  * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.
44301  * The azimuthal angle (theta) is measured from the positive z-axis.
44302  */
44303
44304 class Spherical {
44305
44306         constructor( radius = 1, phi = 0, theta = 0 ) {
44307
44308                 this.radius = radius;
44309                 this.phi = phi; // polar angle
44310                 this.theta = theta; // azimuthal angle
44311
44312                 return this;
44313
44314         }
44315
44316         set( radius, phi, theta ) {
44317
44318                 this.radius = radius;
44319                 this.phi = phi;
44320                 this.theta = theta;
44321
44322                 return this;
44323
44324         }
44325
44326         clone() {
44327
44328                 return new this.constructor().copy( this );
44329
44330         }
44331
44332         copy( other ) {
44333
44334                 this.radius = other.radius;
44335                 this.phi = other.phi;
44336                 this.theta = other.theta;
44337
44338                 return this;
44339
44340         }
44341
44342         // restrict phi to be betwee EPS and PI-EPS
44343         makeSafe() {
44344
44345                 const EPS = 0.000001;
44346                 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
44347
44348                 return this;
44349
44350         }
44351
44352         setFromVector3( v ) {
44353
44354                 return this.setFromCartesianCoords( v.x, v.y, v.z );
44355
44356         }
44357
44358         setFromCartesianCoords( x, y, z ) {
44359
44360                 this.radius = Math.sqrt( x * x + y * y + z * z );
44361
44362                 if ( this.radius === 0 ) {
44363
44364                         this.theta = 0;
44365                         this.phi = 0;
44366
44367                 } else {
44368
44369                         this.theta = Math.atan2( x, z );
44370                         this.phi = Math.acos( MathUtils.clamp( y / this.radius, - 1, 1 ) );
44371
44372                 }
44373
44374                 return this;
44375
44376         }
44377
44378 }
44379
44380 /**
44381  * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
44382  */
44383
44384 class Cylindrical {
44385
44386         constructor( radius, theta, y ) {
44387
44388                 this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane
44389                 this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
44390                 this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane
44391
44392                 return this;
44393
44394         }
44395
44396         set( radius, theta, y ) {
44397
44398                 this.radius = radius;
44399                 this.theta = theta;
44400                 this.y = y;
44401
44402                 return this;
44403
44404         }
44405
44406         clone() {
44407
44408                 return new this.constructor().copy( this );
44409
44410         }
44411
44412         copy( other ) {
44413
44414                 this.radius = other.radius;
44415                 this.theta = other.theta;
44416                 this.y = other.y;
44417
44418                 return this;
44419
44420         }
44421
44422         setFromVector3( v ) {
44423
44424                 return this.setFromCartesianCoords( v.x, v.y, v.z );
44425
44426         }
44427
44428         setFromCartesianCoords( x, y, z ) {
44429
44430                 this.radius = Math.sqrt( x * x + z * z );
44431                 this.theta = Math.atan2( x, z );
44432                 this.y = y;
44433
44434                 return this;
44435
44436         }
44437
44438 }
44439
44440 const _vector$8 = /*@__PURE__*/ new Vector2();
44441
44442 class Box2 {
44443
44444         constructor( min, max ) {
44445
44446                 Object.defineProperty( this, 'isBox2', { value: true } );
44447
44448                 this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
44449                 this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
44450
44451         }
44452
44453         set( min, max ) {
44454
44455                 this.min.copy( min );
44456                 this.max.copy( max );
44457
44458                 return this;
44459
44460         }
44461
44462         setFromPoints( points ) {
44463
44464                 this.makeEmpty();
44465
44466                 for ( let i = 0, il = points.length; i < il; i ++ ) {
44467
44468                         this.expandByPoint( points[ i ] );
44469
44470                 }
44471
44472                 return this;
44473
44474         }
44475
44476         setFromCenterAndSize( center, size ) {
44477
44478                 const halfSize = _vector$8.copy( size ).multiplyScalar( 0.5 );
44479                 this.min.copy( center ).sub( halfSize );
44480                 this.max.copy( center ).add( halfSize );
44481
44482                 return this;
44483
44484         }
44485
44486         clone() {
44487
44488                 return new this.constructor().copy( this );
44489
44490         }
44491
44492         copy( box ) {
44493
44494                 this.min.copy( box.min );
44495                 this.max.copy( box.max );
44496
44497                 return this;
44498
44499         }
44500
44501         makeEmpty() {
44502
44503                 this.min.x = this.min.y = + Infinity;
44504                 this.max.x = this.max.y = - Infinity;
44505
44506                 return this;
44507
44508         }
44509
44510         isEmpty() {
44511
44512                 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
44513
44514                 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
44515
44516         }
44517
44518         getCenter( target ) {
44519
44520                 if ( target === undefined ) {
44521
44522                         console.warn( 'THREE.Box2: .getCenter() target is now required' );
44523                         target = new Vector2();
44524
44525                 }
44526
44527                 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
44528
44529         }
44530
44531         getSize( target ) {
44532
44533                 if ( target === undefined ) {
44534
44535                         console.warn( 'THREE.Box2: .getSize() target is now required' );
44536                         target = new Vector2();
44537
44538                 }
44539
44540                 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
44541
44542         }
44543
44544         expandByPoint( point ) {
44545
44546                 this.min.min( point );
44547                 this.max.max( point );
44548
44549                 return this;
44550
44551         }
44552
44553         expandByVector( vector ) {
44554
44555                 this.min.sub( vector );
44556                 this.max.add( vector );
44557
44558                 return this;
44559
44560         }
44561
44562         expandByScalar( scalar ) {
44563
44564                 this.min.addScalar( - scalar );
44565                 this.max.addScalar( scalar );
44566
44567                 return this;
44568
44569         }
44570
44571         containsPoint( point ) {
44572
44573                 return point.x < this.min.x || point.x > this.max.x ||
44574                         point.y < this.min.y || point.y > this.max.y ? false : true;
44575
44576         }
44577
44578         containsBox( box ) {
44579
44580                 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
44581                         this.min.y <= box.min.y && box.max.y <= this.max.y;
44582
44583         }
44584
44585         getParameter( point, target ) {
44586
44587                 // This can potentially have a divide by zero if the box
44588                 // has a size dimension of 0.
44589
44590                 if ( target === undefined ) {
44591
44592                         console.warn( 'THREE.Box2: .getParameter() target is now required' );
44593                         target = new Vector2();
44594
44595                 }
44596
44597                 return target.set(
44598                         ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
44599                         ( point.y - this.min.y ) / ( this.max.y - this.min.y )
44600                 );
44601
44602         }
44603
44604         intersectsBox( box ) {
44605
44606                 // using 4 splitting planes to rule out intersections
44607
44608                 return box.max.x < this.min.x || box.min.x > this.max.x ||
44609                         box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
44610
44611         }
44612
44613         clampPoint( point, target ) {
44614
44615                 if ( target === undefined ) {
44616
44617                         console.warn( 'THREE.Box2: .clampPoint() target is now required' );
44618                         target = new Vector2();
44619
44620                 }
44621
44622                 return target.copy( point ).clamp( this.min, this.max );
44623
44624         }
44625
44626         distanceToPoint( point ) {
44627
44628                 const clampedPoint = _vector$8.copy( point ).clamp( this.min, this.max );
44629                 return clampedPoint.sub( point ).length();
44630
44631         }
44632
44633         intersect( box ) {
44634
44635                 this.min.max( box.min );
44636                 this.max.min( box.max );
44637
44638                 return this;
44639
44640         }
44641
44642         union( box ) {
44643
44644                 this.min.min( box.min );
44645                 this.max.max( box.max );
44646
44647                 return this;
44648
44649         }
44650
44651         translate( offset ) {
44652
44653                 this.min.add( offset );
44654                 this.max.add( offset );
44655
44656                 return this;
44657
44658         }
44659
44660         equals( box ) {
44661
44662                 return box.min.equals( this.min ) && box.max.equals( this.max );
44663
44664         }
44665
44666 }
44667
44668 const _startP = /*@__PURE__*/ new Vector3();
44669 const _startEnd = /*@__PURE__*/ new Vector3();
44670
44671 class Line3 {
44672
44673         constructor( start, end ) {
44674
44675                 this.start = ( start !== undefined ) ? start : new Vector3();
44676                 this.end = ( end !== undefined ) ? end : new Vector3();
44677
44678         }
44679
44680         set( start, end ) {
44681
44682                 this.start.copy( start );
44683                 this.end.copy( end );
44684
44685                 return this;
44686
44687         }
44688
44689         clone() {
44690
44691                 return new this.constructor().copy( this );
44692
44693         }
44694
44695         copy( line ) {
44696
44697                 this.start.copy( line.start );
44698                 this.end.copy( line.end );
44699
44700                 return this;
44701
44702         }
44703
44704         getCenter( target ) {
44705
44706                 if ( target === undefined ) {
44707
44708                         console.warn( 'THREE.Line3: .getCenter() target is now required' );
44709                         target = new Vector3();
44710
44711                 }
44712
44713                 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
44714
44715         }
44716
44717         delta( target ) {
44718
44719                 if ( target === undefined ) {
44720
44721                         console.warn( 'THREE.Line3: .delta() target is now required' );
44722                         target = new Vector3();
44723
44724                 }
44725
44726                 return target.subVectors( this.end, this.start );
44727
44728         }
44729
44730         distanceSq() {
44731
44732                 return this.start.distanceToSquared( this.end );
44733
44734         }
44735
44736         distance() {
44737
44738                 return this.start.distanceTo( this.end );
44739
44740         }
44741
44742         at( t, target ) {
44743
44744                 if ( target === undefined ) {
44745
44746                         console.warn( 'THREE.Line3: .at() target is now required' );
44747                         target = new Vector3();
44748
44749                 }
44750
44751                 return this.delta( target ).multiplyScalar( t ).add( this.start );
44752
44753         }
44754
44755         closestPointToPointParameter( point, clampToLine ) {
44756
44757                 _startP.subVectors( point, this.start );
44758                 _startEnd.subVectors( this.end, this.start );
44759
44760                 const startEnd2 = _startEnd.dot( _startEnd );
44761                 const startEnd_startP = _startEnd.dot( _startP );
44762
44763                 let t = startEnd_startP / startEnd2;
44764
44765                 if ( clampToLine ) {
44766
44767                         t = MathUtils.clamp( t, 0, 1 );
44768
44769                 }
44770
44771                 return t;
44772
44773         }
44774
44775         closestPointToPoint( point, clampToLine, target ) {
44776
44777                 const t = this.closestPointToPointParameter( point, clampToLine );
44778
44779                 if ( target === undefined ) {
44780
44781                         console.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );
44782                         target = new Vector3();
44783
44784                 }
44785
44786                 return this.delta( target ).multiplyScalar( t ).add( this.start );
44787
44788         }
44789
44790         applyMatrix4( matrix ) {
44791
44792                 this.start.applyMatrix4( matrix );
44793                 this.end.applyMatrix4( matrix );
44794
44795                 return this;
44796
44797         }
44798
44799         equals( line ) {
44800
44801                 return line.start.equals( this.start ) && line.end.equals( this.end );
44802
44803         }
44804
44805 }
44806
44807 function ImmediateRenderObject( material ) {
44808
44809         Object3D.call( this );
44810
44811         this.material = material;
44812         this.render = function ( /* renderCallback */ ) {};
44813
44814         this.hasPositions = false;
44815         this.hasNormals = false;
44816         this.hasColors = false;
44817         this.hasUvs = false;
44818
44819         this.positionArray = null;
44820         this.normalArray = null;
44821         this.colorArray = null;
44822         this.uvArray = null;
44823
44824         this.count = 0;
44825
44826 }
44827
44828 ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
44829 ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
44830
44831 ImmediateRenderObject.prototype.isImmediateRenderObject = true;
44832
44833 const _vector$9 = /*@__PURE__*/ new Vector3();
44834
44835 class SpotLightHelper extends Object3D {
44836
44837         constructor( light, color ) {
44838
44839                 super();
44840                 this.light = light;
44841                 this.light.updateMatrixWorld();
44842
44843                 this.matrix = light.matrixWorld;
44844                 this.matrixAutoUpdate = false;
44845
44846                 this.color = color;
44847
44848                 const geometry = new BufferGeometry();
44849
44850                 const positions = [
44851                         0, 0, 0,        0, 0, 1,
44852                         0, 0, 0,        1, 0, 1,
44853                         0, 0, 0,        - 1, 0, 1,
44854                         0, 0, 0,        0, 1, 1,
44855                         0, 0, 0,        0, - 1, 1
44856                 ];
44857
44858                 for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
44859
44860                         const p1 = ( i / l ) * Math.PI * 2;
44861                         const p2 = ( j / l ) * Math.PI * 2;
44862
44863                         positions.push(
44864                                 Math.cos( p1 ), Math.sin( p1 ), 1,
44865                                 Math.cos( p2 ), Math.sin( p2 ), 1
44866                         );
44867
44868                 }
44869
44870                 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
44871
44872                 const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
44873
44874                 this.cone = new LineSegments( geometry, material );
44875                 this.add( this.cone );
44876
44877                 this.update();
44878
44879         }
44880
44881         dispose() {
44882
44883                 this.cone.geometry.dispose();
44884                 this.cone.material.dispose();
44885
44886         }
44887
44888         update() {
44889
44890                 this.light.updateMatrixWorld();
44891
44892                 const coneLength = this.light.distance ? this.light.distance : 1000;
44893                 const coneWidth = coneLength * Math.tan( this.light.angle );
44894
44895                 this.cone.scale.set( coneWidth, coneWidth, coneLength );
44896
44897                 _vector$9.setFromMatrixPosition( this.light.target.matrixWorld );
44898
44899                 this.cone.lookAt( _vector$9 );
44900
44901                 if ( this.color !== undefined ) {
44902
44903                         this.cone.material.color.set( this.color );
44904
44905                 } else {
44906
44907                         this.cone.material.color.copy( this.light.color );
44908
44909                 }
44910
44911         }
44912
44913 }
44914
44915 const _vector$a = /*@__PURE__*/ new Vector3();
44916 const _boneMatrix = /*@__PURE__*/ new Matrix4();
44917 const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
44918
44919
44920 class SkeletonHelper extends LineSegments {
44921
44922         constructor( object ) {
44923
44924                 const bones = getBoneList( object );
44925
44926                 const geometry = new BufferGeometry();
44927
44928                 const vertices = [];
44929                 const colors = [];
44930
44931                 const color1 = new Color( 0, 0, 1 );
44932                 const color2 = new Color( 0, 1, 0 );
44933
44934                 for ( let i = 0; i < bones.length; i ++ ) {
44935
44936                         const bone = bones[ i ];
44937
44938                         if ( bone.parent && bone.parent.isBone ) {
44939
44940                                 vertices.push( 0, 0, 0 );
44941                                 vertices.push( 0, 0, 0 );
44942                                 colors.push( color1.r, color1.g, color1.b );
44943                                 colors.push( color2.r, color2.g, color2.b );
44944
44945                         }
44946
44947                 }
44948
44949                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
44950                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
44951
44952                 const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
44953
44954                 super( geometry, material );
44955
44956                 this.type = 'SkeletonHelper';
44957                 this.isSkeletonHelper = true;
44958
44959                 this.root = object;
44960                 this.bones = bones;
44961
44962                 this.matrix = object.matrixWorld;
44963                 this.matrixAutoUpdate = false;
44964
44965         }
44966
44967         updateMatrixWorld( force ) {
44968
44969                 const bones = this.bones;
44970
44971                 const geometry = this.geometry;
44972                 const position = geometry.getAttribute( 'position' );
44973
44974                 _matrixWorldInv.copy( this.root.matrixWorld ).invert();
44975
44976                 for ( let i = 0, j = 0; i < bones.length; i ++ ) {
44977
44978                         const bone = bones[ i ];
44979
44980                         if ( bone.parent && bone.parent.isBone ) {
44981
44982                                 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
44983                                 _vector$a.setFromMatrixPosition( _boneMatrix );
44984                                 position.setXYZ( j, _vector$a.x, _vector$a.y, _vector$a.z );
44985
44986                                 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
44987                                 _vector$a.setFromMatrixPosition( _boneMatrix );
44988                                 position.setXYZ( j + 1, _vector$a.x, _vector$a.y, _vector$a.z );
44989
44990                                 j += 2;
44991
44992                         }
44993
44994                 }
44995
44996                 geometry.getAttribute( 'position' ).needsUpdate = true;
44997
44998                 super.updateMatrixWorld( force );
44999
45000         }
45001
45002 }
45003
45004
45005 function getBoneList( object ) {
45006
45007         const boneList = [];
45008
45009         if ( object && object.isBone ) {
45010
45011                 boneList.push( object );
45012
45013         }
45014
45015         for ( let i = 0; i < object.children.length; i ++ ) {
45016
45017                 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
45018
45019         }
45020
45021         return boneList;
45022
45023 }
45024
45025 class PointLightHelper extends Mesh {
45026
45027         constructor( light, sphereSize, color ) {
45028
45029                 const geometry = new SphereGeometry( sphereSize, 4, 2 );
45030                 const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
45031
45032                 super( geometry, material );
45033
45034                 this.light = light;
45035                 this.light.updateMatrixWorld();
45036
45037                 this.color = color;
45038
45039                 this.type = 'PointLightHelper';
45040
45041                 this.matrix = this.light.matrixWorld;
45042                 this.matrixAutoUpdate = false;
45043
45044                 this.update();
45045
45046
45047                 /*
45048         // TODO: delete this comment?
45049         const distanceGeometry = new THREE.IcosahedronBufferGeometry( 1, 2 );
45050         const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
45051
45052         this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
45053         this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
45054
45055         const d = light.distance;
45056
45057         if ( d === 0.0 ) {
45058
45059                 this.lightDistance.visible = false;
45060
45061         } else {
45062
45063                 this.lightDistance.scale.set( d, d, d );
45064
45065         }
45066
45067         this.add( this.lightDistance );
45068         */
45069
45070         }
45071
45072         dispose() {
45073
45074                 this.geometry.dispose();
45075                 this.material.dispose();
45076
45077         }
45078
45079         update() {
45080
45081                 if ( this.color !== undefined ) {
45082
45083                         this.material.color.set( this.color );
45084
45085                 } else {
45086
45087                         this.material.color.copy( this.light.color );
45088
45089                 }
45090
45091                 /*
45092                 const d = this.light.distance;
45093
45094                 if ( d === 0.0 ) {
45095
45096                         this.lightDistance.visible = false;
45097
45098                 } else {
45099
45100                         this.lightDistance.visible = true;
45101                         this.lightDistance.scale.set( d, d, d );
45102
45103                 }
45104                 */
45105
45106         }
45107
45108 }
45109
45110 const _vector$b = /*@__PURE__*/ new Vector3();
45111 const _color1 = /*@__PURE__*/ new Color();
45112 const _color2 = /*@__PURE__*/ new Color();
45113
45114 class HemisphereLightHelper extends Object3D {
45115
45116         constructor( light, size, color ) {
45117
45118                 super();
45119                 this.light = light;
45120                 this.light.updateMatrixWorld();
45121
45122                 this.matrix = light.matrixWorld;
45123                 this.matrixAutoUpdate = false;
45124
45125                 this.color = color;
45126
45127                 const geometry = new OctahedronGeometry( size );
45128                 geometry.rotateY( Math.PI * 0.5 );
45129
45130                 this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
45131                 if ( this.color === undefined ) this.material.vertexColors = true;
45132
45133                 const position = geometry.getAttribute( 'position' );
45134                 const colors = new Float32Array( position.count * 3 );
45135
45136                 geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
45137
45138                 this.add( new Mesh( geometry, this.material ) );
45139
45140                 this.update();
45141
45142         }
45143
45144         dispose() {
45145
45146                 this.children[ 0 ].geometry.dispose();
45147                 this.children[ 0 ].material.dispose();
45148
45149         }
45150
45151         update() {
45152
45153                 const mesh = this.children[ 0 ];
45154
45155                 if ( this.color !== undefined ) {
45156
45157                         this.material.color.set( this.color );
45158
45159                 } else {
45160
45161                         const colors = mesh.geometry.getAttribute( 'color' );
45162
45163                         _color1.copy( this.light.color );
45164                         _color2.copy( this.light.groundColor );
45165
45166                         for ( let i = 0, l = colors.count; i < l; i ++ ) {
45167
45168                                 const color = ( i < ( l / 2 ) ) ? _color1 : _color2;
45169
45170                                 colors.setXYZ( i, color.r, color.g, color.b );
45171
45172                         }
45173
45174                         colors.needsUpdate = true;
45175
45176                 }
45177
45178                 mesh.lookAt( _vector$b.setFromMatrixPosition( this.light.matrixWorld ).negate() );
45179
45180         }
45181
45182 }
45183
45184 class GridHelper extends LineSegments {
45185
45186         constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
45187
45188                 color1 = new Color( color1 );
45189                 color2 = new Color( color2 );
45190
45191                 const center = divisions / 2;
45192                 const step = size / divisions;
45193                 const halfSize = size / 2;
45194
45195                 const vertices = [], colors = [];
45196
45197                 for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
45198
45199                         vertices.push( - halfSize, 0, k, halfSize, 0, k );
45200                         vertices.push( k, 0, - halfSize, k, 0, halfSize );
45201
45202                         const color = i === center ? color1 : color2;
45203
45204                         color.toArray( colors, j ); j += 3;
45205                         color.toArray( colors, j ); j += 3;
45206                         color.toArray( colors, j ); j += 3;
45207                         color.toArray( colors, j ); j += 3;
45208
45209                 }
45210
45211                 const geometry = new BufferGeometry();
45212                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
45213                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
45214
45215                 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
45216
45217                 super( geometry, material );
45218
45219                 this.type = 'GridHelper';
45220
45221         }
45222
45223 }
45224
45225 class PolarGridHelper extends LineSegments {
45226
45227         constructor( radius = 10, radials = 16, circles = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) {
45228
45229                 color1 = new Color( color1 );
45230                 color2 = new Color( color2 );
45231
45232                 const vertices = [];
45233                 const colors = [];
45234
45235                 // create the radials
45236
45237                 for ( let i = 0; i <= radials; i ++ ) {
45238
45239                         const v = ( i / radials ) * ( Math.PI * 2 );
45240
45241                         const x = Math.sin( v ) * radius;
45242                         const z = Math.cos( v ) * radius;
45243
45244                         vertices.push( 0, 0, 0 );
45245                         vertices.push( x, 0, z );
45246
45247                         const color = ( i & 1 ) ? color1 : color2;
45248
45249                         colors.push( color.r, color.g, color.b );
45250                         colors.push( color.r, color.g, color.b );
45251
45252                 }
45253
45254                 // create the circles
45255
45256                 for ( let i = 0; i <= circles; i ++ ) {
45257
45258                         const color = ( i & 1 ) ? color1 : color2;
45259
45260                         const r = radius - ( radius / circles * i );
45261
45262                         for ( let j = 0; j < divisions; j ++ ) {
45263
45264                                 // first vertex
45265
45266                                 let v = ( j / divisions ) * ( Math.PI * 2 );
45267
45268                                 let x = Math.sin( v ) * r;
45269                                 let z = Math.cos( v ) * r;
45270
45271                                 vertices.push( x, 0, z );
45272                                 colors.push( color.r, color.g, color.b );
45273
45274                                 // second vertex
45275
45276                                 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
45277
45278                                 x = Math.sin( v ) * r;
45279                                 z = Math.cos( v ) * r;
45280
45281                                 vertices.push( x, 0, z );
45282                                 colors.push( color.r, color.g, color.b );
45283
45284                         }
45285
45286                 }
45287
45288                 const geometry = new BufferGeometry();
45289                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
45290                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
45291
45292                 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
45293
45294                 super( geometry, material );
45295
45296                 this.type = 'PolarGridHelper';
45297
45298         }
45299
45300 }
45301
45302 const _v1$6 = /*@__PURE__*/ new Vector3();
45303 const _v2$3 = /*@__PURE__*/ new Vector3();
45304 const _v3$1 = /*@__PURE__*/ new Vector3();
45305
45306 class DirectionalLightHelper extends Object3D {
45307
45308         constructor( light, size, color ) {
45309
45310                 super();
45311                 this.light = light;
45312                 this.light.updateMatrixWorld();
45313
45314                 this.matrix = light.matrixWorld;
45315                 this.matrixAutoUpdate = false;
45316
45317                 this.color = color;
45318
45319                 if ( size === undefined ) size = 1;
45320
45321                 let geometry = new BufferGeometry();
45322                 geometry.setAttribute( 'position', new Float32BufferAttribute( [
45323                         - size, size, 0,
45324                         size, size, 0,
45325                         size, - size, 0,
45326                         - size, - size, 0,
45327                         - size, size, 0
45328                 ], 3 ) );
45329
45330                 const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
45331
45332                 this.lightPlane = new Line( geometry, material );
45333                 this.add( this.lightPlane );
45334
45335                 geometry = new BufferGeometry();
45336                 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
45337
45338                 this.targetLine = new Line( geometry, material );
45339                 this.add( this.targetLine );
45340
45341                 this.update();
45342
45343         }
45344
45345         dispose() {
45346
45347                 this.lightPlane.geometry.dispose();
45348                 this.lightPlane.material.dispose();
45349                 this.targetLine.geometry.dispose();
45350                 this.targetLine.material.dispose();
45351
45352         }
45353
45354         update() {
45355
45356                 _v1$6.setFromMatrixPosition( this.light.matrixWorld );
45357                 _v2$3.setFromMatrixPosition( this.light.target.matrixWorld );
45358                 _v3$1.subVectors( _v2$3, _v1$6 );
45359
45360                 this.lightPlane.lookAt( _v2$3 );
45361
45362                 if ( this.color !== undefined ) {
45363
45364                         this.lightPlane.material.color.set( this.color );
45365                         this.targetLine.material.color.set( this.color );
45366
45367                 } else {
45368
45369                         this.lightPlane.material.color.copy( this.light.color );
45370                         this.targetLine.material.color.copy( this.light.color );
45371
45372                 }
45373
45374                 this.targetLine.lookAt( _v2$3 );
45375                 this.targetLine.scale.z = _v3$1.length();
45376
45377         }
45378
45379 }
45380
45381 const _vector$c = /*@__PURE__*/ new Vector3();
45382 const _camera = /*@__PURE__*/ new Camera();
45383
45384 /**
45385  *      - shows frustum, line of sight and up of the camera
45386  *      - suitable for fast updates
45387  *      - based on frustum visualization in lightgl.js shadowmap example
45388  *              http://evanw.github.com/lightgl.js/tests/shadowmap.html
45389  */
45390
45391 class CameraHelper extends LineSegments {
45392
45393         constructor( camera ) {
45394
45395                 const geometry = new BufferGeometry();
45396                 const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
45397
45398                 const vertices = [];
45399                 const colors = [];
45400
45401                 const pointMap = {};
45402
45403                 // colors
45404
45405                 const colorFrustum = new Color( 0xffaa00 );
45406                 const colorCone = new Color( 0xff0000 );
45407                 const colorUp = new Color( 0x00aaff );
45408                 const colorTarget = new Color( 0xffffff );
45409                 const colorCross = new Color( 0x333333 );
45410
45411                 // near
45412
45413                 addLine( 'n1', 'n2', colorFrustum );
45414                 addLine( 'n2', 'n4', colorFrustum );
45415                 addLine( 'n4', 'n3', colorFrustum );
45416                 addLine( 'n3', 'n1', colorFrustum );
45417
45418                 // far
45419
45420                 addLine( 'f1', 'f2', colorFrustum );
45421                 addLine( 'f2', 'f4', colorFrustum );
45422                 addLine( 'f4', 'f3', colorFrustum );
45423                 addLine( 'f3', 'f1', colorFrustum );
45424
45425                 // sides
45426
45427                 addLine( 'n1', 'f1', colorFrustum );
45428                 addLine( 'n2', 'f2', colorFrustum );
45429                 addLine( 'n3', 'f3', colorFrustum );
45430                 addLine( 'n4', 'f4', colorFrustum );
45431
45432                 // cone
45433
45434                 addLine( 'p', 'n1', colorCone );
45435                 addLine( 'p', 'n2', colorCone );
45436                 addLine( 'p', 'n3', colorCone );
45437                 addLine( 'p', 'n4', colorCone );
45438
45439                 // up
45440
45441                 addLine( 'u1', 'u2', colorUp );
45442                 addLine( 'u2', 'u3', colorUp );
45443                 addLine( 'u3', 'u1', colorUp );
45444
45445                 // target
45446
45447                 addLine( 'c', 't', colorTarget );
45448                 addLine( 'p', 'c', colorCross );
45449
45450                 // cross
45451
45452                 addLine( 'cn1', 'cn2', colorCross );
45453                 addLine( 'cn3', 'cn4', colorCross );
45454
45455                 addLine( 'cf1', 'cf2', colorCross );
45456                 addLine( 'cf3', 'cf4', colorCross );
45457
45458                 function addLine( a, b, color ) {
45459
45460                         addPoint( a, color );
45461                         addPoint( b, color );
45462
45463                 }
45464
45465                 function addPoint( id, color ) {
45466
45467                         vertices.push( 0, 0, 0 );
45468                         colors.push( color.r, color.g, color.b );
45469
45470                         if ( pointMap[ id ] === undefined ) {
45471
45472                                 pointMap[ id ] = [];
45473
45474                         }
45475
45476                         pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
45477
45478                 }
45479
45480                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
45481                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
45482
45483                 super( geometry, material );
45484
45485                 this.type = 'CameraHelper';
45486
45487                 this.camera = camera;
45488                 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
45489
45490                 this.matrix = camera.matrixWorld;
45491                 this.matrixAutoUpdate = false;
45492
45493                 this.pointMap = pointMap;
45494
45495                 this.update();
45496
45497         }
45498
45499         update() {
45500
45501                 const geometry = this.geometry;
45502                 const pointMap = this.pointMap;
45503
45504                 const w = 1, h = 1;
45505
45506                 // we need just camera projection matrix inverse
45507                 // world matrix must be identity
45508
45509                 _camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
45510
45511                 // center / target
45512
45513                 setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );
45514                 setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );
45515
45516                 // near
45517
45518                 setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );
45519                 setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );
45520                 setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );
45521                 setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );
45522
45523                 // far
45524
45525                 setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );
45526                 setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );
45527                 setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );
45528                 setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );
45529
45530                 // up
45531
45532                 setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );
45533                 setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );
45534                 setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );
45535
45536                 // cross
45537
45538                 setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );
45539                 setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );
45540                 setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );
45541                 setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );
45542
45543                 setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );
45544                 setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );
45545                 setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );
45546                 setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );
45547
45548                 geometry.getAttribute( 'position' ).needsUpdate = true;
45549
45550         }
45551
45552 }
45553
45554
45555 function setPoint( point, pointMap, geometry, camera, x, y, z ) {
45556
45557         _vector$c.set( x, y, z ).unproject( camera );
45558
45559         const points = pointMap[ point ];
45560
45561         if ( points !== undefined ) {
45562
45563                 const position = geometry.getAttribute( 'position' );
45564
45565                 for ( let i = 0, l = points.length; i < l; i ++ ) {
45566
45567                         position.setXYZ( points[ i ], _vector$c.x, _vector$c.y, _vector$c.z );
45568
45569                 }
45570
45571         }
45572
45573 }
45574
45575 const _box$3 = /*@__PURE__*/ new Box3();
45576
45577 class BoxHelper extends LineSegments {
45578
45579         constructor( object, color = 0xffff00 ) {
45580
45581                 const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
45582                 const positions = new Float32Array( 8 * 3 );
45583
45584                 const geometry = new BufferGeometry();
45585                 geometry.setIndex( new BufferAttribute( indices, 1 ) );
45586                 geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
45587
45588                 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
45589
45590                 this.object = object;
45591                 this.type = 'BoxHelper';
45592
45593                 this.matrixAutoUpdate = false;
45594
45595                 this.update();
45596
45597         }
45598
45599         update( object ) {
45600
45601                 if ( object !== undefined ) {
45602
45603                         console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
45604
45605                 }
45606
45607                 if ( this.object !== undefined ) {
45608
45609                         _box$3.setFromObject( this.object );
45610
45611                 }
45612
45613                 if ( _box$3.isEmpty() ) return;
45614
45615                 const min = _box$3.min;
45616                 const max = _box$3.max;
45617
45618                 /*
45619                         5____4
45620                 1/___0/|
45621                 | 6__|_7
45622                 2/___3/
45623
45624                 0: max.x, max.y, max.z
45625                 1: min.x, max.y, max.z
45626                 2: min.x, min.y, max.z
45627                 3: max.x, min.y, max.z
45628                 4: max.x, max.y, min.z
45629                 5: min.x, max.y, min.z
45630                 6: min.x, min.y, min.z
45631                 7: max.x, min.y, min.z
45632                 */
45633
45634                 const position = this.geometry.attributes.position;
45635                 const array = position.array;
45636
45637                 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
45638                 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
45639                 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
45640                 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
45641                 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
45642                 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
45643                 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
45644                 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
45645
45646                 position.needsUpdate = true;
45647
45648                 this.geometry.computeBoundingSphere();
45649
45650
45651         }
45652
45653         setFromObject( object ) {
45654
45655                 this.object = object;
45656                 this.update();
45657
45658                 return this;
45659
45660         }
45661
45662         copy( source ) {
45663
45664                 LineSegments.prototype.copy.call( this, source );
45665
45666                 this.object = source.object;
45667
45668                 return this;
45669
45670         }
45671
45672 }
45673
45674 class Box3Helper extends LineSegments {
45675
45676         constructor( box, color = 0xffff00 ) {
45677
45678                 const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
45679
45680                 const positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ];
45681
45682                 const geometry = new BufferGeometry();
45683
45684                 geometry.setIndex( new BufferAttribute( indices, 1 ) );
45685
45686                 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
45687
45688                 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
45689
45690                 this.box = box;
45691
45692                 this.type = 'Box3Helper';
45693
45694                 this.geometry.computeBoundingSphere();
45695
45696         }
45697
45698         updateMatrixWorld( force ) {
45699
45700                 const box = this.box;
45701
45702                 if ( box.isEmpty() ) return;
45703
45704                 box.getCenter( this.position );
45705
45706                 box.getSize( this.scale );
45707
45708                 this.scale.multiplyScalar( 0.5 );
45709
45710                 super.updateMatrixWorld( force );
45711
45712         }
45713
45714 }
45715
45716 class PlaneHelper extends Line {
45717
45718         constructor( plane, size = 1, hex = 0xffff00 ) {
45719
45720                 const color = hex;
45721
45722                 const positions = [ 1, - 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 ];
45723
45724                 const geometry = new BufferGeometry();
45725                 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
45726                 geometry.computeBoundingSphere();
45727
45728                 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
45729
45730                 this.type = 'PlaneHelper';
45731
45732                 this.plane = plane;
45733
45734                 this.size = size;
45735
45736                 const positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];
45737
45738                 const geometry2 = new BufferGeometry();
45739                 geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
45740                 geometry2.computeBoundingSphere();
45741
45742                 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
45743
45744         }
45745
45746         updateMatrixWorld( force ) {
45747
45748                 let scale = - this.plane.constant;
45749
45750                 if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter
45751
45752                 this.scale.set( 0.5 * this.size, 0.5 * this.size, scale );
45753
45754                 this.children[ 0 ].material.side = ( scale < 0 ) ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here
45755
45756                 this.lookAt( this.plane.normal );
45757
45758                 super.updateMatrixWorld( force );
45759
45760         }
45761
45762 }
45763
45764 const _axis = /*@__PURE__*/ new Vector3();
45765 let _lineGeometry, _coneGeometry;
45766
45767 class ArrowHelper extends Object3D {
45768
45769         constructor( dir, origin, length, color, headLength, headWidth ) {
45770
45771                 super();
45772                 // dir is assumed to be normalized
45773
45774                 this.type = 'ArrowHelper';
45775
45776                 if ( dir === undefined ) dir = new Vector3( 0, 0, 1 );
45777                 if ( origin === undefined ) origin = new Vector3( 0, 0, 0 );
45778                 if ( length === undefined ) length = 1;
45779                 if ( color === undefined ) color = 0xffff00;
45780                 if ( headLength === undefined ) headLength = 0.2 * length;
45781                 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
45782
45783                 if ( _lineGeometry === undefined ) {
45784
45785                         _lineGeometry = new BufferGeometry();
45786                         _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
45787
45788                         _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 );
45789                         _coneGeometry.translate( 0, - 0.5, 0 );
45790
45791                 }
45792
45793                 this.position.copy( origin );
45794
45795                 this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
45796                 this.line.matrixAutoUpdate = false;
45797                 this.add( this.line );
45798
45799                 this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
45800                 this.cone.matrixAutoUpdate = false;
45801                 this.add( this.cone );
45802
45803                 this.setDirection( dir );
45804                 this.setLength( length, headLength, headWidth );
45805
45806         }
45807
45808         setDirection( dir ) {
45809
45810                 // dir is assumed to be normalized
45811
45812                 if ( dir.y > 0.99999 ) {
45813
45814                         this.quaternion.set( 0, 0, 0, 1 );
45815
45816                 } else if ( dir.y < - 0.99999 ) {
45817
45818                         this.quaternion.set( 1, 0, 0, 0 );
45819
45820                 } else {
45821
45822                         _axis.set( dir.z, 0, - dir.x ).normalize();
45823
45824                         const radians = Math.acos( dir.y );
45825
45826                         this.quaternion.setFromAxisAngle( _axis, radians );
45827
45828                 }
45829
45830         }
45831
45832         setLength( length, headLength, headWidth ) {
45833
45834                 if ( headLength === undefined ) headLength = 0.2 * length;
45835                 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
45836
45837                 this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
45838                 this.line.updateMatrix();
45839
45840                 this.cone.scale.set( headWidth, headLength, headWidth );
45841                 this.cone.position.y = length;
45842                 this.cone.updateMatrix();
45843
45844         }
45845
45846         setColor( color ) {
45847
45848                 this.line.material.color.set( color );
45849                 this.cone.material.color.set( color );
45850
45851         }
45852
45853         copy( source ) {
45854
45855                 super.copy( source, false );
45856
45857                 this.line.copy( source.line );
45858                 this.cone.copy( source.cone );
45859
45860                 return this;
45861
45862         }
45863
45864 }
45865
45866 class AxesHelper extends LineSegments {
45867
45868         constructor( size = 1 ) {
45869
45870                 const vertices = [
45871                         0, 0, 0,        size, 0, 0,
45872                         0, 0, 0,        0, size, 0,
45873                         0, 0, 0,        0, 0, size
45874                 ];
45875
45876                 const colors = [
45877                         1, 0, 0,        1, 0.6, 0,
45878                         0, 1, 0,        0.6, 1, 0,
45879                         0, 0, 1,        0, 0.6, 1
45880                 ];
45881
45882                 const geometry = new BufferGeometry();
45883                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
45884                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
45885
45886                 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
45887
45888                 super( geometry, material );
45889
45890                 this.type = 'AxesHelper';
45891
45892         }
45893
45894 }
45895
45896 const _floatView = new Float32Array( 1 );
45897 const _int32View = new Int32Array( _floatView.buffer );
45898
45899 const DataUtils = {
45900
45901         // Converts float32 to float16 (stored as uint16 value).
45902
45903         toHalfFloat: function ( val ) {
45904
45905                 // Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410
45906
45907                 /* This method is faster than the OpenEXR implementation (very often
45908                 * used, eg. in Ogre), with the additional benefit of rounding, inspired
45909                 * by James Tursa?s half-precision code. */
45910
45911                 _floatView[ 0 ] = val;
45912                 const x = _int32View[ 0 ];
45913
45914                 let bits = ( x >> 16 ) & 0x8000; /* Get the sign */
45915                 let m = ( x >> 12 ) & 0x07ff; /* Keep one extra bit for rounding */
45916                 const e = ( x >> 23 ) & 0xff; /* Using int is faster here */
45917
45918                 /* If zero, or denormal, or exponent underflows too much for a denormal
45919                         * half, return signed zero. */
45920                 if ( e < 103 ) return bits;
45921
45922                 /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
45923                 if ( e > 142 ) {
45924
45925                         bits |= 0x7c00;
45926                         /* If exponent was 0xff and one mantissa bit was set, it means NaN,
45927                                                 * not Inf, so make sure we set one mantissa bit too. */
45928                         bits |= ( ( e == 255 ) ? 0 : 1 ) && ( x & 0x007fffff );
45929                         return bits;
45930
45931                 }
45932
45933                 /* If exponent underflows but not too much, return a denormal */
45934                 if ( e < 113 ) {
45935
45936                         m |= 0x0800;
45937                         /* Extra rounding may overflow and set mantissa to 0 and exponent
45938                                 * to 1, which is OK. */
45939                         bits |= ( m >> ( 114 - e ) ) + ( ( m >> ( 113 - e ) ) & 1 );
45940                         return bits;
45941
45942                 }
45943
45944                 bits |= ( ( e - 112 ) << 10 ) | ( m >> 1 );
45945                 /* Extra rounding. An overflow will set mantissa to 0 and increment
45946                         * the exponent, which is OK. */
45947                 bits += m & 1;
45948                 return bits;
45949
45950         }
45951
45952 };
45953
45954 const LOD_MIN = 4;
45955 const LOD_MAX = 8;
45956 const SIZE_MAX = Math.pow( 2, LOD_MAX );
45957
45958 // The standard deviations (radians) associated with the extra mips. These are
45959 // chosen to approximate a Trowbridge-Reitz distribution function times the
45960 // geometric shadowing function. These sigma values squared must match the
45961 // variance #defines in cube_uv_reflection_fragment.glsl.js.
45962 const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
45963
45964 const TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
45965
45966 // The maximum length of the blur for loop. Smaller sigmas will use fewer
45967 // samples and exit early, but not recompile the shader.
45968 const MAX_SAMPLES = 20;
45969
45970 const ENCODINGS = {
45971         [ LinearEncoding ]: 0,
45972         [ sRGBEncoding ]: 1,
45973         [ RGBEEncoding ]: 2,
45974         [ RGBM7Encoding ]: 3,
45975         [ RGBM16Encoding ]: 4,
45976         [ RGBDEncoding ]: 5,
45977         [ GammaEncoding ]: 6
45978 };
45979
45980 const backgroundMaterial = new MeshBasicMaterial( {
45981         side: BackSide,
45982         depthWrite: false,
45983         depthTest: false,
45984 } );
45985 const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial );
45986
45987 const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
45988 const { _lodPlanes, _sizeLods, _sigmas } = /*@__PURE__*/ _createPlanes();
45989 const _clearColor = /*@__PURE__*/ new Color();
45990 let _oldTarget = null;
45991
45992 // Golden Ratio
45993 const PHI = ( 1 + Math.sqrt( 5 ) ) / 2;
45994 const INV_PHI = 1 / PHI;
45995
45996 // Vertices of a dodecahedron (except the opposites, which represent the
45997 // same axis), used as axis directions evenly spread on a sphere.
45998 const _axisDirections = [
45999         /*@__PURE__*/ new Vector3( 1, 1, 1 ),
46000         /*@__PURE__*/ new Vector3( - 1, 1, 1 ),
46001         /*@__PURE__*/ new Vector3( 1, 1, - 1 ),
46002         /*@__PURE__*/ new Vector3( - 1, 1, - 1 ),
46003         /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ),
46004         /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ),
46005         /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ),
46006         /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ),
46007         /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ),
46008         /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ];
46009
46010 /**
46011  * This class generates a Prefiltered, Mipmapped Radiance Environment Map
46012  * (PMREM) from a cubeMap environment texture. This allows different levels of
46013  * blur to be quickly accessed based on material roughness. It is packed into a
46014  * special CubeUV format that allows us to perform custom interpolation so that
46015  * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
46016  * chain, it only goes down to the LOD_MIN level (above), and then creates extra
46017  * even more filtered 'mips' at the same LOD_MIN resolution, associated with
46018  * higher roughness levels. In this way we maintain resolution to smoothly
46019  * interpolate diffuse lighting while limiting sampling computation.
46020  */
46021
46022 function convertLinearToRGBE( color ) {
46023
46024         const maxComponent = Math.max( color.r, color.g, color.b );
46025         const fExp = Math.min( Math.max( Math.ceil( Math.log2( maxComponent ) ), - 128.0 ), 127.0 );
46026         color.multiplyScalar( Math.pow( 2.0, - fExp ) );
46027
46028         const alpha = ( fExp + 128.0 ) / 255.0;
46029         return alpha;
46030
46031 }
46032
46033 class PMREMGenerator {
46034
46035         constructor( renderer ) {
46036
46037                 this._renderer = renderer;
46038                 this._pingPongRenderTarget = null;
46039
46040                 this._blurMaterial = _getBlurShader( MAX_SAMPLES );
46041                 this._equirectShader = null;
46042                 this._cubemapShader = null;
46043
46044                 this._compileMaterial( this._blurMaterial );
46045
46046         }
46047
46048         /**
46049          * Generates a PMREM from a supplied Scene, which can be faster than using an
46050          * image if networking bandwidth is low. Optional sigma specifies a blur radius
46051          * in radians to be applied to the scene before PMREM generation. Optional near
46052          * and far planes ensure the scene is rendered in its entirety (the cubeCamera
46053          * is placed at the origin).
46054          */
46055         fromScene( scene, sigma = 0, near = 0.1, far = 100 ) {
46056
46057                 _oldTarget = this._renderer.getRenderTarget();
46058                 const cubeUVRenderTarget = this._allocateTargets();
46059
46060                 this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
46061                 if ( sigma > 0 ) {
46062
46063                         this._blur( cubeUVRenderTarget, 0, 0, sigma );
46064
46065                 }
46066
46067                 this._applyPMREM( cubeUVRenderTarget );
46068                 this._cleanup( cubeUVRenderTarget );
46069
46070                 return cubeUVRenderTarget;
46071
46072         }
46073
46074         /**
46075          * Generates a PMREM from an equirectangular texture, which can be either LDR
46076          * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512),
46077          * as this matches best with the 256 x 256 cubemap output.
46078          */
46079         fromEquirectangular( equirectangular ) {
46080
46081                 return this._fromTexture( equirectangular );
46082
46083         }
46084
46085         /**
46086          * Generates a PMREM from an cubemap texture, which can be either LDR
46087          * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256,
46088          * as this matches best with the 256 x 256 cubemap output.
46089          */
46090         fromCubemap( cubemap ) {
46091
46092                 return this._fromTexture( cubemap );
46093
46094         }
46095
46096         /**
46097          * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
46098          * your texture's network fetch for increased concurrency.
46099          */
46100         compileCubemapShader() {
46101
46102                 if ( this._cubemapShader === null ) {
46103
46104                         this._cubemapShader = _getCubemapShader();
46105                         this._compileMaterial( this._cubemapShader );
46106
46107                 }
46108
46109         }
46110
46111         /**
46112          * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
46113          * your texture's network fetch for increased concurrency.
46114          */
46115         compileEquirectangularShader() {
46116
46117                 if ( this._equirectShader === null ) {
46118
46119                         this._equirectShader = _getEquirectShader();
46120                         this._compileMaterial( this._equirectShader );
46121
46122                 }
46123
46124         }
46125
46126         /**
46127          * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
46128          * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
46129          * one of them will cause any others to also become unusable.
46130          */
46131         dispose() {
46132
46133                 this._blurMaterial.dispose();
46134
46135                 if ( this._cubemapShader !== null ) this._cubemapShader.dispose();
46136                 if ( this._equirectShader !== null ) this._equirectShader.dispose();
46137
46138                 for ( let i = 0; i < _lodPlanes.length; i ++ ) {
46139
46140                         _lodPlanes[ i ].dispose();
46141
46142                 }
46143
46144         }
46145
46146         // private interface
46147
46148         _cleanup( outputTarget ) {
46149
46150                 this._pingPongRenderTarget.dispose();
46151                 this._renderer.setRenderTarget( _oldTarget );
46152                 outputTarget.scissorTest = false;
46153                 _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
46154
46155         }
46156
46157         _fromTexture( texture ) {
46158
46159                 _oldTarget = this._renderer.getRenderTarget();
46160                 const cubeUVRenderTarget = this._allocateTargets( texture );
46161                 this._textureToCubeUV( texture, cubeUVRenderTarget );
46162                 this._applyPMREM( cubeUVRenderTarget );
46163                 this._cleanup( cubeUVRenderTarget );
46164
46165                 return cubeUVRenderTarget;
46166
46167         }
46168
46169         _allocateTargets( texture ) { // warning: null texture is valid
46170
46171                 const params = {
46172                         magFilter: NearestFilter,
46173                         minFilter: NearestFilter,
46174                         generateMipmaps: false,
46175                         type: UnsignedByteType,
46176                         format: RGBEFormat,
46177                         encoding: _isLDR( texture ) ? texture.encoding : RGBEEncoding,
46178                         depthBuffer: false
46179                 };
46180
46181                 const cubeUVRenderTarget = _createRenderTarget( params );
46182                 cubeUVRenderTarget.depthBuffer = texture ? false : true;
46183                 this._pingPongRenderTarget = _createRenderTarget( params );
46184                 return cubeUVRenderTarget;
46185
46186         }
46187
46188         _compileMaterial( material ) {
46189
46190                 const tmpMesh = new Mesh( _lodPlanes[ 0 ], material );
46191                 this._renderer.compile( tmpMesh, _flatCamera );
46192
46193         }
46194
46195         _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
46196
46197                 const fov = 90;
46198                 const aspect = 1;
46199                 const cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
46200                 const upSign = [ 1, - 1, 1, 1, 1, 1 ];
46201                 const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ];
46202                 const renderer = this._renderer;
46203
46204                 const originalAutoClear = renderer.autoClear;
46205                 const outputEncoding = renderer.outputEncoding;
46206                 const toneMapping = renderer.toneMapping;
46207                 renderer.getClearColor( _clearColor );
46208
46209                 renderer.toneMapping = NoToneMapping;
46210                 renderer.outputEncoding = LinearEncoding;
46211                 renderer.autoClear = false;
46212
46213                 let useSolidColor = false;
46214                 const background = scene.background;
46215                 if ( background ) {
46216
46217                         if ( background.isColor ) {
46218
46219                                 backgroundMaterial.color.copy( background ).convertSRGBToLinear();
46220                                 scene.background = null;
46221
46222                                 const alpha = convertLinearToRGBE( backgroundMaterial.color );
46223                                 backgroundMaterial.opacity = alpha;
46224                                 useSolidColor = true;
46225
46226                         }
46227
46228                 } else {
46229
46230                         backgroundMaterial.color.copy( _clearColor ).convertSRGBToLinear();
46231
46232                         const alpha = convertLinearToRGBE( backgroundMaterial.color );
46233                         backgroundMaterial.opacity = alpha;
46234                         useSolidColor = true;
46235
46236                 }
46237
46238
46239                 for ( let i = 0; i < 6; i ++ ) {
46240
46241                         const col = i % 3;
46242                         if ( col == 0 ) {
46243
46244                                 cubeCamera.up.set( 0, upSign[ i ], 0 );
46245                                 cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
46246
46247                         } else if ( col == 1 ) {
46248
46249                                 cubeCamera.up.set( 0, 0, upSign[ i ] );
46250                                 cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
46251
46252                         } else {
46253
46254                                 cubeCamera.up.set( 0, upSign[ i ], 0 );
46255                                 cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
46256
46257                         }
46258
46259                         _setViewport( cubeUVRenderTarget,
46260                                 col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX );
46261                         renderer.setRenderTarget( cubeUVRenderTarget );
46262
46263                         if ( useSolidColor ) {
46264
46265                                 renderer.render( backgroundBox, cubeCamera );
46266
46267                         }
46268
46269                         renderer.render( scene, cubeCamera );
46270
46271                 }
46272
46273                 renderer.toneMapping = toneMapping;
46274                 renderer.outputEncoding = outputEncoding;
46275                 renderer.autoClear = originalAutoClear;
46276
46277         }
46278
46279         _textureToCubeUV( texture, cubeUVRenderTarget ) {
46280
46281                 const renderer = this._renderer;
46282
46283                 if ( texture.isCubeTexture ) {
46284
46285                         if ( this._cubemapShader == null ) {
46286
46287                                 this._cubemapShader = _getCubemapShader();
46288
46289                         }
46290
46291                 } else {
46292
46293                         if ( this._equirectShader == null ) {
46294
46295                                 this._equirectShader = _getEquirectShader();
46296
46297                         }
46298
46299                 }
46300
46301                 const material = texture.isCubeTexture ? this._cubemapShader : this._equirectShader;
46302                 const mesh = new Mesh( _lodPlanes[ 0 ], material );
46303
46304                 const uniforms = material.uniforms;
46305
46306                 uniforms[ 'envMap' ].value = texture;
46307
46308                 if ( ! texture.isCubeTexture ) {
46309
46310                         uniforms[ 'texelSize' ].value.set( 1.0 / texture.image.width, 1.0 / texture.image.height );
46311
46312                 }
46313
46314                 uniforms[ 'inputEncoding' ].value = ENCODINGS[ texture.encoding ];
46315                 uniforms[ 'outputEncoding' ].value = ENCODINGS[ cubeUVRenderTarget.texture.encoding ];
46316
46317                 _setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
46318
46319                 renderer.setRenderTarget( cubeUVRenderTarget );
46320                 renderer.render( mesh, _flatCamera );
46321
46322         }
46323
46324         _applyPMREM( cubeUVRenderTarget ) {
46325
46326                 const renderer = this._renderer;
46327                 const autoClear = renderer.autoClear;
46328                 renderer.autoClear = false;
46329
46330                 for ( let i = 1; i < TOTAL_LODS; i ++ ) {
46331
46332                         const sigma = Math.sqrt( _sigmas[ i ] * _sigmas[ i ] - _sigmas[ i - 1 ] * _sigmas[ i - 1 ] );
46333
46334                         const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ];
46335
46336                         this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
46337
46338                 }
46339
46340                 renderer.autoClear = autoClear;
46341
46342         }
46343
46344         /**
46345          * This is a two-pass Gaussian blur for a cubemap. Normally this is done
46346          * vertically and horizontally, but this breaks down on a cube. Here we apply
46347          * the blur latitudinally (around the poles), and then longitudinally (towards
46348          * the poles) to approximate the orthogonally-separable blur. It is least
46349          * accurate at the poles, but still does a decent job.
46350          */
46351         _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
46352
46353                 const pingPongRenderTarget = this._pingPongRenderTarget;
46354
46355                 this._halfBlur(
46356                         cubeUVRenderTarget,
46357                         pingPongRenderTarget,
46358                         lodIn,
46359                         lodOut,
46360                         sigma,
46361                         'latitudinal',
46362                         poleAxis );
46363
46364                 this._halfBlur(
46365                         pingPongRenderTarget,
46366                         cubeUVRenderTarget,
46367                         lodOut,
46368                         lodOut,
46369                         sigma,
46370                         'longitudinal',
46371                         poleAxis );
46372
46373         }
46374
46375         _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
46376
46377                 const renderer = this._renderer;
46378                 const blurMaterial = this._blurMaterial;
46379
46380                 if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
46381
46382                         console.error(
46383                                 'blur direction must be either latitudinal or longitudinal!' );
46384
46385                 }
46386
46387                 // Number of standard deviations at which to cut off the discrete approximation.
46388                 const STANDARD_DEVIATIONS = 3;
46389
46390                 const blurMesh = new Mesh( _lodPlanes[ lodOut ], blurMaterial );
46391                 const blurUniforms = blurMaterial.uniforms;
46392
46393                 const pixels = _sizeLods[ lodIn ] - 1;
46394                 const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
46395                 const sigmaPixels = sigmaRadians / radiansPerPixel;
46396                 const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
46397
46398                 if ( samples > MAX_SAMPLES ) {
46399
46400                         console.warn( `sigmaRadians, ${
46401                                 sigmaRadians}, is too large and will clip, as it requested ${
46402                                 samples} samples when the maximum is set to ${MAX_SAMPLES}` );
46403
46404                 }
46405
46406                 const weights = [];
46407                 let sum = 0;
46408
46409                 for ( let i = 0; i < MAX_SAMPLES; ++ i ) {
46410
46411                         const x = i / sigmaPixels;
46412                         const weight = Math.exp( - x * x / 2 );
46413                         weights.push( weight );
46414
46415                         if ( i == 0 ) {
46416
46417                                 sum += weight;
46418
46419                         } else if ( i < samples ) {
46420
46421                                 sum += 2 * weight;
46422
46423                         }
46424
46425                 }
46426
46427                 for ( let i = 0; i < weights.length; i ++ ) {
46428
46429                         weights[ i ] = weights[ i ] / sum;
46430
46431                 }
46432
46433                 blurUniforms[ 'envMap' ].value = targetIn.texture;
46434                 blurUniforms[ 'samples' ].value = samples;
46435                 blurUniforms[ 'weights' ].value = weights;
46436                 blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal';
46437
46438                 if ( poleAxis ) {
46439
46440                         blurUniforms[ 'poleAxis' ].value = poleAxis;
46441
46442                 }
46443
46444                 blurUniforms[ 'dTheta' ].value = radiansPerPixel;
46445                 blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn;
46446                 blurUniforms[ 'inputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
46447                 blurUniforms[ 'outputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
46448
46449                 const outputSize = _sizeLods[ lodOut ];
46450                 const x = 3 * Math.max( 0, SIZE_MAX - 2 * outputSize );
46451                 const y = ( lodOut === 0 ? 0 : 2 * SIZE_MAX ) + 2 * outputSize * ( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 );
46452
46453                 _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
46454                 renderer.setRenderTarget( targetOut );
46455                 renderer.render( blurMesh, _flatCamera );
46456
46457         }
46458
46459 }
46460
46461 function _isLDR( texture ) {
46462
46463         if ( texture === undefined || texture.type !== UnsignedByteType ) return false;
46464
46465         return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding;
46466
46467 }
46468
46469 function _createPlanes() {
46470
46471         const _lodPlanes = [];
46472         const _sizeLods = [];
46473         const _sigmas = [];
46474
46475         let lod = LOD_MAX;
46476
46477         for ( let i = 0; i < TOTAL_LODS; i ++ ) {
46478
46479                 const sizeLod = Math.pow( 2, lod );
46480                 _sizeLods.push( sizeLod );
46481                 let sigma = 1.0 / sizeLod;
46482
46483                 if ( i > LOD_MAX - LOD_MIN ) {
46484
46485                         sigma = EXTRA_LOD_SIGMA[ i - LOD_MAX + LOD_MIN - 1 ];
46486
46487                 } else if ( i == 0 ) {
46488
46489                         sigma = 0;
46490
46491                 }
46492
46493                 _sigmas.push( sigma );
46494
46495                 const texelSize = 1.0 / ( sizeLod - 1 );
46496                 const min = - texelSize / 2;
46497                 const max = 1 + texelSize / 2;
46498                 const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
46499
46500                 const cubeFaces = 6;
46501                 const vertices = 6;
46502                 const positionSize = 3;
46503                 const uvSize = 2;
46504                 const faceIndexSize = 1;
46505
46506                 const position = new Float32Array( positionSize * vertices * cubeFaces );
46507                 const uv = new Float32Array( uvSize * vertices * cubeFaces );
46508                 const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
46509
46510                 for ( let face = 0; face < cubeFaces; face ++ ) {
46511
46512                         const x = ( face % 3 ) * 2 / 3 - 1;
46513                         const y = face > 2 ? 0 : - 1;
46514                         const coordinates = [
46515                                 x, y, 0,
46516                                 x + 2 / 3, y, 0,
46517                                 x + 2 / 3, y + 1, 0,
46518                                 x, y, 0,
46519                                 x + 2 / 3, y + 1, 0,
46520                                 x, y + 1, 0
46521                         ];
46522                         position.set( coordinates, positionSize * vertices * face );
46523                         uv.set( uv1, uvSize * vertices * face );
46524                         const fill = [ face, face, face, face, face, face ];
46525                         faceIndex.set( fill, faceIndexSize * vertices * face );
46526
46527                 }
46528
46529                 const planes = new BufferGeometry();
46530                 planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
46531                 planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
46532                 planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
46533                 _lodPlanes.push( planes );
46534
46535                 if ( lod > LOD_MIN ) {
46536
46537                         lod --;
46538
46539                 }
46540
46541         }
46542
46543         return { _lodPlanes, _sizeLods, _sigmas };
46544
46545 }
46546
46547 function _createRenderTarget( params ) {
46548
46549         const cubeUVRenderTarget = new WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
46550         cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
46551         cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
46552         cubeUVRenderTarget.scissorTest = true;
46553         return cubeUVRenderTarget;
46554
46555 }
46556
46557 function _setViewport( target, x, y, width, height ) {
46558
46559         target.viewport.set( x, y, width, height );
46560         target.scissor.set( x, y, width, height );
46561
46562 }
46563
46564 function _getBlurShader( maxSamples ) {
46565
46566         const weights = new Float32Array( maxSamples );
46567         const poleAxis = new Vector3( 0, 1, 0 );
46568         const shaderMaterial = new RawShaderMaterial( {
46569
46570                 name: 'SphericalGaussianBlur',
46571
46572                 defines: { 'n': maxSamples },
46573
46574                 uniforms: {
46575                         'envMap': { value: null },
46576                         'samples': { value: 1 },
46577                         'weights': { value: weights },
46578                         'latitudinal': { value: false },
46579                         'dTheta': { value: 0 },
46580                         'mipInt': { value: 0 },
46581                         'poleAxis': { value: poleAxis },
46582                         'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
46583                         'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
46584                 },
46585
46586                 vertexShader: _getCommonVertexShader(),
46587
46588                 fragmentShader: /* glsl */`
46589
46590                         precision mediump float;
46591                         precision mediump int;
46592
46593                         varying vec3 vOutputDirection;
46594
46595                         uniform sampler2D envMap;
46596                         uniform int samples;
46597                         uniform float weights[ n ];
46598                         uniform bool latitudinal;
46599                         uniform float dTheta;
46600                         uniform float mipInt;
46601                         uniform vec3 poleAxis;
46602
46603                         ${ _getEncodings() }
46604
46605                         #define ENVMAP_TYPE_CUBE_UV
46606                         #include <cube_uv_reflection_fragment>
46607
46608                         vec3 getSample( float theta, vec3 axis ) {
46609
46610                                 float cosTheta = cos( theta );
46611                                 // Rodrigues' axis-angle rotation
46612                                 vec3 sampleDirection = vOutputDirection * cosTheta
46613                                         + cross( axis, vOutputDirection ) * sin( theta )
46614                                         + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
46615
46616                                 return bilinearCubeUV( envMap, sampleDirection, mipInt );
46617
46618                         }
46619
46620                         void main() {
46621
46622                                 vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
46623
46624                                 if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
46625
46626                                         axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
46627
46628                                 }
46629
46630                                 axis = normalize( axis );
46631
46632                                 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
46633                                 gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
46634
46635                                 for ( int i = 1; i < n; i++ ) {
46636
46637                                         if ( i >= samples ) {
46638
46639                                                 break;
46640
46641                                         }
46642
46643                                         float theta = dTheta * float( i );
46644                                         gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
46645                                         gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
46646
46647                                 }
46648
46649                                 gl_FragColor = linearToOutputTexel( gl_FragColor );
46650
46651                         }
46652                 `,
46653
46654                 blending: NoBlending,
46655                 depthTest: false,
46656                 depthWrite: false
46657
46658         } );
46659
46660         return shaderMaterial;
46661
46662 }
46663
46664 function _getEquirectShader() {
46665
46666         const texelSize = new Vector2( 1, 1 );
46667         const shaderMaterial = new RawShaderMaterial( {
46668
46669                 name: 'EquirectangularToCubeUV',
46670
46671                 uniforms: {
46672                         'envMap': { value: null },
46673                         'texelSize': { value: texelSize },
46674                         'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
46675                         'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
46676                 },
46677
46678                 vertexShader: _getCommonVertexShader(),
46679
46680                 fragmentShader: /* glsl */`
46681
46682                         precision mediump float;
46683                         precision mediump int;
46684
46685                         varying vec3 vOutputDirection;
46686
46687                         uniform sampler2D envMap;
46688                         uniform vec2 texelSize;
46689
46690                         ${ _getEncodings() }
46691
46692                         #include <common>
46693
46694                         void main() {
46695
46696                                 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
46697
46698                                 vec3 outputDirection = normalize( vOutputDirection );
46699                                 vec2 uv = equirectUv( outputDirection );
46700
46701                                 vec2 f = fract( uv / texelSize - 0.5 );
46702                                 uv -= f * texelSize;
46703                                 vec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
46704                                 uv.x += texelSize.x;
46705                                 vec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
46706                                 uv.y += texelSize.y;
46707                                 vec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
46708                                 uv.x -= texelSize.x;
46709                                 vec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
46710
46711                                 vec3 tm = mix( tl, tr, f.x );
46712                                 vec3 bm = mix( bl, br, f.x );
46713                                 gl_FragColor.rgb = mix( tm, bm, f.y );
46714
46715                                 gl_FragColor = linearToOutputTexel( gl_FragColor );
46716
46717                         }
46718                 `,
46719
46720                 blending: NoBlending,
46721                 depthTest: false,
46722                 depthWrite: false
46723
46724         } );
46725
46726         return shaderMaterial;
46727
46728 }
46729
46730 function _getCubemapShader() {
46731
46732         const shaderMaterial = new RawShaderMaterial( {
46733
46734                 name: 'CubemapToCubeUV',
46735
46736                 uniforms: {
46737                         'envMap': { value: null },
46738                         'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
46739                         'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
46740                 },
46741
46742                 vertexShader: _getCommonVertexShader(),
46743
46744                 fragmentShader: /* glsl */`
46745
46746                         precision mediump float;
46747                         precision mediump int;
46748
46749                         varying vec3 vOutputDirection;
46750
46751                         uniform samplerCube envMap;
46752
46753                         ${ _getEncodings() }
46754
46755                         void main() {
46756
46757                                 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
46758                                 gl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb;
46759                                 gl_FragColor = linearToOutputTexel( gl_FragColor );
46760
46761                         }
46762                 `,
46763
46764                 blending: NoBlending,
46765                 depthTest: false,
46766                 depthWrite: false
46767
46768         } );
46769
46770         return shaderMaterial;
46771
46772 }
46773
46774 function _getCommonVertexShader() {
46775
46776         return /* glsl */`
46777
46778                 precision mediump float;
46779                 precision mediump int;
46780
46781                 attribute vec3 position;
46782                 attribute vec2 uv;
46783                 attribute float faceIndex;
46784
46785                 varying vec3 vOutputDirection;
46786
46787                 // RH coordinate system; PMREM face-indexing convention
46788                 vec3 getDirection( vec2 uv, float face ) {
46789
46790                         uv = 2.0 * uv - 1.0;
46791
46792                         vec3 direction = vec3( uv, 1.0 );
46793
46794                         if ( face == 0.0 ) {
46795
46796                                 direction = direction.zyx; // ( 1, v, u ) pos x
46797
46798                         } else if ( face == 1.0 ) {
46799
46800                                 direction = direction.xzy;
46801                                 direction.xz *= -1.0; // ( -u, 1, -v ) pos y
46802
46803                         } else if ( face == 2.0 ) {
46804
46805                                 direction.x *= -1.0; // ( -u, v, 1 ) pos z
46806
46807                         } else if ( face == 3.0 ) {
46808
46809                                 direction = direction.zyx;
46810                                 direction.xz *= -1.0; // ( -1, v, -u ) neg x
46811
46812                         } else if ( face == 4.0 ) {
46813
46814                                 direction = direction.xzy;
46815                                 direction.xy *= -1.0; // ( -u, -1, v ) neg y
46816
46817                         } else if ( face == 5.0 ) {
46818
46819                                 direction.z *= -1.0; // ( u, v, -1 ) neg z
46820
46821                         }
46822
46823                         return direction;
46824
46825                 }
46826
46827                 void main() {
46828
46829                         vOutputDirection = getDirection( uv, faceIndex );
46830                         gl_Position = vec4( position, 1.0 );
46831
46832                 }
46833         `;
46834
46835 }
46836
46837 function _getEncodings() {
46838
46839         return /* glsl */`
46840
46841                 uniform int inputEncoding;
46842                 uniform int outputEncoding;
46843
46844                 #include <encodings_pars_fragment>
46845
46846                 vec4 inputTexelToLinear( vec4 value ) {
46847
46848                         if ( inputEncoding == 0 ) {
46849
46850                                 return value;
46851
46852                         } else if ( inputEncoding == 1 ) {
46853
46854                                 return sRGBToLinear( value );
46855
46856                         } else if ( inputEncoding == 2 ) {
46857
46858                                 return RGBEToLinear( value );
46859
46860                         } else if ( inputEncoding == 3 ) {
46861
46862                                 return RGBMToLinear( value, 7.0 );
46863
46864                         } else if ( inputEncoding == 4 ) {
46865
46866                                 return RGBMToLinear( value, 16.0 );
46867
46868                         } else if ( inputEncoding == 5 ) {
46869
46870                                 return RGBDToLinear( value, 256.0 );
46871
46872                         } else {
46873
46874                                 return GammaToLinear( value, 2.2 );
46875
46876                         }
46877
46878                 }
46879
46880                 vec4 linearToOutputTexel( vec4 value ) {
46881
46882                         if ( outputEncoding == 0 ) {
46883
46884                                 return value;
46885
46886                         } else if ( outputEncoding == 1 ) {
46887
46888                                 return LinearTosRGB( value );
46889
46890                         } else if ( outputEncoding == 2 ) {
46891
46892                                 return LinearToRGBE( value );
46893
46894                         } else if ( outputEncoding == 3 ) {
46895
46896                                 return LinearToRGBM( value, 7.0 );
46897
46898                         } else if ( outputEncoding == 4 ) {
46899
46900                                 return LinearToRGBM( value, 16.0 );
46901
46902                         } else if ( outputEncoding == 5 ) {
46903
46904                                 return LinearToRGBD( value, 256.0 );
46905
46906                         } else {
46907
46908                                 return LinearToGamma( value, 2.2 );
46909
46910                         }
46911
46912                 }
46913
46914                 vec4 envMapTexelToLinear( vec4 color ) {
46915
46916                         return inputTexelToLinear( color );
46917
46918                 }
46919         `;
46920
46921 }
46922
46923 function Face4( a, b, c, d, normal, color, materialIndex ) {
46924
46925         console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
46926         return new Face3( a, b, c, normal, color, materialIndex );
46927
46928 }
46929
46930 const LineStrip = 0;
46931 const LinePieces = 1;
46932 const NoColors = 0;
46933 const FaceColors = 1;
46934 const VertexColors = 2;
46935
46936 function MeshFaceMaterial( materials ) {
46937
46938         console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );
46939         return materials;
46940
46941 }
46942
46943 function MultiMaterial( materials = [] ) {
46944
46945         console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );
46946         materials.isMultiMaterial = true;
46947         materials.materials = materials;
46948         materials.clone = function () {
46949
46950                 return materials.slice();
46951
46952         };
46953
46954         return materials;
46955
46956 }
46957
46958 function PointCloud( geometry, material ) {
46959
46960         console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
46961         return new Points( geometry, material );
46962
46963 }
46964
46965 function Particle( material ) {
46966
46967         console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );
46968         return new Sprite( material );
46969
46970 }
46971
46972 function ParticleSystem( geometry, material ) {
46973
46974         console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
46975         return new Points( geometry, material );
46976
46977 }
46978
46979 function PointCloudMaterial( parameters ) {
46980
46981         console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
46982         return new PointsMaterial( parameters );
46983
46984 }
46985
46986 function ParticleBasicMaterial( parameters ) {
46987
46988         console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
46989         return new PointsMaterial( parameters );
46990
46991 }
46992
46993 function ParticleSystemMaterial( parameters ) {
46994
46995         console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
46996         return new PointsMaterial( parameters );
46997
46998 }
46999
47000 function Vertex( x, y, z ) {
47001
47002         console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );
47003         return new Vector3( x, y, z );
47004
47005 }
47006
47007 //
47008
47009 function DynamicBufferAttribute( array, itemSize ) {
47010
47011         console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setUsage( THREE.DynamicDrawUsage ) instead.' );
47012         return new BufferAttribute( array, itemSize ).setUsage( DynamicDrawUsage );
47013
47014 }
47015
47016 function Int8Attribute( array, itemSize ) {
47017
47018         console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );
47019         return new Int8BufferAttribute( array, itemSize );
47020
47021 }
47022
47023 function Uint8Attribute( array, itemSize ) {
47024
47025         console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );
47026         return new Uint8BufferAttribute( array, itemSize );
47027
47028 }
47029
47030 function Uint8ClampedAttribute( array, itemSize ) {
47031
47032         console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );
47033         return new Uint8ClampedBufferAttribute( array, itemSize );
47034
47035 }
47036
47037 function Int16Attribute( array, itemSize ) {
47038
47039         console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );
47040         return new Int16BufferAttribute( array, itemSize );
47041
47042 }
47043
47044 function Uint16Attribute( array, itemSize ) {
47045
47046         console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );
47047         return new Uint16BufferAttribute( array, itemSize );
47048
47049 }
47050
47051 function Int32Attribute( array, itemSize ) {
47052
47053         console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );
47054         return new Int32BufferAttribute( array, itemSize );
47055
47056 }
47057
47058 function Uint32Attribute( array, itemSize ) {
47059
47060         console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );
47061         return new Uint32BufferAttribute( array, itemSize );
47062
47063 }
47064
47065 function Float32Attribute( array, itemSize ) {
47066
47067         console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );
47068         return new Float32BufferAttribute( array, itemSize );
47069
47070 }
47071
47072 function Float64Attribute( array, itemSize ) {
47073
47074         console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );
47075         return new Float64BufferAttribute( array, itemSize );
47076
47077 }
47078
47079 //
47080
47081 Curve.create = function ( construct, getPoint ) {
47082
47083         console.log( 'THREE.Curve.create() has been deprecated' );
47084
47085         construct.prototype = Object.create( Curve.prototype );
47086         construct.prototype.constructor = construct;
47087         construct.prototype.getPoint = getPoint;
47088
47089         return construct;
47090
47091 };
47092
47093 //
47094
47095 Object.assign( Path.prototype, {
47096
47097         fromPoints: function ( points ) {
47098
47099                 console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
47100                 return this.setFromPoints( points );
47101
47102         }
47103
47104 } );
47105
47106 //
47107
47108 function ClosedSplineCurve3( points ) {
47109
47110         console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
47111
47112         CatmullRomCurve3.call( this, points );
47113         this.type = 'catmullrom';
47114         this.closed = true;
47115
47116 }
47117
47118 ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
47119
47120 //
47121
47122 function SplineCurve3( points ) {
47123
47124         console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
47125
47126         CatmullRomCurve3.call( this, points );
47127         this.type = 'catmullrom';
47128
47129 }
47130
47131 SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
47132
47133 //
47134
47135 function Spline( points ) {
47136
47137         console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
47138
47139         CatmullRomCurve3.call( this, points );
47140         this.type = 'catmullrom';
47141
47142 }
47143
47144 Spline.prototype = Object.create( CatmullRomCurve3.prototype );
47145
47146 Object.assign( Spline.prototype, {
47147
47148         initFromArray: function ( /* a */ ) {
47149
47150                 console.error( 'THREE.Spline: .initFromArray() has been removed.' );
47151
47152         },
47153         getControlPointsArray: function ( /* optionalTarget */ ) {
47154
47155                 console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
47156
47157         },
47158         reparametrizeByArcLength: function ( /* samplingCoef */ ) {
47159
47160                 console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
47161
47162         }
47163
47164 } );
47165
47166 //
47167
47168 function AxisHelper( size ) {
47169
47170         console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );
47171         return new AxesHelper( size );
47172
47173 }
47174
47175 function BoundingBoxHelper( object, color ) {
47176
47177         console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );
47178         return new BoxHelper( object, color );
47179
47180 }
47181
47182 function EdgesHelper( object, hex ) {
47183
47184         console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );
47185         return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
47186
47187 }
47188
47189 GridHelper.prototype.setColors = function () {
47190
47191         console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
47192
47193 };
47194
47195 SkeletonHelper.prototype.update = function () {
47196
47197         console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
47198
47199 };
47200
47201 function WireframeHelper( object, hex ) {
47202
47203         console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );
47204         return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
47205
47206 }
47207
47208 //
47209
47210 Object.assign( Loader.prototype, {
47211
47212         extractUrlBase: function ( url ) {
47213
47214                 console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
47215                 return LoaderUtils.extractUrlBase( url );
47216
47217         }
47218
47219 } );
47220
47221 Loader.Handlers = {
47222
47223         add: function ( /* regex, loader */ ) {
47224
47225                 console.error( 'THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.' );
47226
47227         },
47228
47229         get: function ( /* file */ ) {
47230
47231                 console.error( 'THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.' );
47232
47233         }
47234
47235 };
47236
47237 function XHRLoader( manager ) {
47238
47239         console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );
47240         return new FileLoader( manager );
47241
47242 }
47243
47244 function BinaryTextureLoader( manager ) {
47245
47246         console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );
47247         return new DataTextureLoader( manager );
47248
47249 }
47250
47251 //
47252
47253 Object.assign( Box2.prototype, {
47254
47255         center: function ( optionalTarget ) {
47256
47257                 console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
47258                 return this.getCenter( optionalTarget );
47259
47260         },
47261         empty: function () {
47262
47263                 console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
47264                 return this.isEmpty();
47265
47266         },
47267         isIntersectionBox: function ( box ) {
47268
47269                 console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
47270                 return this.intersectsBox( box );
47271
47272         },
47273         size: function ( optionalTarget ) {
47274
47275                 console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
47276                 return this.getSize( optionalTarget );
47277
47278         }
47279 } );
47280
47281 Object.assign( Box3.prototype, {
47282
47283         center: function ( optionalTarget ) {
47284
47285                 console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
47286                 return this.getCenter( optionalTarget );
47287
47288         },
47289         empty: function () {
47290
47291                 console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
47292                 return this.isEmpty();
47293
47294         },
47295         isIntersectionBox: function ( box ) {
47296
47297                 console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
47298                 return this.intersectsBox( box );
47299
47300         },
47301         isIntersectionSphere: function ( sphere ) {
47302
47303                 console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
47304                 return this.intersectsSphere( sphere );
47305
47306         },
47307         size: function ( optionalTarget ) {
47308
47309                 console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
47310                 return this.getSize( optionalTarget );
47311
47312         }
47313 } );
47314
47315 Object.assign( Sphere.prototype, {
47316
47317         empty: function () {
47318
47319                 console.warn( 'THREE.Sphere: .empty() has been renamed to .isEmpty().' );
47320                 return this.isEmpty();
47321
47322         },
47323
47324 } );
47325
47326 Frustum.prototype.setFromMatrix = function ( m ) {
47327
47328         console.warn( 'THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix().' );
47329         return this.setFromProjectionMatrix( m );
47330
47331 };
47332
47333 Line3.prototype.center = function ( optionalTarget ) {
47334
47335         console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );
47336         return this.getCenter( optionalTarget );
47337
47338 };
47339
47340 Object.assign( MathUtils, {
47341
47342         random16: function () {
47343
47344                 console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );
47345                 return Math.random();
47346
47347         },
47348
47349         nearestPowerOfTwo: function ( value ) {
47350
47351                 console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );
47352                 return MathUtils.floorPowerOfTwo( value );
47353
47354         },
47355
47356         nextPowerOfTwo: function ( value ) {
47357
47358                 console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );
47359                 return MathUtils.ceilPowerOfTwo( value );
47360
47361         }
47362
47363 } );
47364
47365 Object.assign( Matrix3.prototype, {
47366
47367         flattenToArrayOffset: function ( array, offset ) {
47368
47369                 console.warn( 'THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
47370                 return this.toArray( array, offset );
47371
47372         },
47373         multiplyVector3: function ( vector ) {
47374
47375                 console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
47376                 return vector.applyMatrix3( this );
47377
47378         },
47379         multiplyVector3Array: function ( /* a */ ) {
47380
47381                 console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
47382
47383         },
47384         applyToBufferAttribute: function ( attribute ) {
47385
47386                 console.warn( 'THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead.' );
47387                 return attribute.applyMatrix3( this );
47388
47389         },
47390         applyToVector3Array: function ( /* array, offset, length */ ) {
47391
47392                 console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
47393
47394         },
47395         getInverse: function ( matrix ) {
47396
47397                 console.warn( 'THREE.Matrix3: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
47398                 return this.copy( matrix ).invert();
47399
47400         }
47401
47402 } );
47403
47404 Object.assign( Matrix4.prototype, {
47405
47406         extractPosition: function ( m ) {
47407
47408                 console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
47409                 return this.copyPosition( m );
47410
47411         },
47412         flattenToArrayOffset: function ( array, offset ) {
47413
47414                 console.warn( 'THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
47415                 return this.toArray( array, offset );
47416
47417         },
47418         getPosition: function () {
47419
47420                 console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
47421                 return new Vector3().setFromMatrixColumn( this, 3 );
47422
47423         },
47424         setRotationFromQuaternion: function ( q ) {
47425
47426                 console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
47427                 return this.makeRotationFromQuaternion( q );
47428
47429         },
47430         multiplyToArray: function () {
47431
47432                 console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
47433
47434         },
47435         multiplyVector3: function ( vector ) {
47436
47437                 console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
47438                 return vector.applyMatrix4( this );
47439
47440         },
47441         multiplyVector4: function ( vector ) {
47442
47443                 console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
47444                 return vector.applyMatrix4( this );
47445
47446         },
47447         multiplyVector3Array: function ( /* a */ ) {
47448
47449                 console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
47450
47451         },
47452         rotateAxis: function ( v ) {
47453
47454                 console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
47455                 v.transformDirection( this );
47456
47457         },
47458         crossVector: function ( vector ) {
47459
47460                 console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
47461                 return vector.applyMatrix4( this );
47462
47463         },
47464         translate: function () {
47465
47466                 console.error( 'THREE.Matrix4: .translate() has been removed.' );
47467
47468         },
47469         rotateX: function () {
47470
47471                 console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
47472
47473         },
47474         rotateY: function () {
47475
47476                 console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
47477
47478         },
47479         rotateZ: function () {
47480
47481                 console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
47482
47483         },
47484         rotateByAxis: function () {
47485
47486                 console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
47487
47488         },
47489         applyToBufferAttribute: function ( attribute ) {
47490
47491                 console.warn( 'THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead.' );
47492                 return attribute.applyMatrix4( this );
47493
47494         },
47495         applyToVector3Array: function ( /* array, offset, length */ ) {
47496
47497                 console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
47498
47499         },
47500         makeFrustum: function ( left, right, bottom, top, near, far ) {
47501
47502                 console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
47503                 return this.makePerspective( left, right, top, bottom, near, far );
47504
47505         },
47506         getInverse: function ( matrix ) {
47507
47508                 console.warn( 'THREE.Matrix4: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
47509                 return this.copy( matrix ).invert();
47510
47511         }
47512
47513 } );
47514
47515 Plane.prototype.isIntersectionLine = function ( line ) {
47516
47517         console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
47518         return this.intersectsLine( line );
47519
47520 };
47521
47522 Object.assign( Quaternion.prototype, {
47523
47524         multiplyVector3: function ( vector ) {
47525
47526                 console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
47527                 return vector.applyQuaternion( this );
47528
47529         },
47530         inverse: function ( ) {
47531
47532                 console.warn( 'THREE.Quaternion: .inverse() has been renamed to invert().' );
47533                 return this.invert();
47534
47535         }
47536
47537 } );
47538
47539 Object.assign( Ray.prototype, {
47540
47541         isIntersectionBox: function ( box ) {
47542
47543                 console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
47544                 return this.intersectsBox( box );
47545
47546         },
47547         isIntersectionPlane: function ( plane ) {
47548
47549                 console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
47550                 return this.intersectsPlane( plane );
47551
47552         },
47553         isIntersectionSphere: function ( sphere ) {
47554
47555                 console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
47556                 return this.intersectsSphere( sphere );
47557
47558         }
47559
47560 } );
47561
47562 Object.assign( Triangle.prototype, {
47563
47564         area: function () {
47565
47566                 console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
47567                 return this.getArea();
47568
47569         },
47570         barycoordFromPoint: function ( point, target ) {
47571
47572                 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
47573                 return this.getBarycoord( point, target );
47574
47575         },
47576         midpoint: function ( target ) {
47577
47578                 console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
47579                 return this.getMidpoint( target );
47580
47581         },
47582         normal: function ( target ) {
47583
47584                 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
47585                 return this.getNormal( target );
47586
47587         },
47588         plane: function ( target ) {
47589
47590                 console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
47591                 return this.getPlane( target );
47592
47593         }
47594
47595 } );
47596
47597 Object.assign( Triangle, {
47598
47599         barycoordFromPoint: function ( point, a, b, c, target ) {
47600
47601                 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
47602                 return Triangle.getBarycoord( point, a, b, c, target );
47603
47604         },
47605         normal: function ( a, b, c, target ) {
47606
47607                 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
47608                 return Triangle.getNormal( a, b, c, target );
47609
47610         }
47611
47612 } );
47613
47614 Object.assign( Shape.prototype, {
47615
47616         extractAllPoints: function ( divisions ) {
47617
47618                 console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
47619                 return this.extractPoints( divisions );
47620
47621         },
47622         extrude: function ( options ) {
47623
47624                 console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
47625                 return new ExtrudeGeometry( this, options );
47626
47627         },
47628         makeGeometry: function ( options ) {
47629
47630                 console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
47631                 return new ShapeGeometry( this, options );
47632
47633         }
47634
47635 } );
47636
47637 Object.assign( Vector2.prototype, {
47638
47639         fromAttribute: function ( attribute, index, offset ) {
47640
47641                 console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
47642                 return this.fromBufferAttribute( attribute, index, offset );
47643
47644         },
47645         distanceToManhattan: function ( v ) {
47646
47647                 console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
47648                 return this.manhattanDistanceTo( v );
47649
47650         },
47651         lengthManhattan: function () {
47652
47653                 console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
47654                 return this.manhattanLength();
47655
47656         }
47657
47658 } );
47659
47660 Object.assign( Vector3.prototype, {
47661
47662         setEulerFromRotationMatrix: function () {
47663
47664                 console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
47665
47666         },
47667         setEulerFromQuaternion: function () {
47668
47669                 console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
47670
47671         },
47672         getPositionFromMatrix: function ( m ) {
47673
47674                 console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
47675                 return this.setFromMatrixPosition( m );
47676
47677         },
47678         getScaleFromMatrix: function ( m ) {
47679
47680                 console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
47681                 return this.setFromMatrixScale( m );
47682
47683         },
47684         getColumnFromMatrix: function ( index, matrix ) {
47685
47686                 console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
47687                 return this.setFromMatrixColumn( matrix, index );
47688
47689         },
47690         applyProjection: function ( m ) {
47691
47692                 console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
47693                 return this.applyMatrix4( m );
47694
47695         },
47696         fromAttribute: function ( attribute, index, offset ) {
47697
47698                 console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
47699                 return this.fromBufferAttribute( attribute, index, offset );
47700
47701         },
47702         distanceToManhattan: function ( v ) {
47703
47704                 console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
47705                 return this.manhattanDistanceTo( v );
47706
47707         },
47708         lengthManhattan: function () {
47709
47710                 console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
47711                 return this.manhattanLength();
47712
47713         }
47714
47715 } );
47716
47717 Object.assign( Vector4.prototype, {
47718
47719         fromAttribute: function ( attribute, index, offset ) {
47720
47721                 console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
47722                 return this.fromBufferAttribute( attribute, index, offset );
47723
47724         },
47725         lengthManhattan: function () {
47726
47727                 console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
47728                 return this.manhattanLength();
47729
47730         }
47731
47732 } );
47733
47734 //
47735
47736 Object.assign( Object3D.prototype, {
47737
47738         getChildByName: function ( name ) {
47739
47740                 console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
47741                 return this.getObjectByName( name );
47742
47743         },
47744         renderDepth: function () {
47745
47746                 console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
47747
47748         },
47749         translate: function ( distance, axis ) {
47750
47751                 console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
47752                 return this.translateOnAxis( axis, distance );
47753
47754         },
47755         getWorldRotation: function () {
47756
47757                 console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
47758
47759         },
47760         applyMatrix: function ( matrix ) {
47761
47762                 console.warn( 'THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4().' );
47763                 return this.applyMatrix4( matrix );
47764
47765         }
47766
47767 } );
47768
47769 Object.defineProperties( Object3D.prototype, {
47770
47771         eulerOrder: {
47772                 get: function () {
47773
47774                         console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
47775                         return this.rotation.order;
47776
47777                 },
47778                 set: function ( value ) {
47779
47780                         console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
47781                         this.rotation.order = value;
47782
47783                 }
47784         },
47785         useQuaternion: {
47786                 get: function () {
47787
47788                         console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
47789
47790                 },
47791                 set: function () {
47792
47793                         console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
47794
47795                 }
47796         }
47797
47798 } );
47799
47800 Object.assign( Mesh.prototype, {
47801
47802         setDrawMode: function () {
47803
47804                 console.error( 'THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
47805
47806         },
47807
47808 } );
47809
47810 Object.defineProperties( Mesh.prototype, {
47811
47812         drawMode: {
47813                 get: function () {
47814
47815                         console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.' );
47816                         return TrianglesDrawMode;
47817
47818                 },
47819                 set: function () {
47820
47821                         console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
47822
47823                 }
47824         }
47825
47826 } );
47827
47828 Object.defineProperties( LOD.prototype, {
47829
47830         objects: {
47831                 get: function () {
47832
47833                         console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
47834                         return this.levels;
47835
47836                 }
47837         }
47838
47839 } );
47840
47841 Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
47842
47843         get: function () {
47844
47845                 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
47846
47847         },
47848         set: function () {
47849
47850                 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
47851
47852         }
47853
47854 } );
47855
47856 SkinnedMesh.prototype.initBones = function () {
47857
47858         console.error( 'THREE.SkinnedMesh: initBones() has been removed.' );
47859
47860 };
47861
47862 Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
47863
47864         get: function () {
47865
47866                 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
47867                 return this.arcLengthDivisions;
47868
47869         },
47870         set: function ( value ) {
47871
47872                 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
47873                 this.arcLengthDivisions = value;
47874
47875         }
47876
47877 } );
47878
47879 //
47880
47881 PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
47882
47883         console.warn( 'THREE.PerspectiveCamera.setLens is deprecated. ' +
47884                         'Use .setFocalLength and .filmGauge for a photographic setup.' );
47885
47886         if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
47887         this.setFocalLength( focalLength );
47888
47889 };
47890
47891 //
47892
47893 Object.defineProperties( Light.prototype, {
47894         onlyShadow: {
47895                 set: function () {
47896
47897                         console.warn( 'THREE.Light: .onlyShadow has been removed.' );
47898
47899                 }
47900         },
47901         shadowCameraFov: {
47902                 set: function ( value ) {
47903
47904                         console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
47905                         this.shadow.camera.fov = value;
47906
47907                 }
47908         },
47909         shadowCameraLeft: {
47910                 set: function ( value ) {
47911
47912                         console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
47913                         this.shadow.camera.left = value;
47914
47915                 }
47916         },
47917         shadowCameraRight: {
47918                 set: function ( value ) {
47919
47920                         console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
47921                         this.shadow.camera.right = value;
47922
47923                 }
47924         },
47925         shadowCameraTop: {
47926                 set: function ( value ) {
47927
47928                         console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
47929                         this.shadow.camera.top = value;
47930
47931                 }
47932         },
47933         shadowCameraBottom: {
47934                 set: function ( value ) {
47935
47936                         console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
47937                         this.shadow.camera.bottom = value;
47938
47939                 }
47940         },
47941         shadowCameraNear: {
47942                 set: function ( value ) {
47943
47944                         console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
47945                         this.shadow.camera.near = value;
47946
47947                 }
47948         },
47949         shadowCameraFar: {
47950                 set: function ( value ) {
47951
47952                         console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
47953                         this.shadow.camera.far = value;
47954
47955                 }
47956         },
47957         shadowCameraVisible: {
47958                 set: function () {
47959
47960                         console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
47961
47962                 }
47963         },
47964         shadowBias: {
47965                 set: function ( value ) {
47966
47967                         console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
47968                         this.shadow.bias = value;
47969
47970                 }
47971         },
47972         shadowDarkness: {
47973                 set: function () {
47974
47975                         console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
47976
47977                 }
47978         },
47979         shadowMapWidth: {
47980                 set: function ( value ) {
47981
47982                         console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
47983                         this.shadow.mapSize.width = value;
47984
47985                 }
47986         },
47987         shadowMapHeight: {
47988                 set: function ( value ) {
47989
47990                         console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
47991                         this.shadow.mapSize.height = value;
47992
47993                 }
47994         }
47995 } );
47996
47997 //
47998
47999 Object.defineProperties( BufferAttribute.prototype, {
48000
48001         length: {
48002                 get: function () {
48003
48004                         console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
48005                         return this.array.length;
48006
48007                 }
48008         },
48009         dynamic: {
48010                 get: function () {
48011
48012                         console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
48013                         return this.usage === DynamicDrawUsage;
48014
48015                 },
48016                 set: function ( /* value */ ) {
48017
48018                         console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
48019                         this.setUsage( DynamicDrawUsage );
48020
48021                 }
48022         }
48023
48024 } );
48025
48026 Object.assign( BufferAttribute.prototype, {
48027         setDynamic: function ( value ) {
48028
48029                 console.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );
48030                 this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
48031                 return this;
48032
48033         },
48034         copyIndicesArray: function ( /* indices */ ) {
48035
48036                 console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
48037
48038         },
48039         setArray: function ( /* array */ ) {
48040
48041                 console.error( 'THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
48042
48043         }
48044 } );
48045
48046 Object.assign( BufferGeometry.prototype, {
48047
48048         addIndex: function ( index ) {
48049
48050                 console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
48051                 this.setIndex( index );
48052
48053         },
48054         addAttribute: function ( name, attribute ) {
48055
48056                 console.warn( 'THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().' );
48057
48058                 if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
48059
48060                         console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
48061
48062                         return this.setAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
48063
48064                 }
48065
48066                 if ( name === 'index' ) {
48067
48068                         console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
48069                         this.setIndex( attribute );
48070
48071                         return this;
48072
48073                 }
48074
48075                 return this.setAttribute( name, attribute );
48076
48077         },
48078         addDrawCall: function ( start, count, indexOffset ) {
48079
48080                 if ( indexOffset !== undefined ) {
48081
48082                         console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
48083
48084                 }
48085
48086                 console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
48087                 this.addGroup( start, count );
48088
48089         },
48090         clearDrawCalls: function () {
48091
48092                 console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
48093                 this.clearGroups();
48094
48095         },
48096         computeOffsets: function () {
48097
48098                 console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
48099
48100         },
48101         removeAttribute: function ( name ) {
48102
48103                 console.warn( 'THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().' );
48104
48105                 return this.deleteAttribute( name );
48106
48107         },
48108         applyMatrix: function ( matrix ) {
48109
48110                 console.warn( 'THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4().' );
48111                 return this.applyMatrix4( matrix );
48112
48113         }
48114
48115 } );
48116
48117 Object.defineProperties( BufferGeometry.prototype, {
48118
48119         drawcalls: {
48120                 get: function () {
48121
48122                         console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
48123                         return this.groups;
48124
48125                 }
48126         },
48127         offsets: {
48128                 get: function () {
48129
48130                         console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
48131                         return this.groups;
48132
48133                 }
48134         }
48135
48136 } );
48137
48138 Object.defineProperties( InstancedBufferGeometry.prototype, {
48139
48140         maxInstancedCount: {
48141                 get: function () {
48142
48143                         console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
48144                         return this.instanceCount;
48145
48146                 },
48147                 set: function ( value ) {
48148
48149                         console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
48150                         this.instanceCount = value;
48151
48152                 }
48153         }
48154
48155 } );
48156
48157 Object.defineProperties( Raycaster.prototype, {
48158
48159         linePrecision: {
48160                 get: function () {
48161
48162                         console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
48163                         return this.params.Line.threshold;
48164
48165                 },
48166                 set: function ( value ) {
48167
48168                         console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
48169                         this.params.Line.threshold = value;
48170
48171                 }
48172         }
48173
48174 } );
48175
48176 Object.defineProperties( InterleavedBuffer.prototype, {
48177
48178         dynamic: {
48179                 get: function () {
48180
48181                         console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
48182                         return this.usage === DynamicDrawUsage;
48183
48184                 },
48185                 set: function ( value ) {
48186
48187                         console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
48188                         this.setUsage( value );
48189
48190                 }
48191         }
48192
48193 } );
48194
48195 Object.assign( InterleavedBuffer.prototype, {
48196         setDynamic: function ( value ) {
48197
48198                 console.warn( 'THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.' );
48199                 this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
48200                 return this;
48201
48202         },
48203         setArray: function ( /* array */ ) {
48204
48205                 console.error( 'THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
48206
48207         }
48208 } );
48209
48210 //
48211
48212 Object.assign( ExtrudeGeometry.prototype, {
48213
48214         getArrays: function () {
48215
48216                 console.error( 'THREE.ExtrudeGeometry: .getArrays() has been removed.' );
48217
48218         },
48219
48220         addShapeList: function () {
48221
48222                 console.error( 'THREE.ExtrudeGeometry: .addShapeList() has been removed.' );
48223
48224         },
48225
48226         addShape: function () {
48227
48228                 console.error( 'THREE.ExtrudeGeometry: .addShape() has been removed.' );
48229
48230         }
48231
48232 } );
48233
48234 //
48235
48236 Object.assign( Scene.prototype, {
48237
48238         dispose: function () {
48239
48240                 console.error( 'THREE.Scene: .dispose() has been removed.' );
48241
48242         }
48243
48244 } );
48245
48246 //
48247
48248 Object.defineProperties( Uniform.prototype, {
48249
48250         dynamic: {
48251                 set: function () {
48252
48253                         console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
48254
48255                 }
48256         },
48257         onUpdate: {
48258                 value: function () {
48259
48260                         console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
48261                         return this;
48262
48263                 }
48264         }
48265
48266 } );
48267
48268 //
48269
48270 Object.defineProperties( Material.prototype, {
48271
48272         wrapAround: {
48273                 get: function () {
48274
48275                         console.warn( 'THREE.Material: .wrapAround has been removed.' );
48276
48277                 },
48278                 set: function () {
48279
48280                         console.warn( 'THREE.Material: .wrapAround has been removed.' );
48281
48282                 }
48283         },
48284
48285         overdraw: {
48286                 get: function () {
48287
48288                         console.warn( 'THREE.Material: .overdraw has been removed.' );
48289
48290                 },
48291                 set: function () {
48292
48293                         console.warn( 'THREE.Material: .overdraw has been removed.' );
48294
48295                 }
48296         },
48297
48298         wrapRGB: {
48299                 get: function () {
48300
48301                         console.warn( 'THREE.Material: .wrapRGB has been removed.' );
48302                         return new Color();
48303
48304                 }
48305         },
48306
48307         shading: {
48308                 get: function () {
48309
48310                         console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
48311
48312                 },
48313                 set: function ( value ) {
48314
48315                         console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
48316                         this.flatShading = ( value === FlatShading );
48317
48318                 }
48319         },
48320
48321         stencilMask: {
48322                 get: function () {
48323
48324                         console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
48325                         return this.stencilFuncMask;
48326
48327                 },
48328                 set: function ( value ) {
48329
48330                         console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
48331                         this.stencilFuncMask = value;
48332
48333                 }
48334         }
48335
48336 } );
48337
48338 Object.defineProperties( MeshPhongMaterial.prototype, {
48339
48340         metal: {
48341                 get: function () {
48342
48343                         console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
48344                         return false;
48345
48346                 },
48347                 set: function () {
48348
48349                         console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
48350
48351                 }
48352         }
48353
48354 } );
48355
48356 Object.defineProperties( MeshPhysicalMaterial.prototype, {
48357
48358         transparency: {
48359                 get: function () {
48360
48361                         console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' );
48362                         return this.transmission;
48363
48364                 },
48365                 set: function ( value ) {
48366
48367                         console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' );
48368                         this.transmission = value;
48369
48370                 }
48371         }
48372
48373 } );
48374
48375 Object.defineProperties( ShaderMaterial.prototype, {
48376
48377         derivatives: {
48378                 get: function () {
48379
48380                         console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
48381                         return this.extensions.derivatives;
48382
48383                 },
48384                 set: function ( value ) {
48385
48386                         console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
48387                         this.extensions.derivatives = value;
48388
48389                 }
48390         }
48391
48392 } );
48393
48394 //
48395
48396 Object.assign( WebGLRenderer.prototype, {
48397
48398         clearTarget: function ( renderTarget, color, depth, stencil ) {
48399
48400                 console.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );
48401                 this.setRenderTarget( renderTarget );
48402                 this.clear( color, depth, stencil );
48403
48404         },
48405         animate: function ( callback ) {
48406
48407                 console.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );
48408                 this.setAnimationLoop( callback );
48409
48410         },
48411         getCurrentRenderTarget: function () {
48412
48413                 console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
48414                 return this.getRenderTarget();
48415
48416         },
48417         getMaxAnisotropy: function () {
48418
48419                 console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
48420                 return this.capabilities.getMaxAnisotropy();
48421
48422         },
48423         getPrecision: function () {
48424
48425                 console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
48426                 return this.capabilities.precision;
48427
48428         },
48429         resetGLState: function () {
48430
48431                 console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
48432                 return this.state.reset();
48433
48434         },
48435         supportsFloatTextures: function () {
48436
48437                 console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
48438                 return this.extensions.get( 'OES_texture_float' );
48439
48440         },
48441         supportsHalfFloatTextures: function () {
48442
48443                 console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
48444                 return this.extensions.get( 'OES_texture_half_float' );
48445
48446         },
48447         supportsStandardDerivatives: function () {
48448
48449                 console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
48450                 return this.extensions.get( 'OES_standard_derivatives' );
48451
48452         },
48453         supportsCompressedTextureS3TC: function () {
48454
48455                 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
48456                 return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
48457
48458         },
48459         supportsCompressedTexturePVRTC: function () {
48460
48461                 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
48462                 return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
48463
48464         },
48465         supportsBlendMinMax: function () {
48466
48467                 console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
48468                 return this.extensions.get( 'EXT_blend_minmax' );
48469
48470         },
48471         supportsVertexTextures: function () {
48472
48473                 console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
48474                 return this.capabilities.vertexTextures;
48475
48476         },
48477         supportsInstancedArrays: function () {
48478
48479                 console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
48480                 return this.extensions.get( 'ANGLE_instanced_arrays' );
48481
48482         },
48483         enableScissorTest: function ( boolean ) {
48484
48485                 console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
48486                 this.setScissorTest( boolean );
48487
48488         },
48489         initMaterial: function () {
48490
48491                 console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
48492
48493         },
48494         addPrePlugin: function () {
48495
48496                 console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
48497
48498         },
48499         addPostPlugin: function () {
48500
48501                 console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
48502
48503         },
48504         updateShadowMap: function () {
48505
48506                 console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
48507
48508         },
48509         setFaceCulling: function () {
48510
48511                 console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
48512
48513         },
48514         allocTextureUnit: function () {
48515
48516                 console.warn( 'THREE.WebGLRenderer: .allocTextureUnit() has been removed.' );
48517
48518         },
48519         setTexture: function () {
48520
48521                 console.warn( 'THREE.WebGLRenderer: .setTexture() has been removed.' );
48522
48523         },
48524         setTexture2D: function () {
48525
48526                 console.warn( 'THREE.WebGLRenderer: .setTexture2D() has been removed.' );
48527
48528         },
48529         setTextureCube: function () {
48530
48531                 console.warn( 'THREE.WebGLRenderer: .setTextureCube() has been removed.' );
48532
48533         },
48534         getActiveMipMapLevel: function () {
48535
48536                 console.warn( 'THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().' );
48537                 return this.getActiveMipmapLevel();
48538
48539         }
48540
48541 } );
48542
48543 Object.defineProperties( WebGLRenderer.prototype, {
48544
48545         shadowMapEnabled: {
48546                 get: function () {
48547
48548                         return this.shadowMap.enabled;
48549
48550                 },
48551                 set: function ( value ) {
48552
48553                         console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
48554                         this.shadowMap.enabled = value;
48555
48556                 }
48557         },
48558         shadowMapType: {
48559                 get: function () {
48560
48561                         return this.shadowMap.type;
48562
48563                 },
48564                 set: function ( value ) {
48565
48566                         console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
48567                         this.shadowMap.type = value;
48568
48569                 }
48570         },
48571         shadowMapCullFace: {
48572                 get: function () {
48573
48574                         console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
48575                         return undefined;
48576
48577                 },
48578                 set: function ( /* value */ ) {
48579
48580                         console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
48581
48582                 }
48583         },
48584         context: {
48585                 get: function () {
48586
48587                         console.warn( 'THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.' );
48588                         return this.getContext();
48589
48590                 }
48591         },
48592         vr: {
48593                 get: function () {
48594
48595                         console.warn( 'THREE.WebGLRenderer: .vr has been renamed to .xr' );
48596                         return this.xr;
48597
48598                 }
48599         },
48600         gammaInput: {
48601                 get: function () {
48602
48603                         console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
48604                         return false;
48605
48606                 },
48607                 set: function () {
48608
48609                         console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
48610
48611                 }
48612         },
48613         gammaOutput: {
48614                 get: function () {
48615
48616                         console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
48617                         return false;
48618
48619                 },
48620                 set: function ( value ) {
48621
48622                         console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
48623                         this.outputEncoding = ( value === true ) ? sRGBEncoding : LinearEncoding;
48624
48625                 }
48626         },
48627         toneMappingWhitePoint: {
48628                 get: function () {
48629
48630                         console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
48631                         return 1.0;
48632
48633                 },
48634                 set: function () {
48635
48636                         console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
48637
48638                 }
48639         },
48640
48641 } );
48642
48643 Object.defineProperties( WebGLShadowMap.prototype, {
48644
48645         cullFace: {
48646                 get: function () {
48647
48648                         console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
48649                         return undefined;
48650
48651                 },
48652                 set: function ( /* cullFace */ ) {
48653
48654                         console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
48655
48656                 }
48657         },
48658         renderReverseSided: {
48659                 get: function () {
48660
48661                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
48662                         return undefined;
48663
48664                 },
48665                 set: function () {
48666
48667                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
48668
48669                 }
48670         },
48671         renderSingleSided: {
48672                 get: function () {
48673
48674                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
48675                         return undefined;
48676
48677                 },
48678                 set: function () {
48679
48680                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
48681
48682                 }
48683         }
48684
48685 } );
48686
48687 function WebGLRenderTargetCube( width, height, options ) {
48688
48689         console.warn( 'THREE.WebGLRenderTargetCube( width, height, options ) is now WebGLCubeRenderTarget( size, options ).' );
48690         return new WebGLCubeRenderTarget( width, options );
48691
48692 }
48693
48694 //
48695
48696 Object.defineProperties( WebGLRenderTarget.prototype, {
48697
48698         wrapS: {
48699                 get: function () {
48700
48701                         console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
48702                         return this.texture.wrapS;
48703
48704                 },
48705                 set: function ( value ) {
48706
48707                         console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
48708                         this.texture.wrapS = value;
48709
48710                 }
48711         },
48712         wrapT: {
48713                 get: function () {
48714
48715                         console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
48716                         return this.texture.wrapT;
48717
48718                 },
48719                 set: function ( value ) {
48720
48721                         console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
48722                         this.texture.wrapT = value;
48723
48724                 }
48725         },
48726         magFilter: {
48727                 get: function () {
48728
48729                         console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
48730                         return this.texture.magFilter;
48731
48732                 },
48733                 set: function ( value ) {
48734
48735                         console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
48736                         this.texture.magFilter = value;
48737
48738                 }
48739         },
48740         minFilter: {
48741                 get: function () {
48742
48743                         console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
48744                         return this.texture.minFilter;
48745
48746                 },
48747                 set: function ( value ) {
48748
48749                         console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
48750                         this.texture.minFilter = value;
48751
48752                 }
48753         },
48754         anisotropy: {
48755                 get: function () {
48756
48757                         console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
48758                         return this.texture.anisotropy;
48759
48760                 },
48761                 set: function ( value ) {
48762
48763                         console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
48764                         this.texture.anisotropy = value;
48765
48766                 }
48767         },
48768         offset: {
48769                 get: function () {
48770
48771                         console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
48772                         return this.texture.offset;
48773
48774                 },
48775                 set: function ( value ) {
48776
48777                         console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
48778                         this.texture.offset = value;
48779
48780                 }
48781         },
48782         repeat: {
48783                 get: function () {
48784
48785                         console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
48786                         return this.texture.repeat;
48787
48788                 },
48789                 set: function ( value ) {
48790
48791                         console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
48792                         this.texture.repeat = value;
48793
48794                 }
48795         },
48796         format: {
48797                 get: function () {
48798
48799                         console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
48800                         return this.texture.format;
48801
48802                 },
48803                 set: function ( value ) {
48804
48805                         console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
48806                         this.texture.format = value;
48807
48808                 }
48809         },
48810         type: {
48811                 get: function () {
48812
48813                         console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
48814                         return this.texture.type;
48815
48816                 },
48817                 set: function ( value ) {
48818
48819                         console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
48820                         this.texture.type = value;
48821
48822                 }
48823         },
48824         generateMipmaps: {
48825                 get: function () {
48826
48827                         console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
48828                         return this.texture.generateMipmaps;
48829
48830                 },
48831                 set: function ( value ) {
48832
48833                         console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
48834                         this.texture.generateMipmaps = value;
48835
48836                 }
48837         }
48838
48839 } );
48840
48841 //
48842
48843 Object.defineProperties( Audio.prototype, {
48844
48845         load: {
48846                 value: function ( file ) {
48847
48848                         console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
48849                         const scope = this;
48850                         const audioLoader = new AudioLoader();
48851                         audioLoader.load( file, function ( buffer ) {
48852
48853                                 scope.setBuffer( buffer );
48854
48855                         } );
48856                         return this;
48857
48858                 }
48859         },
48860         startTime: {
48861                 set: function () {
48862
48863                         console.warn( 'THREE.Audio: .startTime is now .play( delay ).' );
48864
48865                 }
48866         }
48867
48868 } );
48869
48870 AudioAnalyser.prototype.getData = function () {
48871
48872         console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );
48873         return this.getFrequencyData();
48874
48875 };
48876
48877 //
48878
48879 CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
48880
48881         console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
48882         return this.update( renderer, scene );
48883
48884 };
48885
48886 CubeCamera.prototype.clear = function ( renderer, color, depth, stencil ) {
48887
48888         console.warn( 'THREE.CubeCamera: .clear() is now .renderTarget.clear().' );
48889         return this.renderTarget.clear( renderer, color, depth, stencil );
48890
48891 };
48892
48893 //
48894
48895 const GeometryUtils = {
48896
48897         merge: function ( geometry1, geometry2, materialIndexOffset ) {
48898
48899                 console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
48900                 let matrix;
48901
48902                 if ( geometry2.isMesh ) {
48903
48904                         geometry2.matrixAutoUpdate && geometry2.updateMatrix();
48905
48906                         matrix = geometry2.matrix;
48907                         geometry2 = geometry2.geometry;
48908
48909                 }
48910
48911                 geometry1.merge( geometry2, matrix, materialIndexOffset );
48912
48913         },
48914
48915         center: function ( geometry ) {
48916
48917                 console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
48918                 return geometry.center();
48919
48920         }
48921
48922 };
48923
48924 ImageUtils.crossOrigin = undefined;
48925
48926 ImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {
48927
48928         console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
48929
48930         const loader = new TextureLoader();
48931         loader.setCrossOrigin( this.crossOrigin );
48932
48933         const texture = loader.load( url, onLoad, undefined, onError );
48934
48935         if ( mapping ) texture.mapping = mapping;
48936
48937         return texture;
48938
48939 };
48940
48941 ImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {
48942
48943         console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
48944
48945         const loader = new CubeTextureLoader();
48946         loader.setCrossOrigin( this.crossOrigin );
48947
48948         const texture = loader.load( urls, onLoad, undefined, onError );
48949
48950         if ( mapping ) texture.mapping = mapping;
48951
48952         return texture;
48953
48954 };
48955
48956 ImageUtils.loadCompressedTexture = function () {
48957
48958         console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
48959
48960 };
48961
48962 ImageUtils.loadCompressedTextureCube = function () {
48963
48964         console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
48965
48966 };
48967
48968 //
48969
48970 function CanvasRenderer() {
48971
48972         console.error( 'THREE.CanvasRenderer has been removed' );
48973
48974 }
48975
48976 //
48977
48978 function JSONLoader() {
48979
48980         console.error( 'THREE.JSONLoader has been removed.' );
48981
48982 }
48983
48984 //
48985
48986 const SceneUtils = {
48987
48988         createMultiMaterialObject: function ( /* geometry, materials */ ) {
48989
48990                 console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
48991
48992         },
48993
48994         detach: function ( /* child, parent, scene */ ) {
48995
48996                 console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
48997
48998         },
48999
49000         attach: function ( /* child, scene, parent */ ) {
49001
49002                 console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
49003
49004         }
49005
49006 };
49007
49008 //
49009
49010 function LensFlare() {
49011
49012         console.error( 'THREE.LensFlare has been moved to /examples/jsm/objects/Lensflare.js' );
49013
49014 }
49015
49016 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
49017
49018         /* eslint-disable no-undef */
49019         __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
49020                 revision: REVISION,
49021         } } ) );
49022         /* eslint-enable no-undef */
49023
49024 }
49025
49026 if ( typeof window !== 'undefined' ) {
49027
49028         if ( window.__THREE__ ) {
49029
49030                 console.warn( 'WARNING: Multiple instances of Three.js being imported.' );
49031
49032         } else {
49033
49034                 window.__THREE__ = REVISION;
49035
49036         }
49037
49038 }
49039
49040 export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, AxisHelper, BackSide, BasicDepthPacking, BasicShadowMap, BinaryTextureLoader, Bone, BooleanKeyframeTrack, BoundingBoxHelper, Box2, Box3, Box3Helper, BoxGeometry as BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasRenderer, CanvasTexture, CatmullRomCurve3, CineonToneMapping, CircleGeometry as CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, ClosedSplineCurve3, Color, ColorKeyframeTrack, CompressedTexture, CompressedTextureLoader, ConeGeometry as ConeBufferGeometry, ConeGeometry, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubeUVRefractionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry as CylinderBufferGeometry, CylinderGeometry, Cylindrical, DataTexture, DataTexture2DArray, DataTexture3D, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry as DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicBufferAttribute, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EdgesHelper, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeGeometry as ExtrudeBufferGeometry, ExtrudeGeometry, Face3, Face4, FaceColors, FileLoader, FlatShading, Float16BufferAttribute, Float32Attribute, Float32BufferAttribute, Float64Attribute, Float64BufferAttribute, FloatType, Fog, FogExp2, Font, FontLoader, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GammaEncoding, GeometryUtils, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronGeometry as IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, ImmediateRenderObject, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16Attribute, Int16BufferAttribute, Int32Attribute, Int32BufferAttribute, Int8Attribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, JSONLoader, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry as LatheBufferGeometry, LatheGeometry, Layers, LensFlare, LessDepth, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LinePieces, LineSegments, LineStrip, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LogLuvEncoding, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils as Math, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshFaceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiMaterial, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverDepth, NeverStencilFunc, NoBlending, NoColors, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry as OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, ParametricGeometry as ParametricBufferGeometry, ParametricGeometry, Particle, ParticleBasicMaterial, ParticleSystem, ParticleSystemMaterial, Path, PerspectiveCamera, Plane, PlaneGeometry as PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointCloud, PointCloudMaterial, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry as PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDEncoding, RGBEEncoding, RGBEFormat, RGBFormat, RGBIntegerFormat, RGBM16Encoding, RGBM7Encoding, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingGeometry as RingBufferGeometry, RingGeometry, SRGB8_ALPHA8_ASTC_10x10_Format, SRGB8_ALPHA8_ASTC_10x5_Format, SRGB8_ALPHA8_ASTC_10x6_Format, SRGB8_ALPHA8_ASTC_10x8_Format, SRGB8_ALPHA8_ASTC_12x10_Format, SRGB8_ALPHA8_ASTC_12x12_Format, SRGB8_ALPHA8_ASTC_4x4_Format, SRGB8_ALPHA8_ASTC_5x4_Format, SRGB8_ALPHA8_ASTC_5x5_Format, SRGB8_ALPHA8_ASTC_6x5_Format, SRGB8_ALPHA8_ASTC_6x6_Format, SRGB8_ALPHA8_ASTC_8x5_Format, SRGB8_ALPHA8_ASTC_8x6_Format, SRGB8_ALPHA8_ASTC_8x8_Format, Scene, SceneUtils, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry as ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SmoothShading, Sphere, SphereGeometry as SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, Spline, SplineCurve, SplineCurve3, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry as TetrahedronBufferGeometry, TetrahedronGeometry, TextGeometry as TextBufferGeometry, TextGeometry, Texture, TextureLoader, TorusGeometry as TorusBufferGeometry, TorusGeometry, TorusKnotGeometry as TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry as TubeBufferGeometry, TubeGeometry, UVMapping, Uint16Attribute, Uint16BufferAttribute, Uint32Attribute, Uint32BufferAttribute, Uint8Attribute, Uint8BufferAttribute, Uint8ClampedAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShort565Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, Vertex, VertexColors, VideoTexture, WebGL1Renderer, WebGLCubeRenderTarget, WebGLMultisampleRenderTarget, WebGLRenderTarget, WebGLRenderTargetCube, WebGLRenderer, WebGLUtils, WireframeGeometry, WireframeHelper, WrapAroundEnding, XHRLoader, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, sRGBEncoding };