]> gitweb.ps.run Git - cloth_sim/blob - Scripts/three.module.js
Distinguish between right and left mouse click for wind and dragging
[cloth_sim] / Scripts / three.module.js
1 // threejs.org/license
2 const REVISION = '123';
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://en.wikipedia.org/wiki/Smoothstep
353
354         smoothstep: function ( x, min, max ) {
355
356                 if ( x <= min ) return 0;
357                 if ( x >= max ) return 1;
358
359                 x = ( x - min ) / ( max - min );
360
361                 return x * x * ( 3 - 2 * x );
362
363         },
364
365         smootherstep: function ( x, min, max ) {
366
367                 if ( x <= min ) return 0;
368                 if ( x >= max ) return 1;
369
370                 x = ( x - min ) / ( max - min );
371
372                 return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
373
374         },
375
376         // Random integer from <low, high> interval
377
378         randInt: function ( low, high ) {
379
380                 return low + Math.floor( Math.random() * ( high - low + 1 ) );
381
382         },
383
384         // Random float from <low, high> interval
385
386         randFloat: function ( low, high ) {
387
388                 return low + Math.random() * ( high - low );
389
390         },
391
392         // Random float from <-range/2, range/2> interval
393
394         randFloatSpread: function ( range ) {
395
396                 return range * ( 0.5 - Math.random() );
397
398         },
399
400         // Deterministic pseudo-random float in the interval [ 0, 1 ]
401
402         seededRandom: function ( s ) {
403
404                 if ( s !== undefined ) _seed = s % 2147483647;
405
406                 // Park-Miller algorithm
407
408                 _seed = _seed * 16807 % 2147483647;
409
410                 return ( _seed - 1 ) / 2147483646;
411
412         },
413
414         degToRad: function ( degrees ) {
415
416                 return degrees * MathUtils.DEG2RAD;
417
418         },
419
420         radToDeg: function ( radians ) {
421
422                 return radians * MathUtils.RAD2DEG;
423
424         },
425
426         isPowerOfTwo: function ( value ) {
427
428                 return ( value & ( value - 1 ) ) === 0 && value !== 0;
429
430         },
431
432         ceilPowerOfTwo: function ( value ) {
433
434                 return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
435
436         },
437
438         floorPowerOfTwo: function ( value ) {
439
440                 return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
441
442         },
443
444         setQuaternionFromProperEuler: function ( q, a, b, c, order ) {
445
446                 // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
447
448                 // rotations are applied to the axes in the order specified by 'order'
449                 // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
450                 // angles are in radians
451
452                 const cos = Math.cos;
453                 const sin = Math.sin;
454
455                 const c2 = cos( b / 2 );
456                 const s2 = sin( b / 2 );
457
458                 const c13 = cos( ( a + c ) / 2 );
459                 const s13 = sin( ( a + c ) / 2 );
460
461                 const c1_3 = cos( ( a - c ) / 2 );
462                 const s1_3 = sin( ( a - c ) / 2 );
463
464                 const c3_1 = cos( ( c - a ) / 2 );
465                 const s3_1 = sin( ( c - a ) / 2 );
466
467                 switch ( order ) {
468
469                         case 'XYX':
470                                 q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
471                                 break;
472
473                         case 'YZY':
474                                 q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
475                                 break;
476
477                         case 'ZXZ':
478                                 q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
479                                 break;
480
481                         case 'XZX':
482                                 q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
483                                 break;
484
485                         case 'YXY':
486                                 q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
487                                 break;
488
489                         case 'ZYZ':
490                                 q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
491                                 break;
492
493                         default:
494                                 console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
495
496                 }
497
498         }
499
500 };
501
502 class Vector2 {
503
504         constructor( x = 0, y = 0 ) {
505
506                 Object.defineProperty( this, 'isVector2', { value: true } );
507
508                 this.x = x;
509                 this.y = y;
510
511         }
512
513         get width() {
514
515                 return this.x;
516
517         }
518
519         set width( value ) {
520
521                 this.x = value;
522
523         }
524
525         get height() {
526
527                 return this.y;
528
529         }
530
531         set height( value ) {
532
533                 this.y = value;
534
535         }
536
537         set( x, y ) {
538
539                 this.x = x;
540                 this.y = y;
541
542                 return this;
543
544         }
545
546         setScalar( scalar ) {
547
548                 this.x = scalar;
549                 this.y = scalar;
550
551                 return this;
552
553         }
554
555         setX( x ) {
556
557                 this.x = x;
558
559                 return this;
560
561         }
562
563         setY( y ) {
564
565                 this.y = y;
566
567                 return this;
568
569         }
570
571         setComponent( index, value ) {
572
573                 switch ( index ) {
574
575                         case 0: this.x = value; break;
576                         case 1: this.y = value; break;
577                         default: throw new Error( 'index is out of range: ' + index );
578
579                 }
580
581                 return this;
582
583         }
584
585         getComponent( index ) {
586
587                 switch ( index ) {
588
589                         case 0: return this.x;
590                         case 1: return this.y;
591                         default: throw new Error( 'index is out of range: ' + index );
592
593                 }
594
595         }
596
597         clone() {
598
599                 return new this.constructor( this.x, this.y );
600
601         }
602
603         copy( v ) {
604
605                 this.x = v.x;
606                 this.y = v.y;
607
608                 return this;
609
610         }
611
612         add( v, w ) {
613
614                 if ( w !== undefined ) {
615
616                         console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
617                         return this.addVectors( v, w );
618
619                 }
620
621                 this.x += v.x;
622                 this.y += v.y;
623
624                 return this;
625
626         }
627
628         addScalar( s ) {
629
630                 this.x += s;
631                 this.y += s;
632
633                 return this;
634
635         }
636
637         addVectors( a, b ) {
638
639                 this.x = a.x + b.x;
640                 this.y = a.y + b.y;
641
642                 return this;
643
644         }
645
646         addScaledVector( v, s ) {
647
648                 this.x += v.x * s;
649                 this.y += v.y * s;
650
651                 return this;
652
653         }
654
655         sub( v, w ) {
656
657                 if ( w !== undefined ) {
658
659                         console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
660                         return this.subVectors( v, w );
661
662                 }
663
664                 this.x -= v.x;
665                 this.y -= v.y;
666
667                 return this;
668
669         }
670
671         subScalar( s ) {
672
673                 this.x -= s;
674                 this.y -= s;
675
676                 return this;
677
678         }
679
680         subVectors( a, b ) {
681
682                 this.x = a.x - b.x;
683                 this.y = a.y - b.y;
684
685                 return this;
686
687         }
688
689         multiply( v ) {
690
691                 this.x *= v.x;
692                 this.y *= v.y;
693
694                 return this;
695
696         }
697
698         multiplyScalar( scalar ) {
699
700                 this.x *= scalar;
701                 this.y *= scalar;
702
703                 return this;
704
705         }
706
707         divide( v ) {
708
709                 this.x /= v.x;
710                 this.y /= v.y;
711
712                 return this;
713
714         }
715
716         divideScalar( scalar ) {
717
718                 return this.multiplyScalar( 1 / scalar );
719
720         }
721
722         applyMatrix3( m ) {
723
724                 const x = this.x, y = this.y;
725                 const e = m.elements;
726
727                 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
728                 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
729
730                 return this;
731
732         }
733
734         min( v ) {
735
736                 this.x = Math.min( this.x, v.x );
737                 this.y = Math.min( this.y, v.y );
738
739                 return this;
740
741         }
742
743         max( v ) {
744
745                 this.x = Math.max( this.x, v.x );
746                 this.y = Math.max( this.y, v.y );
747
748                 return this;
749
750         }
751
752         clamp( min, max ) {
753
754                 // assumes min < max, componentwise
755
756                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
757                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
758
759                 return this;
760
761         }
762
763         clampScalar( minVal, maxVal ) {
764
765                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
766                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
767
768                 return this;
769
770         }
771
772         clampLength( min, max ) {
773
774                 const length = this.length();
775
776                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
777
778         }
779
780         floor() {
781
782                 this.x = Math.floor( this.x );
783                 this.y = Math.floor( this.y );
784
785                 return this;
786
787         }
788
789         ceil() {
790
791                 this.x = Math.ceil( this.x );
792                 this.y = Math.ceil( this.y );
793
794                 return this;
795
796         }
797
798         round() {
799
800                 this.x = Math.round( this.x );
801                 this.y = Math.round( this.y );
802
803                 return this;
804
805         }
806
807         roundToZero() {
808
809                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
810                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
811
812                 return this;
813
814         }
815
816         negate() {
817
818                 this.x = - this.x;
819                 this.y = - this.y;
820
821                 return this;
822
823         }
824
825         dot( v ) {
826
827                 return this.x * v.x + this.y * v.y;
828
829         }
830
831         cross( v ) {
832
833                 return this.x * v.y - this.y * v.x;
834
835         }
836
837         lengthSq() {
838
839                 return this.x * this.x + this.y * this.y;
840
841         }
842
843         length() {
844
845                 return Math.sqrt( this.x * this.x + this.y * this.y );
846
847         }
848
849         manhattanLength() {
850
851                 return Math.abs( this.x ) + Math.abs( this.y );
852
853         }
854
855         normalize() {
856
857                 return this.divideScalar( this.length() || 1 );
858
859         }
860
861         angle() {
862
863                 // computes the angle in radians with respect to the positive x-axis
864
865                 const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
866
867                 return angle;
868
869         }
870
871         distanceTo( v ) {
872
873                 return Math.sqrt( this.distanceToSquared( v ) );
874
875         }
876
877         distanceToSquared( v ) {
878
879                 const dx = this.x - v.x, dy = this.y - v.y;
880                 return dx * dx + dy * dy;
881
882         }
883
884         manhattanDistanceTo( v ) {
885
886                 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
887
888         }
889
890         setLength( length ) {
891
892                 return this.normalize().multiplyScalar( length );
893
894         }
895
896         lerp( v, alpha ) {
897
898                 this.x += ( v.x - this.x ) * alpha;
899                 this.y += ( v.y - this.y ) * alpha;
900
901                 return this;
902
903         }
904
905         lerpVectors( v1, v2, alpha ) {
906
907                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
908                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
909
910                 return this;
911
912         }
913
914         equals( v ) {
915
916                 return ( ( v.x === this.x ) && ( v.y === this.y ) );
917
918         }
919
920         fromArray( array, offset = 0 ) {
921
922                 this.x = array[ offset ];
923                 this.y = array[ offset + 1 ];
924
925                 return this;
926
927         }
928
929         toArray( array = [], offset = 0 ) {
930
931                 array[ offset ] = this.x;
932                 array[ offset + 1 ] = this.y;
933
934                 return array;
935
936         }
937
938         fromBufferAttribute( attribute, index, offset ) {
939
940                 if ( offset !== undefined ) {
941
942                         console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
943
944                 }
945
946                 this.x = attribute.getX( index );
947                 this.y = attribute.getY( index );
948
949                 return this;
950
951         }
952
953         rotateAround( center, angle ) {
954
955                 const c = Math.cos( angle ), s = Math.sin( angle );
956
957                 const x = this.x - center.x;
958                 const y = this.y - center.y;
959
960                 this.x = x * c - y * s + center.x;
961                 this.y = x * s + y * c + center.y;
962
963                 return this;
964
965         }
966
967         random() {
968
969                 this.x = Math.random();
970                 this.y = Math.random();
971
972                 return this;
973
974         }
975
976 }
977
978 class Matrix3 {
979
980         constructor() {
981
982                 Object.defineProperty( this, 'isMatrix3', { value: true } );
983
984                 this.elements = [
985
986                         1, 0, 0,
987                         0, 1, 0,
988                         0, 0, 1
989
990                 ];
991
992                 if ( arguments.length > 0 ) {
993
994                         console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
995
996                 }
997
998         }
999
1000         set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
1001
1002                 const te = this.elements;
1003
1004                 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
1005                 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
1006                 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
1007
1008                 return this;
1009
1010         }
1011
1012         identity() {
1013
1014                 this.set(
1015
1016                         1, 0, 0,
1017                         0, 1, 0,
1018                         0, 0, 1
1019
1020                 );
1021
1022                 return this;
1023
1024         }
1025
1026         clone() {
1027
1028                 return new this.constructor().fromArray( this.elements );
1029
1030         }
1031
1032         copy( m ) {
1033
1034                 const te = this.elements;
1035                 const me = m.elements;
1036
1037                 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
1038                 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
1039                 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
1040
1041                 return this;
1042
1043         }
1044
1045         extractBasis( xAxis, yAxis, zAxis ) {
1046
1047                 xAxis.setFromMatrix3Column( this, 0 );
1048                 yAxis.setFromMatrix3Column( this, 1 );
1049                 zAxis.setFromMatrix3Column( this, 2 );
1050
1051                 return this;
1052
1053         }
1054
1055         setFromMatrix4( m ) {
1056
1057                 const me = m.elements;
1058
1059                 this.set(
1060
1061                         me[ 0 ], me[ 4 ], me[ 8 ],
1062                         me[ 1 ], me[ 5 ], me[ 9 ],
1063                         me[ 2 ], me[ 6 ], me[ 10 ]
1064
1065                 );
1066
1067                 return this;
1068
1069         }
1070
1071         multiply( m ) {
1072
1073                 return this.multiplyMatrices( this, m );
1074
1075         }
1076
1077         premultiply( m ) {
1078
1079                 return this.multiplyMatrices( m, this );
1080
1081         }
1082
1083         multiplyMatrices( a, b ) {
1084
1085                 const ae = a.elements;
1086                 const be = b.elements;
1087                 const te = this.elements;
1088
1089                 const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
1090                 const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
1091                 const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
1092
1093                 const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
1094                 const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
1095                 const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
1096
1097                 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
1098                 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
1099                 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
1100
1101                 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
1102                 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
1103                 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
1104
1105                 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
1106                 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
1107                 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
1108
1109                 return this;
1110
1111         }
1112
1113         multiplyScalar( s ) {
1114
1115                 const te = this.elements;
1116
1117                 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
1118                 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
1119                 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
1120
1121                 return this;
1122
1123         }
1124
1125         determinant() {
1126
1127                 const te = this.elements;
1128
1129                 const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
1130                         d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
1131                         g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
1132
1133                 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
1134
1135         }
1136
1137         invert() {
1138
1139                 const te = this.elements,
1140
1141                         n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
1142                         n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
1143                         n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
1144
1145                         t11 = n33 * n22 - n32 * n23,
1146                         t12 = n32 * n13 - n33 * n12,
1147                         t13 = n23 * n12 - n22 * n13,
1148
1149                         det = n11 * t11 + n21 * t12 + n31 * t13;
1150
1151                 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
1152
1153                 const detInv = 1 / det;
1154
1155                 te[ 0 ] = t11 * detInv;
1156                 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
1157                 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
1158
1159                 te[ 3 ] = t12 * detInv;
1160                 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
1161                 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
1162
1163                 te[ 6 ] = t13 * detInv;
1164                 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
1165                 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
1166
1167                 return this;
1168
1169         }
1170
1171         transpose() {
1172
1173                 let tmp;
1174                 const m = this.elements;
1175
1176                 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
1177                 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
1178                 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
1179
1180                 return this;
1181
1182         }
1183
1184         getNormalMatrix( matrix4 ) {
1185
1186                 return this.setFromMatrix4( matrix4 ).copy( this ).invert().transpose();
1187
1188         }
1189
1190         transposeIntoArray( r ) {
1191
1192                 const m = this.elements;
1193
1194                 r[ 0 ] = m[ 0 ];
1195                 r[ 1 ] = m[ 3 ];
1196                 r[ 2 ] = m[ 6 ];
1197                 r[ 3 ] = m[ 1 ];
1198                 r[ 4 ] = m[ 4 ];
1199                 r[ 5 ] = m[ 7 ];
1200                 r[ 6 ] = m[ 2 ];
1201                 r[ 7 ] = m[ 5 ];
1202                 r[ 8 ] = m[ 8 ];
1203
1204                 return this;
1205
1206         }
1207
1208         setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
1209
1210                 const c = Math.cos( rotation );
1211                 const s = Math.sin( rotation );
1212
1213                 this.set(
1214                         sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
1215                         - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
1216                         0, 0, 1
1217                 );
1218
1219         }
1220
1221         scale( sx, sy ) {
1222
1223                 const te = this.elements;
1224
1225                 te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
1226                 te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
1227
1228                 return this;
1229
1230         }
1231
1232         rotate( theta ) {
1233
1234                 const c = Math.cos( theta );
1235                 const s = Math.sin( theta );
1236
1237                 const te = this.elements;
1238
1239                 const a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
1240                 const a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
1241
1242                 te[ 0 ] = c * a11 + s * a21;
1243                 te[ 3 ] = c * a12 + s * a22;
1244                 te[ 6 ] = c * a13 + s * a23;
1245
1246                 te[ 1 ] = - s * a11 + c * a21;
1247                 te[ 4 ] = - s * a12 + c * a22;
1248                 te[ 7 ] = - s * a13 + c * a23;
1249
1250                 return this;
1251
1252         }
1253
1254         translate( tx, ty ) {
1255
1256                 const te = this.elements;
1257
1258                 te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
1259                 te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
1260
1261                 return this;
1262
1263         }
1264
1265         equals( matrix ) {
1266
1267                 const te = this.elements;
1268                 const me = matrix.elements;
1269
1270                 for ( let i = 0; i < 9; i ++ ) {
1271
1272                         if ( te[ i ] !== me[ i ] ) return false;
1273
1274                 }
1275
1276                 return true;
1277
1278         }
1279
1280         fromArray( array, offset = 0 ) {
1281
1282                 for ( let i = 0; i < 9; i ++ ) {
1283
1284                         this.elements[ i ] = array[ i + offset ];
1285
1286                 }
1287
1288                 return this;
1289
1290         }
1291
1292         toArray( array = [], offset = 0 ) {
1293
1294                 const te = this.elements;
1295
1296                 array[ offset ] = te[ 0 ];
1297                 array[ offset + 1 ] = te[ 1 ];
1298                 array[ offset + 2 ] = te[ 2 ];
1299
1300                 array[ offset + 3 ] = te[ 3 ];
1301                 array[ offset + 4 ] = te[ 4 ];
1302                 array[ offset + 5 ] = te[ 5 ];
1303
1304                 array[ offset + 6 ] = te[ 6 ];
1305                 array[ offset + 7 ] = te[ 7 ];
1306                 array[ offset + 8 ] = te[ 8 ];
1307
1308                 return array;
1309
1310         }
1311
1312 }
1313
1314 let _canvas;
1315
1316 const ImageUtils = {
1317
1318         getDataURL: function ( image ) {
1319
1320                 if ( /^data:/i.test( image.src ) ) {
1321
1322                         return image.src;
1323
1324                 }
1325
1326                 if ( typeof HTMLCanvasElement == 'undefined' ) {
1327
1328                         return image.src;
1329
1330                 }
1331
1332                 let canvas;
1333
1334                 if ( image instanceof HTMLCanvasElement ) {
1335
1336                         canvas = image;
1337
1338                 } else {
1339
1340                         if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
1341
1342                         _canvas.width = image.width;
1343                         _canvas.height = image.height;
1344
1345                         const context = _canvas.getContext( '2d' );
1346
1347                         if ( image instanceof ImageData ) {
1348
1349                                 context.putImageData( image, 0, 0 );
1350
1351                         } else {
1352
1353                                 context.drawImage( image, 0, 0, image.width, image.height );
1354
1355                         }
1356
1357                         canvas = _canvas;
1358
1359                 }
1360
1361                 if ( canvas.width > 2048 || canvas.height > 2048 ) {
1362
1363                         return canvas.toDataURL( 'image/jpeg', 0.6 );
1364
1365                 } else {
1366
1367                         return canvas.toDataURL( 'image/png' );
1368
1369                 }
1370
1371         }
1372
1373 };
1374
1375 let textureId = 0;
1376
1377 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 ) {
1378
1379         Object.defineProperty( this, 'id', { value: textureId ++ } );
1380
1381         this.uuid = MathUtils.generateUUID();
1382
1383         this.name = '';
1384
1385         this.image = image;
1386         this.mipmaps = [];
1387
1388         this.mapping = mapping;
1389
1390         this.wrapS = wrapS;
1391         this.wrapT = wrapT;
1392
1393         this.magFilter = magFilter;
1394         this.minFilter = minFilter;
1395
1396         this.anisotropy = anisotropy;
1397
1398         this.format = format;
1399         this.internalFormat = null;
1400         this.type = type;
1401
1402         this.offset = new Vector2( 0, 0 );
1403         this.repeat = new Vector2( 1, 1 );
1404         this.center = new Vector2( 0, 0 );
1405         this.rotation = 0;
1406
1407         this.matrixAutoUpdate = true;
1408         this.matrix = new Matrix3();
1409
1410         this.generateMipmaps = true;
1411         this.premultiplyAlpha = false;
1412         this.flipY = true;
1413         this.unpackAlignment = 4;       // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
1414
1415         // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
1416         //
1417         // Also changing the encoding after already used by a Material will not automatically make the Material
1418         // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
1419         this.encoding = encoding;
1420
1421         this.version = 0;
1422         this.onUpdate = null;
1423
1424 }
1425
1426 Texture.DEFAULT_IMAGE = undefined;
1427 Texture.DEFAULT_MAPPING = UVMapping;
1428
1429 Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
1430
1431         constructor: Texture,
1432
1433         isTexture: true,
1434
1435         updateMatrix: function () {
1436
1437                 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
1438
1439         },
1440
1441         clone: function () {
1442
1443                 return new this.constructor().copy( this );
1444
1445         },
1446
1447         copy: function ( source ) {
1448
1449                 this.name = source.name;
1450
1451                 this.image = source.image;
1452                 this.mipmaps = source.mipmaps.slice( 0 );
1453
1454                 this.mapping = source.mapping;
1455
1456                 this.wrapS = source.wrapS;
1457                 this.wrapT = source.wrapT;
1458
1459                 this.magFilter = source.magFilter;
1460                 this.minFilter = source.minFilter;
1461
1462                 this.anisotropy = source.anisotropy;
1463
1464                 this.format = source.format;
1465                 this.internalFormat = source.internalFormat;
1466                 this.type = source.type;
1467
1468                 this.offset.copy( source.offset );
1469                 this.repeat.copy( source.repeat );
1470                 this.center.copy( source.center );
1471                 this.rotation = source.rotation;
1472
1473                 this.matrixAutoUpdate = source.matrixAutoUpdate;
1474                 this.matrix.copy( source.matrix );
1475
1476                 this.generateMipmaps = source.generateMipmaps;
1477                 this.premultiplyAlpha = source.premultiplyAlpha;
1478                 this.flipY = source.flipY;
1479                 this.unpackAlignment = source.unpackAlignment;
1480                 this.encoding = source.encoding;
1481
1482                 return this;
1483
1484         },
1485
1486         toJSON: function ( meta ) {
1487
1488                 const isRootObject = ( meta === undefined || typeof meta === 'string' );
1489
1490                 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
1491
1492                         return meta.textures[ this.uuid ];
1493
1494                 }
1495
1496                 const output = {
1497
1498                         metadata: {
1499                                 version: 4.5,
1500                                 type: 'Texture',
1501                                 generator: 'Texture.toJSON'
1502                         },
1503
1504                         uuid: this.uuid,
1505                         name: this.name,
1506
1507                         mapping: this.mapping,
1508
1509                         repeat: [ this.repeat.x, this.repeat.y ],
1510                         offset: [ this.offset.x, this.offset.y ],
1511                         center: [ this.center.x, this.center.y ],
1512                         rotation: this.rotation,
1513
1514                         wrap: [ this.wrapS, this.wrapT ],
1515
1516                         format: this.format,
1517                         type: this.type,
1518                         encoding: this.encoding,
1519
1520                         minFilter: this.minFilter,
1521                         magFilter: this.magFilter,
1522                         anisotropy: this.anisotropy,
1523
1524                         flipY: this.flipY,
1525
1526                         premultiplyAlpha: this.premultiplyAlpha,
1527                         unpackAlignment: this.unpackAlignment
1528
1529                 };
1530
1531                 if ( this.image !== undefined ) {
1532
1533                         // TODO: Move to THREE.Image
1534
1535                         const image = this.image;
1536
1537                         if ( image.uuid === undefined ) {
1538
1539                                 image.uuid = MathUtils.generateUUID(); // UGH
1540
1541                         }
1542
1543                         if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
1544
1545                                 let url;
1546
1547                                 if ( Array.isArray( image ) ) {
1548
1549                                         // process array of images e.g. CubeTexture
1550
1551                                         url = [];
1552
1553                                         for ( let i = 0, l = image.length; i < l; i ++ ) {
1554
1555                                                 // check cube texture with data textures
1556
1557                                                 if ( image[ i ].isDataTexture ) {
1558
1559                                                         url.push( serializeImage( image[ i ].image ) );
1560
1561                                                 } else {
1562
1563                                                         url.push( serializeImage( image[ i ] ) );
1564
1565                                                 }
1566
1567                                         }
1568
1569                                 } else {
1570
1571                                         // process single image
1572
1573                                         url = serializeImage( image );
1574
1575                                 }
1576
1577                                 meta.images[ image.uuid ] = {
1578                                         uuid: image.uuid,
1579                                         url: url
1580                                 };
1581
1582                         }
1583
1584                         output.image = image.uuid;
1585
1586                 }
1587
1588                 if ( ! isRootObject ) {
1589
1590                         meta.textures[ this.uuid ] = output;
1591
1592                 }
1593
1594                 return output;
1595
1596         },
1597
1598         dispose: function () {
1599
1600                 this.dispatchEvent( { type: 'dispose' } );
1601
1602         },
1603
1604         transformUv: function ( uv ) {
1605
1606                 if ( this.mapping !== UVMapping ) return uv;
1607
1608                 uv.applyMatrix3( this.matrix );
1609
1610                 if ( uv.x < 0 || uv.x > 1 ) {
1611
1612                         switch ( this.wrapS ) {
1613
1614                                 case RepeatWrapping:
1615
1616                                         uv.x = uv.x - Math.floor( uv.x );
1617                                         break;
1618
1619                                 case ClampToEdgeWrapping:
1620
1621                                         uv.x = uv.x < 0 ? 0 : 1;
1622                                         break;
1623
1624                                 case MirroredRepeatWrapping:
1625
1626                                         if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
1627
1628                                                 uv.x = Math.ceil( uv.x ) - uv.x;
1629
1630                                         } else {
1631
1632                                                 uv.x = uv.x - Math.floor( uv.x );
1633
1634                                         }
1635
1636                                         break;
1637
1638                         }
1639
1640                 }
1641
1642                 if ( uv.y < 0 || uv.y > 1 ) {
1643
1644                         switch ( this.wrapT ) {
1645
1646                                 case RepeatWrapping:
1647
1648                                         uv.y = uv.y - Math.floor( uv.y );
1649                                         break;
1650
1651                                 case ClampToEdgeWrapping:
1652
1653                                         uv.y = uv.y < 0 ? 0 : 1;
1654                                         break;
1655
1656                                 case MirroredRepeatWrapping:
1657
1658                                         if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
1659
1660                                                 uv.y = Math.ceil( uv.y ) - uv.y;
1661
1662                                         } else {
1663
1664                                                 uv.y = uv.y - Math.floor( uv.y );
1665
1666                                         }
1667
1668                                         break;
1669
1670                         }
1671
1672                 }
1673
1674                 if ( this.flipY ) {
1675
1676                         uv.y = 1 - uv.y;
1677
1678                 }
1679
1680                 return uv;
1681
1682         }
1683
1684 } );
1685
1686 Object.defineProperty( Texture.prototype, "needsUpdate", {
1687
1688         set: function ( value ) {
1689
1690                 if ( value === true ) this.version ++;
1691
1692         }
1693
1694 } );
1695
1696 function serializeImage( image ) {
1697
1698         if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
1699                 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
1700                 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
1701
1702                 // default images
1703
1704                 return ImageUtils.getDataURL( image );
1705
1706         } else {
1707
1708                 if ( image.data ) {
1709
1710                         // images of DataTexture
1711
1712                         return {
1713                                 data: Array.prototype.slice.call( image.data ),
1714                                 width: image.width,
1715                                 height: image.height,
1716                                 type: image.data.constructor.name
1717                         };
1718
1719                 } else {
1720
1721                         console.warn( 'THREE.Texture: Unable to serialize Texture.' );
1722                         return {};
1723
1724                 }
1725
1726         }
1727
1728 }
1729
1730 class Vector4 {
1731
1732         constructor( x = 0, y = 0, z = 0, w = 1 ) {
1733
1734                 Object.defineProperty( this, 'isVector4', { value: true } );
1735
1736                 this.x = x;
1737                 this.y = y;
1738                 this.z = z;
1739                 this.w = w;
1740
1741         }
1742
1743         get width() {
1744
1745                 return this.z;
1746
1747         }
1748
1749         set width( value ) {
1750
1751                 this.z = value;
1752
1753         }
1754
1755         get height() {
1756
1757                 return this.w;
1758
1759         }
1760
1761         set height( value ) {
1762
1763                 this.w = value;
1764
1765         }
1766
1767         set( x, y, z, w ) {
1768
1769                 this.x = x;
1770                 this.y = y;
1771                 this.z = z;
1772                 this.w = w;
1773
1774                 return this;
1775
1776         }
1777
1778         setScalar( scalar ) {
1779
1780                 this.x = scalar;
1781                 this.y = scalar;
1782                 this.z = scalar;
1783                 this.w = scalar;
1784
1785                 return this;
1786
1787         }
1788
1789         setX( x ) {
1790
1791                 this.x = x;
1792
1793                 return this;
1794
1795         }
1796
1797         setY( y ) {
1798
1799                 this.y = y;
1800
1801                 return this;
1802
1803         }
1804
1805         setZ( z ) {
1806
1807                 this.z = z;
1808
1809                 return this;
1810
1811         }
1812
1813         setW( w ) {
1814
1815                 this.w = w;
1816
1817                 return this;
1818
1819         }
1820
1821         setComponent( index, value ) {
1822
1823                 switch ( index ) {
1824
1825                         case 0: this.x = value; break;
1826                         case 1: this.y = value; break;
1827                         case 2: this.z = value; break;
1828                         case 3: this.w = value; break;
1829                         default: throw new Error( 'index is out of range: ' + index );
1830
1831                 }
1832
1833                 return this;
1834
1835         }
1836
1837         getComponent( index ) {
1838
1839                 switch ( index ) {
1840
1841                         case 0: return this.x;
1842                         case 1: return this.y;
1843                         case 2: return this.z;
1844                         case 3: return this.w;
1845                         default: throw new Error( 'index is out of range: ' + index );
1846
1847                 }
1848
1849         }
1850
1851         clone() {
1852
1853                 return new this.constructor( this.x, this.y, this.z, this.w );
1854
1855         }
1856
1857         copy( v ) {
1858
1859                 this.x = v.x;
1860                 this.y = v.y;
1861                 this.z = v.z;
1862                 this.w = ( v.w !== undefined ) ? v.w : 1;
1863
1864                 return this;
1865
1866         }
1867
1868         add( v, w ) {
1869
1870                 if ( w !== undefined ) {
1871
1872                         console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
1873                         return this.addVectors( v, w );
1874
1875                 }
1876
1877                 this.x += v.x;
1878                 this.y += v.y;
1879                 this.z += v.z;
1880                 this.w += v.w;
1881
1882                 return this;
1883
1884         }
1885
1886         addScalar( s ) {
1887
1888                 this.x += s;
1889                 this.y += s;
1890                 this.z += s;
1891                 this.w += s;
1892
1893                 return this;
1894
1895         }
1896
1897         addVectors( a, b ) {
1898
1899                 this.x = a.x + b.x;
1900                 this.y = a.y + b.y;
1901                 this.z = a.z + b.z;
1902                 this.w = a.w + b.w;
1903
1904                 return this;
1905
1906         }
1907
1908         addScaledVector( v, s ) {
1909
1910                 this.x += v.x * s;
1911                 this.y += v.y * s;
1912                 this.z += v.z * s;
1913                 this.w += v.w * s;
1914
1915                 return this;
1916
1917         }
1918
1919         sub( v, w ) {
1920
1921                 if ( w !== undefined ) {
1922
1923                         console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
1924                         return this.subVectors( v, w );
1925
1926                 }
1927
1928                 this.x -= v.x;
1929                 this.y -= v.y;
1930                 this.z -= v.z;
1931                 this.w -= v.w;
1932
1933                 return this;
1934
1935         }
1936
1937         subScalar( s ) {
1938
1939                 this.x -= s;
1940                 this.y -= s;
1941                 this.z -= s;
1942                 this.w -= s;
1943
1944                 return this;
1945
1946         }
1947
1948         subVectors( a, b ) {
1949
1950                 this.x = a.x - b.x;
1951                 this.y = a.y - b.y;
1952                 this.z = a.z - b.z;
1953                 this.w = a.w - b.w;
1954
1955                 return this;
1956
1957         }
1958
1959         multiplyScalar( scalar ) {
1960
1961                 this.x *= scalar;
1962                 this.y *= scalar;
1963                 this.z *= scalar;
1964                 this.w *= scalar;
1965
1966                 return this;
1967
1968         }
1969
1970         applyMatrix4( m ) {
1971
1972                 const x = this.x, y = this.y, z = this.z, w = this.w;
1973                 const e = m.elements;
1974
1975                 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
1976                 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
1977                 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
1978                 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
1979
1980                 return this;
1981
1982         }
1983
1984         divideScalar( scalar ) {
1985
1986                 return this.multiplyScalar( 1 / scalar );
1987
1988         }
1989
1990         setAxisAngleFromQuaternion( q ) {
1991
1992                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
1993
1994                 // q is assumed to be normalized
1995
1996                 this.w = 2 * Math.acos( q.w );
1997
1998                 const s = Math.sqrt( 1 - q.w * q.w );
1999
2000                 if ( s < 0.0001 ) {
2001
2002                         this.x = 1;
2003                         this.y = 0;
2004                         this.z = 0;
2005
2006                 } else {
2007
2008                         this.x = q.x / s;
2009                         this.y = q.y / s;
2010                         this.z = q.z / s;
2011
2012                 }
2013
2014                 return this;
2015
2016         }
2017
2018         setAxisAngleFromRotationMatrix( m ) {
2019
2020                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
2021
2022                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2023
2024                 let angle, x, y, z; // variables for result
2025                 const epsilon = 0.01,           // margin to allow for rounding errors
2026                         epsilon2 = 0.1,         // margin to distinguish between 0 and 180 degrees
2027
2028                         te = m.elements,
2029
2030                         m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2031                         m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2032                         m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
2033
2034                 if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
2035                      ( Math.abs( m13 - m31 ) < epsilon ) &&
2036                      ( Math.abs( m23 - m32 ) < epsilon ) ) {
2037
2038                         // singularity found
2039                         // first check for identity matrix which must have +1 for all terms
2040                         // in leading diagonal and zero in other terms
2041
2042                         if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
2043                              ( Math.abs( m13 + m31 ) < epsilon2 ) &&
2044                              ( Math.abs( m23 + m32 ) < epsilon2 ) &&
2045                              ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
2046
2047                                 // this singularity is identity matrix so angle = 0
2048
2049                                 this.set( 1, 0, 0, 0 );
2050
2051                                 return this; // zero angle, arbitrary axis
2052
2053                         }
2054
2055                         // otherwise this singularity is angle = 180
2056
2057                         angle = Math.PI;
2058
2059                         const xx = ( m11 + 1 ) / 2;
2060                         const yy = ( m22 + 1 ) / 2;
2061                         const zz = ( m33 + 1 ) / 2;
2062                         const xy = ( m12 + m21 ) / 4;
2063                         const xz = ( m13 + m31 ) / 4;
2064                         const yz = ( m23 + m32 ) / 4;
2065
2066                         if ( ( xx > yy ) && ( xx > zz ) ) {
2067
2068                                 // m11 is the largest diagonal term
2069
2070                                 if ( xx < epsilon ) {
2071
2072                                         x = 0;
2073                                         y = 0.707106781;
2074                                         z = 0.707106781;
2075
2076                                 } else {
2077
2078                                         x = Math.sqrt( xx );
2079                                         y = xy / x;
2080                                         z = xz / x;
2081
2082                                 }
2083
2084                         } else if ( yy > zz ) {
2085
2086                                 // m22 is the largest diagonal term
2087
2088                                 if ( yy < epsilon ) {
2089
2090                                         x = 0.707106781;
2091                                         y = 0;
2092                                         z = 0.707106781;
2093
2094                                 } else {
2095
2096                                         y = Math.sqrt( yy );
2097                                         x = xy / y;
2098                                         z = yz / y;
2099
2100                                 }
2101
2102                         } else {
2103
2104                                 // m33 is the largest diagonal term so base result on this
2105
2106                                 if ( zz < epsilon ) {
2107
2108                                         x = 0.707106781;
2109                                         y = 0.707106781;
2110                                         z = 0;
2111
2112                                 } else {
2113
2114                                         z = Math.sqrt( zz );
2115                                         x = xz / z;
2116                                         y = yz / z;
2117
2118                                 }
2119
2120                         }
2121
2122                         this.set( x, y, z, angle );
2123
2124                         return this; // return 180 deg rotation
2125
2126                 }
2127
2128                 // as we have reached here there are no singularities so we can handle normally
2129
2130                 let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
2131                         ( m13 - m31 ) * ( m13 - m31 ) +
2132                         ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
2133
2134                 if ( Math.abs( s ) < 0.001 ) s = 1;
2135
2136                 // prevent divide by zero, should not happen if matrix is orthogonal and should be
2137                 // caught by singularity test above, but I've left it in just in case
2138
2139                 this.x = ( m32 - m23 ) / s;
2140                 this.y = ( m13 - m31 ) / s;
2141                 this.z = ( m21 - m12 ) / s;
2142                 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
2143
2144                 return this;
2145
2146         }
2147
2148         min( v ) {
2149
2150                 this.x = Math.min( this.x, v.x );
2151                 this.y = Math.min( this.y, v.y );
2152                 this.z = Math.min( this.z, v.z );
2153                 this.w = Math.min( this.w, v.w );
2154
2155                 return this;
2156
2157         }
2158
2159         max( v ) {
2160
2161                 this.x = Math.max( this.x, v.x );
2162                 this.y = Math.max( this.y, v.y );
2163                 this.z = Math.max( this.z, v.z );
2164                 this.w = Math.max( this.w, v.w );
2165
2166                 return this;
2167
2168         }
2169
2170         clamp( min, max ) {
2171
2172                 // assumes min < max, componentwise
2173
2174                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2175                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2176                 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2177                 this.w = Math.max( min.w, Math.min( max.w, this.w ) );
2178
2179                 return this;
2180
2181         }
2182
2183         clampScalar( minVal, maxVal ) {
2184
2185                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
2186                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
2187                 this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
2188                 this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
2189
2190                 return this;
2191
2192         }
2193
2194         clampLength( min, max ) {
2195
2196                 const length = this.length();
2197
2198                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
2199
2200         }
2201
2202         floor() {
2203
2204                 this.x = Math.floor( this.x );
2205                 this.y = Math.floor( this.y );
2206                 this.z = Math.floor( this.z );
2207                 this.w = Math.floor( this.w );
2208
2209                 return this;
2210
2211         }
2212
2213         ceil() {
2214
2215                 this.x = Math.ceil( this.x );
2216                 this.y = Math.ceil( this.y );
2217                 this.z = Math.ceil( this.z );
2218                 this.w = Math.ceil( this.w );
2219
2220                 return this;
2221
2222         }
2223
2224         round() {
2225
2226                 this.x = Math.round( this.x );
2227                 this.y = Math.round( this.y );
2228                 this.z = Math.round( this.z );
2229                 this.w = Math.round( this.w );
2230
2231                 return this;
2232
2233         }
2234
2235         roundToZero() {
2236
2237                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
2238                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
2239                 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
2240                 this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
2241
2242                 return this;
2243
2244         }
2245
2246         negate() {
2247
2248                 this.x = - this.x;
2249                 this.y = - this.y;
2250                 this.z = - this.z;
2251                 this.w = - this.w;
2252
2253                 return this;
2254
2255         }
2256
2257         dot( v ) {
2258
2259                 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
2260
2261         }
2262
2263         lengthSq() {
2264
2265                 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
2266
2267         }
2268
2269         length() {
2270
2271                 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
2272
2273         }
2274
2275         manhattanLength() {
2276
2277                 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
2278
2279         }
2280
2281         normalize() {
2282
2283                 return this.divideScalar( this.length() || 1 );
2284
2285         }
2286
2287         setLength( length ) {
2288
2289                 return this.normalize().multiplyScalar( length );
2290
2291         }
2292
2293         lerp( v, alpha ) {
2294
2295                 this.x += ( v.x - this.x ) * alpha;
2296                 this.y += ( v.y - this.y ) * alpha;
2297                 this.z += ( v.z - this.z ) * alpha;
2298                 this.w += ( v.w - this.w ) * alpha;
2299
2300                 return this;
2301
2302         }
2303
2304         lerpVectors( v1, v2, alpha ) {
2305
2306                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
2307                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
2308                 this.z = v1.z + ( v2.z - v1.z ) * alpha;
2309                 this.w = v1.w + ( v2.w - v1.w ) * alpha;
2310
2311                 return this;
2312
2313         }
2314
2315         equals( v ) {
2316
2317                 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
2318
2319         }
2320
2321         fromArray( array, offset = 0 ) {
2322
2323                 this.x = array[ offset ];
2324                 this.y = array[ offset + 1 ];
2325                 this.z = array[ offset + 2 ];
2326                 this.w = array[ offset + 3 ];
2327
2328                 return this;
2329
2330         }
2331
2332         toArray( array = [], offset = 0 ) {
2333
2334                 array[ offset ] = this.x;
2335                 array[ offset + 1 ] = this.y;
2336                 array[ offset + 2 ] = this.z;
2337                 array[ offset + 3 ] = this.w;
2338
2339                 return array;
2340
2341         }
2342
2343         fromBufferAttribute( attribute, index, offset ) {
2344
2345                 if ( offset !== undefined ) {
2346
2347                         console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
2348
2349                 }
2350
2351                 this.x = attribute.getX( index );
2352                 this.y = attribute.getY( index );
2353                 this.z = attribute.getZ( index );
2354                 this.w = attribute.getW( index );
2355
2356                 return this;
2357
2358         }
2359
2360         random() {
2361
2362                 this.x = Math.random();
2363                 this.y = Math.random();
2364                 this.z = Math.random();
2365                 this.w = Math.random();
2366
2367                 return this;
2368
2369         }
2370
2371 }
2372
2373 /*
2374  In options, we can specify:
2375  * Texture parameters for an auto-generated target texture
2376  * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
2377 */
2378 function WebGLRenderTarget( width, height, options ) {
2379
2380         this.width = width;
2381         this.height = height;
2382
2383         this.scissor = new Vector4( 0, 0, width, height );
2384         this.scissorTest = false;
2385
2386         this.viewport = new Vector4( 0, 0, width, height );
2387
2388         options = options || {};
2389
2390         this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
2391
2392         this.texture.image = {};
2393         this.texture.image.width = width;
2394         this.texture.image.height = height;
2395
2396         this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
2397         this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
2398
2399         this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
2400         this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
2401         this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
2402
2403 }
2404
2405 WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
2406
2407         constructor: WebGLRenderTarget,
2408
2409         isWebGLRenderTarget: true,
2410
2411         setSize: function ( width, height ) {
2412
2413                 if ( this.width !== width || this.height !== height ) {
2414
2415                         this.width = width;
2416                         this.height = height;
2417
2418                         this.texture.image.width = width;
2419                         this.texture.image.height = height;
2420
2421                         this.dispose();
2422
2423                 }
2424
2425                 this.viewport.set( 0, 0, width, height );
2426                 this.scissor.set( 0, 0, width, height );
2427
2428         },
2429
2430         clone: function () {
2431
2432                 return new this.constructor().copy( this );
2433
2434         },
2435
2436         copy: function ( source ) {
2437
2438                 this.width = source.width;
2439                 this.height = source.height;
2440
2441                 this.viewport.copy( source.viewport );
2442
2443                 this.texture = source.texture.clone();
2444
2445                 this.depthBuffer = source.depthBuffer;
2446                 this.stencilBuffer = source.stencilBuffer;
2447                 this.depthTexture = source.depthTexture;
2448
2449                 return this;
2450
2451         },
2452
2453         dispose: function () {
2454
2455                 this.dispatchEvent( { type: 'dispose' } );
2456
2457         }
2458
2459 } );
2460
2461 function WebGLMultisampleRenderTarget( width, height, options ) {
2462
2463         WebGLRenderTarget.call( this, width, height, options );
2464
2465         this.samples = 4;
2466
2467 }
2468
2469 WebGLMultisampleRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {
2470
2471         constructor: WebGLMultisampleRenderTarget,
2472
2473         isWebGLMultisampleRenderTarget: true,
2474
2475         copy: function ( source ) {
2476
2477                 WebGLRenderTarget.prototype.copy.call( this, source );
2478
2479                 this.samples = source.samples;
2480
2481                 return this;
2482
2483         }
2484
2485 } );
2486
2487 class Quaternion {
2488
2489         constructor( x = 0, y = 0, z = 0, w = 1 ) {
2490
2491                 Object.defineProperty( this, 'isQuaternion', { value: true } );
2492
2493                 this._x = x;
2494                 this._y = y;
2495                 this._z = z;
2496                 this._w = w;
2497
2498         }
2499
2500         static slerp( qa, qb, qm, t ) {
2501
2502                 return qm.copy( qa ).slerp( qb, t );
2503
2504         }
2505
2506         static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
2507
2508                 // fuzz-free, array-based Quaternion SLERP operation
2509
2510                 let x0 = src0[ srcOffset0 + 0 ],
2511                         y0 = src0[ srcOffset0 + 1 ],
2512                         z0 = src0[ srcOffset0 + 2 ],
2513                         w0 = src0[ srcOffset0 + 3 ];
2514
2515                 const x1 = src1[ srcOffset1 + 0 ],
2516                         y1 = src1[ srcOffset1 + 1 ],
2517                         z1 = src1[ srcOffset1 + 2 ],
2518                         w1 = src1[ srcOffset1 + 3 ];
2519
2520                 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
2521
2522                         let s = 1 - t;
2523                         const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
2524                                 dir = ( cos >= 0 ? 1 : - 1 ),
2525                                 sqrSin = 1 - cos * cos;
2526
2527                         // Skip the Slerp for tiny steps to avoid numeric problems:
2528                         if ( sqrSin > Number.EPSILON ) {
2529
2530                                 const sin = Math.sqrt( sqrSin ),
2531                                         len = Math.atan2( sin, cos * dir );
2532
2533                                 s = Math.sin( s * len ) / sin;
2534                                 t = Math.sin( t * len ) / sin;
2535
2536                         }
2537
2538                         const tDir = t * dir;
2539
2540                         x0 = x0 * s + x1 * tDir;
2541                         y0 = y0 * s + y1 * tDir;
2542                         z0 = z0 * s + z1 * tDir;
2543                         w0 = w0 * s + w1 * tDir;
2544
2545                         // Normalize in case we just did a lerp:
2546                         if ( s === 1 - t ) {
2547
2548                                 const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
2549
2550                                 x0 *= f;
2551                                 y0 *= f;
2552                                 z0 *= f;
2553                                 w0 *= f;
2554
2555                         }
2556
2557                 }
2558
2559                 dst[ dstOffset ] = x0;
2560                 dst[ dstOffset + 1 ] = y0;
2561                 dst[ dstOffset + 2 ] = z0;
2562                 dst[ dstOffset + 3 ] = w0;
2563
2564         }
2565
2566         static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
2567
2568                 const x0 = src0[ srcOffset0 ];
2569                 const y0 = src0[ srcOffset0 + 1 ];
2570                 const z0 = src0[ srcOffset0 + 2 ];
2571                 const w0 = src0[ srcOffset0 + 3 ];
2572
2573                 const x1 = src1[ srcOffset1 ];
2574                 const y1 = src1[ srcOffset1 + 1 ];
2575                 const z1 = src1[ srcOffset1 + 2 ];
2576                 const w1 = src1[ srcOffset1 + 3 ];
2577
2578                 dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
2579                 dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
2580                 dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
2581                 dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
2582
2583                 return dst;
2584
2585         }
2586
2587         get x() {
2588
2589                 return this._x;
2590
2591         }
2592
2593         set x( value ) {
2594
2595                 this._x = value;
2596                 this._onChangeCallback();
2597
2598         }
2599
2600         get y() {
2601
2602                 return this._y;
2603
2604         }
2605
2606         set y( value ) {
2607
2608                 this._y = value;
2609                 this._onChangeCallback();
2610
2611         }
2612
2613         get z() {
2614
2615                 return this._z;
2616
2617         }
2618
2619         set z( value ) {
2620
2621                 this._z = value;
2622                 this._onChangeCallback();
2623
2624         }
2625
2626         get w() {
2627
2628                 return this._w;
2629
2630         }
2631
2632         set w( value ) {
2633
2634                 this._w = value;
2635                 this._onChangeCallback();
2636
2637         }
2638
2639         set( x, y, z, w ) {
2640
2641                 this._x = x;
2642                 this._y = y;
2643                 this._z = z;
2644                 this._w = w;
2645
2646                 this._onChangeCallback();
2647
2648                 return this;
2649
2650         }
2651
2652         clone() {
2653
2654                 return new this.constructor( this._x, this._y, this._z, this._w );
2655
2656         }
2657
2658         copy( quaternion ) {
2659
2660                 this._x = quaternion.x;
2661                 this._y = quaternion.y;
2662                 this._z = quaternion.z;
2663                 this._w = quaternion.w;
2664
2665                 this._onChangeCallback();
2666
2667                 return this;
2668
2669         }
2670
2671         setFromEuler( euler, update ) {
2672
2673                 if ( ! ( euler && euler.isEuler ) ) {
2674
2675                         throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2676
2677                 }
2678
2679                 const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
2680
2681                 // http://www.mathworks.com/matlabcentral/fileexchange/
2682                 //      20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
2683                 //      content/SpinCalc.m
2684
2685                 const cos = Math.cos;
2686                 const sin = Math.sin;
2687
2688                 const c1 = cos( x / 2 );
2689                 const c2 = cos( y / 2 );
2690                 const c3 = cos( z / 2 );
2691
2692                 const s1 = sin( x / 2 );
2693                 const s2 = sin( y / 2 );
2694                 const s3 = sin( z / 2 );
2695
2696                 switch ( order ) {
2697
2698                         case 'XYZ':
2699                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2700                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2701                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2702                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2703                                 break;
2704
2705                         case 'YXZ':
2706                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2707                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2708                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2709                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2710                                 break;
2711
2712                         case 'ZXY':
2713                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2714                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2715                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2716                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2717                                 break;
2718
2719                         case 'ZYX':
2720                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2721                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2722                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2723                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2724                                 break;
2725
2726                         case 'YZX':
2727                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2728                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2729                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2730                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2731                                 break;
2732
2733                         case 'XZY':
2734                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2735                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2736                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2737                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2738                                 break;
2739
2740                         default:
2741                                 console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
2742
2743                 }
2744
2745                 if ( update !== false ) this._onChangeCallback();
2746
2747                 return this;
2748
2749         }
2750
2751         setFromAxisAngle( axis, angle ) {
2752
2753                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
2754
2755                 // assumes axis is normalized
2756
2757                 const halfAngle = angle / 2, s = Math.sin( halfAngle );
2758
2759                 this._x = axis.x * s;
2760                 this._y = axis.y * s;
2761                 this._z = axis.z * s;
2762                 this._w = Math.cos( halfAngle );
2763
2764                 this._onChangeCallback();
2765
2766                 return this;
2767
2768         }
2769
2770         setFromRotationMatrix( m ) {
2771
2772                 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
2773
2774                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2775
2776                 const te = m.elements,
2777
2778                         m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2779                         m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2780                         m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
2781
2782                         trace = m11 + m22 + m33;
2783
2784                 if ( trace > 0 ) {
2785
2786                         const s = 0.5 / Math.sqrt( trace + 1.0 );
2787
2788                         this._w = 0.25 / s;
2789                         this._x = ( m32 - m23 ) * s;
2790                         this._y = ( m13 - m31 ) * s;
2791                         this._z = ( m21 - m12 ) * s;
2792
2793                 } else if ( m11 > m22 && m11 > m33 ) {
2794
2795                         const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
2796
2797                         this._w = ( m32 - m23 ) / s;
2798                         this._x = 0.25 * s;
2799                         this._y = ( m12 + m21 ) / s;
2800                         this._z = ( m13 + m31 ) / s;
2801
2802                 } else if ( m22 > m33 ) {
2803
2804                         const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
2805
2806                         this._w = ( m13 - m31 ) / s;
2807                         this._x = ( m12 + m21 ) / s;
2808                         this._y = 0.25 * s;
2809                         this._z = ( m23 + m32 ) / s;
2810
2811                 } else {
2812
2813                         const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
2814
2815                         this._w = ( m21 - m12 ) / s;
2816                         this._x = ( m13 + m31 ) / s;
2817                         this._y = ( m23 + m32 ) / s;
2818                         this._z = 0.25 * s;
2819
2820                 }
2821
2822                 this._onChangeCallback();
2823
2824                 return this;
2825
2826         }
2827
2828         setFromUnitVectors( vFrom, vTo ) {
2829
2830                 // assumes direction vectors vFrom and vTo are normalized
2831
2832                 const EPS = 0.000001;
2833
2834                 let r = vFrom.dot( vTo ) + 1;
2835
2836                 if ( r < EPS ) {
2837
2838                         r = 0;
2839
2840                         if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
2841
2842                                 this._x = - vFrom.y;
2843                                 this._y = vFrom.x;
2844                                 this._z = 0;
2845                                 this._w = r;
2846
2847                         } else {
2848
2849                                 this._x = 0;
2850                                 this._y = - vFrom.z;
2851                                 this._z = vFrom.y;
2852                                 this._w = r;
2853
2854                         }
2855
2856                 } else {
2857
2858                         // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
2859
2860                         this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
2861                         this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
2862                         this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
2863                         this._w = r;
2864
2865                 }
2866
2867                 return this.normalize();
2868
2869         }
2870
2871         angleTo( q ) {
2872
2873                 return 2 * Math.acos( Math.abs( MathUtils.clamp( this.dot( q ), - 1, 1 ) ) );
2874
2875         }
2876
2877         rotateTowards( q, step ) {
2878
2879                 const angle = this.angleTo( q );
2880
2881                 if ( angle === 0 ) return this;
2882
2883                 const t = Math.min( 1, step / angle );
2884
2885                 this.slerp( q, t );
2886
2887                 return this;
2888
2889         }
2890
2891         identity() {
2892
2893                 return this.set( 0, 0, 0, 1 );
2894
2895         }
2896
2897         invert() {
2898
2899                 // quaternion is assumed to have unit length
2900
2901                 return this.conjugate();
2902
2903         }
2904
2905         conjugate() {
2906
2907                 this._x *= - 1;
2908                 this._y *= - 1;
2909                 this._z *= - 1;
2910
2911                 this._onChangeCallback();
2912
2913                 return this;
2914
2915         }
2916
2917         dot( v ) {
2918
2919                 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
2920
2921         }
2922
2923         lengthSq() {
2924
2925                 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
2926
2927         }
2928
2929         length() {
2930
2931                 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
2932
2933         }
2934
2935         normalize() {
2936
2937                 let l = this.length();
2938
2939                 if ( l === 0 ) {
2940
2941                         this._x = 0;
2942                         this._y = 0;
2943                         this._z = 0;
2944                         this._w = 1;
2945
2946                 } else {
2947
2948                         l = 1 / l;
2949
2950                         this._x = this._x * l;
2951                         this._y = this._y * l;
2952                         this._z = this._z * l;
2953                         this._w = this._w * l;
2954
2955                 }
2956
2957                 this._onChangeCallback();
2958
2959                 return this;
2960
2961         }
2962
2963         multiply( q, p ) {
2964
2965                 if ( p !== undefined ) {
2966
2967                         console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
2968                         return this.multiplyQuaternions( q, p );
2969
2970                 }
2971
2972                 return this.multiplyQuaternions( this, q );
2973
2974         }
2975
2976         premultiply( q ) {
2977
2978                 return this.multiplyQuaternions( q, this );
2979
2980         }
2981
2982         multiplyQuaternions( a, b ) {
2983
2984                 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
2985
2986                 const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
2987                 const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
2988
2989                 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
2990                 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
2991                 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
2992                 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
2993
2994                 this._onChangeCallback();
2995
2996                 return this;
2997
2998         }
2999
3000         slerp( qb, t ) {
3001
3002                 if ( t === 0 ) return this;
3003                 if ( t === 1 ) return this.copy( qb );
3004
3005                 const x = this._x, y = this._y, z = this._z, w = this._w;
3006
3007                 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
3008
3009                 let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
3010
3011                 if ( cosHalfTheta < 0 ) {
3012
3013                         this._w = - qb._w;
3014                         this._x = - qb._x;
3015                         this._y = - qb._y;
3016                         this._z = - qb._z;
3017
3018                         cosHalfTheta = - cosHalfTheta;
3019
3020                 } else {
3021
3022                         this.copy( qb );
3023
3024                 }
3025
3026                 if ( cosHalfTheta >= 1.0 ) {
3027
3028                         this._w = w;
3029                         this._x = x;
3030                         this._y = y;
3031                         this._z = z;
3032
3033                         return this;
3034
3035                 }
3036
3037                 const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
3038
3039                 if ( sqrSinHalfTheta <= Number.EPSILON ) {
3040
3041                         const s = 1 - t;
3042                         this._w = s * w + t * this._w;
3043                         this._x = s * x + t * this._x;
3044                         this._y = s * y + t * this._y;
3045                         this._z = s * z + t * this._z;
3046
3047                         this.normalize();
3048                         this._onChangeCallback();
3049
3050                         return this;
3051
3052                 }
3053
3054                 const sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
3055                 const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
3056                 const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
3057                         ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
3058
3059                 this._w = ( w * ratioA + this._w * ratioB );
3060                 this._x = ( x * ratioA + this._x * ratioB );
3061                 this._y = ( y * ratioA + this._y * ratioB );
3062                 this._z = ( z * ratioA + this._z * ratioB );
3063
3064                 this._onChangeCallback();
3065
3066                 return this;
3067
3068         }
3069
3070         equals( quaternion ) {
3071
3072                 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
3073
3074         }
3075
3076         fromArray( array, offset = 0 ) {
3077
3078                 this._x = array[ offset ];
3079                 this._y = array[ offset + 1 ];
3080                 this._z = array[ offset + 2 ];
3081                 this._w = array[ offset + 3 ];
3082
3083                 this._onChangeCallback();
3084
3085                 return this;
3086
3087         }
3088
3089         toArray( array = [], offset = 0 ) {
3090
3091                 array[ offset ] = this._x;
3092                 array[ offset + 1 ] = this._y;
3093                 array[ offset + 2 ] = this._z;
3094                 array[ offset + 3 ] = this._w;
3095
3096                 return array;
3097
3098         }
3099
3100         fromBufferAttribute( attribute, index ) {
3101
3102                 this._x = attribute.getX( index );
3103                 this._y = attribute.getY( index );
3104                 this._z = attribute.getZ( index );
3105                 this._w = attribute.getW( index );
3106
3107                 return this;
3108
3109         }
3110
3111         _onChange( callback ) {
3112
3113                 this._onChangeCallback = callback;
3114
3115                 return this;
3116
3117         }
3118
3119         _onChangeCallback() {}
3120
3121 }
3122
3123 class Vector3 {
3124
3125         constructor( x = 0, y = 0, z = 0 ) {
3126
3127                 Object.defineProperty( this, 'isVector3', { value: true } );
3128
3129                 this.x = x;
3130                 this.y = y;
3131                 this.z = z;
3132
3133         }
3134
3135         set( x, y, z ) {
3136
3137                 if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
3138
3139                 this.x = x;
3140                 this.y = y;
3141                 this.z = z;
3142
3143                 return this;
3144
3145         }
3146
3147         setScalar( scalar ) {
3148
3149                 this.x = scalar;
3150                 this.y = scalar;
3151                 this.z = scalar;
3152
3153                 return this;
3154
3155         }
3156
3157         setX( x ) {
3158
3159                 this.x = x;
3160
3161                 return this;
3162
3163         }
3164
3165         setY( y ) {
3166
3167                 this.y = y;
3168
3169                 return this;
3170
3171         }
3172
3173         setZ( z ) {
3174
3175                 this.z = z;
3176
3177                 return this;
3178
3179         }
3180
3181         setComponent( index, value ) {
3182
3183                 switch ( index ) {
3184
3185                         case 0: this.x = value; break;
3186                         case 1: this.y = value; break;
3187                         case 2: this.z = value; break;
3188                         default: throw new Error( 'index is out of range: ' + index );
3189
3190                 }
3191
3192                 return this;
3193
3194         }
3195
3196         getComponent( index ) {
3197
3198                 switch ( index ) {
3199
3200                         case 0: return this.x;
3201                         case 1: return this.y;
3202                         case 2: return this.z;
3203                         default: throw new Error( 'index is out of range: ' + index );
3204
3205                 }
3206
3207         }
3208
3209         clone() {
3210
3211                 return new this.constructor( this.x, this.y, this.z );
3212
3213         }
3214
3215         copy( v ) {
3216
3217                 this.x = v.x;
3218                 this.y = v.y;
3219                 this.z = v.z;
3220
3221                 return this;
3222
3223         }
3224
3225         add( v, w ) {
3226
3227                 if ( w !== undefined ) {
3228
3229                         console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
3230                         return this.addVectors( v, w );
3231
3232                 }
3233
3234                 this.x += v.x;
3235                 this.y += v.y;
3236                 this.z += v.z;
3237
3238                 return this;
3239
3240         }
3241
3242         addScalar( s ) {
3243
3244                 this.x += s;
3245                 this.y += s;
3246                 this.z += s;
3247
3248                 return this;
3249
3250         }
3251
3252         addVectors( a, b ) {
3253
3254                 this.x = a.x + b.x;
3255                 this.y = a.y + b.y;
3256                 this.z = a.z + b.z;
3257
3258                 return this;
3259
3260         }
3261
3262         addScaledVector( v, s ) {
3263
3264                 this.x += v.x * s;
3265                 this.y += v.y * s;
3266                 this.z += v.z * s;
3267
3268                 return this;
3269
3270         }
3271
3272         sub( v, w ) {
3273
3274                 if ( w !== undefined ) {
3275
3276                         console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
3277                         return this.subVectors( v, w );
3278
3279                 }
3280
3281                 this.x -= v.x;
3282                 this.y -= v.y;
3283                 this.z -= v.z;
3284
3285                 return this;
3286
3287         }
3288
3289         subScalar( s ) {
3290
3291                 this.x -= s;
3292                 this.y -= s;
3293                 this.z -= s;
3294
3295                 return this;
3296
3297         }
3298
3299         subVectors( a, b ) {
3300
3301                 this.x = a.x - b.x;
3302                 this.y = a.y - b.y;
3303                 this.z = a.z - b.z;
3304
3305                 return this;
3306
3307         }
3308
3309         multiply( v, w ) {
3310
3311                 if ( w !== undefined ) {
3312
3313                         console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
3314                         return this.multiplyVectors( v, w );
3315
3316                 }
3317
3318                 this.x *= v.x;
3319                 this.y *= v.y;
3320                 this.z *= v.z;
3321
3322                 return this;
3323
3324         }
3325
3326         multiplyScalar( scalar ) {
3327
3328                 this.x *= scalar;
3329                 this.y *= scalar;
3330                 this.z *= scalar;
3331
3332                 return this;
3333
3334         }
3335
3336         multiplyVectors( a, b ) {
3337
3338                 this.x = a.x * b.x;
3339                 this.y = a.y * b.y;
3340                 this.z = a.z * b.z;
3341
3342                 return this;
3343
3344         }
3345
3346         applyEuler( euler ) {
3347
3348                 if ( ! ( euler && euler.isEuler ) ) {
3349
3350                         console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
3351
3352                 }
3353
3354                 return this.applyQuaternion( _quaternion.setFromEuler( euler ) );
3355
3356         }
3357
3358         applyAxisAngle( axis, angle ) {
3359
3360                 return this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );
3361
3362         }
3363
3364         applyMatrix3( m ) {
3365
3366                 const x = this.x, y = this.y, z = this.z;
3367                 const e = m.elements;
3368
3369                 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
3370                 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
3371                 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
3372
3373                 return this;
3374
3375         }
3376
3377         applyNormalMatrix( m ) {
3378
3379                 return this.applyMatrix3( m ).normalize();
3380
3381         }
3382
3383         applyMatrix4( m ) {
3384
3385                 const x = this.x, y = this.y, z = this.z;
3386                 const e = m.elements;
3387
3388                 const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
3389
3390                 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
3391                 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
3392                 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
3393
3394                 return this;
3395
3396         }
3397
3398         applyQuaternion( q ) {
3399
3400                 const x = this.x, y = this.y, z = this.z;
3401                 const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
3402
3403                 // calculate quat * vector
3404
3405                 const ix = qw * x + qy * z - qz * y;
3406                 const iy = qw * y + qz * x - qx * z;
3407                 const iz = qw * z + qx * y - qy * x;
3408                 const iw = - qx * x - qy * y - qz * z;
3409
3410                 // calculate result * inverse quat
3411
3412                 this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
3413                 this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
3414                 this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
3415
3416                 return this;
3417
3418         }
3419
3420         project( camera ) {
3421
3422                 return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
3423
3424         }
3425
3426         unproject( camera ) {
3427
3428                 return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
3429
3430         }
3431
3432         transformDirection( m ) {
3433
3434                 // input: THREE.Matrix4 affine matrix
3435                 // vector interpreted as a direction
3436
3437                 const x = this.x, y = this.y, z = this.z;
3438                 const e = m.elements;
3439
3440                 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
3441                 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
3442                 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
3443
3444                 return this.normalize();
3445
3446         }
3447
3448         divide( v ) {
3449
3450                 this.x /= v.x;
3451                 this.y /= v.y;
3452                 this.z /= v.z;
3453
3454                 return this;
3455
3456         }
3457
3458         divideScalar( scalar ) {
3459
3460                 return this.multiplyScalar( 1 / scalar );
3461
3462         }
3463
3464         min( v ) {
3465
3466                 this.x = Math.min( this.x, v.x );
3467                 this.y = Math.min( this.y, v.y );
3468                 this.z = Math.min( this.z, v.z );
3469
3470                 return this;
3471
3472         }
3473
3474         max( v ) {
3475
3476                 this.x = Math.max( this.x, v.x );
3477                 this.y = Math.max( this.y, v.y );
3478                 this.z = Math.max( this.z, v.z );
3479
3480                 return this;
3481
3482         }
3483
3484         clamp( min, max ) {
3485
3486                 // assumes min < max, componentwise
3487
3488                 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
3489                 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
3490                 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
3491
3492                 return this;
3493
3494         }
3495
3496         clampScalar( minVal, maxVal ) {
3497
3498                 this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
3499                 this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
3500                 this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
3501
3502                 return this;
3503
3504         }
3505
3506         clampLength( min, max ) {
3507
3508                 const length = this.length();
3509
3510                 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
3511
3512         }
3513
3514         floor() {
3515
3516                 this.x = Math.floor( this.x );
3517                 this.y = Math.floor( this.y );
3518                 this.z = Math.floor( this.z );
3519
3520                 return this;
3521
3522         }
3523
3524         ceil() {
3525
3526                 this.x = Math.ceil( this.x );
3527                 this.y = Math.ceil( this.y );
3528                 this.z = Math.ceil( this.z );
3529
3530                 return this;
3531
3532         }
3533
3534         round() {
3535
3536                 this.x = Math.round( this.x );
3537                 this.y = Math.round( this.y );
3538                 this.z = Math.round( this.z );
3539
3540                 return this;
3541
3542         }
3543
3544         roundToZero() {
3545
3546                 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
3547                 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
3548                 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
3549
3550                 return this;
3551
3552         }
3553
3554         negate() {
3555
3556                 this.x = - this.x;
3557                 this.y = - this.y;
3558                 this.z = - this.z;
3559
3560                 return this;
3561
3562         }
3563
3564         dot( v ) {
3565
3566                 return this.x * v.x + this.y * v.y + this.z * v.z;
3567
3568         }
3569
3570         // TODO lengthSquared?
3571
3572         lengthSq() {
3573
3574                 return this.x * this.x + this.y * this.y + this.z * this.z;
3575
3576         }
3577
3578         length() {
3579
3580                 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
3581
3582         }
3583
3584         manhattanLength() {
3585
3586                 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
3587
3588         }
3589
3590         normalize() {
3591
3592                 return this.divideScalar( this.length() || 1 );
3593
3594         }
3595
3596         setLength( length ) {
3597
3598                 return this.normalize().multiplyScalar( length );
3599
3600         }
3601
3602         lerp( v, alpha ) {
3603
3604                 this.x += ( v.x - this.x ) * alpha;
3605                 this.y += ( v.y - this.y ) * alpha;
3606                 this.z += ( v.z - this.z ) * alpha;
3607
3608                 return this;
3609
3610         }
3611
3612         lerpVectors( v1, v2, alpha ) {
3613
3614                 this.x = v1.x + ( v2.x - v1.x ) * alpha;
3615                 this.y = v1.y + ( v2.y - v1.y ) * alpha;
3616                 this.z = v1.z + ( v2.z - v1.z ) * alpha;
3617
3618                 return this;
3619
3620         }
3621
3622         cross( v, w ) {
3623
3624                 if ( w !== undefined ) {
3625
3626                         console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
3627                         return this.crossVectors( v, w );
3628
3629                 }
3630
3631                 return this.crossVectors( this, v );
3632
3633         }
3634
3635         crossVectors( a, b ) {
3636
3637                 const ax = a.x, ay = a.y, az = a.z;
3638                 const bx = b.x, by = b.y, bz = b.z;
3639
3640                 this.x = ay * bz - az * by;
3641                 this.y = az * bx - ax * bz;
3642                 this.z = ax * by - ay * bx;
3643
3644                 return this;
3645
3646         }
3647
3648         projectOnVector( v ) {
3649
3650                 const denominator = v.lengthSq();
3651
3652                 if ( denominator === 0 ) return this.set( 0, 0, 0 );
3653
3654                 const scalar = v.dot( this ) / denominator;
3655
3656                 return this.copy( v ).multiplyScalar( scalar );
3657
3658         }
3659
3660         projectOnPlane( planeNormal ) {
3661
3662                 _vector.copy( this ).projectOnVector( planeNormal );
3663
3664                 return this.sub( _vector );
3665
3666         }
3667
3668         reflect( normal ) {
3669
3670                 // reflect incident vector off plane orthogonal to normal
3671                 // normal is assumed to have unit length
3672
3673                 return this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
3674
3675         }
3676
3677         angleTo( v ) {
3678
3679                 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
3680
3681                 if ( denominator === 0 ) return Math.PI / 2;
3682
3683                 const theta = this.dot( v ) / denominator;
3684
3685                 // clamp, to handle numerical problems
3686
3687                 return Math.acos( MathUtils.clamp( theta, - 1, 1 ) );
3688
3689         }
3690
3691         distanceTo( v ) {
3692
3693                 return Math.sqrt( this.distanceToSquared( v ) );
3694
3695         }
3696
3697         distanceToSquared( v ) {
3698
3699                 const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
3700
3701                 return dx * dx + dy * dy + dz * dz;
3702
3703         }
3704
3705         manhattanDistanceTo( v ) {
3706
3707                 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
3708
3709         }
3710
3711         setFromSpherical( s ) {
3712
3713                 return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
3714
3715         }
3716
3717         setFromSphericalCoords( radius, phi, theta ) {
3718
3719                 const sinPhiRadius = Math.sin( phi ) * radius;
3720
3721                 this.x = sinPhiRadius * Math.sin( theta );
3722                 this.y = Math.cos( phi ) * radius;
3723                 this.z = sinPhiRadius * Math.cos( theta );
3724
3725                 return this;
3726
3727         }
3728
3729         setFromCylindrical( c ) {
3730
3731                 return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
3732
3733         }
3734
3735         setFromCylindricalCoords( radius, theta, y ) {
3736
3737                 this.x = radius * Math.sin( theta );
3738                 this.y = y;
3739                 this.z = radius * Math.cos( theta );
3740
3741                 return this;
3742
3743         }
3744
3745         setFromMatrixPosition( m ) {
3746
3747                 const e = m.elements;
3748
3749                 this.x = e[ 12 ];
3750                 this.y = e[ 13 ];
3751                 this.z = e[ 14 ];
3752
3753                 return this;
3754
3755         }
3756
3757         setFromMatrixScale( m ) {
3758
3759                 const sx = this.setFromMatrixColumn( m, 0 ).length();
3760                 const sy = this.setFromMatrixColumn( m, 1 ).length();
3761                 const sz = this.setFromMatrixColumn( m, 2 ).length();
3762
3763                 this.x = sx;
3764                 this.y = sy;
3765                 this.z = sz;
3766
3767                 return this;
3768
3769         }
3770
3771         setFromMatrixColumn( m, index ) {
3772
3773                 return this.fromArray( m.elements, index * 4 );
3774
3775         }
3776
3777         setFromMatrix3Column( m, index ) {
3778
3779                 return this.fromArray( m.elements, index * 3 );
3780
3781         }
3782
3783         equals( v ) {
3784
3785                 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
3786
3787         }
3788
3789         fromArray( array, offset = 0 ) {
3790
3791                 this.x = array[ offset ];
3792                 this.y = array[ offset + 1 ];
3793                 this.z = array[ offset + 2 ];
3794
3795                 return this;
3796
3797         }
3798
3799         toArray( array = [], offset = 0 ) {
3800
3801                 array[ offset ] = this.x;
3802                 array[ offset + 1 ] = this.y;
3803                 array[ offset + 2 ] = this.z;
3804
3805                 return array;
3806
3807         }
3808
3809         fromBufferAttribute( attribute, index, offset ) {
3810
3811                 if ( offset !== undefined ) {
3812
3813                         console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
3814
3815                 }
3816
3817                 this.x = attribute.getX( index );
3818                 this.y = attribute.getY( index );
3819                 this.z = attribute.getZ( index );
3820
3821                 return this;
3822
3823         }
3824
3825         random() {
3826
3827                 this.x = Math.random();
3828                 this.y = Math.random();
3829                 this.z = Math.random();
3830
3831                 return this;
3832
3833         }
3834
3835 }
3836
3837 const _vector = /*@__PURE__*/ new Vector3();
3838 const _quaternion = /*@__PURE__*/ new Quaternion();
3839
3840 class Box3 {
3841
3842         constructor( min, max ) {
3843
3844                 Object.defineProperty( this, 'isBox3', { value: true } );
3845
3846                 this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
3847                 this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
3848
3849         }
3850
3851         set( min, max ) {
3852
3853                 this.min.copy( min );
3854                 this.max.copy( max );
3855
3856                 return this;
3857
3858         }
3859
3860         setFromArray( array ) {
3861
3862                 let minX = + Infinity;
3863                 let minY = + Infinity;
3864                 let minZ = + Infinity;
3865
3866                 let maxX = - Infinity;
3867                 let maxY = - Infinity;
3868                 let maxZ = - Infinity;
3869
3870                 for ( let i = 0, l = array.length; i < l; i += 3 ) {
3871
3872                         const x = array[ i ];
3873                         const y = array[ i + 1 ];
3874                         const z = array[ i + 2 ];
3875
3876                         if ( x < minX ) minX = x;
3877                         if ( y < minY ) minY = y;
3878                         if ( z < minZ ) minZ = z;
3879
3880                         if ( x > maxX ) maxX = x;
3881                         if ( y > maxY ) maxY = y;
3882                         if ( z > maxZ ) maxZ = z;
3883
3884                 }
3885
3886                 this.min.set( minX, minY, minZ );
3887                 this.max.set( maxX, maxY, maxZ );
3888
3889                 return this;
3890
3891         }
3892
3893         setFromBufferAttribute( attribute ) {
3894
3895                 let minX = + Infinity;
3896                 let minY = + Infinity;
3897                 let minZ = + Infinity;
3898
3899                 let maxX = - Infinity;
3900                 let maxY = - Infinity;
3901                 let maxZ = - Infinity;
3902
3903                 for ( let i = 0, l = attribute.count; i < l; i ++ ) {
3904
3905                         const x = attribute.getX( i );
3906                         const y = attribute.getY( i );
3907                         const z = attribute.getZ( i );
3908
3909                         if ( x < minX ) minX = x;
3910                         if ( y < minY ) minY = y;
3911                         if ( z < minZ ) minZ = z;
3912
3913                         if ( x > maxX ) maxX = x;
3914                         if ( y > maxY ) maxY = y;
3915                         if ( z > maxZ ) maxZ = z;
3916
3917                 }
3918
3919                 this.min.set( minX, minY, minZ );
3920                 this.max.set( maxX, maxY, maxZ );
3921
3922                 return this;
3923
3924         }
3925
3926         setFromPoints( points ) {
3927
3928                 this.makeEmpty();
3929
3930                 for ( let i = 0, il = points.length; i < il; i ++ ) {
3931
3932                         this.expandByPoint( points[ i ] );
3933
3934                 }
3935
3936                 return this;
3937
3938         }
3939
3940         setFromCenterAndSize( center, size ) {
3941
3942                 const halfSize = _vector$1.copy( size ).multiplyScalar( 0.5 );
3943
3944                 this.min.copy( center ).sub( halfSize );
3945                 this.max.copy( center ).add( halfSize );
3946
3947                 return this;
3948
3949         }
3950
3951         setFromObject( object ) {
3952
3953                 this.makeEmpty();
3954
3955                 return this.expandByObject( object );
3956
3957         }
3958
3959         clone() {
3960
3961                 return new this.constructor().copy( this );
3962
3963         }
3964
3965         copy( box ) {
3966
3967                 this.min.copy( box.min );
3968                 this.max.copy( box.max );
3969
3970                 return this;
3971
3972         }
3973
3974         makeEmpty() {
3975
3976                 this.min.x = this.min.y = this.min.z = + Infinity;
3977                 this.max.x = this.max.y = this.max.z = - Infinity;
3978
3979                 return this;
3980
3981         }
3982
3983         isEmpty() {
3984
3985                 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
3986
3987                 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
3988
3989         }
3990
3991         getCenter( target ) {
3992
3993                 if ( target === undefined ) {
3994
3995                         console.warn( 'THREE.Box3: .getCenter() target is now required' );
3996                         target = new Vector3();
3997
3998                 }
3999
4000                 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4001
4002         }
4003
4004         getSize( target ) {
4005
4006                 if ( target === undefined ) {
4007
4008                         console.warn( 'THREE.Box3: .getSize() target is now required' );
4009                         target = new Vector3();
4010
4011                 }
4012
4013                 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
4014
4015         }
4016
4017         expandByPoint( point ) {
4018
4019                 this.min.min( point );
4020                 this.max.max( point );
4021
4022                 return this;
4023
4024         }
4025
4026         expandByVector( vector ) {
4027
4028                 this.min.sub( vector );
4029                 this.max.add( vector );
4030
4031                 return this;
4032
4033         }
4034
4035         expandByScalar( scalar ) {
4036
4037                 this.min.addScalar( - scalar );
4038                 this.max.addScalar( scalar );
4039
4040                 return this;
4041
4042         }
4043
4044         expandByObject( object ) {
4045
4046                 // Computes the world-axis-aligned bounding box of an object (including its children),
4047                 // accounting for both the object's, and children's, world transforms
4048
4049                 object.updateWorldMatrix( false, false );
4050
4051                 const geometry = object.geometry;
4052
4053                 if ( geometry !== undefined ) {
4054
4055                         if ( geometry.boundingBox === null ) {
4056
4057                                 geometry.computeBoundingBox();
4058
4059                         }
4060
4061                         _box.copy( geometry.boundingBox );
4062                         _box.applyMatrix4( object.matrixWorld );
4063
4064                         this.union( _box );
4065
4066                 }
4067
4068                 const children = object.children;
4069
4070                 for ( let i = 0, l = children.length; i < l; i ++ ) {
4071
4072                         this.expandByObject( children[ i ] );
4073
4074                 }
4075
4076                 return this;
4077
4078         }
4079
4080         containsPoint( point ) {
4081
4082                 return point.x < this.min.x || point.x > this.max.x ||
4083                         point.y < this.min.y || point.y > this.max.y ||
4084                         point.z < this.min.z || point.z > this.max.z ? false : true;
4085
4086         }
4087
4088         containsBox( box ) {
4089
4090                 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
4091                         this.min.y <= box.min.y && box.max.y <= this.max.y &&
4092                         this.min.z <= box.min.z && box.max.z <= this.max.z;
4093
4094         }
4095
4096         getParameter( point, target ) {
4097
4098                 // This can potentially have a divide by zero if the box
4099                 // has a size dimension of 0.
4100
4101                 if ( target === undefined ) {
4102
4103                         console.warn( 'THREE.Box3: .getParameter() target is now required' );
4104                         target = new Vector3();
4105
4106                 }
4107
4108                 return target.set(
4109                         ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
4110                         ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
4111                         ( point.z - this.min.z ) / ( this.max.z - this.min.z )
4112                 );
4113
4114         }
4115
4116         intersectsBox( box ) {
4117
4118                 // using 6 splitting planes to rule out intersections.
4119                 return box.max.x < this.min.x || box.min.x > this.max.x ||
4120                         box.max.y < this.min.y || box.min.y > this.max.y ||
4121                         box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
4122
4123         }
4124
4125         intersectsSphere( sphere ) {
4126
4127                 // Find the point on the AABB closest to the sphere center.
4128                 this.clampPoint( sphere.center, _vector$1 );
4129
4130                 // If that point is inside the sphere, the AABB and sphere intersect.
4131                 return _vector$1.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
4132
4133         }
4134
4135         intersectsPlane( plane ) {
4136
4137                 // We compute the minimum and maximum dot product values. If those values
4138                 // are on the same side (back or front) of the plane, then there is no intersection.
4139
4140                 let min, max;
4141
4142                 if ( plane.normal.x > 0 ) {
4143
4144                         min = plane.normal.x * this.min.x;
4145                         max = plane.normal.x * this.max.x;
4146
4147                 } else {
4148
4149                         min = plane.normal.x * this.max.x;
4150                         max = plane.normal.x * this.min.x;
4151
4152                 }
4153
4154                 if ( plane.normal.y > 0 ) {
4155
4156                         min += plane.normal.y * this.min.y;
4157                         max += plane.normal.y * this.max.y;
4158
4159                 } else {
4160
4161                         min += plane.normal.y * this.max.y;
4162                         max += plane.normal.y * this.min.y;
4163
4164                 }
4165
4166                 if ( plane.normal.z > 0 ) {
4167
4168                         min += plane.normal.z * this.min.z;
4169                         max += plane.normal.z * this.max.z;
4170
4171                 } else {
4172
4173                         min += plane.normal.z * this.max.z;
4174                         max += plane.normal.z * this.min.z;
4175
4176                 }
4177
4178                 return ( min <= - plane.constant && max >= - plane.constant );
4179
4180         }
4181
4182         intersectsTriangle( triangle ) {
4183
4184                 if ( this.isEmpty() ) {
4185
4186                         return false;
4187
4188                 }
4189
4190                 // compute box center and extents
4191                 this.getCenter( _center );
4192                 _extents.subVectors( this.max, _center );
4193
4194                 // translate triangle to aabb origin
4195                 _v0.subVectors( triangle.a, _center );
4196                 _v1.subVectors( triangle.b, _center );
4197                 _v2.subVectors( triangle.c, _center );
4198
4199                 // compute edge vectors for triangle
4200                 _f0.subVectors( _v1, _v0 );
4201                 _f1.subVectors( _v2, _v1 );
4202                 _f2.subVectors( _v0, _v2 );
4203
4204                 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
4205                 // 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
4206                 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
4207                 let axes = [
4208                         0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
4209                         _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
4210                         - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
4211                 ];
4212                 if ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {
4213
4214                         return false;
4215
4216                 }
4217
4218                 // test 3 face normals from the aabb
4219                 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
4220                 if ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {
4221
4222                         return false;
4223
4224                 }
4225
4226                 // finally testing the face normal of the triangle
4227                 // use already existing triangle edge vectors here
4228                 _triangleNormal.crossVectors( _f0, _f1 );
4229                 axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
4230
4231                 return satForAxes( axes, _v0, _v1, _v2, _extents );
4232
4233         }
4234
4235         clampPoint( point, target ) {
4236
4237                 if ( target === undefined ) {
4238
4239                         console.warn( 'THREE.Box3: .clampPoint() target is now required' );
4240                         target = new Vector3();
4241
4242                 }
4243
4244                 return target.copy( point ).clamp( this.min, this.max );
4245
4246         }
4247
4248         distanceToPoint( point ) {
4249
4250                 const clampedPoint = _vector$1.copy( point ).clamp( this.min, this.max );
4251
4252                 return clampedPoint.sub( point ).length();
4253
4254         }
4255
4256         getBoundingSphere( target ) {
4257
4258                 if ( target === undefined ) {
4259
4260                         console.error( 'THREE.Box3: .getBoundingSphere() target is now required' );
4261                         //target = new Sphere(); // removed to avoid cyclic dependency
4262
4263                 }
4264
4265                 this.getCenter( target.center );
4266
4267                 target.radius = this.getSize( _vector$1 ).length() * 0.5;
4268
4269                 return target;
4270
4271         }
4272
4273         intersect( box ) {
4274
4275                 this.min.max( box.min );
4276                 this.max.min( box.max );
4277
4278                 // 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.
4279                 if ( this.isEmpty() ) this.makeEmpty();
4280
4281                 return this;
4282
4283         }
4284
4285         union( box ) {
4286
4287                 this.min.min( box.min );
4288                 this.max.max( box.max );
4289
4290                 return this;
4291
4292         }
4293
4294         applyMatrix4( matrix ) {
4295
4296                 // transform of empty box is an empty box.
4297                 if ( this.isEmpty() ) return this;
4298
4299                 // NOTE: I am using a binary pattern to specify all 2^3 combinations below
4300                 _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
4301                 _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
4302                 _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
4303                 _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
4304                 _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
4305                 _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
4306                 _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
4307                 _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
4308
4309                 this.setFromPoints( _points );
4310
4311                 return this;
4312
4313         }
4314
4315         translate( offset ) {
4316
4317                 this.min.add( offset );
4318                 this.max.add( offset );
4319
4320                 return this;
4321
4322         }
4323
4324         equals( box ) {
4325
4326                 return box.min.equals( this.min ) && box.max.equals( this.max );
4327
4328         }
4329
4330 }
4331
4332 function satForAxes( axes, v0, v1, v2, extents ) {
4333
4334         for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
4335
4336                 _testAxis.fromArray( axes, i );
4337                 // project the aabb onto the seperating axis
4338                 const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
4339                 // project all 3 vertices of the triangle onto the seperating axis
4340                 const p0 = v0.dot( _testAxis );
4341                 const p1 = v1.dot( _testAxis );
4342                 const p2 = v2.dot( _testAxis );
4343                 // actual test, basically see if either of the most extreme of the triangle points intersects r
4344                 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
4345
4346                         // points of the projected triangle are outside the projected half-length of the aabb
4347                         // the axis is seperating and we can exit
4348                         return false;
4349
4350                 }
4351
4352         }
4353
4354         return true;
4355
4356 }
4357
4358 const _points = [
4359         /*@__PURE__*/ new Vector3(),
4360         /*@__PURE__*/ new Vector3(),
4361         /*@__PURE__*/ new Vector3(),
4362         /*@__PURE__*/ new Vector3(),
4363         /*@__PURE__*/ new Vector3(),
4364         /*@__PURE__*/ new Vector3(),
4365         /*@__PURE__*/ new Vector3(),
4366         /*@__PURE__*/ new Vector3()
4367 ];
4368
4369 const _vector$1 = /*@__PURE__*/ new Vector3();
4370
4371 const _box = /*@__PURE__*/ new Box3();
4372
4373 // triangle centered vertices
4374
4375 const _v0 = /*@__PURE__*/ new Vector3();
4376 const _v1 = /*@__PURE__*/ new Vector3();
4377 const _v2 = /*@__PURE__*/ new Vector3();
4378
4379 // triangle edge vectors
4380
4381 const _f0 = /*@__PURE__*/ new Vector3();
4382 const _f1 = /*@__PURE__*/ new Vector3();
4383 const _f2 = /*@__PURE__*/ new Vector3();
4384
4385 const _center = /*@__PURE__*/ new Vector3();
4386 const _extents = /*@__PURE__*/ new Vector3();
4387 const _triangleNormal = /*@__PURE__*/ new Vector3();
4388 const _testAxis = /*@__PURE__*/ new Vector3();
4389
4390 const _box$1 = /*@__PURE__*/ new Box3();
4391
4392 class Sphere {
4393
4394         constructor( center, radius ) {
4395
4396                 this.center = ( center !== undefined ) ? center : new Vector3();
4397                 this.radius = ( radius !== undefined ) ? radius : - 1;
4398
4399         }
4400
4401         set( center, radius ) {
4402
4403                 this.center.copy( center );
4404                 this.radius = radius;
4405
4406                 return this;
4407
4408         }
4409
4410         setFromPoints( points, optionalCenter ) {
4411
4412                 const center = this.center;
4413
4414                 if ( optionalCenter !== undefined ) {
4415
4416                         center.copy( optionalCenter );
4417
4418                 } else {
4419
4420                         _box$1.setFromPoints( points ).getCenter( center );
4421
4422                 }
4423
4424                 let maxRadiusSq = 0;
4425
4426                 for ( let i = 0, il = points.length; i < il; i ++ ) {
4427
4428                         maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
4429
4430                 }
4431
4432                 this.radius = Math.sqrt( maxRadiusSq );
4433
4434                 return this;
4435
4436         }
4437
4438         clone() {
4439
4440                 return new this.constructor().copy( this );
4441
4442         }
4443
4444         copy( sphere ) {
4445
4446                 this.center.copy( sphere.center );
4447                 this.radius = sphere.radius;
4448
4449                 return this;
4450
4451         }
4452
4453         isEmpty() {
4454
4455                 return ( this.radius < 0 );
4456
4457         }
4458
4459         makeEmpty() {
4460
4461                 this.center.set( 0, 0, 0 );
4462                 this.radius = - 1;
4463
4464                 return this;
4465
4466         }
4467
4468         containsPoint( point ) {
4469
4470                 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
4471
4472         }
4473
4474         distanceToPoint( point ) {
4475
4476                 return ( point.distanceTo( this.center ) - this.radius );
4477
4478         }
4479
4480         intersectsSphere( sphere ) {
4481
4482                 const radiusSum = this.radius + sphere.radius;
4483
4484                 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
4485
4486         }
4487
4488         intersectsBox( box ) {
4489
4490                 return box.intersectsSphere( this );
4491
4492         }
4493
4494         intersectsPlane( plane ) {
4495
4496                 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
4497
4498         }
4499
4500         clampPoint( point, target ) {
4501
4502                 const deltaLengthSq = this.center.distanceToSquared( point );
4503
4504                 if ( target === undefined ) {
4505
4506                         console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
4507                         target = new Vector3();
4508
4509                 }
4510
4511                 target.copy( point );
4512
4513                 if ( deltaLengthSq > ( this.radius * this.radius ) ) {
4514
4515                         target.sub( this.center ).normalize();
4516                         target.multiplyScalar( this.radius ).add( this.center );
4517
4518                 }
4519
4520                 return target;
4521
4522         }
4523
4524         getBoundingBox( target ) {
4525
4526                 if ( target === undefined ) {
4527
4528                         console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
4529                         target = new Box3();
4530
4531                 }
4532
4533                 if ( this.isEmpty() ) {
4534
4535                         // Empty sphere produces empty bounding box
4536                         target.makeEmpty();
4537                         return target;
4538
4539                 }
4540
4541                 target.set( this.center, this.center );
4542                 target.expandByScalar( this.radius );
4543
4544                 return target;
4545
4546         }
4547
4548         applyMatrix4( matrix ) {
4549
4550                 this.center.applyMatrix4( matrix );
4551                 this.radius = this.radius * matrix.getMaxScaleOnAxis();
4552
4553                 return this;
4554
4555         }
4556
4557         translate( offset ) {
4558
4559                 this.center.add( offset );
4560
4561                 return this;
4562
4563         }
4564
4565         equals( sphere ) {
4566
4567                 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
4568
4569         }
4570
4571 }
4572
4573 const _vector$2 = /*@__PURE__*/ new Vector3();
4574 const _segCenter = /*@__PURE__*/ new Vector3();
4575 const _segDir = /*@__PURE__*/ new Vector3();
4576 const _diff = /*@__PURE__*/ new Vector3();
4577
4578 const _edge1 = /*@__PURE__*/ new Vector3();
4579 const _edge2 = /*@__PURE__*/ new Vector3();
4580 const _normal = /*@__PURE__*/ new Vector3();
4581
4582 class Ray {
4583
4584         constructor( origin, direction ) {
4585
4586                 this.origin = ( origin !== undefined ) ? origin : new Vector3();
4587                 this.direction = ( direction !== undefined ) ? direction : new Vector3( 0, 0, - 1 );
4588
4589         }
4590
4591         set( origin, direction ) {
4592
4593                 this.origin.copy( origin );
4594                 this.direction.copy( direction );
4595
4596                 return this;
4597
4598         }
4599
4600         clone() {
4601
4602                 return new this.constructor().copy( this );
4603
4604         }
4605
4606         copy( ray ) {
4607
4608                 this.origin.copy( ray.origin );
4609                 this.direction.copy( ray.direction );
4610
4611                 return this;
4612
4613         }
4614
4615         at( t, target ) {
4616
4617                 if ( target === undefined ) {
4618
4619                         console.warn( 'THREE.Ray: .at() target is now required' );
4620                         target = new Vector3();
4621
4622                 }
4623
4624                 return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
4625
4626         }
4627
4628         lookAt( v ) {
4629
4630                 this.direction.copy( v ).sub( this.origin ).normalize();
4631
4632                 return this;
4633
4634         }
4635
4636         recast( t ) {
4637
4638                 this.origin.copy( this.at( t, _vector$2 ) );
4639
4640                 return this;
4641
4642         }
4643
4644         closestPointToPoint( point, target ) {
4645
4646                 if ( target === undefined ) {
4647
4648                         console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
4649                         target = new Vector3();
4650
4651                 }
4652
4653                 target.subVectors( point, this.origin );
4654
4655                 const directionDistance = target.dot( this.direction );
4656
4657                 if ( directionDistance < 0 ) {
4658
4659                         return target.copy( this.origin );
4660
4661                 }
4662
4663                 return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
4664
4665         }
4666
4667         distanceToPoint( point ) {
4668
4669                 return Math.sqrt( this.distanceSqToPoint( point ) );
4670
4671         }
4672
4673         distanceSqToPoint( point ) {
4674
4675                 const directionDistance = _vector$2.subVectors( point, this.origin ).dot( this.direction );
4676
4677                 // point behind the ray
4678
4679                 if ( directionDistance < 0 ) {
4680
4681                         return this.origin.distanceToSquared( point );
4682
4683                 }
4684
4685                 _vector$2.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
4686
4687                 return _vector$2.distanceToSquared( point );
4688
4689         }
4690
4691         distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
4692
4693                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
4694                 // It returns the min distance between the ray and the segment
4695                 // defined by v0 and v1
4696                 // It can also set two optional targets :
4697                 // - The closest point on the ray
4698                 // - The closest point on the segment
4699
4700                 _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
4701                 _segDir.copy( v1 ).sub( v0 ).normalize();
4702                 _diff.copy( this.origin ).sub( _segCenter );
4703
4704                 const segExtent = v0.distanceTo( v1 ) * 0.5;
4705                 const a01 = - this.direction.dot( _segDir );
4706                 const b0 = _diff.dot( this.direction );
4707                 const b1 = - _diff.dot( _segDir );
4708                 const c = _diff.lengthSq();
4709                 const det = Math.abs( 1 - a01 * a01 );
4710                 let s0, s1, sqrDist, extDet;
4711
4712                 if ( det > 0 ) {
4713
4714                         // The ray and segment are not parallel.
4715
4716                         s0 = a01 * b1 - b0;
4717                         s1 = a01 * b0 - b1;
4718                         extDet = segExtent * det;
4719
4720                         if ( s0 >= 0 ) {
4721
4722                                 if ( s1 >= - extDet ) {
4723
4724                                         if ( s1 <= extDet ) {
4725
4726                                                 // region 0
4727                                                 // Minimum at interior points of ray and segment.
4728
4729                                                 const invDet = 1 / det;
4730                                                 s0 *= invDet;
4731                                                 s1 *= invDet;
4732                                                 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
4733
4734                                         } else {
4735
4736                                                 // region 1
4737
4738                                                 s1 = segExtent;
4739                                                 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
4740                                                 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4741
4742                                         }
4743
4744                                 } else {
4745
4746                                         // region 5
4747
4748                                         s1 = - segExtent;
4749                                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
4750                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4751
4752                                 }
4753
4754                         } else {
4755
4756                                 if ( s1 <= - extDet ) {
4757
4758                                         // region 4
4759
4760                                         s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
4761                                         s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
4762                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4763
4764                                 } else if ( s1 <= extDet ) {
4765
4766                                         // region 3
4767
4768                                         s0 = 0;
4769                                         s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
4770                                         sqrDist = s1 * ( s1 + 2 * b1 ) + c;
4771
4772                                 } else {
4773
4774                                         // region 2
4775
4776                                         s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
4777                                         s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
4778                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4779
4780                                 }
4781
4782                         }
4783
4784                 } else {
4785
4786                         // Ray and segment are parallel.
4787
4788                         s1 = ( a01 > 0 ) ? - segExtent : segExtent;
4789                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
4790                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
4791
4792                 }
4793
4794                 if ( optionalPointOnRay ) {
4795
4796                         optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
4797
4798                 }
4799
4800                 if ( optionalPointOnSegment ) {
4801
4802                         optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );
4803
4804                 }
4805
4806                 return sqrDist;
4807
4808         }
4809
4810         intersectSphere( sphere, target ) {
4811
4812                 _vector$2.subVectors( sphere.center, this.origin );
4813                 const tca = _vector$2.dot( this.direction );
4814                 const d2 = _vector$2.dot( _vector$2 ) - tca * tca;
4815                 const radius2 = sphere.radius * sphere.radius;
4816
4817                 if ( d2 > radius2 ) return null;
4818
4819                 const thc = Math.sqrt( radius2 - d2 );
4820
4821                 // t0 = first intersect point - entrance on front of sphere
4822                 const t0 = tca - thc;
4823
4824                 // t1 = second intersect point - exit point on back of sphere
4825                 const t1 = tca + thc;
4826
4827                 // test to see if both t0 and t1 are behind the ray - if so, return null
4828                 if ( t0 < 0 && t1 < 0 ) return null;
4829
4830                 // test to see if t0 is behind the ray:
4831                 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
4832                 // in order to always return an intersect point that is in front of the ray.
4833                 if ( t0 < 0 ) return this.at( t1, target );
4834
4835                 // else t0 is in front of the ray, so return the first collision point scaled by t0
4836                 return this.at( t0, target );
4837
4838         }
4839
4840         intersectsSphere( sphere ) {
4841
4842                 return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
4843
4844         }
4845
4846         distanceToPlane( plane ) {
4847
4848                 const denominator = plane.normal.dot( this.direction );
4849
4850                 if ( denominator === 0 ) {
4851
4852                         // line is coplanar, return origin
4853                         if ( plane.distanceToPoint( this.origin ) === 0 ) {
4854
4855                                 return 0;
4856
4857                         }
4858
4859                         // Null is preferable to undefined since undefined means.... it is undefined
4860
4861                         return null;
4862
4863                 }
4864
4865                 const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
4866
4867                 // Return if the ray never intersects the plane
4868
4869                 return t >= 0 ? t : null;
4870
4871         }
4872
4873         intersectPlane( plane, target ) {
4874
4875                 const t = this.distanceToPlane( plane );
4876
4877                 if ( t === null ) {
4878
4879                         return null;
4880
4881                 }
4882
4883                 return this.at( t, target );
4884
4885         }
4886
4887         intersectsPlane( plane ) {
4888
4889                 // check if the ray lies on the plane first
4890
4891                 const distToPoint = plane.distanceToPoint( this.origin );
4892
4893                 if ( distToPoint === 0 ) {
4894
4895                         return true;
4896
4897                 }
4898
4899                 const denominator = plane.normal.dot( this.direction );
4900
4901                 if ( denominator * distToPoint < 0 ) {
4902
4903                         return true;
4904
4905                 }
4906
4907                 // ray origin is behind the plane (and is pointing behind it)
4908
4909                 return false;
4910
4911         }
4912
4913         intersectBox( box, target ) {
4914
4915                 let tmin, tmax, tymin, tymax, tzmin, tzmax;
4916
4917                 const invdirx = 1 / this.direction.x,
4918                         invdiry = 1 / this.direction.y,
4919                         invdirz = 1 / this.direction.z;
4920
4921                 const origin = this.origin;
4922
4923                 if ( invdirx >= 0 ) {
4924
4925                         tmin = ( box.min.x - origin.x ) * invdirx;
4926                         tmax = ( box.max.x - origin.x ) * invdirx;
4927
4928                 } else {
4929
4930                         tmin = ( box.max.x - origin.x ) * invdirx;
4931                         tmax = ( box.min.x - origin.x ) * invdirx;
4932
4933                 }
4934
4935                 if ( invdiry >= 0 ) {
4936
4937                         tymin = ( box.min.y - origin.y ) * invdiry;
4938                         tymax = ( box.max.y - origin.y ) * invdiry;
4939
4940                 } else {
4941
4942                         tymin = ( box.max.y - origin.y ) * invdiry;
4943                         tymax = ( box.min.y - origin.y ) * invdiry;
4944
4945                 }
4946
4947                 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
4948
4949                 // These lines also handle the case where tmin or tmax is NaN
4950                 // (result of 0 * Infinity). x !== x returns true if x is NaN
4951
4952                 if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
4953
4954                 if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
4955
4956                 if ( invdirz >= 0 ) {
4957
4958                         tzmin = ( box.min.z - origin.z ) * invdirz;
4959                         tzmax = ( box.max.z - origin.z ) * invdirz;
4960
4961                 } else {
4962
4963                         tzmin = ( box.max.z - origin.z ) * invdirz;
4964                         tzmax = ( box.min.z - origin.z ) * invdirz;
4965
4966                 }
4967
4968                 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
4969
4970                 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
4971
4972                 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
4973
4974                 //return point closest to the ray (positive side)
4975
4976                 if ( tmax < 0 ) return null;
4977
4978                 return this.at( tmin >= 0 ? tmin : tmax, target );
4979
4980         }
4981
4982         intersectsBox( box ) {
4983
4984                 return this.intersectBox( box, _vector$2 ) !== null;
4985
4986         }
4987
4988         intersectTriangle( a, b, c, backfaceCulling, target ) {
4989
4990                 // Compute the offset origin, edges, and normal.
4991
4992                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
4993
4994                 _edge1.subVectors( b, a );
4995                 _edge2.subVectors( c, a );
4996                 _normal.crossVectors( _edge1, _edge2 );
4997
4998                 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
4999                 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
5000                 //   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
5001                 //   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
5002                 //   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
5003                 let DdN = this.direction.dot( _normal );
5004                 let sign;
5005
5006                 if ( DdN > 0 ) {
5007
5008                         if ( backfaceCulling ) return null;
5009                         sign = 1;
5010
5011                 } else if ( DdN < 0 ) {
5012
5013                         sign = - 1;
5014                         DdN = - DdN;
5015
5016                 } else {
5017
5018                         return null;
5019
5020                 }
5021
5022                 _diff.subVectors( this.origin, a );
5023                 const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
5024
5025                 // b1 < 0, no intersection
5026                 if ( DdQxE2 < 0 ) {
5027
5028                         return null;
5029
5030                 }
5031
5032                 const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
5033
5034                 // b2 < 0, no intersection
5035                 if ( DdE1xQ < 0 ) {
5036
5037                         return null;
5038
5039                 }
5040
5041                 // b1+b2 > 1, no intersection
5042                 if ( DdQxE2 + DdE1xQ > DdN ) {
5043
5044                         return null;
5045
5046                 }
5047
5048                 // Line intersects triangle, check if ray does.
5049                 const QdN = - sign * _diff.dot( _normal );
5050
5051                 // t < 0, no intersection
5052                 if ( QdN < 0 ) {
5053
5054                         return null;
5055
5056                 }
5057
5058                 // Ray intersects triangle.
5059                 return this.at( QdN / DdN, target );
5060
5061         }
5062
5063         applyMatrix4( matrix4 ) {
5064
5065                 this.origin.applyMatrix4( matrix4 );
5066                 this.direction.transformDirection( matrix4 );
5067
5068                 return this;
5069
5070         }
5071
5072         equals( ray ) {
5073
5074                 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
5075
5076         }
5077
5078 }
5079
5080 class Matrix4 {
5081
5082         constructor() {
5083
5084                 Object.defineProperty( this, 'isMatrix4', { value: true } );
5085
5086                 this.elements = [
5087
5088                         1, 0, 0, 0,
5089                         0, 1, 0, 0,
5090                         0, 0, 1, 0,
5091                         0, 0, 0, 1
5092
5093                 ];
5094
5095                 if ( arguments.length > 0 ) {
5096
5097                         console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
5098
5099                 }
5100
5101         }
5102
5103         set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
5104
5105                 const te = this.elements;
5106
5107                 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
5108                 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
5109                 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
5110                 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
5111
5112                 return this;
5113
5114         }
5115
5116         identity() {
5117
5118                 this.set(
5119
5120                         1, 0, 0, 0,
5121                         0, 1, 0, 0,
5122                         0, 0, 1, 0,
5123                         0, 0, 0, 1
5124
5125                 );
5126
5127                 return this;
5128
5129         }
5130
5131         clone() {
5132
5133                 return new Matrix4().fromArray( this.elements );
5134
5135         }
5136
5137         copy( m ) {
5138
5139                 const te = this.elements;
5140                 const me = m.elements;
5141
5142                 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
5143                 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
5144                 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
5145                 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
5146
5147                 return this;
5148
5149         }
5150
5151         copyPosition( m ) {
5152
5153                 const te = this.elements, me = m.elements;
5154
5155                 te[ 12 ] = me[ 12 ];
5156                 te[ 13 ] = me[ 13 ];
5157                 te[ 14 ] = me[ 14 ];
5158
5159                 return this;
5160
5161         }
5162
5163         extractBasis( xAxis, yAxis, zAxis ) {
5164
5165                 xAxis.setFromMatrixColumn( this, 0 );
5166                 yAxis.setFromMatrixColumn( this, 1 );
5167                 zAxis.setFromMatrixColumn( this, 2 );
5168
5169                 return this;
5170
5171         }
5172
5173         makeBasis( xAxis, yAxis, zAxis ) {
5174
5175                 this.set(
5176                         xAxis.x, yAxis.x, zAxis.x, 0,
5177                         xAxis.y, yAxis.y, zAxis.y, 0,
5178                         xAxis.z, yAxis.z, zAxis.z, 0,
5179                         0, 0, 0, 1
5180                 );
5181
5182                 return this;
5183
5184         }
5185
5186         extractRotation( m ) {
5187
5188                 // this method does not support reflection matrices
5189
5190                 const te = this.elements;
5191                 const me = m.elements;
5192
5193                 const scaleX = 1 / _v1$1.setFromMatrixColumn( m, 0 ).length();
5194                 const scaleY = 1 / _v1$1.setFromMatrixColumn( m, 1 ).length();
5195                 const scaleZ = 1 / _v1$1.setFromMatrixColumn( m, 2 ).length();
5196
5197                 te[ 0 ] = me[ 0 ] * scaleX;
5198                 te[ 1 ] = me[ 1 ] * scaleX;
5199                 te[ 2 ] = me[ 2 ] * scaleX;
5200                 te[ 3 ] = 0;
5201
5202                 te[ 4 ] = me[ 4 ] * scaleY;
5203                 te[ 5 ] = me[ 5 ] * scaleY;
5204                 te[ 6 ] = me[ 6 ] * scaleY;
5205                 te[ 7 ] = 0;
5206
5207                 te[ 8 ] = me[ 8 ] * scaleZ;
5208                 te[ 9 ] = me[ 9 ] * scaleZ;
5209                 te[ 10 ] = me[ 10 ] * scaleZ;
5210                 te[ 11 ] = 0;
5211
5212                 te[ 12 ] = 0;
5213                 te[ 13 ] = 0;
5214                 te[ 14 ] = 0;
5215                 te[ 15 ] = 1;
5216
5217                 return this;
5218
5219         }
5220
5221         makeRotationFromEuler( euler ) {
5222
5223                 if ( ! ( euler && euler.isEuler ) ) {
5224
5225                         console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
5226
5227                 }
5228
5229                 const te = this.elements;
5230
5231                 const x = euler.x, y = euler.y, z = euler.z;
5232                 const a = Math.cos( x ), b = Math.sin( x );
5233                 const c = Math.cos( y ), d = Math.sin( y );
5234                 const e = Math.cos( z ), f = Math.sin( z );
5235
5236                 if ( euler.order === 'XYZ' ) {
5237
5238                         const ae = a * e, af = a * f, be = b * e, bf = b * f;
5239
5240                         te[ 0 ] = c * e;
5241                         te[ 4 ] = - c * f;
5242                         te[ 8 ] = d;
5243
5244                         te[ 1 ] = af + be * d;
5245                         te[ 5 ] = ae - bf * d;
5246                         te[ 9 ] = - b * c;
5247
5248                         te[ 2 ] = bf - ae * d;
5249                         te[ 6 ] = be + af * d;
5250                         te[ 10 ] = a * c;
5251
5252                 } else if ( euler.order === 'YXZ' ) {
5253
5254                         const ce = c * e, cf = c * f, de = d * e, df = d * f;
5255
5256                         te[ 0 ] = ce + df * b;
5257                         te[ 4 ] = de * b - cf;
5258                         te[ 8 ] = a * d;
5259
5260                         te[ 1 ] = a * f;
5261                         te[ 5 ] = a * e;
5262                         te[ 9 ] = - b;
5263
5264                         te[ 2 ] = cf * b - de;
5265                         te[ 6 ] = df + ce * b;
5266                         te[ 10 ] = a * c;
5267
5268                 } else if ( euler.order === 'ZXY' ) {
5269
5270                         const ce = c * e, cf = c * f, de = d * e, df = d * f;
5271
5272                         te[ 0 ] = ce - df * b;
5273                         te[ 4 ] = - a * f;
5274                         te[ 8 ] = de + cf * b;
5275
5276                         te[ 1 ] = cf + de * b;
5277                         te[ 5 ] = a * e;
5278                         te[ 9 ] = df - ce * b;
5279
5280                         te[ 2 ] = - a * d;
5281                         te[ 6 ] = b;
5282                         te[ 10 ] = a * c;
5283
5284                 } else if ( euler.order === 'ZYX' ) {
5285
5286                         const ae = a * e, af = a * f, be = b * e, bf = b * f;
5287
5288                         te[ 0 ] = c * e;
5289                         te[ 4 ] = be * d - af;
5290                         te[ 8 ] = ae * d + bf;
5291
5292                         te[ 1 ] = c * f;
5293                         te[ 5 ] = bf * d + ae;
5294                         te[ 9 ] = af * d - be;
5295
5296                         te[ 2 ] = - d;
5297                         te[ 6 ] = b * c;
5298                         te[ 10 ] = a * c;
5299
5300                 } else if ( euler.order === 'YZX' ) {
5301
5302                         const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
5303
5304                         te[ 0 ] = c * e;
5305                         te[ 4 ] = bd - ac * f;
5306                         te[ 8 ] = bc * f + ad;
5307
5308                         te[ 1 ] = f;
5309                         te[ 5 ] = a * e;
5310                         te[ 9 ] = - b * e;
5311
5312                         te[ 2 ] = - d * e;
5313                         te[ 6 ] = ad * f + bc;
5314                         te[ 10 ] = ac - bd * f;
5315
5316                 } else if ( euler.order === 'XZY' ) {
5317
5318                         const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
5319
5320                         te[ 0 ] = c * e;
5321                         te[ 4 ] = - f;
5322                         te[ 8 ] = d * e;
5323
5324                         te[ 1 ] = ac * f + bd;
5325                         te[ 5 ] = a * e;
5326                         te[ 9 ] = ad * f - bc;
5327
5328                         te[ 2 ] = bc * f - ad;
5329                         te[ 6 ] = b * e;
5330                         te[ 10 ] = bd * f + ac;
5331
5332                 }
5333
5334                 // bottom row
5335                 te[ 3 ] = 0;
5336                 te[ 7 ] = 0;
5337                 te[ 11 ] = 0;
5338
5339                 // last column
5340                 te[ 12 ] = 0;
5341                 te[ 13 ] = 0;
5342                 te[ 14 ] = 0;
5343                 te[ 15 ] = 1;
5344
5345                 return this;
5346
5347         }
5348
5349         makeRotationFromQuaternion( q ) {
5350
5351                 return this.compose( _zero, q, _one );
5352
5353         }
5354
5355         lookAt( eye, target, up ) {
5356
5357                 const te = this.elements;
5358
5359                 _z.subVectors( eye, target );
5360
5361                 if ( _z.lengthSq() === 0 ) {
5362
5363                         // eye and target are in the same position
5364
5365                         _z.z = 1;
5366
5367                 }
5368
5369                 _z.normalize();
5370                 _x.crossVectors( up, _z );
5371
5372                 if ( _x.lengthSq() === 0 ) {
5373
5374                         // up and z are parallel
5375
5376                         if ( Math.abs( up.z ) === 1 ) {
5377
5378                                 _z.x += 0.0001;
5379
5380                         } else {
5381
5382                                 _z.z += 0.0001;
5383
5384                         }
5385
5386                         _z.normalize();
5387                         _x.crossVectors( up, _z );
5388
5389                 }
5390
5391                 _x.normalize();
5392                 _y.crossVectors( _z, _x );
5393
5394                 te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
5395                 te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
5396                 te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
5397
5398                 return this;
5399
5400         }
5401
5402         multiply( m, n ) {
5403
5404                 if ( n !== undefined ) {
5405
5406                         console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
5407                         return this.multiplyMatrices( m, n );
5408
5409                 }
5410
5411                 return this.multiplyMatrices( this, m );
5412
5413         }
5414
5415         premultiply( m ) {
5416
5417                 return this.multiplyMatrices( m, this );
5418
5419         }
5420
5421         multiplyMatrices( a, b ) {
5422
5423                 const ae = a.elements;
5424                 const be = b.elements;
5425                 const te = this.elements;
5426
5427                 const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
5428                 const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
5429                 const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
5430                 const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
5431
5432                 const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
5433                 const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
5434                 const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
5435                 const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
5436
5437                 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
5438                 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
5439                 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
5440                 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
5441
5442                 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
5443                 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
5444                 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
5445                 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
5446
5447                 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
5448                 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
5449                 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
5450                 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
5451
5452                 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
5453                 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
5454                 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
5455                 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
5456
5457                 return this;
5458
5459         }
5460
5461         multiplyScalar( s ) {
5462
5463                 const te = this.elements;
5464
5465                 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
5466                 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
5467                 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
5468                 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
5469
5470                 return this;
5471
5472         }
5473
5474         determinant() {
5475
5476                 const te = this.elements;
5477
5478                 const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
5479                 const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
5480                 const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
5481                 const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
5482
5483                 //TODO: make this more efficient
5484                 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
5485
5486                 return (
5487                         n41 * (
5488                                 + n14 * n23 * n32
5489                                  - n13 * n24 * n32
5490                                  - n14 * n22 * n33
5491                                  + n12 * n24 * n33
5492                                  + n13 * n22 * n34
5493                                  - n12 * n23 * n34
5494                         ) +
5495                         n42 * (
5496                                 + n11 * n23 * n34
5497                                  - n11 * n24 * n33
5498                                  + n14 * n21 * n33
5499                                  - n13 * n21 * n34
5500                                  + n13 * n24 * n31
5501                                  - n14 * n23 * n31
5502                         ) +
5503                         n43 * (
5504                                 + n11 * n24 * n32
5505                                  - n11 * n22 * n34
5506                                  - n14 * n21 * n32
5507                                  + n12 * n21 * n34
5508                                  + n14 * n22 * n31
5509                                  - n12 * n24 * n31
5510                         ) +
5511                         n44 * (
5512                                 - n13 * n22 * n31
5513                                  - n11 * n23 * n32
5514                                  + n11 * n22 * n33
5515                                  + n13 * n21 * n32
5516                                  - n12 * n21 * n33
5517                                  + n12 * n23 * n31
5518                         )
5519
5520                 );
5521
5522         }
5523
5524         transpose() {
5525
5526                 const te = this.elements;
5527                 let tmp;
5528
5529                 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
5530                 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
5531                 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
5532
5533                 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
5534                 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
5535                 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
5536
5537                 return this;
5538
5539         }
5540
5541         setPosition( x, y, z ) {
5542
5543                 const te = this.elements;
5544
5545                 if ( x.isVector3 ) {
5546
5547                         te[ 12 ] = x.x;
5548                         te[ 13 ] = x.y;
5549                         te[ 14 ] = x.z;
5550
5551                 } else {
5552
5553                         te[ 12 ] = x;
5554                         te[ 13 ] = y;
5555                         te[ 14 ] = z;
5556
5557                 }
5558
5559                 return this;
5560
5561         }
5562
5563         invert() {
5564
5565                 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
5566                 const te = this.elements,
5567
5568                         n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
5569                         n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
5570                         n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
5571                         n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
5572
5573                         t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
5574                         t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
5575                         t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
5576                         t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
5577
5578                 const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
5579
5580                 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
5581
5582                 const detInv = 1 / det;
5583
5584                 te[ 0 ] = t11 * detInv;
5585                 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
5586                 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
5587                 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
5588
5589                 te[ 4 ] = t12 * detInv;
5590                 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
5591                 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
5592                 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
5593
5594                 te[ 8 ] = t13 * detInv;
5595                 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
5596                 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
5597                 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
5598
5599                 te[ 12 ] = t14 * detInv;
5600                 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
5601                 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
5602                 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
5603
5604                 return this;
5605
5606         }
5607
5608         scale( v ) {
5609
5610                 const te = this.elements;
5611                 const x = v.x, y = v.y, z = v.z;
5612
5613                 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
5614                 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
5615                 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
5616                 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
5617
5618                 return this;
5619
5620         }
5621
5622         getMaxScaleOnAxis() {
5623
5624                 const te = this.elements;
5625
5626                 const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
5627                 const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
5628                 const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
5629
5630                 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
5631
5632         }
5633
5634         makeTranslation( x, y, z ) {
5635
5636                 this.set(
5637
5638                         1, 0, 0, x,
5639                         0, 1, 0, y,
5640                         0, 0, 1, z,
5641                         0, 0, 0, 1
5642
5643                 );
5644
5645                 return this;
5646
5647         }
5648
5649         makeRotationX( theta ) {
5650
5651                 const c = Math.cos( theta ), s = Math.sin( theta );
5652
5653                 this.set(
5654
5655                         1, 0, 0, 0,
5656                         0, c, - s, 0,
5657                         0, s, c, 0,
5658                         0, 0, 0, 1
5659
5660                 );
5661
5662                 return this;
5663
5664         }
5665
5666         makeRotationY( theta ) {
5667
5668                 const c = Math.cos( theta ), s = Math.sin( theta );
5669
5670                 this.set(
5671
5672                          c, 0, s, 0,
5673                          0, 1, 0, 0,
5674                         - s, 0, c, 0,
5675                          0, 0, 0, 1
5676
5677                 );
5678
5679                 return this;
5680
5681         }
5682
5683         makeRotationZ( theta ) {
5684
5685                 const c = Math.cos( theta ), s = Math.sin( theta );
5686
5687                 this.set(
5688
5689                         c, - s, 0, 0,
5690                         s, c, 0, 0,
5691                         0, 0, 1, 0,
5692                         0, 0, 0, 1
5693
5694                 );
5695
5696                 return this;
5697
5698         }
5699
5700         makeRotationAxis( axis, angle ) {
5701
5702                 // Based on http://www.gamedev.net/reference/articles/article1199.asp
5703
5704                 const c = Math.cos( angle );
5705                 const s = Math.sin( angle );
5706                 const t = 1 - c;
5707                 const x = axis.x, y = axis.y, z = axis.z;
5708                 const tx = t * x, ty = t * y;
5709
5710                 this.set(
5711
5712                         tx * x + c, tx * y - s * z, tx * z + s * y, 0,
5713                         tx * y + s * z, ty * y + c, ty * z - s * x, 0,
5714                         tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
5715                         0, 0, 0, 1
5716
5717                 );
5718
5719                 return this;
5720
5721         }
5722
5723         makeScale( x, y, z ) {
5724
5725                 this.set(
5726
5727                         x, 0, 0, 0,
5728                         0, y, 0, 0,
5729                         0, 0, z, 0,
5730                         0, 0, 0, 1
5731
5732                 );
5733
5734                 return this;
5735
5736         }
5737
5738         makeShear( x, y, z ) {
5739
5740                 this.set(
5741
5742                         1, y, z, 0,
5743                         x, 1, z, 0,
5744                         x, y, 1, 0,
5745                         0, 0, 0, 1
5746
5747                 );
5748
5749                 return this;
5750
5751         }
5752
5753         compose( position, quaternion, scale ) {
5754
5755                 const te = this.elements;
5756
5757                 const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
5758                 const x2 = x + x,       y2 = y + y, z2 = z + z;
5759                 const xx = x * x2, xy = x * y2, xz = x * z2;
5760                 const yy = y * y2, yz = y * z2, zz = z * z2;
5761                 const wx = w * x2, wy = w * y2, wz = w * z2;
5762
5763                 const sx = scale.x, sy = scale.y, sz = scale.z;
5764
5765                 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
5766                 te[ 1 ] = ( xy + wz ) * sx;
5767                 te[ 2 ] = ( xz - wy ) * sx;
5768                 te[ 3 ] = 0;
5769
5770                 te[ 4 ] = ( xy - wz ) * sy;
5771                 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
5772                 te[ 6 ] = ( yz + wx ) * sy;
5773                 te[ 7 ] = 0;
5774
5775                 te[ 8 ] = ( xz + wy ) * sz;
5776                 te[ 9 ] = ( yz - wx ) * sz;
5777                 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
5778                 te[ 11 ] = 0;
5779
5780                 te[ 12 ] = position.x;
5781                 te[ 13 ] = position.y;
5782                 te[ 14 ] = position.z;
5783                 te[ 15 ] = 1;
5784
5785                 return this;
5786
5787         }
5788
5789         decompose( position, quaternion, scale ) {
5790
5791                 const te = this.elements;
5792
5793                 let sx = _v1$1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
5794                 const sy = _v1$1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
5795                 const sz = _v1$1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
5796
5797                 // if determine is negative, we need to invert one scale
5798                 const det = this.determinant();
5799                 if ( det < 0 ) sx = - sx;
5800
5801                 position.x = te[ 12 ];
5802                 position.y = te[ 13 ];
5803                 position.z = te[ 14 ];
5804
5805                 // scale the rotation part
5806                 _m1.copy( this );
5807
5808                 const invSX = 1 / sx;
5809                 const invSY = 1 / sy;
5810                 const invSZ = 1 / sz;
5811
5812                 _m1.elements[ 0 ] *= invSX;
5813                 _m1.elements[ 1 ] *= invSX;
5814                 _m1.elements[ 2 ] *= invSX;
5815
5816                 _m1.elements[ 4 ] *= invSY;
5817                 _m1.elements[ 5 ] *= invSY;
5818                 _m1.elements[ 6 ] *= invSY;
5819
5820                 _m1.elements[ 8 ] *= invSZ;
5821                 _m1.elements[ 9 ] *= invSZ;
5822                 _m1.elements[ 10 ] *= invSZ;
5823
5824                 quaternion.setFromRotationMatrix( _m1 );
5825
5826                 scale.x = sx;
5827                 scale.y = sy;
5828                 scale.z = sz;
5829
5830                 return this;
5831
5832         }
5833
5834         makePerspective( left, right, top, bottom, near, far ) {
5835
5836                 if ( far === undefined ) {
5837
5838                         console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
5839
5840                 }
5841
5842                 const te = this.elements;
5843                 const x = 2 * near / ( right - left );
5844                 const y = 2 * near / ( top - bottom );
5845
5846                 const a = ( right + left ) / ( right - left );
5847                 const b = ( top + bottom ) / ( top - bottom );
5848                 const c = - ( far + near ) / ( far - near );
5849                 const d = - 2 * far * near / ( far - near );
5850
5851                 te[ 0 ] = x;    te[ 4 ] = 0;    te[ 8 ] = a;    te[ 12 ] = 0;
5852                 te[ 1 ] = 0;    te[ 5 ] = y;    te[ 9 ] = b;    te[ 13 ] = 0;
5853                 te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = c;   te[ 14 ] = d;
5854                 te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = - 1; te[ 15 ] = 0;
5855
5856                 return this;
5857
5858         }
5859
5860         makeOrthographic( left, right, top, bottom, near, far ) {
5861
5862                 const te = this.elements;
5863                 const w = 1.0 / ( right - left );
5864                 const h = 1.0 / ( top - bottom );
5865                 const p = 1.0 / ( far - near );
5866
5867                 const x = ( right + left ) * w;
5868                 const y = ( top + bottom ) * h;
5869                 const z = ( far + near ) * p;
5870
5871                 te[ 0 ] = 2 * w;        te[ 4 ] = 0;    te[ 8 ] = 0;    te[ 12 ] = - x;
5872                 te[ 1 ] = 0;    te[ 5 ] = 2 * h;        te[ 9 ] = 0;    te[ 13 ] = - y;
5873                 te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = - 2 * p;     te[ 14 ] = - z;
5874                 te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = 0;   te[ 15 ] = 1;
5875
5876                 return this;
5877
5878         }
5879
5880         equals( matrix ) {
5881
5882                 const te = this.elements;
5883                 const me = matrix.elements;
5884
5885                 for ( let i = 0; i < 16; i ++ ) {
5886
5887                         if ( te[ i ] !== me[ i ] ) return false;
5888
5889                 }
5890
5891                 return true;
5892
5893         }
5894
5895         fromArray( array, offset = 0 ) {
5896
5897                 for ( let i = 0; i < 16; i ++ ) {
5898
5899                         this.elements[ i ] = array[ i + offset ];
5900
5901                 }
5902
5903                 return this;
5904
5905         }
5906
5907         toArray( array = [], offset = 0 ) {
5908
5909                 const te = this.elements;
5910
5911                 array[ offset ] = te[ 0 ];
5912                 array[ offset + 1 ] = te[ 1 ];
5913                 array[ offset + 2 ] = te[ 2 ];
5914                 array[ offset + 3 ] = te[ 3 ];
5915
5916                 array[ offset + 4 ] = te[ 4 ];
5917                 array[ offset + 5 ] = te[ 5 ];
5918                 array[ offset + 6 ] = te[ 6 ];
5919                 array[ offset + 7 ] = te[ 7 ];
5920
5921                 array[ offset + 8 ] = te[ 8 ];
5922                 array[ offset + 9 ] = te[ 9 ];
5923                 array[ offset + 10 ] = te[ 10 ];
5924                 array[ offset + 11 ] = te[ 11 ];
5925
5926                 array[ offset + 12 ] = te[ 12 ];
5927                 array[ offset + 13 ] = te[ 13 ];
5928                 array[ offset + 14 ] = te[ 14 ];
5929                 array[ offset + 15 ] = te[ 15 ];
5930
5931                 return array;
5932
5933         }
5934
5935 }
5936
5937 const _v1$1 = /*@__PURE__*/ new Vector3();
5938 const _m1 = /*@__PURE__*/ new Matrix4();
5939 const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
5940 const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
5941 const _x = /*@__PURE__*/ new Vector3();
5942 const _y = /*@__PURE__*/ new Vector3();
5943 const _z = /*@__PURE__*/ new Vector3();
5944
5945 class Euler {
5946
5947         constructor( x = 0, y = 0, z = 0, order = Euler.DefaultOrder ) {
5948
5949                 Object.defineProperty( this, 'isEuler', { value: true } );
5950
5951                 this._x = x;
5952                 this._y = y;
5953                 this._z = z;
5954                 this._order = order;
5955
5956         }
5957
5958         get x() {
5959
5960                 return this._x;
5961
5962         }
5963
5964         set x( value ) {
5965
5966                 this._x = value;
5967                 this._onChangeCallback();
5968
5969         }
5970
5971         get y() {
5972
5973                 return this._y;
5974
5975         }
5976
5977         set y( value ) {
5978
5979                 this._y = value;
5980                 this._onChangeCallback();
5981
5982         }
5983
5984         get z() {
5985
5986                 return this._z;
5987
5988         }
5989
5990         set z( value ) {
5991
5992                 this._z = value;
5993                 this._onChangeCallback();
5994
5995         }
5996
5997         get order() {
5998
5999                 return this._order;
6000
6001         }
6002
6003         set order( value ) {
6004
6005                 this._order = value;
6006                 this._onChangeCallback();
6007
6008         }
6009
6010         set( x, y, z, order ) {
6011
6012                 this._x = x;
6013                 this._y = y;
6014                 this._z = z;
6015                 this._order = order || this._order;
6016
6017                 this._onChangeCallback();
6018
6019                 return this;
6020
6021         }
6022
6023         clone() {
6024
6025                 return new this.constructor( this._x, this._y, this._z, this._order );
6026
6027         }
6028
6029         copy( euler ) {
6030
6031                 this._x = euler._x;
6032                 this._y = euler._y;
6033                 this._z = euler._z;
6034                 this._order = euler._order;
6035
6036                 this._onChangeCallback();
6037
6038                 return this;
6039
6040         }
6041
6042         setFromRotationMatrix( m, order, update ) {
6043
6044                 const clamp = MathUtils.clamp;
6045
6046                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6047
6048                 const te = m.elements;
6049                 const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
6050                 const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
6051                 const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
6052
6053                 order = order || this._order;
6054
6055                 switch ( order ) {
6056
6057                         case 'XYZ':
6058
6059                                 this._y = Math.asin( clamp( m13, - 1, 1 ) );
6060
6061                                 if ( Math.abs( m13 ) < 0.9999999 ) {
6062
6063                                         this._x = Math.atan2( - m23, m33 );
6064                                         this._z = Math.atan2( - m12, m11 );
6065
6066                                 } else {
6067
6068                                         this._x = Math.atan2( m32, m22 );
6069                                         this._z = 0;
6070
6071                                 }
6072
6073                                 break;
6074
6075                         case 'YXZ':
6076
6077                                 this._x = Math.asin( - clamp( m23, - 1, 1 ) );
6078
6079                                 if ( Math.abs( m23 ) < 0.9999999 ) {
6080
6081                                         this._y = Math.atan2( m13, m33 );
6082                                         this._z = Math.atan2( m21, m22 );
6083
6084                                 } else {
6085
6086                                         this._y = Math.atan2( - m31, m11 );
6087                                         this._z = 0;
6088
6089                                 }
6090
6091                                 break;
6092
6093                         case 'ZXY':
6094
6095                                 this._x = Math.asin( clamp( m32, - 1, 1 ) );
6096
6097                                 if ( Math.abs( m32 ) < 0.9999999 ) {
6098
6099                                         this._y = Math.atan2( - m31, m33 );
6100                                         this._z = Math.atan2( - m12, m22 );
6101
6102                                 } else {
6103
6104                                         this._y = 0;
6105                                         this._z = Math.atan2( m21, m11 );
6106
6107                                 }
6108
6109                                 break;
6110
6111                         case 'ZYX':
6112
6113                                 this._y = Math.asin( - clamp( m31, - 1, 1 ) );
6114
6115                                 if ( Math.abs( m31 ) < 0.9999999 ) {
6116
6117                                         this._x = Math.atan2( m32, m33 );
6118                                         this._z = Math.atan2( m21, m11 );
6119
6120                                 } else {
6121
6122                                         this._x = 0;
6123                                         this._z = Math.atan2( - m12, m22 );
6124
6125                                 }
6126
6127                                 break;
6128
6129                         case 'YZX':
6130
6131                                 this._z = Math.asin( clamp( m21, - 1, 1 ) );
6132
6133                                 if ( Math.abs( m21 ) < 0.9999999 ) {
6134
6135                                         this._x = Math.atan2( - m23, m22 );
6136                                         this._y = Math.atan2( - m31, m11 );
6137
6138                                 } else {
6139
6140                                         this._x = 0;
6141                                         this._y = Math.atan2( m13, m33 );
6142
6143                                 }
6144
6145                                 break;
6146
6147                         case 'XZY':
6148
6149                                 this._z = Math.asin( - clamp( m12, - 1, 1 ) );
6150
6151                                 if ( Math.abs( m12 ) < 0.9999999 ) {
6152
6153                                         this._x = Math.atan2( m32, m22 );
6154                                         this._y = Math.atan2( m13, m11 );
6155
6156                                 } else {
6157
6158                                         this._x = Math.atan2( - m23, m33 );
6159                                         this._y = 0;
6160
6161                                 }
6162
6163                                 break;
6164
6165                         default:
6166
6167                                 console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
6168
6169                 }
6170
6171                 this._order = order;
6172
6173                 if ( update !== false ) this._onChangeCallback();
6174
6175                 return this;
6176
6177         }
6178
6179         setFromQuaternion( q, order, update ) {
6180
6181                 _matrix.makeRotationFromQuaternion( q );
6182
6183                 return this.setFromRotationMatrix( _matrix, order, update );
6184
6185         }
6186
6187         setFromVector3( v, order ) {
6188
6189                 return this.set( v.x, v.y, v.z, order || this._order );
6190
6191         }
6192
6193         reorder( newOrder ) {
6194
6195                 // WARNING: this discards revolution information -bhouston
6196
6197                 _quaternion$1.setFromEuler( this );
6198
6199                 return this.setFromQuaternion( _quaternion$1, newOrder );
6200
6201         }
6202
6203         equals( euler ) {
6204
6205                 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
6206
6207         }
6208
6209         fromArray( array ) {
6210
6211                 this._x = array[ 0 ];
6212                 this._y = array[ 1 ];
6213                 this._z = array[ 2 ];
6214                 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
6215
6216                 this._onChangeCallback();
6217
6218                 return this;
6219
6220         }
6221
6222         toArray( array = [], offset = 0 ) {
6223
6224                 array[ offset ] = this._x;
6225                 array[ offset + 1 ] = this._y;
6226                 array[ offset + 2 ] = this._z;
6227                 array[ offset + 3 ] = this._order;
6228
6229                 return array;
6230
6231         }
6232
6233         toVector3( optionalResult ) {
6234
6235                 if ( optionalResult ) {
6236
6237                         return optionalResult.set( this._x, this._y, this._z );
6238
6239                 } else {
6240
6241                         return new Vector3( this._x, this._y, this._z );
6242
6243                 }
6244
6245         }
6246
6247         _onChange( callback ) {
6248
6249                 this._onChangeCallback = callback;
6250
6251                 return this;
6252
6253         }
6254
6255         _onChangeCallback() {}
6256
6257 }
6258
6259 Euler.DefaultOrder = 'XYZ';
6260 Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
6261
6262 const _matrix = /*@__PURE__*/ new Matrix4();
6263 const _quaternion$1 = /*@__PURE__*/ new Quaternion();
6264
6265 class Layers {
6266
6267         constructor() {
6268
6269                 this.mask = 1 | 0;
6270
6271         }
6272
6273         set( channel ) {
6274
6275                 this.mask = 1 << channel | 0;
6276
6277         }
6278
6279         enable( channel ) {
6280
6281                 this.mask |= 1 << channel | 0;
6282
6283         }
6284
6285         enableAll() {
6286
6287                 this.mask = 0xffffffff | 0;
6288
6289         }
6290
6291         toggle( channel ) {
6292
6293                 this.mask ^= 1 << channel | 0;
6294
6295         }
6296
6297         disable( channel ) {
6298
6299                 this.mask &= ~ ( 1 << channel | 0 );
6300
6301         }
6302
6303         disableAll() {
6304
6305                 this.mask = 0;
6306
6307         }
6308
6309         test( layers ) {
6310
6311                 return ( this.mask & layers.mask ) !== 0;
6312
6313         }
6314
6315 }
6316
6317 let _object3DId = 0;
6318
6319 const _v1$2 = new Vector3();
6320 const _q1 = new Quaternion();
6321 const _m1$1 = new Matrix4();
6322 const _target = new Vector3();
6323
6324 const _position = new Vector3();
6325 const _scale = new Vector3();
6326 const _quaternion$2 = new Quaternion();
6327
6328 const _xAxis = new Vector3( 1, 0, 0 );
6329 const _yAxis = new Vector3( 0, 1, 0 );
6330 const _zAxis = new Vector3( 0, 0, 1 );
6331
6332 const _addedEvent = { type: 'added' };
6333 const _removedEvent = { type: 'removed' };
6334
6335 function Object3D() {
6336
6337         Object.defineProperty( this, 'id', { value: _object3DId ++ } );
6338
6339         this.uuid = MathUtils.generateUUID();
6340
6341         this.name = '';
6342         this.type = 'Object3D';
6343
6344         this.parent = null;
6345         this.children = [];
6346
6347         this.up = Object3D.DefaultUp.clone();
6348
6349         const position = new Vector3();
6350         const rotation = new Euler();
6351         const quaternion = new Quaternion();
6352         const scale = new Vector3( 1, 1, 1 );
6353
6354         function onRotationChange() {
6355
6356                 quaternion.setFromEuler( rotation, false );
6357
6358         }
6359
6360         function onQuaternionChange() {
6361
6362                 rotation.setFromQuaternion( quaternion, undefined, false );
6363
6364         }
6365
6366         rotation._onChange( onRotationChange );
6367         quaternion._onChange( onQuaternionChange );
6368
6369         Object.defineProperties( this, {
6370                 position: {
6371                         configurable: true,
6372                         enumerable: true,
6373                         value: position
6374                 },
6375                 rotation: {
6376                         configurable: true,
6377                         enumerable: true,
6378                         value: rotation
6379                 },
6380                 quaternion: {
6381                         configurable: true,
6382                         enumerable: true,
6383                         value: quaternion
6384                 },
6385                 scale: {
6386                         configurable: true,
6387                         enumerable: true,
6388                         value: scale
6389                 },
6390                 modelViewMatrix: {
6391                         value: new Matrix4()
6392                 },
6393                 normalMatrix: {
6394                         value: new Matrix3()
6395                 }
6396         } );
6397
6398         this.matrix = new Matrix4();
6399         this.matrixWorld = new Matrix4();
6400
6401         this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
6402         this.matrixWorldNeedsUpdate = false;
6403
6404         this.layers = new Layers();
6405         this.visible = true;
6406
6407         this.castShadow = false;
6408         this.receiveShadow = false;
6409
6410         this.frustumCulled = true;
6411         this.renderOrder = 0;
6412
6413         this.animations = [];
6414
6415         this.userData = {};
6416
6417 }
6418
6419 Object3D.DefaultUp = new Vector3( 0, 1, 0 );
6420 Object3D.DefaultMatrixAutoUpdate = true;
6421
6422 Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
6423
6424         constructor: Object3D,
6425
6426         isObject3D: true,
6427
6428         onBeforeRender: function () {},
6429         onAfterRender: function () {},
6430
6431         applyMatrix4: function ( matrix ) {
6432
6433                 if ( this.matrixAutoUpdate ) this.updateMatrix();
6434
6435                 this.matrix.premultiply( matrix );
6436
6437                 this.matrix.decompose( this.position, this.quaternion, this.scale );
6438
6439         },
6440
6441         applyQuaternion: function ( q ) {
6442
6443                 this.quaternion.premultiply( q );
6444
6445                 return this;
6446
6447         },
6448
6449         setRotationFromAxisAngle: function ( axis, angle ) {
6450
6451                 // assumes axis is normalized
6452
6453                 this.quaternion.setFromAxisAngle( axis, angle );
6454
6455         },
6456
6457         setRotationFromEuler: function ( euler ) {
6458
6459                 this.quaternion.setFromEuler( euler, true );
6460
6461         },
6462
6463         setRotationFromMatrix: function ( m ) {
6464
6465                 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6466
6467                 this.quaternion.setFromRotationMatrix( m );
6468
6469         },
6470
6471         setRotationFromQuaternion: function ( q ) {
6472
6473                 // assumes q is normalized
6474
6475                 this.quaternion.copy( q );
6476
6477         },
6478
6479         rotateOnAxis: function ( axis, angle ) {
6480
6481                 // rotate object on axis in object space
6482                 // axis is assumed to be normalized
6483
6484                 _q1.setFromAxisAngle( axis, angle );
6485
6486                 this.quaternion.multiply( _q1 );
6487
6488                 return this;
6489
6490         },
6491
6492         rotateOnWorldAxis: function ( axis, angle ) {
6493
6494                 // rotate object on axis in world space
6495                 // axis is assumed to be normalized
6496                 // method assumes no rotated parent
6497
6498                 _q1.setFromAxisAngle( axis, angle );
6499
6500                 this.quaternion.premultiply( _q1 );
6501
6502                 return this;
6503
6504         },
6505
6506         rotateX: function ( angle ) {
6507
6508                 return this.rotateOnAxis( _xAxis, angle );
6509
6510         },
6511
6512         rotateY: function ( angle ) {
6513
6514                 return this.rotateOnAxis( _yAxis, angle );
6515
6516         },
6517
6518         rotateZ: function ( angle ) {
6519
6520                 return this.rotateOnAxis( _zAxis, angle );
6521
6522         },
6523
6524         translateOnAxis: function ( axis, distance ) {
6525
6526                 // translate object by distance along axis in object space
6527                 // axis is assumed to be normalized
6528
6529                 _v1$2.copy( axis ).applyQuaternion( this.quaternion );
6530
6531                 this.position.add( _v1$2.multiplyScalar( distance ) );
6532
6533                 return this;
6534
6535         },
6536
6537         translateX: function ( distance ) {
6538
6539                 return this.translateOnAxis( _xAxis, distance );
6540
6541         },
6542
6543         translateY: function ( distance ) {
6544
6545                 return this.translateOnAxis( _yAxis, distance );
6546
6547         },
6548
6549         translateZ: function ( distance ) {
6550
6551                 return this.translateOnAxis( _zAxis, distance );
6552
6553         },
6554
6555         localToWorld: function ( vector ) {
6556
6557                 return vector.applyMatrix4( this.matrixWorld );
6558
6559         },
6560
6561         worldToLocal: function ( vector ) {
6562
6563                 return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
6564
6565         },
6566
6567         lookAt: function ( x, y, z ) {
6568
6569                 // This method does not support objects having non-uniformly-scaled parent(s)
6570
6571                 if ( x.isVector3 ) {
6572
6573                         _target.copy( x );
6574
6575                 } else {
6576
6577                         _target.set( x, y, z );
6578
6579                 }
6580
6581                 const parent = this.parent;
6582
6583                 this.updateWorldMatrix( true, false );
6584
6585                 _position.setFromMatrixPosition( this.matrixWorld );
6586
6587                 if ( this.isCamera || this.isLight ) {
6588
6589                         _m1$1.lookAt( _position, _target, this.up );
6590
6591                 } else {
6592
6593                         _m1$1.lookAt( _target, _position, this.up );
6594
6595                 }
6596
6597                 this.quaternion.setFromRotationMatrix( _m1$1 );
6598
6599                 if ( parent ) {
6600
6601                         _m1$1.extractRotation( parent.matrixWorld );
6602                         _q1.setFromRotationMatrix( _m1$1 );
6603                         this.quaternion.premultiply( _q1.invert() );
6604
6605                 }
6606
6607         },
6608
6609         add: function ( object ) {
6610
6611                 if ( arguments.length > 1 ) {
6612
6613                         for ( let i = 0; i < arguments.length; i ++ ) {
6614
6615                                 this.add( arguments[ i ] );
6616
6617                         }
6618
6619                         return this;
6620
6621                 }
6622
6623                 if ( object === this ) {
6624
6625                         console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
6626                         return this;
6627
6628                 }
6629
6630                 if ( ( object && object.isObject3D ) ) {
6631
6632                         if ( object.parent !== null ) {
6633
6634                                 object.parent.remove( object );
6635
6636                         }
6637
6638                         object.parent = this;
6639                         this.children.push( object );
6640
6641                         object.dispatchEvent( _addedEvent );
6642
6643                 } else {
6644
6645                         console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
6646
6647                 }
6648
6649                 return this;
6650
6651         },
6652
6653         remove: function ( object ) {
6654
6655                 if ( arguments.length > 1 ) {
6656
6657                         for ( let i = 0; i < arguments.length; i ++ ) {
6658
6659                                 this.remove( arguments[ i ] );
6660
6661                         }
6662
6663                         return this;
6664
6665                 }
6666
6667                 const index = this.children.indexOf( object );
6668
6669                 if ( index !== - 1 ) {
6670
6671                         object.parent = null;
6672                         this.children.splice( index, 1 );
6673
6674                         object.dispatchEvent( _removedEvent );
6675
6676                 }
6677
6678                 return this;
6679
6680         },
6681
6682         clear: function () {
6683
6684                 for ( let i = 0; i < this.children.length; i ++ ) {
6685
6686                         const object = this.children[ i ];
6687
6688                         object.parent = null;
6689
6690                         object.dispatchEvent( _removedEvent );
6691
6692                 }
6693
6694                 this.children.length = 0;
6695
6696                 return this;
6697
6698
6699         },
6700
6701         attach: function ( object ) {
6702
6703                 // adds object as a child of this, while maintaining the object's world transform
6704
6705                 this.updateWorldMatrix( true, false );
6706
6707                 _m1$1.copy( this.matrixWorld ).invert();
6708
6709                 if ( object.parent !== null ) {
6710
6711                         object.parent.updateWorldMatrix( true, false );
6712
6713                         _m1$1.multiply( object.parent.matrixWorld );
6714
6715                 }
6716
6717                 object.applyMatrix4( _m1$1 );
6718
6719                 object.updateWorldMatrix( false, false );
6720
6721                 this.add( object );
6722
6723                 return this;
6724
6725         },
6726
6727         getObjectById: function ( id ) {
6728
6729                 return this.getObjectByProperty( 'id', id );
6730
6731         },
6732
6733         getObjectByName: function ( name ) {
6734
6735                 return this.getObjectByProperty( 'name', name );
6736
6737         },
6738
6739         getObjectByProperty: function ( name, value ) {
6740
6741                 if ( this[ name ] === value ) return this;
6742
6743                 for ( let i = 0, l = this.children.length; i < l; i ++ ) {
6744
6745                         const child = this.children[ i ];
6746                         const object = child.getObjectByProperty( name, value );
6747
6748                         if ( object !== undefined ) {
6749
6750                                 return object;
6751
6752                         }
6753
6754                 }
6755
6756                 return undefined;
6757
6758         },
6759
6760         getWorldPosition: function ( target ) {
6761
6762                 if ( target === undefined ) {
6763
6764                         console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
6765                         target = new Vector3();
6766
6767                 }
6768
6769                 this.updateWorldMatrix( true, false );
6770
6771                 return target.setFromMatrixPosition( this.matrixWorld );
6772
6773         },
6774
6775         getWorldQuaternion: function ( target ) {
6776
6777                 if ( target === undefined ) {
6778
6779                         console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
6780                         target = new Quaternion();
6781
6782                 }
6783
6784                 this.updateWorldMatrix( true, false );
6785
6786                 this.matrixWorld.decompose( _position, target, _scale );
6787
6788                 return target;
6789
6790         },
6791
6792         getWorldScale: function ( target ) {
6793
6794                 if ( target === undefined ) {
6795
6796                         console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
6797                         target = new Vector3();
6798
6799                 }
6800
6801                 this.updateWorldMatrix( true, false );
6802
6803                 this.matrixWorld.decompose( _position, _quaternion$2, target );
6804
6805                 return target;
6806
6807         },
6808
6809         getWorldDirection: function ( target ) {
6810
6811                 if ( target === undefined ) {
6812
6813                         console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
6814                         target = new Vector3();
6815
6816                 }
6817
6818                 this.updateWorldMatrix( true, false );
6819
6820                 const e = this.matrixWorld.elements;
6821
6822                 return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
6823
6824         },
6825
6826         raycast: function () {},
6827
6828         traverse: function ( callback ) {
6829
6830                 callback( this );
6831
6832                 const children = this.children;
6833
6834                 for ( let i = 0, l = children.length; i < l; i ++ ) {
6835
6836                         children[ i ].traverse( callback );
6837
6838                 }
6839
6840         },
6841
6842         traverseVisible: function ( callback ) {
6843
6844                 if ( this.visible === false ) return;
6845
6846                 callback( this );
6847
6848                 const children = this.children;
6849
6850                 for ( let i = 0, l = children.length; i < l; i ++ ) {
6851
6852                         children[ i ].traverseVisible( callback );
6853
6854                 }
6855
6856         },
6857
6858         traverseAncestors: function ( callback ) {
6859
6860                 const parent = this.parent;
6861
6862                 if ( parent !== null ) {
6863
6864                         callback( parent );
6865
6866                         parent.traverseAncestors( callback );
6867
6868                 }
6869
6870         },
6871
6872         updateMatrix: function () {
6873
6874                 this.matrix.compose( this.position, this.quaternion, this.scale );
6875
6876                 this.matrixWorldNeedsUpdate = true;
6877
6878         },
6879
6880         updateMatrixWorld: function ( force ) {
6881
6882                 if ( this.matrixAutoUpdate ) this.updateMatrix();
6883
6884                 if ( this.matrixWorldNeedsUpdate || force ) {
6885
6886                         if ( this.parent === null ) {
6887
6888                                 this.matrixWorld.copy( this.matrix );
6889
6890                         } else {
6891
6892                                 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
6893
6894                         }
6895
6896                         this.matrixWorldNeedsUpdate = false;
6897
6898                         force = true;
6899
6900                 }
6901
6902                 // update children
6903
6904                 const children = this.children;
6905
6906                 for ( let i = 0, l = children.length; i < l; i ++ ) {
6907
6908                         children[ i ].updateMatrixWorld( force );
6909
6910                 }
6911
6912         },
6913
6914         updateWorldMatrix: function ( updateParents, updateChildren ) {
6915
6916                 const parent = this.parent;
6917
6918                 if ( updateParents === true && parent !== null ) {
6919
6920                         parent.updateWorldMatrix( true, false );
6921
6922                 }
6923
6924                 if ( this.matrixAutoUpdate ) this.updateMatrix();
6925
6926                 if ( this.parent === null ) {
6927
6928                         this.matrixWorld.copy( this.matrix );
6929
6930                 } else {
6931
6932                         this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
6933
6934                 }
6935
6936                 // update children
6937
6938                 if ( updateChildren === true ) {
6939
6940                         const children = this.children;
6941
6942                         for ( let i = 0, l = children.length; i < l; i ++ ) {
6943
6944                                 children[ i ].updateWorldMatrix( false, true );
6945
6946                         }
6947
6948                 }
6949
6950         },
6951
6952         toJSON: function ( meta ) {
6953
6954                 // meta is a string when called from JSON.stringify
6955                 const isRootObject = ( meta === undefined || typeof meta === 'string' );
6956
6957                 const output = {};
6958
6959                 // meta is a hash used to collect geometries, materials.
6960                 // not providing it implies that this is the root object
6961                 // being serialized.
6962                 if ( isRootObject ) {
6963
6964                         // initialize meta obj
6965                         meta = {
6966                                 geometries: {},
6967                                 materials: {},
6968                                 textures: {},
6969                                 images: {},
6970                                 shapes: {},
6971                                 skeletons: {},
6972                                 animations: {}
6973                         };
6974
6975                         output.metadata = {
6976                                 version: 4.5,
6977                                 type: 'Object',
6978                                 generator: 'Object3D.toJSON'
6979                         };
6980
6981                 }
6982
6983                 // standard Object3D serialization
6984
6985                 const object = {};
6986
6987                 object.uuid = this.uuid;
6988                 object.type = this.type;
6989
6990                 if ( this.name !== '' ) object.name = this.name;
6991                 if ( this.castShadow === true ) object.castShadow = true;
6992                 if ( this.receiveShadow === true ) object.receiveShadow = true;
6993                 if ( this.visible === false ) object.visible = false;
6994                 if ( this.frustumCulled === false ) object.frustumCulled = false;
6995                 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
6996                 if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
6997
6998                 object.layers = this.layers.mask;
6999                 object.matrix = this.matrix.toArray();
7000
7001                 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
7002
7003                 // object specific properties
7004
7005                 if ( this.isInstancedMesh ) {
7006
7007                         object.type = 'InstancedMesh';
7008                         object.count = this.count;
7009                         object.instanceMatrix = this.instanceMatrix.toJSON();
7010
7011                 }
7012
7013                 //
7014
7015                 function serialize( library, element ) {
7016
7017                         if ( library[ element.uuid ] === undefined ) {
7018
7019                                 library[ element.uuid ] = element.toJSON( meta );
7020
7021                         }
7022
7023                         return element.uuid;
7024
7025                 }
7026
7027                 if ( this.isMesh || this.isLine || this.isPoints ) {
7028
7029                         object.geometry = serialize( meta.geometries, this.geometry );
7030
7031                         const parameters = this.geometry.parameters;
7032
7033                         if ( parameters !== undefined && parameters.shapes !== undefined ) {
7034
7035                                 const shapes = parameters.shapes;
7036
7037                                 if ( Array.isArray( shapes ) ) {
7038
7039                                         for ( let i = 0, l = shapes.length; i < l; i ++ ) {
7040
7041                                                 const shape = shapes[ i ];
7042
7043                                                 serialize( meta.shapes, shape );
7044
7045                                         }
7046
7047                                 } else {
7048
7049                                         serialize( meta.shapes, shapes );
7050
7051                                 }
7052
7053                         }
7054
7055                 }
7056
7057                 if ( this.isSkinnedMesh ) {
7058
7059                         object.bindMode = this.bindMode;
7060                         object.bindMatrix = this.bindMatrix.toArray();
7061
7062                         if ( this.skeleton !== undefined ) {
7063
7064                                 serialize( meta.skeletons, this.skeleton );
7065
7066                                 object.skeleton = this.skeleton.uuid;
7067
7068                         }
7069
7070                 }
7071
7072                 if ( this.material !== undefined ) {
7073
7074                         if ( Array.isArray( this.material ) ) {
7075
7076                                 const uuids = [];
7077
7078                                 for ( let i = 0, l = this.material.length; i < l; i ++ ) {
7079
7080                                         uuids.push( serialize( meta.materials, this.material[ i ] ) );
7081
7082                                 }
7083
7084                                 object.material = uuids;
7085
7086                         } else {
7087
7088                                 object.material = serialize( meta.materials, this.material );
7089
7090                         }
7091
7092                 }
7093
7094                 //
7095
7096                 if ( this.children.length > 0 ) {
7097
7098                         object.children = [];
7099
7100                         for ( let i = 0; i < this.children.length; i ++ ) {
7101
7102                                 object.children.push( this.children[ i ].toJSON( meta ).object );
7103
7104                         }
7105
7106                 }
7107
7108                 //
7109
7110                 if ( this.animations.length > 0 ) {
7111
7112                         object.animations = [];
7113
7114                         for ( let i = 0; i < this.animations.length; i ++ ) {
7115
7116                                 const animation = this.animations[ i ];
7117
7118                                 object.animations.push( serialize( meta.animations, animation ) );
7119
7120                         }
7121
7122                 }
7123
7124                 if ( isRootObject ) {
7125
7126                         const geometries = extractFromCache( meta.geometries );
7127                         const materials = extractFromCache( meta.materials );
7128                         const textures = extractFromCache( meta.textures );
7129                         const images = extractFromCache( meta.images );
7130                         const shapes = extractFromCache( meta.shapes );
7131                         const skeletons = extractFromCache( meta.skeletons );
7132                         const animations = extractFromCache( meta.animations );
7133
7134                         if ( geometries.length > 0 ) output.geometries = geometries;
7135                         if ( materials.length > 0 ) output.materials = materials;
7136                         if ( textures.length > 0 ) output.textures = textures;
7137                         if ( images.length > 0 ) output.images = images;
7138                         if ( shapes.length > 0 ) output.shapes = shapes;
7139                         if ( skeletons.length > 0 ) output.skeletons = skeletons;
7140                         if ( animations.length > 0 ) output.animations = animations;
7141
7142                 }
7143
7144                 output.object = object;
7145
7146                 return output;
7147
7148                 // extract data from the cache hash
7149                 // remove metadata on each item
7150                 // and return as array
7151                 function extractFromCache( cache ) {
7152
7153                         const values = [];
7154                         for ( const key in cache ) {
7155
7156                                 const data = cache[ key ];
7157                                 delete data.metadata;
7158                                 values.push( data );
7159
7160                         }
7161
7162                         return values;
7163
7164                 }
7165
7166         },
7167
7168         clone: function ( recursive ) {
7169
7170                 return new this.constructor().copy( this, recursive );
7171
7172         },
7173
7174         copy: function ( source, recursive = true ) {
7175
7176                 this.name = source.name;
7177
7178                 this.up.copy( source.up );
7179
7180                 this.position.copy( source.position );
7181                 this.rotation.order = source.rotation.order;
7182                 this.quaternion.copy( source.quaternion );
7183                 this.scale.copy( source.scale );
7184
7185                 this.matrix.copy( source.matrix );
7186                 this.matrixWorld.copy( source.matrixWorld );
7187
7188                 this.matrixAutoUpdate = source.matrixAutoUpdate;
7189                 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
7190
7191                 this.layers.mask = source.layers.mask;
7192                 this.visible = source.visible;
7193
7194                 this.castShadow = source.castShadow;
7195                 this.receiveShadow = source.receiveShadow;
7196
7197                 this.frustumCulled = source.frustumCulled;
7198                 this.renderOrder = source.renderOrder;
7199
7200                 this.userData = JSON.parse( JSON.stringify( source.userData ) );
7201
7202                 if ( recursive === true ) {
7203
7204                         for ( let i = 0; i < source.children.length; i ++ ) {
7205
7206                                 const child = source.children[ i ];
7207                                 this.add( child.clone() );
7208
7209                         }
7210
7211                 }
7212
7213                 return this;
7214
7215         }
7216
7217 } );
7218
7219 const _vector1 = /*@__PURE__*/ new Vector3();
7220 const _vector2 = /*@__PURE__*/ new Vector3();
7221 const _normalMatrix = /*@__PURE__*/ new Matrix3();
7222
7223 class Plane {
7224
7225         constructor( normal, constant ) {
7226
7227                 Object.defineProperty( this, 'isPlane', { value: true } );
7228
7229                 // normal is assumed to be normalized
7230
7231                 this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
7232                 this.constant = ( constant !== undefined ) ? constant : 0;
7233
7234         }
7235
7236         set( normal, constant ) {
7237
7238                 this.normal.copy( normal );
7239                 this.constant = constant;
7240
7241                 return this;
7242
7243         }
7244
7245         setComponents( x, y, z, w ) {
7246
7247                 this.normal.set( x, y, z );
7248                 this.constant = w;
7249
7250                 return this;
7251
7252         }
7253
7254         setFromNormalAndCoplanarPoint( normal, point ) {
7255
7256                 this.normal.copy( normal );
7257                 this.constant = - point.dot( this.normal );
7258
7259                 return this;
7260
7261         }
7262
7263         setFromCoplanarPoints( a, b, c ) {
7264
7265                 const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
7266
7267                 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
7268
7269                 this.setFromNormalAndCoplanarPoint( normal, a );
7270
7271                 return this;
7272
7273         }
7274
7275         clone() {
7276
7277                 return new this.constructor().copy( this );
7278
7279         }
7280
7281         copy( plane ) {
7282
7283                 this.normal.copy( plane.normal );
7284                 this.constant = plane.constant;
7285
7286                 return this;
7287
7288         }
7289
7290         normalize() {
7291
7292                 // Note: will lead to a divide by zero if the plane is invalid.
7293
7294                 const inverseNormalLength = 1.0 / this.normal.length();
7295                 this.normal.multiplyScalar( inverseNormalLength );
7296                 this.constant *= inverseNormalLength;
7297
7298                 return this;
7299
7300         }
7301
7302         negate() {
7303
7304                 this.constant *= - 1;
7305                 this.normal.negate();
7306
7307                 return this;
7308
7309         }
7310
7311         distanceToPoint( point ) {
7312
7313                 return this.normal.dot( point ) + this.constant;
7314
7315         }
7316
7317         distanceToSphere( sphere ) {
7318
7319                 return this.distanceToPoint( sphere.center ) - sphere.radius;
7320
7321         }
7322
7323         projectPoint( point, target ) {
7324
7325                 if ( target === undefined ) {
7326
7327                         console.warn( 'THREE.Plane: .projectPoint() target is now required' );
7328                         target = new Vector3();
7329
7330                 }
7331
7332                 return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
7333
7334         }
7335
7336         intersectLine( line, target ) {
7337
7338                 if ( target === undefined ) {
7339
7340                         console.warn( 'THREE.Plane: .intersectLine() target is now required' );
7341                         target = new Vector3();
7342
7343                 }
7344
7345                 const direction = line.delta( _vector1 );
7346
7347                 const denominator = this.normal.dot( direction );
7348
7349                 if ( denominator === 0 ) {
7350
7351                         // line is coplanar, return origin
7352                         if ( this.distanceToPoint( line.start ) === 0 ) {
7353
7354                                 return target.copy( line.start );
7355
7356                         }
7357
7358                         // Unsure if this is the correct method to handle this case.
7359                         return undefined;
7360
7361                 }
7362
7363                 const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
7364
7365                 if ( t < 0 || t > 1 ) {
7366
7367                         return undefined;
7368
7369                 }
7370
7371                 return target.copy( direction ).multiplyScalar( t ).add( line.start );
7372
7373         }
7374
7375         intersectsLine( line ) {
7376
7377                 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
7378
7379                 const startSign = this.distanceToPoint( line.start );
7380                 const endSign = this.distanceToPoint( line.end );
7381
7382                 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
7383
7384         }
7385
7386         intersectsBox( box ) {
7387
7388                 return box.intersectsPlane( this );
7389
7390         }
7391
7392         intersectsSphere( sphere ) {
7393
7394                 return sphere.intersectsPlane( this );
7395
7396         }
7397
7398         coplanarPoint( target ) {
7399
7400                 if ( target === undefined ) {
7401
7402                         console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
7403                         target = new Vector3();
7404
7405                 }
7406
7407                 return target.copy( this.normal ).multiplyScalar( - this.constant );
7408
7409         }
7410
7411         applyMatrix4( matrix, optionalNormalMatrix ) {
7412
7413                 const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
7414
7415                 const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
7416
7417                 const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
7418
7419                 this.constant = - referencePoint.dot( normal );
7420
7421                 return this;
7422
7423         }
7424
7425         translate( offset ) {
7426
7427                 this.constant -= offset.dot( this.normal );
7428
7429                 return this;
7430
7431         }
7432
7433         equals( plane ) {
7434
7435                 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
7436
7437         }
7438
7439 }
7440
7441 const _v0$1 = /*@__PURE__*/ new Vector3();
7442 const _v1$3 = /*@__PURE__*/ new Vector3();
7443 const _v2$1 = /*@__PURE__*/ new Vector3();
7444 const _v3 = /*@__PURE__*/ new Vector3();
7445
7446 const _vab = /*@__PURE__*/ new Vector3();
7447 const _vac = /*@__PURE__*/ new Vector3();
7448 const _vbc = /*@__PURE__*/ new Vector3();
7449 const _vap = /*@__PURE__*/ new Vector3();
7450 const _vbp = /*@__PURE__*/ new Vector3();
7451 const _vcp = /*@__PURE__*/ new Vector3();
7452
7453 class Triangle {
7454
7455         constructor( a, b, c ) {
7456
7457                 this.a = ( a !== undefined ) ? a : new Vector3();
7458                 this.b = ( b !== undefined ) ? b : new Vector3();
7459                 this.c = ( c !== undefined ) ? c : new Vector3();
7460
7461         }
7462
7463         static getNormal( a, b, c, target ) {
7464
7465                 if ( target === undefined ) {
7466
7467                         console.warn( 'THREE.Triangle: .getNormal() target is now required' );
7468                         target = new Vector3();
7469
7470                 }
7471
7472                 target.subVectors( c, b );
7473                 _v0$1.subVectors( a, b );
7474                 target.cross( _v0$1 );
7475
7476                 const targetLengthSq = target.lengthSq();
7477                 if ( targetLengthSq > 0 ) {
7478
7479                         return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
7480
7481                 }
7482
7483                 return target.set( 0, 0, 0 );
7484
7485         }
7486
7487         // static/instance method to calculate barycentric coordinates
7488         // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
7489         static getBarycoord( point, a, b, c, target ) {
7490
7491                 _v0$1.subVectors( c, a );
7492                 _v1$3.subVectors( b, a );
7493                 _v2$1.subVectors( point, a );
7494
7495                 const dot00 = _v0$1.dot( _v0$1 );
7496                 const dot01 = _v0$1.dot( _v1$3 );
7497                 const dot02 = _v0$1.dot( _v2$1 );
7498                 const dot11 = _v1$3.dot( _v1$3 );
7499                 const dot12 = _v1$3.dot( _v2$1 );
7500
7501                 const denom = ( dot00 * dot11 - dot01 * dot01 );
7502
7503                 if ( target === undefined ) {
7504
7505                         console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
7506                         target = new Vector3();
7507
7508                 }
7509
7510                 // collinear or singular triangle
7511                 if ( denom === 0 ) {
7512
7513                         // arbitrary location outside of triangle?
7514                         // not sure if this is the best idea, maybe should be returning undefined
7515                         return target.set( - 2, - 1, - 1 );
7516
7517                 }
7518
7519                 const invDenom = 1 / denom;
7520                 const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
7521                 const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
7522
7523                 // barycentric coordinates must always sum to 1
7524                 return target.set( 1 - u - v, v, u );
7525
7526         }
7527
7528         static containsPoint( point, a, b, c ) {
7529
7530                 this.getBarycoord( point, a, b, c, _v3 );
7531
7532                 return ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );
7533
7534         }
7535
7536         static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) {
7537
7538                 this.getBarycoord( point, p1, p2, p3, _v3 );
7539
7540                 target.set( 0, 0 );
7541                 target.addScaledVector( uv1, _v3.x );
7542                 target.addScaledVector( uv2, _v3.y );
7543                 target.addScaledVector( uv3, _v3.z );
7544
7545                 return target;
7546
7547         }
7548
7549         static isFrontFacing( a, b, c, direction ) {
7550
7551                 _v0$1.subVectors( c, b );
7552                 _v1$3.subVectors( a, b );
7553
7554                 // strictly front facing
7555                 return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
7556
7557         }
7558
7559         set( a, b, c ) {
7560
7561                 this.a.copy( a );
7562                 this.b.copy( b );
7563                 this.c.copy( c );
7564
7565                 return this;
7566
7567         }
7568
7569         setFromPointsAndIndices( points, i0, i1, i2 ) {
7570
7571                 this.a.copy( points[ i0 ] );
7572                 this.b.copy( points[ i1 ] );
7573                 this.c.copy( points[ i2 ] );
7574
7575                 return this;
7576
7577         }
7578
7579         clone() {
7580
7581                 return new this.constructor().copy( this );
7582
7583         }
7584
7585         copy( triangle ) {
7586
7587                 this.a.copy( triangle.a );
7588                 this.b.copy( triangle.b );
7589                 this.c.copy( triangle.c );
7590
7591                 return this;
7592
7593         }
7594
7595         getArea() {
7596
7597                 _v0$1.subVectors( this.c, this.b );
7598                 _v1$3.subVectors( this.a, this.b );
7599
7600                 return _v0$1.cross( _v1$3 ).length() * 0.5;
7601
7602         }
7603
7604         getMidpoint( target ) {
7605
7606                 if ( target === undefined ) {
7607
7608                         console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
7609                         target = new Vector3();
7610
7611                 }
7612
7613                 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
7614
7615         }
7616
7617         getNormal( target ) {
7618
7619                 return Triangle.getNormal( this.a, this.b, this.c, target );
7620
7621         }
7622
7623         getPlane( target ) {
7624
7625                 if ( target === undefined ) {
7626
7627                         console.warn( 'THREE.Triangle: .getPlane() target is now required' );
7628                         target = new Plane();
7629
7630                 }
7631
7632                 return target.setFromCoplanarPoints( this.a, this.b, this.c );
7633
7634         }
7635
7636         getBarycoord( point, target ) {
7637
7638                 return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
7639
7640         }
7641
7642         getUV( point, uv1, uv2, uv3, target ) {
7643
7644                 return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
7645
7646         }
7647
7648         containsPoint( point ) {
7649
7650                 return Triangle.containsPoint( point, this.a, this.b, this.c );
7651
7652         }
7653
7654         isFrontFacing( direction ) {
7655
7656                 return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
7657
7658         }
7659
7660         intersectsBox( box ) {
7661
7662                 return box.intersectsTriangle( this );
7663
7664         }
7665
7666         closestPointToPoint( p, target ) {
7667
7668                 if ( target === undefined ) {
7669
7670                         console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
7671                         target = new Vector3();
7672
7673                 }
7674
7675                 const a = this.a, b = this.b, c = this.c;
7676                 let v, w;
7677
7678                 // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
7679                 // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
7680                 // under the accompanying license; see chapter 5.1.5 for detailed explanation.
7681                 // basically, we're distinguishing which of the voronoi regions of the triangle
7682                 // the point lies in with the minimum amount of redundant computation.
7683
7684                 _vab.subVectors( b, a );
7685                 _vac.subVectors( c, a );
7686                 _vap.subVectors( p, a );
7687                 const d1 = _vab.dot( _vap );
7688                 const d2 = _vac.dot( _vap );
7689                 if ( d1 <= 0 && d2 <= 0 ) {
7690
7691                         // vertex region of A; barycentric coords (1, 0, 0)
7692                         return target.copy( a );
7693
7694                 }
7695
7696                 _vbp.subVectors( p, b );
7697                 const d3 = _vab.dot( _vbp );
7698                 const d4 = _vac.dot( _vbp );
7699                 if ( d3 >= 0 && d4 <= d3 ) {
7700
7701                         // vertex region of B; barycentric coords (0, 1, 0)
7702                         return target.copy( b );
7703
7704                 }
7705
7706                 const vc = d1 * d4 - d3 * d2;
7707                 if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
7708
7709                         v = d1 / ( d1 - d3 );
7710                         // edge region of AB; barycentric coords (1-v, v, 0)
7711                         return target.copy( a ).addScaledVector( _vab, v );
7712
7713                 }
7714
7715                 _vcp.subVectors( p, c );
7716                 const d5 = _vab.dot( _vcp );
7717                 const d6 = _vac.dot( _vcp );
7718                 if ( d6 >= 0 && d5 <= d6 ) {
7719
7720                         // vertex region of C; barycentric coords (0, 0, 1)
7721                         return target.copy( c );
7722
7723                 }
7724
7725                 const vb = d5 * d2 - d1 * d6;
7726                 if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
7727
7728                         w = d2 / ( d2 - d6 );
7729                         // edge region of AC; barycentric coords (1-w, 0, w)
7730                         return target.copy( a ).addScaledVector( _vac, w );
7731
7732                 }
7733
7734                 const va = d3 * d6 - d5 * d4;
7735                 if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
7736
7737                         _vbc.subVectors( c, b );
7738                         w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
7739                         // edge region of BC; barycentric coords (0, 1-w, w)
7740                         return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
7741
7742                 }
7743
7744                 // face region
7745                 const denom = 1 / ( va + vb + vc );
7746                 // u = va * denom
7747                 v = vb * denom;
7748                 w = vc * denom;
7749
7750                 return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
7751
7752         }
7753
7754         equals( triangle ) {
7755
7756                 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
7757
7758         }
7759
7760 }
7761
7762 const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
7763         'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
7764         'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
7765         'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
7766         'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
7767         'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
7768         'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
7769         'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
7770         'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
7771         'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
7772         'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
7773         'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
7774         'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
7775         'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
7776         'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
7777         'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
7778         'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
7779         'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
7780         'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
7781         'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
7782         'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
7783         'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
7784         'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
7785         'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
7786
7787 const _hslA = { h: 0, s: 0, l: 0 };
7788 const _hslB = { h: 0, s: 0, l: 0 };
7789
7790 function hue2rgb( p, q, t ) {
7791
7792         if ( t < 0 ) t += 1;
7793         if ( t > 1 ) t -= 1;
7794         if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
7795         if ( t < 1 / 2 ) return q;
7796         if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
7797         return p;
7798
7799 }
7800
7801 function SRGBToLinear( c ) {
7802
7803         return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
7804
7805 }
7806
7807 function LinearToSRGB( c ) {
7808
7809         return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
7810
7811 }
7812
7813 class Color {
7814
7815         constructor( r, g, b ) {
7816
7817                 Object.defineProperty( this, 'isColor', { value: true } );
7818
7819                 if ( g === undefined && b === undefined ) {
7820
7821                         // r is THREE.Color, hex or string
7822                         return this.set( r );
7823
7824                 }
7825
7826                 return this.setRGB( r, g, b );
7827
7828         }
7829
7830         set( value ) {
7831
7832                 if ( value && value.isColor ) {
7833
7834                         this.copy( value );
7835
7836                 } else if ( typeof value === 'number' ) {
7837
7838                         this.setHex( value );
7839
7840                 } else if ( typeof value === 'string' ) {
7841
7842                         this.setStyle( value );
7843
7844                 }
7845
7846                 return this;
7847
7848         }
7849
7850         setScalar( scalar ) {
7851
7852                 this.r = scalar;
7853                 this.g = scalar;
7854                 this.b = scalar;
7855
7856                 return this;
7857
7858         }
7859
7860         setHex( hex ) {
7861
7862                 hex = Math.floor( hex );
7863
7864                 this.r = ( hex >> 16 & 255 ) / 255;
7865                 this.g = ( hex >> 8 & 255 ) / 255;
7866                 this.b = ( hex & 255 ) / 255;
7867
7868                 return this;
7869
7870         }
7871
7872         setRGB( r, g, b ) {
7873
7874                 this.r = r;
7875                 this.g = g;
7876                 this.b = b;
7877
7878                 return this;
7879
7880         }
7881
7882         setHSL( h, s, l ) {
7883
7884                 // h,s,l ranges are in 0.0 - 1.0
7885                 h = MathUtils.euclideanModulo( h, 1 );
7886                 s = MathUtils.clamp( s, 0, 1 );
7887                 l = MathUtils.clamp( l, 0, 1 );
7888
7889                 if ( s === 0 ) {
7890
7891                         this.r = this.g = this.b = l;
7892
7893                 } else {
7894
7895                         const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
7896                         const q = ( 2 * l ) - p;
7897
7898                         this.r = hue2rgb( q, p, h + 1 / 3 );
7899                         this.g = hue2rgb( q, p, h );
7900                         this.b = hue2rgb( q, p, h - 1 / 3 );
7901
7902                 }
7903
7904                 return this;
7905
7906         }
7907
7908         setStyle( style ) {
7909
7910                 function handleAlpha( string ) {
7911
7912                         if ( string === undefined ) return;
7913
7914                         if ( parseFloat( string ) < 1 ) {
7915
7916                                 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
7917
7918                         }
7919
7920                 }
7921
7922
7923                 let m;
7924
7925                 if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
7926
7927                         // rgb / hsl
7928
7929                         let color;
7930                         const name = m[ 1 ];
7931                         const components = m[ 2 ];
7932
7933                         switch ( name ) {
7934
7935                                 case 'rgb':
7936                                 case 'rgba':
7937
7938                                         if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
7939
7940                                                 // rgb(255,0,0) rgba(255,0,0,0.5)
7941                                                 this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
7942                                                 this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
7943                                                 this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
7944
7945                                                 handleAlpha( color[ 5 ] );
7946
7947                                                 return this;
7948
7949                                         }
7950
7951                                         if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
7952
7953                                                 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
7954                                                 this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
7955                                                 this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
7956                                                 this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
7957
7958                                                 handleAlpha( color[ 5 ] );
7959
7960                                                 return this;
7961
7962                                         }
7963
7964                                         break;
7965
7966                                 case 'hsl':
7967                                 case 'hsla':
7968
7969                                         if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
7970
7971                                                 // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
7972                                                 const h = parseFloat( color[ 1 ] ) / 360;
7973                                                 const s = parseInt( color[ 2 ], 10 ) / 100;
7974                                                 const l = parseInt( color[ 3 ], 10 ) / 100;
7975
7976                                                 handleAlpha( color[ 5 ] );
7977
7978                                                 return this.setHSL( h, s, l );
7979
7980                                         }
7981
7982                                         break;
7983
7984                         }
7985
7986                 } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
7987
7988                         // hex color
7989
7990                         const hex = m[ 1 ];
7991                         const size = hex.length;
7992
7993                         if ( size === 3 ) {
7994
7995                                 // #ff0
7996                                 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
7997                                 this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
7998                                 this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
7999
8000                                 return this;
8001
8002                         } else if ( size === 6 ) {
8003
8004                                 // #ff0000
8005                                 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
8006                                 this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
8007                                 this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
8008
8009                                 return this;
8010
8011                         }
8012
8013                 }
8014
8015                 if ( style && style.length > 0 ) {
8016
8017                         return this.setColorName( style );
8018
8019                 }
8020
8021                 return this;
8022
8023         }
8024
8025         setColorName( style ) {
8026
8027                 // color keywords
8028                 const hex = _colorKeywords[ style ];
8029
8030                 if ( hex !== undefined ) {
8031
8032                         // red
8033                         this.setHex( hex );
8034
8035                 } else {
8036
8037                         // unknown color
8038                         console.warn( 'THREE.Color: Unknown color ' + style );
8039
8040                 }
8041
8042                 return this;
8043
8044         }
8045
8046         clone() {
8047
8048                 return new this.constructor( this.r, this.g, this.b );
8049
8050         }
8051
8052         copy( color ) {
8053
8054                 this.r = color.r;
8055                 this.g = color.g;
8056                 this.b = color.b;
8057
8058                 return this;
8059
8060         }
8061
8062         copyGammaToLinear( color, gammaFactor = 2.0 ) {
8063
8064                 this.r = Math.pow( color.r, gammaFactor );
8065                 this.g = Math.pow( color.g, gammaFactor );
8066                 this.b = Math.pow( color.b, gammaFactor );
8067
8068                 return this;
8069
8070         }
8071
8072         copyLinearToGamma( color, gammaFactor = 2.0 ) {
8073
8074                 const safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
8075
8076                 this.r = Math.pow( color.r, safeInverse );
8077                 this.g = Math.pow( color.g, safeInverse );
8078                 this.b = Math.pow( color.b, safeInverse );
8079
8080                 return this;
8081
8082         }
8083
8084         convertGammaToLinear( gammaFactor ) {
8085
8086                 this.copyGammaToLinear( this, gammaFactor );
8087
8088                 return this;
8089
8090         }
8091
8092         convertLinearToGamma( gammaFactor ) {
8093
8094                 this.copyLinearToGamma( this, gammaFactor );
8095
8096                 return this;
8097
8098         }
8099
8100         copySRGBToLinear( color ) {
8101
8102                 this.r = SRGBToLinear( color.r );
8103                 this.g = SRGBToLinear( color.g );
8104                 this.b = SRGBToLinear( color.b );
8105
8106                 return this;
8107
8108         }
8109
8110         copyLinearToSRGB( color ) {
8111
8112                 this.r = LinearToSRGB( color.r );
8113                 this.g = LinearToSRGB( color.g );
8114                 this.b = LinearToSRGB( color.b );
8115
8116                 return this;
8117
8118         }
8119
8120         convertSRGBToLinear() {
8121
8122                 this.copySRGBToLinear( this );
8123
8124                 return this;
8125
8126         }
8127
8128         convertLinearToSRGB() {
8129
8130                 this.copyLinearToSRGB( this );
8131
8132                 return this;
8133
8134         }
8135
8136         getHex() {
8137
8138                 return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
8139
8140         }
8141
8142         getHexString() {
8143
8144                 return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
8145
8146         }
8147
8148         getHSL( target ) {
8149
8150                 // h,s,l ranges are in 0.0 - 1.0
8151
8152                 if ( target === undefined ) {
8153
8154                         console.warn( 'THREE.Color: .getHSL() target is now required' );
8155                         target = { h: 0, s: 0, l: 0 };
8156
8157                 }
8158
8159                 const r = this.r, g = this.g, b = this.b;
8160
8161                 const max = Math.max( r, g, b );
8162                 const min = Math.min( r, g, b );
8163
8164                 let hue, saturation;
8165                 const lightness = ( min + max ) / 2.0;
8166
8167                 if ( min === max ) {
8168
8169                         hue = 0;
8170                         saturation = 0;
8171
8172                 } else {
8173
8174                         const delta = max - min;
8175
8176                         saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
8177
8178                         switch ( max ) {
8179
8180                                 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
8181                                 case g: hue = ( b - r ) / delta + 2; break;
8182                                 case b: hue = ( r - g ) / delta + 4; break;
8183
8184                         }
8185
8186                         hue /= 6;
8187
8188                 }
8189
8190                 target.h = hue;
8191                 target.s = saturation;
8192                 target.l = lightness;
8193
8194                 return target;
8195
8196         }
8197
8198         getStyle() {
8199
8200                 return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
8201
8202         }
8203
8204         offsetHSL( h, s, l ) {
8205
8206                 this.getHSL( _hslA );
8207
8208                 _hslA.h += h; _hslA.s += s; _hslA.l += l;
8209
8210                 this.setHSL( _hslA.h, _hslA.s, _hslA.l );
8211
8212                 return this;
8213
8214         }
8215
8216         add( color ) {
8217
8218                 this.r += color.r;
8219                 this.g += color.g;
8220                 this.b += color.b;
8221
8222                 return this;
8223
8224         }
8225
8226         addColors( color1, color2 ) {
8227
8228                 this.r = color1.r + color2.r;
8229                 this.g = color1.g + color2.g;
8230                 this.b = color1.b + color2.b;
8231
8232                 return this;
8233
8234         }
8235
8236         addScalar( s ) {
8237
8238                 this.r += s;
8239                 this.g += s;
8240                 this.b += s;
8241
8242                 return this;
8243
8244         }
8245
8246         sub( color ) {
8247
8248                 this.r = Math.max( 0, this.r - color.r );
8249                 this.g = Math.max( 0, this.g - color.g );
8250                 this.b = Math.max( 0, this.b - color.b );
8251
8252                 return this;
8253
8254         }
8255
8256         multiply( color ) {
8257
8258                 this.r *= color.r;
8259                 this.g *= color.g;
8260                 this.b *= color.b;
8261
8262                 return this;
8263
8264         }
8265
8266         multiplyScalar( s ) {
8267
8268                 this.r *= s;
8269                 this.g *= s;
8270                 this.b *= s;
8271
8272                 return this;
8273
8274         }
8275
8276         lerp( color, alpha ) {
8277
8278                 this.r += ( color.r - this.r ) * alpha;
8279                 this.g += ( color.g - this.g ) * alpha;
8280                 this.b += ( color.b - this.b ) * alpha;
8281
8282                 return this;
8283
8284         }
8285
8286         lerpHSL( color, alpha ) {
8287
8288                 this.getHSL( _hslA );
8289                 color.getHSL( _hslB );
8290
8291                 const h = MathUtils.lerp( _hslA.h, _hslB.h, alpha );
8292                 const s = MathUtils.lerp( _hslA.s, _hslB.s, alpha );
8293                 const l = MathUtils.lerp( _hslA.l, _hslB.l, alpha );
8294
8295                 this.setHSL( h, s, l );
8296
8297                 return this;
8298
8299         }
8300
8301         equals( c ) {
8302
8303                 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
8304
8305         }
8306
8307         fromArray( array, offset = 0 ) {
8308
8309                 this.r = array[ offset ];
8310                 this.g = array[ offset + 1 ];
8311                 this.b = array[ offset + 2 ];
8312
8313                 return this;
8314
8315         }
8316
8317         toArray( array = [], offset = 0 ) {
8318
8319                 array[ offset ] = this.r;
8320                 array[ offset + 1 ] = this.g;
8321                 array[ offset + 2 ] = this.b;
8322
8323                 return array;
8324
8325         }
8326
8327         fromBufferAttribute( attribute, index ) {
8328
8329                 this.r = attribute.getX( index );
8330                 this.g = attribute.getY( index );
8331                 this.b = attribute.getZ( index );
8332
8333                 if ( attribute.normalized === true ) {
8334
8335                         // assuming Uint8Array
8336
8337                         this.r /= 255;
8338                         this.g /= 255;
8339                         this.b /= 255;
8340
8341                 }
8342
8343                 return this;
8344
8345         }
8346
8347         toJSON() {
8348
8349                 return this.getHex();
8350
8351         }
8352
8353 }
8354
8355 Color.NAMES = _colorKeywords;
8356 Color.prototype.r = 1;
8357 Color.prototype.g = 1;
8358 Color.prototype.b = 1;
8359
8360 class Face3 {
8361
8362         constructor( a, b, c, normal, color, materialIndex = 0 ) {
8363
8364                 this.a = a;
8365                 this.b = b;
8366                 this.c = c;
8367
8368                 this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
8369                 this.vertexNormals = Array.isArray( normal ) ? normal : [];
8370
8371                 this.color = ( color && color.isColor ) ? color : new Color();
8372                 this.vertexColors = Array.isArray( color ) ? color : [];
8373
8374                 this.materialIndex = materialIndex;
8375
8376         }
8377
8378         clone() {
8379
8380                 return new this.constructor().copy( this );
8381
8382         }
8383
8384         copy( source ) {
8385
8386                 this.a = source.a;
8387                 this.b = source.b;
8388                 this.c = source.c;
8389
8390                 this.normal.copy( source.normal );
8391                 this.color.copy( source.color );
8392
8393                 this.materialIndex = source.materialIndex;
8394
8395                 for ( let i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
8396
8397                         this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
8398
8399                 }
8400
8401                 for ( let i = 0, il = source.vertexColors.length; i < il; i ++ ) {
8402
8403                         this.vertexColors[ i ] = source.vertexColors[ i ].clone();
8404
8405                 }
8406
8407                 return this;
8408
8409         }
8410
8411 }
8412
8413 let materialId = 0;
8414
8415 function Material() {
8416
8417         Object.defineProperty( this, 'id', { value: materialId ++ } );
8418
8419         this.uuid = MathUtils.generateUUID();
8420
8421         this.name = '';
8422         this.type = 'Material';
8423
8424         this.fog = true;
8425
8426         this.blending = NormalBlending;
8427         this.side = FrontSide;
8428         this.flatShading = false;
8429         this.vertexColors = false;
8430
8431         this.opacity = 1;
8432         this.transparent = false;
8433
8434         this.blendSrc = SrcAlphaFactor;
8435         this.blendDst = OneMinusSrcAlphaFactor;
8436         this.blendEquation = AddEquation;
8437         this.blendSrcAlpha = null;
8438         this.blendDstAlpha = null;
8439         this.blendEquationAlpha = null;
8440
8441         this.depthFunc = LessEqualDepth;
8442         this.depthTest = true;
8443         this.depthWrite = true;
8444
8445         this.stencilWriteMask = 0xff;
8446         this.stencilFunc = AlwaysStencilFunc;
8447         this.stencilRef = 0;
8448         this.stencilFuncMask = 0xff;
8449         this.stencilFail = KeepStencilOp;
8450         this.stencilZFail = KeepStencilOp;
8451         this.stencilZPass = KeepStencilOp;
8452         this.stencilWrite = false;
8453
8454         this.clippingPlanes = null;
8455         this.clipIntersection = false;
8456         this.clipShadows = false;
8457
8458         this.shadowSide = null;
8459
8460         this.colorWrite = true;
8461
8462         this.precision = null; // override the renderer's default precision for this material
8463
8464         this.polygonOffset = false;
8465         this.polygonOffsetFactor = 0;
8466         this.polygonOffsetUnits = 0;
8467
8468         this.dithering = false;
8469
8470         this.alphaTest = 0;
8471         this.premultipliedAlpha = false;
8472
8473         this.visible = true;
8474
8475         this.toneMapped = true;
8476
8477         this.userData = {};
8478
8479         this.version = 0;
8480
8481 }
8482
8483 Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
8484
8485         constructor: Material,
8486
8487         isMaterial: true,
8488
8489         onBeforeCompile: function ( /* shaderobject, renderer */ ) {},
8490
8491         customProgramCacheKey: function () {
8492
8493                 return this.onBeforeCompile.toString();
8494
8495         },
8496
8497         setValues: function ( values ) {
8498
8499                 if ( values === undefined ) return;
8500
8501                 for ( const key in values ) {
8502
8503                         const newValue = values[ key ];
8504
8505                         if ( newValue === undefined ) {
8506
8507                                 console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
8508                                 continue;
8509
8510                         }
8511
8512                         // for backward compatability if shading is set in the constructor
8513                         if ( key === 'shading' ) {
8514
8515                                 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
8516                                 this.flatShading = ( newValue === FlatShading ) ? true : false;
8517                                 continue;
8518
8519                         }
8520
8521                         const currentValue = this[ key ];
8522
8523                         if ( currentValue === undefined ) {
8524
8525                                 console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
8526                                 continue;
8527
8528                         }
8529
8530                         if ( currentValue && currentValue.isColor ) {
8531
8532                                 currentValue.set( newValue );
8533
8534                         } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
8535
8536                                 currentValue.copy( newValue );
8537
8538                         } else {
8539
8540                                 this[ key ] = newValue;
8541
8542                         }
8543
8544                 }
8545
8546         },
8547
8548         toJSON: function ( meta ) {
8549
8550                 const isRoot = ( meta === undefined || typeof meta === 'string' );
8551
8552                 if ( isRoot ) {
8553
8554                         meta = {
8555                                 textures: {},
8556                                 images: {}
8557                         };
8558
8559                 }
8560
8561                 const data = {
8562                         metadata: {
8563                                 version: 4.5,
8564                                 type: 'Material',
8565                                 generator: 'Material.toJSON'
8566                         }
8567                 };
8568
8569                 // standard Material serialization
8570                 data.uuid = this.uuid;
8571                 data.type = this.type;
8572
8573                 if ( this.name !== '' ) data.name = this.name;
8574
8575                 if ( this.color && this.color.isColor ) data.color = this.color.getHex();
8576
8577                 if ( this.roughness !== undefined ) data.roughness = this.roughness;
8578                 if ( this.metalness !== undefined ) data.metalness = this.metalness;
8579
8580                 if ( this.sheen && this.sheen.isColor ) data.sheen = this.sheen.getHex();
8581                 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
8582                 if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
8583
8584                 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
8585                 if ( this.shininess !== undefined ) data.shininess = this.shininess;
8586                 if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
8587                 if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
8588
8589                 if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
8590
8591                         data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
8592
8593                 }
8594
8595                 if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
8596
8597                         data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
8598
8599                 }
8600
8601                 if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
8602
8603                         data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
8604                         data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
8605
8606                 }
8607
8608                 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
8609                 if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
8610                 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
8611                 if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
8612
8613                 if ( this.aoMap && this.aoMap.isTexture ) {
8614
8615                         data.aoMap = this.aoMap.toJSON( meta ).uuid;
8616                         data.aoMapIntensity = this.aoMapIntensity;
8617
8618                 }
8619
8620                 if ( this.bumpMap && this.bumpMap.isTexture ) {
8621
8622                         data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
8623                         data.bumpScale = this.bumpScale;
8624
8625                 }
8626
8627                 if ( this.normalMap && this.normalMap.isTexture ) {
8628
8629                         data.normalMap = this.normalMap.toJSON( meta ).uuid;
8630                         data.normalMapType = this.normalMapType;
8631                         data.normalScale = this.normalScale.toArray();
8632
8633                 }
8634
8635                 if ( this.displacementMap && this.displacementMap.isTexture ) {
8636
8637                         data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
8638                         data.displacementScale = this.displacementScale;
8639                         data.displacementBias = this.displacementBias;
8640
8641                 }
8642
8643                 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
8644                 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
8645
8646                 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
8647                 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
8648
8649                 if ( this.envMap && this.envMap.isTexture ) {
8650
8651                         data.envMap = this.envMap.toJSON( meta ).uuid;
8652                         data.reflectivity = this.reflectivity; // Scale behind envMap
8653                         data.refractionRatio = this.refractionRatio;
8654
8655                         if ( this.combine !== undefined ) data.combine = this.combine;
8656                         if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
8657
8658                 }
8659
8660                 if ( this.gradientMap && this.gradientMap.isTexture ) {
8661
8662                         data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
8663
8664                 }
8665
8666                 if ( this.size !== undefined ) data.size = this.size;
8667                 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
8668
8669                 if ( this.blending !== NormalBlending ) data.blending = this.blending;
8670                 if ( this.flatShading === true ) data.flatShading = this.flatShading;
8671                 if ( this.side !== FrontSide ) data.side = this.side;
8672                 if ( this.vertexColors ) data.vertexColors = true;
8673
8674                 if ( this.opacity < 1 ) data.opacity = this.opacity;
8675                 if ( this.transparent === true ) data.transparent = this.transparent;
8676
8677                 data.depthFunc = this.depthFunc;
8678                 data.depthTest = this.depthTest;
8679                 data.depthWrite = this.depthWrite;
8680
8681                 data.stencilWrite = this.stencilWrite;
8682                 data.stencilWriteMask = this.stencilWriteMask;
8683                 data.stencilFunc = this.stencilFunc;
8684                 data.stencilRef = this.stencilRef;
8685                 data.stencilFuncMask = this.stencilFuncMask;
8686                 data.stencilFail = this.stencilFail;
8687                 data.stencilZFail = this.stencilZFail;
8688                 data.stencilZPass = this.stencilZPass;
8689
8690                 // rotation (SpriteMaterial)
8691                 if ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation;
8692
8693                 if ( this.polygonOffset === true ) data.polygonOffset = true;
8694                 if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
8695                 if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
8696
8697                 if ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth;
8698                 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
8699                 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
8700                 if ( this.scale !== undefined ) data.scale = this.scale;
8701
8702                 if ( this.dithering === true ) data.dithering = true;
8703
8704                 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
8705                 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
8706
8707                 if ( this.wireframe === true ) data.wireframe = this.wireframe;
8708                 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
8709                 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
8710                 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
8711
8712                 if ( this.morphTargets === true ) data.morphTargets = true;
8713                 if ( this.morphNormals === true ) data.morphNormals = true;
8714                 if ( this.skinning === true ) data.skinning = true;
8715
8716                 if ( this.visible === false ) data.visible = false;
8717
8718                 if ( this.toneMapped === false ) data.toneMapped = false;
8719
8720                 if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
8721
8722                 // TODO: Copied from Object3D.toJSON
8723
8724                 function extractFromCache( cache ) {
8725
8726                         const values = [];
8727
8728                         for ( const key in cache ) {
8729
8730                                 const data = cache[ key ];
8731                                 delete data.metadata;
8732                                 values.push( data );
8733
8734                         }
8735
8736                         return values;
8737
8738                 }
8739
8740                 if ( isRoot ) {
8741
8742                         const textures = extractFromCache( meta.textures );
8743                         const images = extractFromCache( meta.images );
8744
8745                         if ( textures.length > 0 ) data.textures = textures;
8746                         if ( images.length > 0 ) data.images = images;
8747
8748                 }
8749
8750                 return data;
8751
8752         },
8753
8754         clone: function () {
8755
8756                 return new this.constructor().copy( this );
8757
8758         },
8759
8760         copy: function ( source ) {
8761
8762                 this.name = source.name;
8763
8764                 this.fog = source.fog;
8765
8766                 this.blending = source.blending;
8767                 this.side = source.side;
8768                 this.flatShading = source.flatShading;
8769                 this.vertexColors = source.vertexColors;
8770
8771                 this.opacity = source.opacity;
8772                 this.transparent = source.transparent;
8773
8774                 this.blendSrc = source.blendSrc;
8775                 this.blendDst = source.blendDst;
8776                 this.blendEquation = source.blendEquation;
8777                 this.blendSrcAlpha = source.blendSrcAlpha;
8778                 this.blendDstAlpha = source.blendDstAlpha;
8779                 this.blendEquationAlpha = source.blendEquationAlpha;
8780
8781                 this.depthFunc = source.depthFunc;
8782                 this.depthTest = source.depthTest;
8783                 this.depthWrite = source.depthWrite;
8784
8785                 this.stencilWriteMask = source.stencilWriteMask;
8786                 this.stencilFunc = source.stencilFunc;
8787                 this.stencilRef = source.stencilRef;
8788                 this.stencilFuncMask = source.stencilFuncMask;
8789                 this.stencilFail = source.stencilFail;
8790                 this.stencilZFail = source.stencilZFail;
8791                 this.stencilZPass = source.stencilZPass;
8792                 this.stencilWrite = source.stencilWrite;
8793
8794                 const srcPlanes = source.clippingPlanes;
8795                 let dstPlanes = null;
8796
8797                 if ( srcPlanes !== null ) {
8798
8799                         const n = srcPlanes.length;
8800                         dstPlanes = new Array( n );
8801
8802                         for ( let i = 0; i !== n; ++ i ) {
8803
8804                                 dstPlanes[ i ] = srcPlanes[ i ].clone();
8805
8806                         }
8807
8808                 }
8809
8810                 this.clippingPlanes = dstPlanes;
8811                 this.clipIntersection = source.clipIntersection;
8812                 this.clipShadows = source.clipShadows;
8813
8814                 this.shadowSide = source.shadowSide;
8815
8816                 this.colorWrite = source.colorWrite;
8817
8818                 this.precision = source.precision;
8819
8820                 this.polygonOffset = source.polygonOffset;
8821                 this.polygonOffsetFactor = source.polygonOffsetFactor;
8822                 this.polygonOffsetUnits = source.polygonOffsetUnits;
8823
8824                 this.dithering = source.dithering;
8825
8826                 this.alphaTest = source.alphaTest;
8827                 this.premultipliedAlpha = source.premultipliedAlpha;
8828
8829                 this.visible = source.visible;
8830
8831                 this.toneMapped = source.toneMapped;
8832
8833                 this.userData = JSON.parse( JSON.stringify( source.userData ) );
8834
8835                 return this;
8836
8837         },
8838
8839         dispose: function () {
8840
8841                 this.dispatchEvent( { type: 'dispose' } );
8842
8843         }
8844
8845 } );
8846
8847 Object.defineProperty( Material.prototype, 'needsUpdate', {
8848
8849         set: function ( value ) {
8850
8851                 if ( value === true ) this.version ++;
8852
8853         }
8854
8855 } );
8856
8857 /**
8858  * parameters = {
8859  *  color: <hex>,
8860  *  opacity: <float>,
8861  *  map: new THREE.Texture( <Image> ),
8862  *
8863  *  lightMap: new THREE.Texture( <Image> ),
8864  *  lightMapIntensity: <float>
8865  *
8866  *  aoMap: new THREE.Texture( <Image> ),
8867  *  aoMapIntensity: <float>
8868  *
8869  *  specularMap: new THREE.Texture( <Image> ),
8870  *
8871  *  alphaMap: new THREE.Texture( <Image> ),
8872  *
8873  *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
8874  *  combine: THREE.Multiply,
8875  *  reflectivity: <float>,
8876  *  refractionRatio: <float>,
8877  *
8878  *  depthTest: <bool>,
8879  *  depthWrite: <bool>,
8880  *
8881  *  wireframe: <boolean>,
8882  *  wireframeLinewidth: <float>,
8883  *
8884  *  skinning: <bool>,
8885  *  morphTargets: <bool>
8886  * }
8887  */
8888
8889 function MeshBasicMaterial( parameters ) {
8890
8891         Material.call( this );
8892
8893         this.type = 'MeshBasicMaterial';
8894
8895         this.color = new Color( 0xffffff ); // emissive
8896
8897         this.map = null;
8898
8899         this.lightMap = null;
8900         this.lightMapIntensity = 1.0;
8901
8902         this.aoMap = null;
8903         this.aoMapIntensity = 1.0;
8904
8905         this.specularMap = null;
8906
8907         this.alphaMap = null;
8908
8909         this.envMap = null;
8910         this.combine = MultiplyOperation;
8911         this.reflectivity = 1;
8912         this.refractionRatio = 0.98;
8913
8914         this.wireframe = false;
8915         this.wireframeLinewidth = 1;
8916         this.wireframeLinecap = 'round';
8917         this.wireframeLinejoin = 'round';
8918
8919         this.skinning = false;
8920         this.morphTargets = false;
8921
8922         this.setValues( parameters );
8923
8924 }
8925
8926 MeshBasicMaterial.prototype = Object.create( Material.prototype );
8927 MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
8928
8929 MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
8930
8931 MeshBasicMaterial.prototype.copy = function ( source ) {
8932
8933         Material.prototype.copy.call( this, source );
8934
8935         this.color.copy( source.color );
8936
8937         this.map = source.map;
8938
8939         this.lightMap = source.lightMap;
8940         this.lightMapIntensity = source.lightMapIntensity;
8941
8942         this.aoMap = source.aoMap;
8943         this.aoMapIntensity = source.aoMapIntensity;
8944
8945         this.specularMap = source.specularMap;
8946
8947         this.alphaMap = source.alphaMap;
8948
8949         this.envMap = source.envMap;
8950         this.combine = source.combine;
8951         this.reflectivity = source.reflectivity;
8952         this.refractionRatio = source.refractionRatio;
8953
8954         this.wireframe = source.wireframe;
8955         this.wireframeLinewidth = source.wireframeLinewidth;
8956         this.wireframeLinecap = source.wireframeLinecap;
8957         this.wireframeLinejoin = source.wireframeLinejoin;
8958
8959         this.skinning = source.skinning;
8960         this.morphTargets = source.morphTargets;
8961
8962         return this;
8963
8964 };
8965
8966 const _vector$3 = new Vector3();
8967 const _vector2$1 = new Vector2();
8968
8969 function BufferAttribute( array, itemSize, normalized ) {
8970
8971         if ( Array.isArray( array ) ) {
8972
8973                 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
8974
8975         }
8976
8977         this.name = '';
8978
8979         this.array = array;
8980         this.itemSize = itemSize;
8981         this.count = array !== undefined ? array.length / itemSize : 0;
8982         this.normalized = normalized === true;
8983
8984         this.usage = StaticDrawUsage;
8985         this.updateRange = { offset: 0, count: - 1 };
8986
8987         this.version = 0;
8988
8989 }
8990
8991 Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
8992
8993         set: function ( value ) {
8994
8995                 if ( value === true ) this.version ++;
8996
8997         }
8998
8999 } );
9000
9001 Object.assign( BufferAttribute.prototype, {
9002
9003         isBufferAttribute: true,
9004
9005         onUploadCallback: function () {},
9006
9007         setUsage: function ( value ) {
9008
9009                 this.usage = value;
9010
9011                 return this;
9012
9013         },
9014
9015         copy: function ( source ) {
9016
9017                 this.name = source.name;
9018                 this.array = new source.array.constructor( source.array );
9019                 this.itemSize = source.itemSize;
9020                 this.count = source.count;
9021                 this.normalized = source.normalized;
9022
9023                 this.usage = source.usage;
9024
9025                 return this;
9026
9027         },
9028
9029         copyAt: function ( index1, attribute, index2 ) {
9030
9031                 index1 *= this.itemSize;
9032                 index2 *= attribute.itemSize;
9033
9034                 for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
9035
9036                         this.array[ index1 + i ] = attribute.array[ index2 + i ];
9037
9038                 }
9039
9040                 return this;
9041
9042         },
9043
9044         copyArray: function ( array ) {
9045
9046                 this.array.set( array );
9047
9048                 return this;
9049
9050         },
9051
9052         copyColorsArray: function ( colors ) {
9053
9054                 const array = this.array;
9055                 let offset = 0;
9056
9057                 for ( let i = 0, l = colors.length; i < l; i ++ ) {
9058
9059                         let color = colors[ i ];
9060
9061                         if ( color === undefined ) {
9062
9063                                 console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
9064                                 color = new Color();
9065
9066                         }
9067
9068                         array[ offset ++ ] = color.r;
9069                         array[ offset ++ ] = color.g;
9070                         array[ offset ++ ] = color.b;
9071
9072                 }
9073
9074                 return this;
9075
9076         },
9077
9078         copyVector2sArray: function ( vectors ) {
9079
9080                 const array = this.array;
9081                 let offset = 0;
9082
9083                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
9084
9085                         let vector = vectors[ i ];
9086
9087                         if ( vector === undefined ) {
9088
9089                                 console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
9090                                 vector = new Vector2();
9091
9092                         }
9093
9094                         array[ offset ++ ] = vector.x;
9095                         array[ offset ++ ] = vector.y;
9096
9097                 }
9098
9099                 return this;
9100
9101         },
9102
9103         copyVector3sArray: function ( vectors ) {
9104
9105                 const array = this.array;
9106                 let offset = 0;
9107
9108                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
9109
9110                         let vector = vectors[ i ];
9111
9112                         if ( vector === undefined ) {
9113
9114                                 console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
9115                                 vector = new Vector3();
9116
9117                         }
9118
9119                         array[ offset ++ ] = vector.x;
9120                         array[ offset ++ ] = vector.y;
9121                         array[ offset ++ ] = vector.z;
9122
9123                 }
9124
9125                 return this;
9126
9127         },
9128
9129         copyVector4sArray: function ( vectors ) {
9130
9131                 const array = this.array;
9132                 let offset = 0;
9133
9134                 for ( let i = 0, l = vectors.length; i < l; i ++ ) {
9135
9136                         let vector = vectors[ i ];
9137
9138                         if ( vector === undefined ) {
9139
9140                                 console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
9141                                 vector = new Vector4();
9142
9143                         }
9144
9145                         array[ offset ++ ] = vector.x;
9146                         array[ offset ++ ] = vector.y;
9147                         array[ offset ++ ] = vector.z;
9148                         array[ offset ++ ] = vector.w;
9149
9150                 }
9151
9152                 return this;
9153
9154         },
9155
9156         applyMatrix3: function ( m ) {
9157
9158                 if ( this.itemSize === 2 ) {
9159
9160                         for ( let i = 0, l = this.count; i < l; i ++ ) {
9161
9162                                 _vector2$1.fromBufferAttribute( this, i );
9163                                 _vector2$1.applyMatrix3( m );
9164
9165                                 this.setXY( i, _vector2$1.x, _vector2$1.y );
9166
9167                         }
9168
9169                 } else if ( this.itemSize === 3 ) {
9170
9171                         for ( let i = 0, l = this.count; i < l; i ++ ) {
9172
9173                                 _vector$3.fromBufferAttribute( this, i );
9174                                 _vector$3.applyMatrix3( m );
9175
9176                                 this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9177
9178                         }
9179
9180                 }
9181
9182                 return this;
9183
9184         },
9185
9186         applyMatrix4: function ( m ) {
9187
9188                 for ( let i = 0, l = this.count; i < l; i ++ ) {
9189
9190                         _vector$3.x = this.getX( i );
9191                         _vector$3.y = this.getY( i );
9192                         _vector$3.z = this.getZ( i );
9193
9194                         _vector$3.applyMatrix4( m );
9195
9196                         this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9197
9198                 }
9199
9200                 return this;
9201
9202         },
9203
9204         applyNormalMatrix: function ( m ) {
9205
9206                 for ( let i = 0, l = this.count; i < l; i ++ ) {
9207
9208                         _vector$3.x = this.getX( i );
9209                         _vector$3.y = this.getY( i );
9210                         _vector$3.z = this.getZ( i );
9211
9212                         _vector$3.applyNormalMatrix( m );
9213
9214                         this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9215
9216                 }
9217
9218                 return this;
9219
9220         },
9221
9222         transformDirection: function ( m ) {
9223
9224                 for ( let i = 0, l = this.count; i < l; i ++ ) {
9225
9226                         _vector$3.x = this.getX( i );
9227                         _vector$3.y = this.getY( i );
9228                         _vector$3.z = this.getZ( i );
9229
9230                         _vector$3.transformDirection( m );
9231
9232                         this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9233
9234                 }
9235
9236                 return this;
9237
9238         },
9239
9240         set: function ( value, offset = 0 ) {
9241
9242                 this.array.set( value, offset );
9243
9244                 return this;
9245
9246         },
9247
9248         getX: function ( index ) {
9249
9250                 return this.array[ index * this.itemSize ];
9251
9252         },
9253
9254         setX: function ( index, x ) {
9255
9256                 this.array[ index * this.itemSize ] = x;
9257
9258                 return this;
9259
9260         },
9261
9262         getY: function ( index ) {
9263
9264                 return this.array[ index * this.itemSize + 1 ];
9265
9266         },
9267
9268         setY: function ( index, y ) {
9269
9270                 this.array[ index * this.itemSize + 1 ] = y;
9271
9272                 return this;
9273
9274         },
9275
9276         getZ: function ( index ) {
9277
9278                 return this.array[ index * this.itemSize + 2 ];
9279
9280         },
9281
9282         setZ: function ( index, z ) {
9283
9284                 this.array[ index * this.itemSize + 2 ] = z;
9285
9286                 return this;
9287
9288         },
9289
9290         getW: function ( index ) {
9291
9292                 return this.array[ index * this.itemSize + 3 ];
9293
9294         },
9295
9296         setW: function ( index, w ) {
9297
9298                 this.array[ index * this.itemSize + 3 ] = w;
9299
9300                 return this;
9301
9302         },
9303
9304         setXY: function ( index, x, y ) {
9305
9306                 index *= this.itemSize;
9307
9308                 this.array[ index + 0 ] = x;
9309                 this.array[ index + 1 ] = y;
9310
9311                 return this;
9312
9313         },
9314
9315         setXYZ: function ( index, x, y, z ) {
9316
9317                 index *= this.itemSize;
9318
9319                 this.array[ index + 0 ] = x;
9320                 this.array[ index + 1 ] = y;
9321                 this.array[ index + 2 ] = z;
9322
9323                 return this;
9324
9325         },
9326
9327         setXYZW: function ( index, x, y, z, w ) {
9328
9329                 index *= this.itemSize;
9330
9331                 this.array[ index + 0 ] = x;
9332                 this.array[ index + 1 ] = y;
9333                 this.array[ index + 2 ] = z;
9334                 this.array[ index + 3 ] = w;
9335
9336                 return this;
9337
9338         },
9339
9340         onUpload: function ( callback ) {
9341
9342                 this.onUploadCallback = callback;
9343
9344                 return this;
9345
9346         },
9347
9348         clone: function () {
9349
9350                 return new this.constructor( this.array, this.itemSize ).copy( this );
9351
9352         },
9353
9354         toJSON: function () {
9355
9356                 return {
9357                         itemSize: this.itemSize,
9358                         type: this.array.constructor.name,
9359                         array: Array.prototype.slice.call( this.array ),
9360                         normalized: this.normalized
9361                 };
9362
9363         }
9364
9365 } );
9366
9367 //
9368
9369 function Int8BufferAttribute( array, itemSize, normalized ) {
9370
9371         BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
9372
9373 }
9374
9375 Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9376 Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
9377
9378
9379 function Uint8BufferAttribute( array, itemSize, normalized ) {
9380
9381         BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
9382
9383 }
9384
9385 Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9386 Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
9387
9388
9389 function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
9390
9391         BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
9392
9393 }
9394
9395 Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9396 Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
9397
9398
9399 function Int16BufferAttribute( array, itemSize, normalized ) {
9400
9401         BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
9402
9403 }
9404
9405 Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9406 Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
9407
9408
9409 function Uint16BufferAttribute( array, itemSize, normalized ) {
9410
9411         BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
9412
9413 }
9414
9415 Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9416 Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
9417
9418
9419 function Int32BufferAttribute( array, itemSize, normalized ) {
9420
9421         BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
9422
9423 }
9424
9425 Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9426 Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
9427
9428
9429 function Uint32BufferAttribute( array, itemSize, normalized ) {
9430
9431         BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
9432
9433 }
9434
9435 Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9436 Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
9437
9438 function Float16BufferAttribute( array, itemSize, normalized ) {
9439
9440         BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
9441
9442 }
9443
9444 Float16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9445 Float16BufferAttribute.prototype.constructor = Float16BufferAttribute;
9446 Float16BufferAttribute.prototype.isFloat16BufferAttribute = true;
9447
9448 function Float32BufferAttribute( array, itemSize, normalized ) {
9449
9450         BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
9451
9452 }
9453
9454 Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9455 Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
9456
9457
9458 function Float64BufferAttribute( array, itemSize, normalized ) {
9459
9460         BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
9461
9462 }
9463
9464 Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9465 Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
9466
9467 class DirectGeometry {
9468
9469         constructor() {
9470
9471                 this.vertices = [];
9472                 this.normals = [];
9473                 this.colors = [];
9474                 this.uvs = [];
9475                 this.uvs2 = [];
9476
9477                 this.groups = [];
9478
9479                 this.morphTargets = {};
9480
9481                 this.skinWeights = [];
9482                 this.skinIndices = [];
9483
9484                 // this.lineDistances = [];
9485
9486                 this.boundingBox = null;
9487                 this.boundingSphere = null;
9488
9489                 // update flags
9490
9491                 this.verticesNeedUpdate = false;
9492                 this.normalsNeedUpdate = false;
9493                 this.colorsNeedUpdate = false;
9494                 this.uvsNeedUpdate = false;
9495                 this.groupsNeedUpdate = false;
9496
9497         }
9498
9499         computeGroups( geometry ) {
9500
9501                 const groups = [];
9502
9503                 let group, i;
9504                 let materialIndex = undefined;
9505
9506                 const faces = geometry.faces;
9507
9508                 for ( i = 0; i < faces.length; i ++ ) {
9509
9510                         const face = faces[ i ];
9511
9512                         // materials
9513
9514                         if ( face.materialIndex !== materialIndex ) {
9515
9516                                 materialIndex = face.materialIndex;
9517
9518                                 if ( group !== undefined ) {
9519
9520                                         group.count = ( i * 3 ) - group.start;
9521                                         groups.push( group );
9522
9523                                 }
9524
9525                                 group = {
9526                                         start: i * 3,
9527                                         materialIndex: materialIndex
9528                                 };
9529
9530                         }
9531
9532                 }
9533
9534                 if ( group !== undefined ) {
9535
9536                         group.count = ( i * 3 ) - group.start;
9537                         groups.push( group );
9538
9539                 }
9540
9541                 this.groups = groups;
9542
9543         }
9544
9545         fromGeometry( geometry ) {
9546
9547                 const faces = geometry.faces;
9548                 const vertices = geometry.vertices;
9549                 const faceVertexUvs = geometry.faceVertexUvs;
9550
9551                 const hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
9552                 const hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
9553
9554                 // morphs
9555
9556                 const morphTargets = geometry.morphTargets;
9557                 const morphTargetsLength = morphTargets.length;
9558
9559                 let morphTargetsPosition;
9560
9561                 if ( morphTargetsLength > 0 ) {
9562
9563                         morphTargetsPosition = [];
9564
9565                         for ( let i = 0; i < morphTargetsLength; i ++ ) {
9566
9567                                 morphTargetsPosition[ i ] = {
9568                                         name: morphTargets[ i ].name,
9569                                         data: []
9570                                 };
9571
9572                         }
9573
9574                         this.morphTargets.position = morphTargetsPosition;
9575
9576                 }
9577
9578                 const morphNormals = geometry.morphNormals;
9579                 const morphNormalsLength = morphNormals.length;
9580
9581                 let morphTargetsNormal;
9582
9583                 if ( morphNormalsLength > 0 ) {
9584
9585                         morphTargetsNormal = [];
9586
9587                         for ( let i = 0; i < morphNormalsLength; i ++ ) {
9588
9589                                 morphTargetsNormal[ i ] = {
9590                                         name: morphNormals[ i ].name,
9591                                         data: []
9592                                 };
9593
9594                         }
9595
9596                         this.morphTargets.normal = morphTargetsNormal;
9597
9598                 }
9599
9600                 // skins
9601
9602                 const skinIndices = geometry.skinIndices;
9603                 const skinWeights = geometry.skinWeights;
9604
9605                 const hasSkinIndices = skinIndices.length === vertices.length;
9606                 const hasSkinWeights = skinWeights.length === vertices.length;
9607
9608                 //
9609
9610                 if ( vertices.length > 0 && faces.length === 0 ) {
9611
9612                         console.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );
9613
9614                 }
9615
9616                 for ( let i = 0; i < faces.length; i ++ ) {
9617
9618                         const face = faces[ i ];
9619
9620                         this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
9621
9622                         const vertexNormals = face.vertexNormals;
9623
9624                         if ( vertexNormals.length === 3 ) {
9625
9626                                 this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
9627
9628                         } else {
9629
9630                                 const normal = face.normal;
9631
9632                                 this.normals.push( normal, normal, normal );
9633
9634                         }
9635
9636                         const vertexColors = face.vertexColors;
9637
9638                         if ( vertexColors.length === 3 ) {
9639
9640                                 this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
9641
9642                         } else {
9643
9644                                 const color = face.color;
9645
9646                                 this.colors.push( color, color, color );
9647
9648                         }
9649
9650                         if ( hasFaceVertexUv === true ) {
9651
9652                                 const vertexUvs = faceVertexUvs[ 0 ][ i ];
9653
9654                                 if ( vertexUvs !== undefined ) {
9655
9656                                         this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
9657
9658                                 } else {
9659
9660                                         console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
9661
9662                                         this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
9663
9664                                 }
9665
9666                         }
9667
9668                         if ( hasFaceVertexUv2 === true ) {
9669
9670                                 const vertexUvs = faceVertexUvs[ 1 ][ i ];
9671
9672                                 if ( vertexUvs !== undefined ) {
9673
9674                                         this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
9675
9676                                 } else {
9677
9678                                         console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
9679
9680                                         this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
9681
9682                                 }
9683
9684                         }
9685
9686                         // morphs
9687
9688                         for ( let j = 0; j < morphTargetsLength; j ++ ) {
9689
9690                                 const morphTarget = morphTargets[ j ].vertices;
9691
9692                                 morphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
9693
9694                         }
9695
9696                         for ( let j = 0; j < morphNormalsLength; j ++ ) {
9697
9698                                 const morphNormal = morphNormals[ j ].vertexNormals[ i ];
9699
9700                                 morphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );
9701
9702                         }
9703
9704                         // skins
9705
9706                         if ( hasSkinIndices ) {
9707
9708                                 this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
9709
9710                         }
9711
9712                         if ( hasSkinWeights ) {
9713
9714                                 this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
9715
9716                         }
9717
9718                 }
9719
9720                 this.computeGroups( geometry );
9721
9722                 this.verticesNeedUpdate = geometry.verticesNeedUpdate;
9723                 this.normalsNeedUpdate = geometry.normalsNeedUpdate;
9724                 this.colorsNeedUpdate = geometry.colorsNeedUpdate;
9725                 this.uvsNeedUpdate = geometry.uvsNeedUpdate;
9726                 this.groupsNeedUpdate = geometry.groupsNeedUpdate;
9727
9728                 if ( geometry.boundingSphere !== null ) {
9729
9730                         this.boundingSphere = geometry.boundingSphere.clone();
9731
9732                 }
9733
9734                 if ( geometry.boundingBox !== null ) {
9735
9736                         this.boundingBox = geometry.boundingBox.clone();
9737
9738                 }
9739
9740                 return this;
9741
9742         }
9743
9744 }
9745
9746 function arrayMax( array ) {
9747
9748         if ( array.length === 0 ) return - Infinity;
9749
9750         let max = array[ 0 ];
9751
9752         for ( let i = 1, l = array.length; i < l; ++ i ) {
9753
9754                 if ( array[ i ] > max ) max = array[ i ];
9755
9756         }
9757
9758         return max;
9759
9760 }
9761
9762 const TYPED_ARRAYS = {
9763         Int8Array: Int8Array,
9764         Uint8Array: Uint8Array,
9765         // Workaround for IE11 pre KB2929437. See #11440
9766         Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
9767         Int16Array: Int16Array,
9768         Uint16Array: Uint16Array,
9769         Int32Array: Int32Array,
9770         Uint32Array: Uint32Array,
9771         Float32Array: Float32Array,
9772         Float64Array: Float64Array
9773 };
9774
9775 function getTypedArray( type, buffer ) {
9776
9777         return new TYPED_ARRAYS[ type ]( buffer );
9778
9779 }
9780
9781 let _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
9782
9783 const _m1$2 = new Matrix4();
9784 const _obj = new Object3D();
9785 const _offset = new Vector3();
9786 const _box$2 = new Box3();
9787 const _boxMorphTargets = new Box3();
9788 const _vector$4 = new Vector3();
9789
9790 function BufferGeometry() {
9791
9792         Object.defineProperty( this, 'id', { value: _bufferGeometryId += 2 } );
9793
9794         this.uuid = MathUtils.generateUUID();
9795
9796         this.name = '';
9797         this.type = 'BufferGeometry';
9798
9799         this.index = null;
9800         this.attributes = {};
9801
9802         this.morphAttributes = {};
9803         this.morphTargetsRelative = false;
9804
9805         this.groups = [];
9806
9807         this.boundingBox = null;
9808         this.boundingSphere = null;
9809
9810         this.drawRange = { start: 0, count: Infinity };
9811
9812         this.userData = {};
9813
9814 }
9815
9816 BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
9817
9818         constructor: BufferGeometry,
9819
9820         isBufferGeometry: true,
9821
9822         getIndex: function () {
9823
9824                 return this.index;
9825
9826         },
9827
9828         setIndex: function ( index ) {
9829
9830                 if ( Array.isArray( index ) ) {
9831
9832                         this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
9833
9834                 } else {
9835
9836                         this.index = index;
9837
9838                 }
9839
9840                 return this;
9841
9842         },
9843
9844         getAttribute: function ( name ) {
9845
9846                 return this.attributes[ name ];
9847
9848         },
9849
9850         setAttribute: function ( name, attribute ) {
9851
9852                 this.attributes[ name ] = attribute;
9853
9854                 return this;
9855
9856         },
9857
9858         deleteAttribute: function ( name ) {
9859
9860                 delete this.attributes[ name ];
9861
9862                 return this;
9863
9864         },
9865
9866         hasAttribute: function ( name ) {
9867
9868                 return this.attributes[ name ] !== undefined;
9869
9870         },
9871
9872         addGroup: function ( start, count, materialIndex = 0 ) {
9873
9874                 this.groups.push( {
9875
9876                         start: start,
9877                         count: count,
9878                         materialIndex: materialIndex
9879
9880                 } );
9881
9882         },
9883
9884         clearGroups: function () {
9885
9886                 this.groups = [];
9887
9888         },
9889
9890         setDrawRange: function ( start, count ) {
9891
9892                 this.drawRange.start = start;
9893                 this.drawRange.count = count;
9894
9895         },
9896
9897         applyMatrix4: function ( matrix ) {
9898
9899                 const position = this.attributes.position;
9900
9901                 if ( position !== undefined ) {
9902
9903                         position.applyMatrix4( matrix );
9904
9905                         position.needsUpdate = true;
9906
9907                 }
9908
9909                 const normal = this.attributes.normal;
9910
9911                 if ( normal !== undefined ) {
9912
9913                         const normalMatrix = new Matrix3().getNormalMatrix( matrix );
9914
9915                         normal.applyNormalMatrix( normalMatrix );
9916
9917                         normal.needsUpdate = true;
9918
9919                 }
9920
9921                 const tangent = this.attributes.tangent;
9922
9923                 if ( tangent !== undefined ) {
9924
9925                         tangent.transformDirection( matrix );
9926
9927                         tangent.needsUpdate = true;
9928
9929                 }
9930
9931                 if ( this.boundingBox !== null ) {
9932
9933                         this.computeBoundingBox();
9934
9935                 }
9936
9937                 if ( this.boundingSphere !== null ) {
9938
9939                         this.computeBoundingSphere();
9940
9941                 }
9942
9943                 return this;
9944
9945         },
9946
9947         rotateX: function ( angle ) {
9948
9949                 // rotate geometry around world x-axis
9950
9951                 _m1$2.makeRotationX( angle );
9952
9953                 this.applyMatrix4( _m1$2 );
9954
9955                 return this;
9956
9957         },
9958
9959         rotateY: function ( angle ) {
9960
9961                 // rotate geometry around world y-axis
9962
9963                 _m1$2.makeRotationY( angle );
9964
9965                 this.applyMatrix4( _m1$2 );
9966
9967                 return this;
9968
9969         },
9970
9971         rotateZ: function ( angle ) {
9972
9973                 // rotate geometry around world z-axis
9974
9975                 _m1$2.makeRotationZ( angle );
9976
9977                 this.applyMatrix4( _m1$2 );
9978
9979                 return this;
9980
9981         },
9982
9983         translate: function ( x, y, z ) {
9984
9985                 // translate geometry
9986
9987                 _m1$2.makeTranslation( x, y, z );
9988
9989                 this.applyMatrix4( _m1$2 );
9990
9991                 return this;
9992
9993         },
9994
9995         scale: function ( x, y, z ) {
9996
9997                 // scale geometry
9998
9999                 _m1$2.makeScale( x, y, z );
10000
10001                 this.applyMatrix4( _m1$2 );
10002
10003                 return this;
10004
10005         },
10006
10007         lookAt: function ( vector ) {
10008
10009                 _obj.lookAt( vector );
10010
10011                 _obj.updateMatrix();
10012
10013                 this.applyMatrix4( _obj.matrix );
10014
10015                 return this;
10016
10017         },
10018
10019         center: function () {
10020
10021                 this.computeBoundingBox();
10022
10023                 this.boundingBox.getCenter( _offset ).negate();
10024
10025                 this.translate( _offset.x, _offset.y, _offset.z );
10026
10027                 return this;
10028
10029         },
10030
10031         setFromObject: function ( object ) {
10032
10033                 // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
10034
10035                 const geometry = object.geometry;
10036
10037                 if ( object.isPoints || object.isLine ) {
10038
10039                         const positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
10040                         const colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
10041
10042                         this.setAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
10043                         this.setAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
10044
10045                         if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
10046
10047                                 const lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
10048
10049                                 this.setAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
10050
10051                         }
10052
10053                         if ( geometry.boundingSphere !== null ) {
10054
10055                                 this.boundingSphere = geometry.boundingSphere.clone();
10056
10057                         }
10058
10059                         if ( geometry.boundingBox !== null ) {
10060
10061                                 this.boundingBox = geometry.boundingBox.clone();
10062
10063                         }
10064
10065                 } else if ( object.isMesh ) {
10066
10067                         if ( geometry && geometry.isGeometry ) {
10068
10069                                 this.fromGeometry( geometry );
10070
10071                         }
10072
10073                 }
10074
10075                 return this;
10076
10077         },
10078
10079         setFromPoints: function ( points ) {
10080
10081                 const position = [];
10082
10083                 for ( let i = 0, l = points.length; i < l; i ++ ) {
10084
10085                         const point = points[ i ];
10086                         position.push( point.x, point.y, point.z || 0 );
10087
10088                 }
10089
10090                 this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
10091
10092                 return this;
10093
10094         },
10095
10096         updateFromObject: function ( object ) {
10097
10098                 let geometry = object.geometry;
10099
10100                 if ( object.isMesh ) {
10101
10102                         let direct = geometry.__directGeometry;
10103
10104                         if ( geometry.elementsNeedUpdate === true ) {
10105
10106                                 direct = undefined;
10107                                 geometry.elementsNeedUpdate = false;
10108
10109                         }
10110
10111                         if ( direct === undefined ) {
10112
10113                                 return this.fromGeometry( geometry );
10114
10115                         }
10116
10117                         direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
10118                         direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
10119                         direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
10120                         direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
10121                         direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
10122
10123                         geometry.verticesNeedUpdate = false;
10124                         geometry.normalsNeedUpdate = false;
10125                         geometry.colorsNeedUpdate = false;
10126                         geometry.uvsNeedUpdate = false;
10127                         geometry.groupsNeedUpdate = false;
10128
10129                         geometry = direct;
10130
10131                 }
10132
10133                 if ( geometry.verticesNeedUpdate === true ) {
10134
10135                         const attribute = this.attributes.position;
10136
10137                         if ( attribute !== undefined ) {
10138
10139                                 attribute.copyVector3sArray( geometry.vertices );
10140                                 attribute.needsUpdate = true;
10141
10142                         }
10143
10144                         geometry.verticesNeedUpdate = false;
10145
10146                 }
10147
10148                 if ( geometry.normalsNeedUpdate === true ) {
10149
10150                         const attribute = this.attributes.normal;
10151
10152                         if ( attribute !== undefined ) {
10153
10154                                 attribute.copyVector3sArray( geometry.normals );
10155                                 attribute.needsUpdate = true;
10156
10157                         }
10158
10159                         geometry.normalsNeedUpdate = false;
10160
10161                 }
10162
10163                 if ( geometry.colorsNeedUpdate === true ) {
10164
10165                         const attribute = this.attributes.color;
10166
10167                         if ( attribute !== undefined ) {
10168
10169                                 attribute.copyColorsArray( geometry.colors );
10170                                 attribute.needsUpdate = true;
10171
10172                         }
10173
10174                         geometry.colorsNeedUpdate = false;
10175
10176                 }
10177
10178                 if ( geometry.uvsNeedUpdate ) {
10179
10180                         const attribute = this.attributes.uv;
10181
10182                         if ( attribute !== undefined ) {
10183
10184                                 attribute.copyVector2sArray( geometry.uvs );
10185                                 attribute.needsUpdate = true;
10186
10187                         }
10188
10189                         geometry.uvsNeedUpdate = false;
10190
10191                 }
10192
10193                 if ( geometry.lineDistancesNeedUpdate ) {
10194
10195                         const attribute = this.attributes.lineDistance;
10196
10197                         if ( attribute !== undefined ) {
10198
10199                                 attribute.copyArray( geometry.lineDistances );
10200                                 attribute.needsUpdate = true;
10201
10202                         }
10203
10204                         geometry.lineDistancesNeedUpdate = false;
10205
10206                 }
10207
10208                 if ( geometry.groupsNeedUpdate ) {
10209
10210                         geometry.computeGroups( object.geometry );
10211                         this.groups = geometry.groups;
10212
10213                         geometry.groupsNeedUpdate = false;
10214
10215                 }
10216
10217                 return this;
10218
10219         },
10220
10221         fromGeometry: function ( geometry ) {
10222
10223                 geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
10224
10225                 return this.fromDirectGeometry( geometry.__directGeometry );
10226
10227         },
10228
10229         fromDirectGeometry: function ( geometry ) {
10230
10231                 const positions = new Float32Array( geometry.vertices.length * 3 );
10232                 this.setAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
10233
10234                 if ( geometry.normals.length > 0 ) {
10235
10236                         const normals = new Float32Array( geometry.normals.length * 3 );
10237                         this.setAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
10238
10239                 }
10240
10241                 if ( geometry.colors.length > 0 ) {
10242
10243                         const colors = new Float32Array( geometry.colors.length * 3 );
10244                         this.setAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
10245
10246                 }
10247
10248                 if ( geometry.uvs.length > 0 ) {
10249
10250                         const uvs = new Float32Array( geometry.uvs.length * 2 );
10251                         this.setAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
10252
10253                 }
10254
10255                 if ( geometry.uvs2.length > 0 ) {
10256
10257                         const uvs2 = new Float32Array( geometry.uvs2.length * 2 );
10258                         this.setAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
10259
10260                 }
10261
10262                 // groups
10263
10264                 this.groups = geometry.groups;
10265
10266                 // morphs
10267
10268                 for ( const name in geometry.morphTargets ) {
10269
10270                         const array = [];
10271                         const morphTargets = geometry.morphTargets[ name ];
10272
10273                         for ( let i = 0, l = morphTargets.length; i < l; i ++ ) {
10274
10275                                 const morphTarget = morphTargets[ i ];
10276
10277                                 const attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );
10278                                 attribute.name = morphTarget.name;
10279
10280                                 array.push( attribute.copyVector3sArray( morphTarget.data ) );
10281
10282                         }
10283
10284                         this.morphAttributes[ name ] = array;
10285
10286                 }
10287
10288                 // skinning
10289
10290                 if ( geometry.skinIndices.length > 0 ) {
10291
10292                         const skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
10293                         this.setAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
10294
10295                 }
10296
10297                 if ( geometry.skinWeights.length > 0 ) {
10298
10299                         const skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
10300                         this.setAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
10301
10302                 }
10303
10304                 //
10305
10306                 if ( geometry.boundingSphere !== null ) {
10307
10308                         this.boundingSphere = geometry.boundingSphere.clone();
10309
10310                 }
10311
10312                 if ( geometry.boundingBox !== null ) {
10313
10314                         this.boundingBox = geometry.boundingBox.clone();
10315
10316                 }
10317
10318                 return this;
10319
10320         },
10321
10322         computeBoundingBox: function () {
10323
10324                 if ( this.boundingBox === null ) {
10325
10326                         this.boundingBox = new Box3();
10327
10328                 }
10329
10330                 const position = this.attributes.position;
10331                 const morphAttributesPosition = this.morphAttributes.position;
10332
10333                 if ( position && position.isGLBufferAttribute ) {
10334
10335                         console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this );
10336
10337                         this.boundingBox.set(
10338                                 new Vector3( - Infinity, - Infinity, - Infinity ),
10339                                 new Vector3( + Infinity, + Infinity, + Infinity )
10340                         );
10341
10342                         return;
10343
10344                 }
10345
10346                 if ( position !== undefined ) {
10347
10348                         this.boundingBox.setFromBufferAttribute( position );
10349
10350                         // process morph attributes if present
10351
10352                         if ( morphAttributesPosition ) {
10353
10354                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10355
10356                                         const morphAttribute = morphAttributesPosition[ i ];
10357                                         _box$2.setFromBufferAttribute( morphAttribute );
10358
10359                                         if ( this.morphTargetsRelative ) {
10360
10361                                                 _vector$4.addVectors( this.boundingBox.min, _box$2.min );
10362                                                 this.boundingBox.expandByPoint( _vector$4 );
10363
10364                                                 _vector$4.addVectors( this.boundingBox.max, _box$2.max );
10365                                                 this.boundingBox.expandByPoint( _vector$4 );
10366
10367                                         } else {
10368
10369                                                 this.boundingBox.expandByPoint( _box$2.min );
10370                                                 this.boundingBox.expandByPoint( _box$2.max );
10371
10372                                         }
10373
10374                                 }
10375
10376                         }
10377
10378                 } else {
10379
10380                         this.boundingBox.makeEmpty();
10381
10382                 }
10383
10384                 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
10385
10386                         console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
10387
10388                 }
10389
10390         },
10391
10392         computeBoundingSphere: function () {
10393
10394                 if ( this.boundingSphere === null ) {
10395
10396                         this.boundingSphere = new Sphere();
10397
10398                 }
10399
10400                 const position = this.attributes.position;
10401                 const morphAttributesPosition = this.morphAttributes.position;
10402
10403                 if ( position && position.isGLBufferAttribute ) {
10404
10405                         console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this );
10406
10407                         this.boundingSphere.set( new Vector3(), Infinity );
10408
10409                         return;
10410
10411                 }
10412
10413                 if ( position ) {
10414
10415                         // first, find the center of the bounding sphere
10416
10417                         const center = this.boundingSphere.center;
10418
10419                         _box$2.setFromBufferAttribute( position );
10420
10421                         // process morph attributes if present
10422
10423                         if ( morphAttributesPosition ) {
10424
10425                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10426
10427                                         const morphAttribute = morphAttributesPosition[ i ];
10428                                         _boxMorphTargets.setFromBufferAttribute( morphAttribute );
10429
10430                                         if ( this.morphTargetsRelative ) {
10431
10432                                                 _vector$4.addVectors( _box$2.min, _boxMorphTargets.min );
10433                                                 _box$2.expandByPoint( _vector$4 );
10434
10435                                                 _vector$4.addVectors( _box$2.max, _boxMorphTargets.max );
10436                                                 _box$2.expandByPoint( _vector$4 );
10437
10438                                         } else {
10439
10440                                                 _box$2.expandByPoint( _boxMorphTargets.min );
10441                                                 _box$2.expandByPoint( _boxMorphTargets.max );
10442
10443                                         }
10444
10445                                 }
10446
10447                         }
10448
10449                         _box$2.getCenter( center );
10450
10451                         // second, try to find a boundingSphere with a radius smaller than the
10452                         // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
10453
10454                         let maxRadiusSq = 0;
10455
10456                         for ( let i = 0, il = position.count; i < il; i ++ ) {
10457
10458                                 _vector$4.fromBufferAttribute( position, i );
10459
10460                                 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
10461
10462                         }
10463
10464                         // process morph attributes if present
10465
10466                         if ( morphAttributesPosition ) {
10467
10468                                 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10469
10470                                         const morphAttribute = morphAttributesPosition[ i ];
10471                                         const morphTargetsRelative = this.morphTargetsRelative;
10472
10473                                         for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
10474
10475                                                 _vector$4.fromBufferAttribute( morphAttribute, j );
10476
10477                                                 if ( morphTargetsRelative ) {
10478
10479                                                         _offset.fromBufferAttribute( position, j );
10480                                                         _vector$4.add( _offset );
10481
10482                                                 }
10483
10484                                                 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
10485
10486                                         }
10487
10488                                 }
10489
10490                         }
10491
10492                         this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
10493
10494                         if ( isNaN( this.boundingSphere.radius ) ) {
10495
10496                                 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
10497
10498                         }
10499
10500                 }
10501
10502         },
10503
10504         computeFaceNormals: function () {
10505
10506                 // backwards compatibility
10507
10508         },
10509
10510         computeVertexNormals: function () {
10511
10512                 const index = this.index;
10513                 const positionAttribute = this.getAttribute( 'position' );
10514
10515                 if ( positionAttribute !== undefined ) {
10516
10517                         let normalAttribute = this.getAttribute( 'normal' );
10518
10519                         if ( normalAttribute === undefined ) {
10520
10521                                 normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
10522                                 this.setAttribute( 'normal', normalAttribute );
10523
10524                         } else {
10525
10526                                 // reset existing normals to zero
10527
10528                                 for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
10529
10530                                         normalAttribute.setXYZ( i, 0, 0, 0 );
10531
10532                                 }
10533
10534                         }
10535
10536                         const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
10537                         const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
10538                         const cb = new Vector3(), ab = new Vector3();
10539
10540                         // indexed elements
10541
10542                         if ( index ) {
10543
10544                                 for ( let i = 0, il = index.count; i < il; i += 3 ) {
10545
10546                                         const vA = index.getX( i + 0 );
10547                                         const vB = index.getX( i + 1 );
10548                                         const vC = index.getX( i + 2 );
10549
10550                                         pA.fromBufferAttribute( positionAttribute, vA );
10551                                         pB.fromBufferAttribute( positionAttribute, vB );
10552                                         pC.fromBufferAttribute( positionAttribute, vC );
10553
10554                                         cb.subVectors( pC, pB );
10555                                         ab.subVectors( pA, pB );
10556                                         cb.cross( ab );
10557
10558                                         nA.fromBufferAttribute( normalAttribute, vA );
10559                                         nB.fromBufferAttribute( normalAttribute, vB );
10560                                         nC.fromBufferAttribute( normalAttribute, vC );
10561
10562                                         nA.add( cb );
10563                                         nB.add( cb );
10564                                         nC.add( cb );
10565
10566                                         normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
10567                                         normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
10568                                         normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
10569
10570                                 }
10571
10572                         } else {
10573
10574                                 // non-indexed elements (unconnected triangle soup)
10575
10576                                 for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
10577
10578                                         pA.fromBufferAttribute( positionAttribute, i + 0 );
10579                                         pB.fromBufferAttribute( positionAttribute, i + 1 );
10580                                         pC.fromBufferAttribute( positionAttribute, i + 2 );
10581
10582                                         cb.subVectors( pC, pB );
10583                                         ab.subVectors( pA, pB );
10584                                         cb.cross( ab );
10585
10586                                         normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
10587                                         normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
10588                                         normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
10589
10590                                 }
10591
10592                         }
10593
10594                         this.normalizeNormals();
10595
10596                         normalAttribute.needsUpdate = true;
10597
10598                 }
10599
10600         },
10601
10602         merge: function ( geometry, offset ) {
10603
10604                 if ( ! ( geometry && geometry.isBufferGeometry ) ) {
10605
10606                         console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
10607                         return;
10608
10609                 }
10610
10611                 if ( offset === undefined ) {
10612
10613                         offset = 0;
10614
10615                         console.warn(
10616                                 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
10617                                 + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
10618                         );
10619
10620                 }
10621
10622                 const attributes = this.attributes;
10623
10624                 for ( const key in attributes ) {
10625
10626                         if ( geometry.attributes[ key ] === undefined ) continue;
10627
10628                         const attribute1 = attributes[ key ];
10629                         const attributeArray1 = attribute1.array;
10630
10631                         const attribute2 = geometry.attributes[ key ];
10632                         const attributeArray2 = attribute2.array;
10633
10634                         const attributeOffset = attribute2.itemSize * offset;
10635                         const length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );
10636
10637                         for ( let i = 0, j = attributeOffset; i < length; i ++, j ++ ) {
10638
10639                                 attributeArray1[ j ] = attributeArray2[ i ];
10640
10641                         }
10642
10643                 }
10644
10645                 return this;
10646
10647         },
10648
10649         normalizeNormals: function () {
10650
10651                 const normals = this.attributes.normal;
10652
10653                 for ( let i = 0, il = normals.count; i < il; i ++ ) {
10654
10655                         _vector$4.fromBufferAttribute( normals, i );
10656
10657                         _vector$4.normalize();
10658
10659                         normals.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );
10660
10661                 }
10662
10663         },
10664
10665         toNonIndexed: function () {
10666
10667                 function convertBufferAttribute( attribute, indices ) {
10668
10669                         const array = attribute.array;
10670                         const itemSize = attribute.itemSize;
10671                         const normalized = attribute.normalized;
10672
10673                         const array2 = new array.constructor( indices.length * itemSize );
10674
10675                         let index = 0, index2 = 0;
10676
10677                         for ( let i = 0, l = indices.length; i < l; i ++ ) {
10678
10679                                 index = indices[ i ] * itemSize;
10680
10681                                 for ( let j = 0; j < itemSize; j ++ ) {
10682
10683                                         array2[ index2 ++ ] = array[ index ++ ];
10684
10685                                 }
10686
10687                         }
10688
10689                         return new BufferAttribute( array2, itemSize, normalized );
10690
10691                 }
10692
10693                 //
10694
10695                 if ( this.index === null ) {
10696
10697                         console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
10698                         return this;
10699
10700                 }
10701
10702                 const geometry2 = new BufferGeometry();
10703
10704                 const indices = this.index.array;
10705                 const attributes = this.attributes;
10706
10707                 // attributes
10708
10709                 for ( const name in attributes ) {
10710
10711                         const attribute = attributes[ name ];
10712
10713                         const newAttribute = convertBufferAttribute( attribute, indices );
10714
10715                         geometry2.setAttribute( name, newAttribute );
10716
10717                 }
10718
10719                 // morph attributes
10720
10721                 const morphAttributes = this.morphAttributes;
10722
10723                 for ( const name in morphAttributes ) {
10724
10725                         const morphArray = [];
10726                         const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
10727
10728                         for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
10729
10730                                 const attribute = morphAttribute[ i ];
10731
10732                                 const newAttribute = convertBufferAttribute( attribute, indices );
10733
10734                                 morphArray.push( newAttribute );
10735
10736                         }
10737
10738                         geometry2.morphAttributes[ name ] = morphArray;
10739
10740                 }
10741
10742                 geometry2.morphTargetsRelative = this.morphTargetsRelative;
10743
10744                 // groups
10745
10746                 const groups = this.groups;
10747
10748                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
10749
10750                         const group = groups[ i ];
10751                         geometry2.addGroup( group.start, group.count, group.materialIndex );
10752
10753                 }
10754
10755                 return geometry2;
10756
10757         },
10758
10759         toJSON: function () {
10760
10761                 const data = {
10762                         metadata: {
10763                                 version: 4.5,
10764                                 type: 'BufferGeometry',
10765                                 generator: 'BufferGeometry.toJSON'
10766                         }
10767                 };
10768
10769                 // standard BufferGeometry serialization
10770
10771                 data.uuid = this.uuid;
10772                 data.type = this.type;
10773                 if ( this.name !== '' ) data.name = this.name;
10774                 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
10775
10776                 if ( this.parameters !== undefined ) {
10777
10778                         const parameters = this.parameters;
10779
10780                         for ( const key in parameters ) {
10781
10782                                 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
10783
10784                         }
10785
10786                         return data;
10787
10788                 }
10789
10790                 data.data = { attributes: {} };
10791
10792                 const index = this.index;
10793
10794                 if ( index !== null ) {
10795
10796                         data.data.index = {
10797                                 type: index.array.constructor.name,
10798                                 array: Array.prototype.slice.call( index.array )
10799                         };
10800
10801                 }
10802
10803                 const attributes = this.attributes;
10804
10805                 for ( const key in attributes ) {
10806
10807                         const attribute = attributes[ key ];
10808
10809                         const attributeData = attribute.toJSON( data.data );
10810
10811                         if ( attribute.name !== '' ) attributeData.name = attribute.name;
10812
10813                         data.data.attributes[ key ] = attributeData;
10814
10815                 }
10816
10817                 const morphAttributes = {};
10818                 let hasMorphAttributes = false;
10819
10820                 for ( const key in this.morphAttributes ) {
10821
10822                         const attributeArray = this.morphAttributes[ key ];
10823
10824                         const array = [];
10825
10826                         for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
10827
10828                                 const attribute = attributeArray[ i ];
10829
10830                                 const attributeData = attribute.toJSON( data.data );
10831
10832                                 if ( attribute.name !== '' ) attributeData.name = attribute.name;
10833
10834                                 array.push( attributeData );
10835
10836                         }
10837
10838                         if ( array.length > 0 ) {
10839
10840                                 morphAttributes[ key ] = array;
10841
10842                                 hasMorphAttributes = true;
10843
10844                         }
10845
10846                 }
10847
10848                 if ( hasMorphAttributes ) {
10849
10850                         data.data.morphAttributes = morphAttributes;
10851                         data.data.morphTargetsRelative = this.morphTargetsRelative;
10852
10853                 }
10854
10855                 const groups = this.groups;
10856
10857                 if ( groups.length > 0 ) {
10858
10859                         data.data.groups = JSON.parse( JSON.stringify( groups ) );
10860
10861                 }
10862
10863                 const boundingSphere = this.boundingSphere;
10864
10865                 if ( boundingSphere !== null ) {
10866
10867                         data.data.boundingSphere = {
10868                                 center: boundingSphere.center.toArray(),
10869                                 radius: boundingSphere.radius
10870                         };
10871
10872                 }
10873
10874                 return data;
10875
10876         },
10877
10878         clone: function () {
10879
10880                 /*
10881                  // Handle primitives
10882
10883                  const parameters = this.parameters;
10884
10885                  if ( parameters !== undefined ) {
10886
10887                  const values = [];
10888
10889                  for ( const key in parameters ) {
10890
10891                  values.push( parameters[ key ] );
10892
10893                  }
10894
10895                  const geometry = Object.create( this.constructor.prototype );
10896                  this.constructor.apply( geometry, values );
10897                  return geometry;
10898
10899                  }
10900
10901                  return new this.constructor().copy( this );
10902                  */
10903
10904                 return new BufferGeometry().copy( this );
10905
10906         },
10907
10908         copy: function ( source ) {
10909
10910                 // reset
10911
10912                 this.index = null;
10913                 this.attributes = {};
10914                 this.morphAttributes = {};
10915                 this.groups = [];
10916                 this.boundingBox = null;
10917                 this.boundingSphere = null;
10918
10919                 // used for storing cloned, shared data
10920
10921                 const data = {};
10922
10923                 // name
10924
10925                 this.name = source.name;
10926
10927                 // index
10928
10929                 const index = source.index;
10930
10931                 if ( index !== null ) {
10932
10933                         this.setIndex( index.clone( data ) );
10934
10935                 }
10936
10937                 // attributes
10938
10939                 const attributes = source.attributes;
10940
10941                 for ( const name in attributes ) {
10942
10943                         const attribute = attributes[ name ];
10944                         this.setAttribute( name, attribute.clone( data ) );
10945
10946                 }
10947
10948                 // morph attributes
10949
10950                 const morphAttributes = source.morphAttributes;
10951
10952                 for ( const name in morphAttributes ) {
10953
10954                         const array = [];
10955                         const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
10956
10957                         for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
10958
10959                                 array.push( morphAttribute[ i ].clone( data ) );
10960
10961                         }
10962
10963                         this.morphAttributes[ name ] = array;
10964
10965                 }
10966
10967                 this.morphTargetsRelative = source.morphTargetsRelative;
10968
10969                 // groups
10970
10971                 const groups = source.groups;
10972
10973                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
10974
10975                         const group = groups[ i ];
10976                         this.addGroup( group.start, group.count, group.materialIndex );
10977
10978                 }
10979
10980                 // bounding box
10981
10982                 const boundingBox = source.boundingBox;
10983
10984                 if ( boundingBox !== null ) {
10985
10986                         this.boundingBox = boundingBox.clone();
10987
10988                 }
10989
10990                 // bounding sphere
10991
10992                 const boundingSphere = source.boundingSphere;
10993
10994                 if ( boundingSphere !== null ) {
10995
10996                         this.boundingSphere = boundingSphere.clone();
10997
10998                 }
10999
11000                 // draw range
11001
11002                 this.drawRange.start = source.drawRange.start;
11003                 this.drawRange.count = source.drawRange.count;
11004
11005                 // user data
11006
11007                 this.userData = source.userData;
11008
11009                 return this;
11010
11011         },
11012
11013         dispose: function () {
11014
11015                 this.dispatchEvent( { type: 'dispose' } );
11016
11017         }
11018
11019 } );
11020
11021 const _inverseMatrix = new Matrix4();
11022 const _ray = new Ray();
11023 const _sphere = new Sphere();
11024
11025 const _vA = new Vector3();
11026 const _vB = new Vector3();
11027 const _vC = new Vector3();
11028
11029 const _tempA = new Vector3();
11030 const _tempB = new Vector3();
11031 const _tempC = new Vector3();
11032
11033 const _morphA = new Vector3();
11034 const _morphB = new Vector3();
11035 const _morphC = new Vector3();
11036
11037 const _uvA = new Vector2();
11038 const _uvB = new Vector2();
11039 const _uvC = new Vector2();
11040
11041 const _intersectionPoint = new Vector3();
11042 const _intersectionPointWorld = new Vector3();
11043
11044 function Mesh( geometry, material ) {
11045
11046         Object3D.call( this );
11047
11048         this.type = 'Mesh';
11049
11050         this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
11051         this.material = material !== undefined ? material : new MeshBasicMaterial();
11052
11053         this.updateMorphTargets();
11054
11055 }
11056
11057 Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
11058
11059         constructor: Mesh,
11060
11061         isMesh: true,
11062
11063         copy: function ( source ) {
11064
11065                 Object3D.prototype.copy.call( this, source );
11066
11067                 if ( source.morphTargetInfluences !== undefined ) {
11068
11069                         this.morphTargetInfluences = source.morphTargetInfluences.slice();
11070
11071                 }
11072
11073                 if ( source.morphTargetDictionary !== undefined ) {
11074
11075                         this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
11076
11077                 }
11078
11079                 this.material = source.material;
11080                 this.geometry = source.geometry;
11081
11082                 return this;
11083
11084         },
11085
11086         updateMorphTargets: function () {
11087
11088                 const geometry = this.geometry;
11089
11090                 if ( geometry.isBufferGeometry ) {
11091
11092                         const morphAttributes = geometry.morphAttributes;
11093                         const keys = Object.keys( morphAttributes );
11094
11095                         if ( keys.length > 0 ) {
11096
11097                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
11098
11099                                 if ( morphAttribute !== undefined ) {
11100
11101                                         this.morphTargetInfluences = [];
11102                                         this.morphTargetDictionary = {};
11103
11104                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
11105
11106                                                 const name = morphAttribute[ m ].name || String( m );
11107
11108                                                 this.morphTargetInfluences.push( 0 );
11109                                                 this.morphTargetDictionary[ name ] = m;
11110
11111                                         }
11112
11113                                 }
11114
11115                         }
11116
11117                 } else {
11118
11119                         const morphTargets = geometry.morphTargets;
11120
11121                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
11122
11123                                 console.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
11124
11125                         }
11126
11127                 }
11128
11129         },
11130
11131         raycast: function ( raycaster, intersects ) {
11132
11133                 const geometry = this.geometry;
11134                 const material = this.material;
11135                 const matrixWorld = this.matrixWorld;
11136
11137                 if ( material === undefined ) return;
11138
11139                 // Checking boundingSphere distance to ray
11140
11141                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
11142
11143                 _sphere.copy( geometry.boundingSphere );
11144                 _sphere.applyMatrix4( matrixWorld );
11145
11146                 if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
11147
11148                 //
11149
11150                 _inverseMatrix.copy( matrixWorld ).invert();
11151                 _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
11152
11153                 // Check boundingBox before continuing
11154
11155                 if ( geometry.boundingBox !== null ) {
11156
11157                         if ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;
11158
11159                 }
11160
11161                 let intersection;
11162
11163                 if ( geometry.isBufferGeometry ) {
11164
11165                         const index = geometry.index;
11166                         const position = geometry.attributes.position;
11167                         const morphPosition = geometry.morphAttributes.position;
11168                         const morphTargetsRelative = geometry.morphTargetsRelative;
11169                         const uv = geometry.attributes.uv;
11170                         const uv2 = geometry.attributes.uv2;
11171                         const groups = geometry.groups;
11172                         const drawRange = geometry.drawRange;
11173
11174                         if ( index !== null ) {
11175
11176                                 // indexed buffer geometry
11177
11178                                 if ( Array.isArray( material ) ) {
11179
11180                                         for ( let i = 0, il = groups.length; i < il; i ++ ) {
11181
11182                                                 const group = groups[ i ];
11183                                                 const groupMaterial = material[ group.materialIndex ];
11184
11185                                                 const start = Math.max( group.start, drawRange.start );
11186                                                 const end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
11187
11188                                                 for ( let j = start, jl = end; j < jl; j += 3 ) {
11189
11190                                                         const a = index.getX( j );
11191                                                         const b = index.getX( j + 1 );
11192                                                         const c = index.getX( j + 2 );
11193
11194                                                         intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
11195
11196                                                         if ( intersection ) {
11197
11198                                                                 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
11199                                                                 intersection.face.materialIndex = group.materialIndex;
11200                                                                 intersects.push( intersection );
11201
11202                                                         }
11203
11204                                                 }
11205
11206                                         }
11207
11208                                 } else {
11209
11210                                         const start = Math.max( 0, drawRange.start );
11211                                         const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
11212
11213                                         for ( let i = start, il = end; i < il; i += 3 ) {
11214
11215                                                 const a = index.getX( i );
11216                                                 const b = index.getX( i + 1 );
11217                                                 const c = index.getX( i + 2 );
11218
11219                                                 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
11220
11221                                                 if ( intersection ) {
11222
11223                                                         intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
11224                                                         intersects.push( intersection );
11225
11226                                                 }
11227
11228                                         }
11229
11230                                 }
11231
11232                         } else if ( position !== undefined ) {
11233
11234                                 // non-indexed buffer geometry
11235
11236                                 if ( Array.isArray( material ) ) {
11237
11238                                         for ( let i = 0, il = groups.length; i < il; i ++ ) {
11239
11240                                                 const group = groups[ i ];
11241                                                 const groupMaterial = material[ group.materialIndex ];
11242
11243                                                 const start = Math.max( group.start, drawRange.start );
11244                                                 const end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
11245
11246                                                 for ( let j = start, jl = end; j < jl; j += 3 ) {
11247
11248                                                         const a = j;
11249                                                         const b = j + 1;
11250                                                         const c = j + 2;
11251
11252                                                         intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
11253
11254                                                         if ( intersection ) {
11255
11256                                                                 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
11257                                                                 intersection.face.materialIndex = group.materialIndex;
11258                                                                 intersects.push( intersection );
11259
11260                                                         }
11261
11262                                                 }
11263
11264                                         }
11265
11266                                 } else {
11267
11268                                         const start = Math.max( 0, drawRange.start );
11269                                         const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
11270
11271                                         for ( let i = start, il = end; i < il; i += 3 ) {
11272
11273                                                 const a = i;
11274                                                 const b = i + 1;
11275                                                 const c = i + 2;
11276
11277                                                 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
11278
11279                                                 if ( intersection ) {
11280
11281                                                         intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
11282                                                         intersects.push( intersection );
11283
11284                                                 }
11285
11286                                         }
11287
11288                                 }
11289
11290                         }
11291
11292                 } else if ( geometry.isGeometry ) {
11293
11294                         const isMultiMaterial = Array.isArray( material );
11295
11296                         const vertices = geometry.vertices;
11297                         const faces = geometry.faces;
11298                         let uvs;
11299
11300                         const faceVertexUvs = geometry.faceVertexUvs[ 0 ];
11301                         if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
11302
11303                         for ( let f = 0, fl = faces.length; f < fl; f ++ ) {
11304
11305                                 const face = faces[ f ];
11306                                 const faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
11307
11308                                 if ( faceMaterial === undefined ) continue;
11309
11310                                 const fvA = vertices[ face.a ];
11311                                 const fvB = vertices[ face.b ];
11312                                 const fvC = vertices[ face.c ];
11313
11314                                 intersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );
11315
11316                                 if ( intersection ) {
11317
11318                                         if ( uvs && uvs[ f ] ) {
11319
11320                                                 const uvs_f = uvs[ f ];
11321                                                 _uvA.copy( uvs_f[ 0 ] );
11322                                                 _uvB.copy( uvs_f[ 1 ] );
11323                                                 _uvC.copy( uvs_f[ 2 ] );
11324
11325                                                 intersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );
11326
11327                                         }
11328
11329                                         intersection.face = face;
11330                                         intersection.faceIndex = f;
11331                                         intersects.push( intersection );
11332
11333                                 }
11334
11335                         }
11336
11337                 }
11338
11339         }
11340
11341 } );
11342
11343 function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
11344
11345         let intersect;
11346
11347         if ( material.side === BackSide ) {
11348
11349                 intersect = ray.intersectTriangle( pC, pB, pA, true, point );
11350
11351         } else {
11352
11353                 intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
11354
11355         }
11356
11357         if ( intersect === null ) return null;
11358
11359         _intersectionPointWorld.copy( point );
11360         _intersectionPointWorld.applyMatrix4( object.matrixWorld );
11361
11362         const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
11363
11364         if ( distance < raycaster.near || distance > raycaster.far ) return null;
11365
11366         return {
11367                 distance: distance,
11368                 point: _intersectionPointWorld.clone(),
11369                 object: object
11370         };
11371
11372 }
11373
11374 function checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {
11375
11376         _vA.fromBufferAttribute( position, a );
11377         _vB.fromBufferAttribute( position, b );
11378         _vC.fromBufferAttribute( position, c );
11379
11380         const morphInfluences = object.morphTargetInfluences;
11381
11382         if ( material.morphTargets && morphPosition && morphInfluences ) {
11383
11384                 _morphA.set( 0, 0, 0 );
11385                 _morphB.set( 0, 0, 0 );
11386                 _morphC.set( 0, 0, 0 );
11387
11388                 for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
11389
11390                         const influence = morphInfluences[ i ];
11391                         const morphAttribute = morphPosition[ i ];
11392
11393                         if ( influence === 0 ) continue;
11394
11395                         _tempA.fromBufferAttribute( morphAttribute, a );
11396                         _tempB.fromBufferAttribute( morphAttribute, b );
11397                         _tempC.fromBufferAttribute( morphAttribute, c );
11398
11399                         if ( morphTargetsRelative ) {
11400
11401                                 _morphA.addScaledVector( _tempA, influence );
11402                                 _morphB.addScaledVector( _tempB, influence );
11403                                 _morphC.addScaledVector( _tempC, influence );
11404
11405                         } else {
11406
11407                                 _morphA.addScaledVector( _tempA.sub( _vA ), influence );
11408                                 _morphB.addScaledVector( _tempB.sub( _vB ), influence );
11409                                 _morphC.addScaledVector( _tempC.sub( _vC ), influence );
11410
11411                         }
11412
11413                 }
11414
11415                 _vA.add( _morphA );
11416                 _vB.add( _morphB );
11417                 _vC.add( _morphC );
11418
11419         }
11420
11421         if ( object.isSkinnedMesh ) {
11422
11423                 object.boneTransform( a, _vA );
11424                 object.boneTransform( b, _vB );
11425                 object.boneTransform( c, _vC );
11426
11427         }
11428
11429         const intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
11430
11431         if ( intersection ) {
11432
11433                 if ( uv ) {
11434
11435                         _uvA.fromBufferAttribute( uv, a );
11436                         _uvB.fromBufferAttribute( uv, b );
11437                         _uvC.fromBufferAttribute( uv, c );
11438
11439                         intersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
11440
11441                 }
11442
11443                 if ( uv2 ) {
11444
11445                         _uvA.fromBufferAttribute( uv2, a );
11446                         _uvB.fromBufferAttribute( uv2, b );
11447                         _uvC.fromBufferAttribute( uv2, c );
11448
11449                         intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
11450
11451                 }
11452
11453                 const face = new Face3( a, b, c );
11454                 Triangle.getNormal( _vA, _vB, _vC, face.normal );
11455
11456                 intersection.face = face;
11457
11458         }
11459
11460         return intersection;
11461
11462 }
11463
11464 class BoxBufferGeometry extends BufferGeometry {
11465
11466         constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
11467
11468                 super();
11469
11470                 this.type = 'BoxBufferGeometry';
11471
11472                 this.parameters = {
11473                         width: width,
11474                         height: height,
11475                         depth: depth,
11476                         widthSegments: widthSegments,
11477                         heightSegments: heightSegments,
11478                         depthSegments: depthSegments
11479                 };
11480
11481                 const scope = this;
11482
11483                 // segments
11484
11485                 widthSegments = Math.floor( widthSegments );
11486                 heightSegments = Math.floor( heightSegments );
11487                 depthSegments = Math.floor( depthSegments );
11488
11489                 // buffers
11490
11491                 const indices = [];
11492                 const vertices = [];
11493                 const normals = [];
11494                 const uvs = [];
11495
11496                 // helper variables
11497
11498                 let numberOfVertices = 0;
11499                 let groupStart = 0;
11500
11501                 // build each side of the box geometry
11502
11503                 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
11504                 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
11505                 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
11506                 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
11507                 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
11508                 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
11509
11510                 // build geometry
11511
11512                 this.setIndex( indices );
11513                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
11514                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
11515                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
11516
11517                 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
11518
11519                         const segmentWidth = width / gridX;
11520                         const segmentHeight = height / gridY;
11521
11522                         const widthHalf = width / 2;
11523                         const heightHalf = height / 2;
11524                         const depthHalf = depth / 2;
11525
11526                         const gridX1 = gridX + 1;
11527                         const gridY1 = gridY + 1;
11528
11529                         let vertexCounter = 0;
11530                         let groupCount = 0;
11531
11532                         const vector = new Vector3();
11533
11534                         // generate vertices, normals and uvs
11535
11536                         for ( let iy = 0; iy < gridY1; iy ++ ) {
11537
11538                                 const y = iy * segmentHeight - heightHalf;
11539
11540                                 for ( let ix = 0; ix < gridX1; ix ++ ) {
11541
11542                                         const x = ix * segmentWidth - widthHalf;
11543
11544                                         // set values to correct vector component
11545
11546                                         vector[ u ] = x * udir;
11547                                         vector[ v ] = y * vdir;
11548                                         vector[ w ] = depthHalf;
11549
11550                                         // now apply vector to vertex buffer
11551
11552                                         vertices.push( vector.x, vector.y, vector.z );
11553
11554                                         // set values to correct vector component
11555
11556                                         vector[ u ] = 0;
11557                                         vector[ v ] = 0;
11558                                         vector[ w ] = depth > 0 ? 1 : - 1;
11559
11560                                         // now apply vector to normal buffer
11561
11562                                         normals.push( vector.x, vector.y, vector.z );
11563
11564                                         // uvs
11565
11566                                         uvs.push( ix / gridX );
11567                                         uvs.push( 1 - ( iy / gridY ) );
11568
11569                                         // counters
11570
11571                                         vertexCounter += 1;
11572
11573                                 }
11574
11575                         }
11576
11577                         // indices
11578
11579                         // 1. you need three indices to draw a single face
11580                         // 2. a single segment consists of two faces
11581                         // 3. so we need to generate six (2*3) indices per segment
11582
11583                         for ( let iy = 0; iy < gridY; iy ++ ) {
11584
11585                                 for ( let ix = 0; ix < gridX; ix ++ ) {
11586
11587                                         const a = numberOfVertices + ix + gridX1 * iy;
11588                                         const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
11589                                         const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
11590                                         const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
11591
11592                                         // faces
11593
11594                                         indices.push( a, b, d );
11595                                         indices.push( b, c, d );
11596
11597                                         // increase counter
11598
11599                                         groupCount += 6;
11600
11601                                 }
11602
11603                         }
11604
11605                         // add a group to the geometry. this will ensure multi material support
11606
11607                         scope.addGroup( groupStart, groupCount, materialIndex );
11608
11609                         // calculate new start value for groups
11610
11611                         groupStart += groupCount;
11612
11613                         // update total number of vertices
11614
11615                         numberOfVertices += vertexCounter;
11616
11617                 }
11618
11619         }
11620
11621 }
11622
11623 /**
11624  * Uniform Utilities
11625  */
11626
11627 function cloneUniforms( src ) {
11628
11629         const dst = {};
11630
11631         for ( const u in src ) {
11632
11633                 dst[ u ] = {};
11634
11635                 for ( const p in src[ u ] ) {
11636
11637                         const property = src[ u ][ p ];
11638
11639                         if ( property && ( property.isColor ||
11640                                 property.isMatrix3 || property.isMatrix4 ||
11641                                 property.isVector2 || property.isVector3 || property.isVector4 ||
11642                                 property.isTexture ) ) {
11643
11644                                 dst[ u ][ p ] = property.clone();
11645
11646                         } else if ( Array.isArray( property ) ) {
11647
11648                                 dst[ u ][ p ] = property.slice();
11649
11650                         } else {
11651
11652                                 dst[ u ][ p ] = property;
11653
11654                         }
11655
11656                 }
11657
11658         }
11659
11660         return dst;
11661
11662 }
11663
11664 function mergeUniforms( uniforms ) {
11665
11666         const merged = {};
11667
11668         for ( let u = 0; u < uniforms.length; u ++ ) {
11669
11670                 const tmp = cloneUniforms( uniforms[ u ] );
11671
11672                 for ( const p in tmp ) {
11673
11674                         merged[ p ] = tmp[ p ];
11675
11676                 }
11677
11678         }
11679
11680         return merged;
11681
11682 }
11683
11684 // Legacy
11685
11686 const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
11687
11688 var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
11689
11690 var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
11691
11692 /**
11693  * parameters = {
11694  *  defines: { "label" : "value" },
11695  *  uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
11696  *
11697  *  fragmentShader: <string>,
11698  *  vertexShader: <string>,
11699  *
11700  *  wireframe: <boolean>,
11701  *  wireframeLinewidth: <float>,
11702  *
11703  *  lights: <bool>,
11704  *
11705  *  skinning: <bool>,
11706  *  morphTargets: <bool>,
11707  *  morphNormals: <bool>
11708  * }
11709  */
11710
11711 function ShaderMaterial( parameters ) {
11712
11713         Material.call( this );
11714
11715         this.type = 'ShaderMaterial';
11716
11717         this.defines = {};
11718         this.uniforms = {};
11719
11720         this.vertexShader = default_vertex;
11721         this.fragmentShader = default_fragment;
11722
11723         this.linewidth = 1;
11724
11725         this.wireframe = false;
11726         this.wireframeLinewidth = 1;
11727
11728         this.fog = false; // set to use scene fog
11729         this.lights = false; // set to use scene lights
11730         this.clipping = false; // set to use user-defined clipping planes
11731
11732         this.skinning = false; // set to use skinning attribute streams
11733         this.morphTargets = false; // set to use morph targets
11734         this.morphNormals = false; // set to use morph normals
11735
11736         this.extensions = {
11737                 derivatives: false, // set to use derivatives
11738                 fragDepth: false, // set to use fragment depth values
11739                 drawBuffers: false, // set to use draw buffers
11740                 shaderTextureLOD: false // set to use shader texture LOD
11741         };
11742
11743         // When rendered geometry doesn't include these attributes but the material does,
11744         // use these default values in WebGL. This avoids errors when buffer data is missing.
11745         this.defaultAttributeValues = {
11746                 'color': [ 1, 1, 1 ],
11747                 'uv': [ 0, 0 ],
11748                 'uv2': [ 0, 0 ]
11749         };
11750
11751         this.index0AttributeName = undefined;
11752         this.uniformsNeedUpdate = false;
11753
11754         this.glslVersion = null;
11755
11756         if ( parameters !== undefined ) {
11757
11758                 if ( parameters.attributes !== undefined ) {
11759
11760                         console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
11761
11762                 }
11763
11764                 this.setValues( parameters );
11765
11766         }
11767
11768 }
11769
11770 ShaderMaterial.prototype = Object.create( Material.prototype );
11771 ShaderMaterial.prototype.constructor = ShaderMaterial;
11772
11773 ShaderMaterial.prototype.isShaderMaterial = true;
11774
11775 ShaderMaterial.prototype.copy = function ( source ) {
11776
11777         Material.prototype.copy.call( this, source );
11778
11779         this.fragmentShader = source.fragmentShader;
11780         this.vertexShader = source.vertexShader;
11781
11782         this.uniforms = cloneUniforms( source.uniforms );
11783
11784         this.defines = Object.assign( {}, source.defines );
11785
11786         this.wireframe = source.wireframe;
11787         this.wireframeLinewidth = source.wireframeLinewidth;
11788
11789         this.lights = source.lights;
11790         this.clipping = source.clipping;
11791
11792         this.skinning = source.skinning;
11793
11794         this.morphTargets = source.morphTargets;
11795         this.morphNormals = source.morphNormals;
11796
11797         this.extensions = Object.assign( {}, source.extensions );
11798
11799         this.glslVersion = source.glslVersion;
11800
11801         return this;
11802
11803 };
11804
11805 ShaderMaterial.prototype.toJSON = function ( meta ) {
11806
11807         const data = Material.prototype.toJSON.call( this, meta );
11808
11809         data.glslVersion = this.glslVersion;
11810         data.uniforms = {};
11811
11812         for ( const name in this.uniforms ) {
11813
11814                 const uniform = this.uniforms[ name ];
11815                 const value = uniform.value;
11816
11817                 if ( value && value.isTexture ) {
11818
11819                         data.uniforms[ name ] = {
11820                                 type: 't',
11821                                 value: value.toJSON( meta ).uuid
11822                         };
11823
11824                 } else if ( value && value.isColor ) {
11825
11826                         data.uniforms[ name ] = {
11827                                 type: 'c',
11828                                 value: value.getHex()
11829                         };
11830
11831                 } else if ( value && value.isVector2 ) {
11832
11833                         data.uniforms[ name ] = {
11834                                 type: 'v2',
11835                                 value: value.toArray()
11836                         };
11837
11838                 } else if ( value && value.isVector3 ) {
11839
11840                         data.uniforms[ name ] = {
11841                                 type: 'v3',
11842                                 value: value.toArray()
11843                         };
11844
11845                 } else if ( value && value.isVector4 ) {
11846
11847                         data.uniforms[ name ] = {
11848                                 type: 'v4',
11849                                 value: value.toArray()
11850                         };
11851
11852                 } else if ( value && value.isMatrix3 ) {
11853
11854                         data.uniforms[ name ] = {
11855                                 type: 'm3',
11856                                 value: value.toArray()
11857                         };
11858
11859                 } else if ( value && value.isMatrix4 ) {
11860
11861                         data.uniforms[ name ] = {
11862                                 type: 'm4',
11863                                 value: value.toArray()
11864                         };
11865
11866                 } else {
11867
11868                         data.uniforms[ name ] = {
11869                                 value: value
11870                         };
11871
11872                         // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
11873
11874                 }
11875
11876         }
11877
11878         if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
11879
11880         data.vertexShader = this.vertexShader;
11881         data.fragmentShader = this.fragmentShader;
11882
11883         const extensions = {};
11884
11885         for ( const key in this.extensions ) {
11886
11887                 if ( this.extensions[ key ] === true ) extensions[ key ] = true;
11888
11889         }
11890
11891         if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
11892
11893         return data;
11894
11895 };
11896
11897 function Camera() {
11898
11899         Object3D.call( this );
11900
11901         this.type = 'Camera';
11902
11903         this.matrixWorldInverse = new Matrix4();
11904
11905         this.projectionMatrix = new Matrix4();
11906         this.projectionMatrixInverse = new Matrix4();
11907
11908 }
11909
11910 Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
11911
11912         constructor: Camera,
11913
11914         isCamera: true,
11915
11916         copy: function ( source, recursive ) {
11917
11918                 Object3D.prototype.copy.call( this, source, recursive );
11919
11920                 this.matrixWorldInverse.copy( source.matrixWorldInverse );
11921
11922                 this.projectionMatrix.copy( source.projectionMatrix );
11923                 this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
11924
11925                 return this;
11926
11927         },
11928
11929         getWorldDirection: function ( target ) {
11930
11931                 if ( target === undefined ) {
11932
11933                         console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
11934                         target = new Vector3();
11935
11936                 }
11937
11938                 this.updateWorldMatrix( true, false );
11939
11940                 const e = this.matrixWorld.elements;
11941
11942                 return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();
11943
11944         },
11945
11946         updateMatrixWorld: function ( force ) {
11947
11948                 Object3D.prototype.updateMatrixWorld.call( this, force );
11949
11950                 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
11951
11952         },
11953
11954         updateWorldMatrix: function ( updateParents, updateChildren ) {
11955
11956                 Object3D.prototype.updateWorldMatrix.call( this, updateParents, updateChildren );
11957
11958                 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
11959
11960         },
11961
11962         clone: function () {
11963
11964                 return new this.constructor().copy( this );
11965
11966         }
11967
11968 } );
11969
11970 function PerspectiveCamera( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
11971
11972         Camera.call( this );
11973
11974         this.type = 'PerspectiveCamera';
11975
11976         this.fov = fov;
11977         this.zoom = 1;
11978
11979         this.near = near;
11980         this.far = far;
11981         this.focus = 10;
11982
11983         this.aspect = aspect;
11984         this.view = null;
11985
11986         this.filmGauge = 35;    // width of the film (default in millimeters)
11987         this.filmOffset = 0;    // horizontal film offset (same unit as gauge)
11988
11989         this.updateProjectionMatrix();
11990
11991 }
11992
11993 PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
11994
11995         constructor: PerspectiveCamera,
11996
11997         isPerspectiveCamera: true,
11998
11999         copy: function ( source, recursive ) {
12000
12001                 Camera.prototype.copy.call( this, source, recursive );
12002
12003                 this.fov = source.fov;
12004                 this.zoom = source.zoom;
12005
12006                 this.near = source.near;
12007                 this.far = source.far;
12008                 this.focus = source.focus;
12009
12010                 this.aspect = source.aspect;
12011                 this.view = source.view === null ? null : Object.assign( {}, source.view );
12012
12013                 this.filmGauge = source.filmGauge;
12014                 this.filmOffset = source.filmOffset;
12015
12016                 return this;
12017
12018         },
12019
12020         /**
12021          * Sets the FOV by focal length in respect to the current .filmGauge.
12022          *
12023          * The default film gauge is 35, so that the focal length can be specified for
12024          * a 35mm (full frame) camera.
12025          *
12026          * Values for focal length and film gauge must have the same unit.
12027          */
12028         setFocalLength: function ( focalLength ) {
12029
12030                 // see http://www.bobatkins.com/photography/technical/field_of_view.html
12031                 const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
12032
12033                 this.fov = MathUtils.RAD2DEG * 2 * Math.atan( vExtentSlope );
12034                 this.updateProjectionMatrix();
12035
12036         },
12037
12038         /**
12039          * Calculates the focal length from the current .fov and .filmGauge.
12040          */
12041         getFocalLength: function () {
12042
12043                 const vExtentSlope = Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov );
12044
12045                 return 0.5 * this.getFilmHeight() / vExtentSlope;
12046
12047         },
12048
12049         getEffectiveFOV: function () {
12050
12051                 return MathUtils.RAD2DEG * 2 * Math.atan(
12052                         Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom );
12053
12054         },
12055
12056         getFilmWidth: function () {
12057
12058                 // film not completely covered in portrait format (aspect < 1)
12059                 return this.filmGauge * Math.min( this.aspect, 1 );
12060
12061         },
12062
12063         getFilmHeight: function () {
12064
12065                 // film not completely covered in landscape format (aspect > 1)
12066                 return this.filmGauge / Math.max( this.aspect, 1 );
12067
12068         },
12069
12070         /**
12071          * Sets an offset in a larger frustum. This is useful for multi-window or
12072          * multi-monitor/multi-machine setups.
12073          *
12074          * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
12075          * the monitors are in grid like this
12076          *
12077          *   +---+---+---+
12078          *   | A | B | C |
12079          *   +---+---+---+
12080          *   | D | E | F |
12081          *   +---+---+---+
12082          *
12083          * then for each monitor you would call it like this
12084          *
12085          *   const w = 1920;
12086          *   const h = 1080;
12087          *   const fullWidth = w * 3;
12088          *   const fullHeight = h * 2;
12089          *
12090          *   --A--
12091          *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
12092          *   --B--
12093          *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
12094          *   --C--
12095          *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
12096          *   --D--
12097          *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
12098          *   --E--
12099          *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
12100          *   --F--
12101          *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
12102          *
12103          *   Note there is no reason monitors have to be the same size or in a grid.
12104          */
12105         setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
12106
12107                 this.aspect = fullWidth / fullHeight;
12108
12109                 if ( this.view === null ) {
12110
12111                         this.view = {
12112                                 enabled: true,
12113                                 fullWidth: 1,
12114                                 fullHeight: 1,
12115                                 offsetX: 0,
12116                                 offsetY: 0,
12117                                 width: 1,
12118                                 height: 1
12119                         };
12120
12121                 }
12122
12123                 this.view.enabled = true;
12124                 this.view.fullWidth = fullWidth;
12125                 this.view.fullHeight = fullHeight;
12126                 this.view.offsetX = x;
12127                 this.view.offsetY = y;
12128                 this.view.width = width;
12129                 this.view.height = height;
12130
12131                 this.updateProjectionMatrix();
12132
12133         },
12134
12135         clearViewOffset: function () {
12136
12137                 if ( this.view !== null ) {
12138
12139                         this.view.enabled = false;
12140
12141                 }
12142
12143                 this.updateProjectionMatrix();
12144
12145         },
12146
12147         updateProjectionMatrix: function () {
12148
12149                 const near = this.near;
12150                 let top = near * Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom;
12151                 let height = 2 * top;
12152                 let width = this.aspect * height;
12153                 let left = - 0.5 * width;
12154                 const view = this.view;
12155
12156                 if ( this.view !== null && this.view.enabled ) {
12157
12158                         const fullWidth = view.fullWidth,
12159                                 fullHeight = view.fullHeight;
12160
12161                         left += view.offsetX * width / fullWidth;
12162                         top -= view.offsetY * height / fullHeight;
12163                         width *= view.width / fullWidth;
12164                         height *= view.height / fullHeight;
12165
12166                 }
12167
12168                 const skew = this.filmOffset;
12169                 if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
12170
12171                 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
12172
12173                 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
12174
12175         },
12176
12177         toJSON: function ( meta ) {
12178
12179                 const data = Object3D.prototype.toJSON.call( this, meta );
12180
12181                 data.object.fov = this.fov;
12182                 data.object.zoom = this.zoom;
12183
12184                 data.object.near = this.near;
12185                 data.object.far = this.far;
12186                 data.object.focus = this.focus;
12187
12188                 data.object.aspect = this.aspect;
12189
12190                 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
12191
12192                 data.object.filmGauge = this.filmGauge;
12193                 data.object.filmOffset = this.filmOffset;
12194
12195                 return data;
12196
12197         }
12198
12199 } );
12200
12201 const fov = 90, aspect = 1;
12202
12203 function CubeCamera( near, far, renderTarget ) {
12204
12205         Object3D.call( this );
12206
12207         this.type = 'CubeCamera';
12208
12209         if ( renderTarget.isWebGLCubeRenderTarget !== true ) {
12210
12211                 console.error( 'THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.' );
12212                 return;
12213
12214         }
12215
12216         this.renderTarget = renderTarget;
12217
12218         const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
12219         cameraPX.layers = this.layers;
12220         cameraPX.up.set( 0, - 1, 0 );
12221         cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
12222         this.add( cameraPX );
12223
12224         const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
12225         cameraNX.layers = this.layers;
12226         cameraNX.up.set( 0, - 1, 0 );
12227         cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
12228         this.add( cameraNX );
12229
12230         const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
12231         cameraPY.layers = this.layers;
12232         cameraPY.up.set( 0, 0, 1 );
12233         cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
12234         this.add( cameraPY );
12235
12236         const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
12237         cameraNY.layers = this.layers;
12238         cameraNY.up.set( 0, 0, - 1 );
12239         cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
12240         this.add( cameraNY );
12241
12242         const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
12243         cameraPZ.layers = this.layers;
12244         cameraPZ.up.set( 0, - 1, 0 );
12245         cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
12246         this.add( cameraPZ );
12247
12248         const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
12249         cameraNZ.layers = this.layers;
12250         cameraNZ.up.set( 0, - 1, 0 );
12251         cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
12252         this.add( cameraNZ );
12253
12254         this.update = function ( renderer, scene ) {
12255
12256                 if ( this.parent === null ) this.updateMatrixWorld();
12257
12258                 const currentXrEnabled = renderer.xr.enabled;
12259                 const currentRenderTarget = renderer.getRenderTarget();
12260
12261                 renderer.xr.enabled = false;
12262
12263                 const generateMipmaps = renderTarget.texture.generateMipmaps;
12264
12265                 renderTarget.texture.generateMipmaps = false;
12266
12267                 renderer.setRenderTarget( renderTarget, 0 );
12268                 renderer.render( scene, cameraPX );
12269
12270                 renderer.setRenderTarget( renderTarget, 1 );
12271                 renderer.render( scene, cameraNX );
12272
12273                 renderer.setRenderTarget( renderTarget, 2 );
12274                 renderer.render( scene, cameraPY );
12275
12276                 renderer.setRenderTarget( renderTarget, 3 );
12277                 renderer.render( scene, cameraNY );
12278
12279                 renderer.setRenderTarget( renderTarget, 4 );
12280                 renderer.render( scene, cameraPZ );
12281
12282                 renderTarget.texture.generateMipmaps = generateMipmaps;
12283
12284                 renderer.setRenderTarget( renderTarget, 5 );
12285                 renderer.render( scene, cameraNZ );
12286
12287                 renderer.setRenderTarget( currentRenderTarget );
12288
12289                 renderer.xr.enabled = currentXrEnabled;
12290
12291         };
12292
12293 }
12294
12295 CubeCamera.prototype = Object.create( Object3D.prototype );
12296 CubeCamera.prototype.constructor = CubeCamera;
12297
12298 function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
12299
12300         images = images !== undefined ? images : [];
12301         mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
12302         format = format !== undefined ? format : RGBFormat;
12303
12304         Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
12305
12306         this.flipY = false;
12307
12308         // Why CubeTexture._needsFlipEnvMap is necessary:
12309         //
12310         // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
12311         // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
12312         // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
12313
12314         // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
12315         // and the flag _needsFlipEnvMap controls this conversion. The flip is not required (and thus _needsFlipEnvMap is set to false)
12316         // when using WebGLCubeRenderTarget.texture as a cube texture.
12317
12318         this._needsFlipEnvMap = true;
12319
12320 }
12321
12322 CubeTexture.prototype = Object.create( Texture.prototype );
12323 CubeTexture.prototype.constructor = CubeTexture;
12324
12325 CubeTexture.prototype.isCubeTexture = true;
12326
12327 Object.defineProperty( CubeTexture.prototype, 'images', {
12328
12329         get: function () {
12330
12331                 return this.image;
12332
12333         },
12334
12335         set: function ( value ) {
12336
12337                 this.image = value;
12338
12339         }
12340
12341 } );
12342
12343 function WebGLCubeRenderTarget( size, options, dummy ) {
12344
12345         if ( Number.isInteger( options ) ) {
12346
12347                 console.warn( 'THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )' );
12348
12349                 options = dummy;
12350
12351         }
12352
12353         WebGLRenderTarget.call( this, size, size, options );
12354
12355         options = options || {};
12356
12357         this.texture = new CubeTexture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
12358
12359         this.texture._needsFlipEnvMap = false;
12360
12361 }
12362
12363 WebGLCubeRenderTarget.prototype = Object.create( WebGLRenderTarget.prototype );
12364 WebGLCubeRenderTarget.prototype.constructor = WebGLCubeRenderTarget;
12365
12366 WebGLCubeRenderTarget.prototype.isWebGLCubeRenderTarget = true;
12367
12368 WebGLCubeRenderTarget.prototype.fromEquirectangularTexture = function ( renderer, texture ) {
12369
12370         this.texture.type = texture.type;
12371         this.texture.format = RGBAFormat; // see #18859
12372         this.texture.encoding = texture.encoding;
12373
12374         this.texture.generateMipmaps = texture.generateMipmaps;
12375         this.texture.minFilter = texture.minFilter;
12376         this.texture.magFilter = texture.magFilter;
12377
12378         const shader = {
12379
12380                 uniforms: {
12381                         tEquirect: { value: null },
12382                 },
12383
12384                 vertexShader: /* glsl */`
12385
12386                         varying vec3 vWorldDirection;
12387
12388                         vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
12389
12390                                 return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
12391
12392                         }
12393
12394                         void main() {
12395
12396                                 vWorldDirection = transformDirection( position, modelMatrix );
12397
12398                                 #include <begin_vertex>
12399                                 #include <project_vertex>
12400
12401                         }
12402                 `,
12403
12404                 fragmentShader: /* glsl */`
12405
12406                         uniform sampler2D tEquirect;
12407
12408                         varying vec3 vWorldDirection;
12409
12410                         #include <common>
12411
12412                         void main() {
12413
12414                                 vec3 direction = normalize( vWorldDirection );
12415
12416                                 vec2 sampleUV = equirectUv( direction );
12417
12418                                 gl_FragColor = texture2D( tEquirect, sampleUV );
12419
12420                         }
12421                 `
12422         };
12423
12424         const geometry = new BoxBufferGeometry( 5, 5, 5 );
12425
12426         const material = new ShaderMaterial( {
12427
12428                 name: 'CubemapFromEquirect',
12429
12430                 uniforms: cloneUniforms( shader.uniforms ),
12431                 vertexShader: shader.vertexShader,
12432                 fragmentShader: shader.fragmentShader,
12433                 side: BackSide,
12434                 blending: NoBlending
12435
12436         } );
12437
12438         material.uniforms.tEquirect.value = texture;
12439
12440         const mesh = new Mesh( geometry, material );
12441
12442         const currentMinFilter = texture.minFilter;
12443
12444         // Avoid blurred poles
12445         if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
12446
12447         const camera = new CubeCamera( 1, 10, this );
12448         camera.update( renderer, mesh );
12449
12450         texture.minFilter = currentMinFilter;
12451
12452         mesh.geometry.dispose();
12453         mesh.material.dispose();
12454
12455         return this;
12456
12457 };
12458
12459 WebGLCubeRenderTarget.prototype.clear = function ( renderer, color, depth, stencil ) {
12460
12461         const currentRenderTarget = renderer.getRenderTarget();
12462
12463         for ( let i = 0; i < 6; i ++ ) {
12464
12465                 renderer.setRenderTarget( this, i );
12466
12467                 renderer.clear( color, depth, stencil );
12468
12469         }
12470
12471         renderer.setRenderTarget( currentRenderTarget );
12472
12473 };
12474
12475 function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
12476
12477         Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
12478
12479         this.image = { data: data || null, width: width || 1, height: height || 1 };
12480
12481         this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
12482         this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
12483
12484         this.generateMipmaps = false;
12485         this.flipY = false;
12486         this.unpackAlignment = 1;
12487
12488         this.needsUpdate = true;
12489
12490 }
12491
12492 DataTexture.prototype = Object.create( Texture.prototype );
12493 DataTexture.prototype.constructor = DataTexture;
12494
12495 DataTexture.prototype.isDataTexture = true;
12496
12497 const _sphere$1 = /*@__PURE__*/ new Sphere();
12498 const _vector$5 = /*@__PURE__*/ new Vector3();
12499
12500 class Frustum {
12501
12502         constructor( p0, p1, p2, p3, p4, p5 ) {
12503
12504                 this.planes = [
12505
12506                         ( p0 !== undefined ) ? p0 : new Plane(),
12507                         ( p1 !== undefined ) ? p1 : new Plane(),
12508                         ( p2 !== undefined ) ? p2 : new Plane(),
12509                         ( p3 !== undefined ) ? p3 : new Plane(),
12510                         ( p4 !== undefined ) ? p4 : new Plane(),
12511                         ( p5 !== undefined ) ? p5 : new Plane()
12512
12513                 ];
12514
12515         }
12516
12517         set( p0, p1, p2, p3, p4, p5 ) {
12518
12519                 const planes = this.planes;
12520
12521                 planes[ 0 ].copy( p0 );
12522                 planes[ 1 ].copy( p1 );
12523                 planes[ 2 ].copy( p2 );
12524                 planes[ 3 ].copy( p3 );
12525                 planes[ 4 ].copy( p4 );
12526                 planes[ 5 ].copy( p5 );
12527
12528                 return this;
12529
12530         }
12531
12532         clone() {
12533
12534                 return new this.constructor().copy( this );
12535
12536         }
12537
12538         copy( frustum ) {
12539
12540                 const planes = this.planes;
12541
12542                 for ( let i = 0; i < 6; i ++ ) {
12543
12544                         planes[ i ].copy( frustum.planes[ i ] );
12545
12546                 }
12547
12548                 return this;
12549
12550         }
12551
12552         setFromProjectionMatrix( m ) {
12553
12554                 const planes = this.planes;
12555                 const me = m.elements;
12556                 const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
12557                 const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
12558                 const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
12559                 const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
12560
12561                 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
12562                 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
12563                 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
12564                 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
12565                 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
12566                 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
12567
12568                 return this;
12569
12570         }
12571
12572         intersectsObject( object ) {
12573
12574                 const geometry = object.geometry;
12575
12576                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
12577
12578                 _sphere$1.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
12579
12580                 return this.intersectsSphere( _sphere$1 );
12581
12582         }
12583
12584         intersectsSprite( sprite ) {
12585
12586                 _sphere$1.center.set( 0, 0, 0 );
12587                 _sphere$1.radius = 0.7071067811865476;
12588                 _sphere$1.applyMatrix4( sprite.matrixWorld );
12589
12590                 return this.intersectsSphere( _sphere$1 );
12591
12592         }
12593
12594         intersectsSphere( sphere ) {
12595
12596                 const planes = this.planes;
12597                 const center = sphere.center;
12598                 const negRadius = - sphere.radius;
12599
12600                 for ( let i = 0; i < 6; i ++ ) {
12601
12602                         const distance = planes[ i ].distanceToPoint( center );
12603
12604                         if ( distance < negRadius ) {
12605
12606                                 return false;
12607
12608                         }
12609
12610                 }
12611
12612                 return true;
12613
12614         }
12615
12616         intersectsBox( box ) {
12617
12618                 const planes = this.planes;
12619
12620                 for ( let i = 0; i < 6; i ++ ) {
12621
12622                         const plane = planes[ i ];
12623
12624                         // corner at max distance
12625
12626                         _vector$5.x = plane.normal.x > 0 ? box.max.x : box.min.x;
12627                         _vector$5.y = plane.normal.y > 0 ? box.max.y : box.min.y;
12628                         _vector$5.z = plane.normal.z > 0 ? box.max.z : box.min.z;
12629
12630                         if ( plane.distanceToPoint( _vector$5 ) < 0 ) {
12631
12632                                 return false;
12633
12634                         }
12635
12636                 }
12637
12638                 return true;
12639
12640         }
12641
12642         containsPoint( point ) {
12643
12644                 const planes = this.planes;
12645
12646                 for ( let i = 0; i < 6; i ++ ) {
12647
12648                         if ( planes[ i ].distanceToPoint( point ) < 0 ) {
12649
12650                                 return false;
12651
12652                         }
12653
12654                 }
12655
12656                 return true;
12657
12658         }
12659
12660 }
12661
12662 function WebGLAnimation() {
12663
12664         let context = null;
12665         let isAnimating = false;
12666         let animationLoop = null;
12667         let requestId = null;
12668
12669         function onAnimationFrame( time, frame ) {
12670
12671                 animationLoop( time, frame );
12672
12673                 requestId = context.requestAnimationFrame( onAnimationFrame );
12674
12675         }
12676
12677         return {
12678
12679                 start: function () {
12680
12681                         if ( isAnimating === true ) return;
12682                         if ( animationLoop === null ) return;
12683
12684                         requestId = context.requestAnimationFrame( onAnimationFrame );
12685
12686                         isAnimating = true;
12687
12688                 },
12689
12690                 stop: function () {
12691
12692                         context.cancelAnimationFrame( requestId );
12693
12694                         isAnimating = false;
12695
12696                 },
12697
12698                 setAnimationLoop: function ( callback ) {
12699
12700                         animationLoop = callback;
12701
12702                 },
12703
12704                 setContext: function ( value ) {
12705
12706                         context = value;
12707
12708                 }
12709
12710         };
12711
12712 }
12713
12714 function WebGLAttributes( gl, capabilities ) {
12715
12716         const isWebGL2 = capabilities.isWebGL2;
12717
12718         const buffers = new WeakMap();
12719
12720         function createBuffer( attribute, bufferType ) {
12721
12722                 const array = attribute.array;
12723                 const usage = attribute.usage;
12724
12725                 const buffer = gl.createBuffer();
12726
12727                 gl.bindBuffer( bufferType, buffer );
12728                 gl.bufferData( bufferType, array, usage );
12729
12730                 attribute.onUploadCallback();
12731
12732                 let type = 5126;
12733
12734                 if ( array instanceof Float32Array ) {
12735
12736                         type = 5126;
12737
12738                 } else if ( array instanceof Float64Array ) {
12739
12740                         console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
12741
12742                 } else if ( array instanceof Uint16Array ) {
12743
12744                         if ( attribute.isFloat16BufferAttribute ) {
12745
12746                                 if ( isWebGL2 ) {
12747
12748                                         type = 5131;
12749
12750                                 } else {
12751
12752                                         console.warn( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' );
12753
12754                                 }
12755
12756                         } else {
12757
12758                                 type = 5123;
12759
12760                         }
12761
12762                 } else if ( array instanceof Int16Array ) {
12763
12764                         type = 5122;
12765
12766                 } else if ( array instanceof Uint32Array ) {
12767
12768                         type = 5125;
12769
12770                 } else if ( array instanceof Int32Array ) {
12771
12772                         type = 5124;
12773
12774                 } else if ( array instanceof Int8Array ) {
12775
12776                         type = 5120;
12777
12778                 } else if ( array instanceof Uint8Array ) {
12779
12780                         type = 5121;
12781
12782                 }
12783
12784                 return {
12785                         buffer: buffer,
12786                         type: type,
12787                         bytesPerElement: array.BYTES_PER_ELEMENT,
12788                         version: attribute.version
12789                 };
12790
12791         }
12792
12793         function updateBuffer( buffer, attribute, bufferType ) {
12794
12795                 const array = attribute.array;
12796                 const updateRange = attribute.updateRange;
12797
12798                 gl.bindBuffer( bufferType, buffer );
12799
12800                 if ( updateRange.count === - 1 ) {
12801
12802                         // Not using update ranges
12803
12804                         gl.bufferSubData( bufferType, 0, array );
12805
12806                 } else {
12807
12808                         if ( isWebGL2 ) {
12809
12810                                 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
12811                                         array, updateRange.offset, updateRange.count );
12812
12813                         } else {
12814
12815                                 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
12816                                         array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
12817
12818                         }
12819
12820                         updateRange.count = - 1; // reset range
12821
12822                 }
12823
12824         }
12825
12826         //
12827
12828         function get( attribute ) {
12829
12830                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
12831
12832                 return buffers.get( attribute );
12833
12834         }
12835
12836         function remove( attribute ) {
12837
12838                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
12839
12840                 const data = buffers.get( attribute );
12841
12842                 if ( data ) {
12843
12844                         gl.deleteBuffer( data.buffer );
12845
12846                         buffers.delete( attribute );
12847
12848                 }
12849
12850         }
12851
12852         function update( attribute, bufferType ) {
12853
12854                 if ( attribute.isGLBufferAttribute ) {
12855
12856                         const cached = buffers.get( attribute );
12857
12858                         if ( ! cached || cached.version < attribute.version ) {
12859
12860                                 buffers.set( attribute, {
12861                                         buffer: attribute.buffer,
12862                                         type: attribute.type,
12863                                         bytesPerElement: attribute.elementSize,
12864                                         version: attribute.version
12865                                 } );
12866
12867                         }
12868
12869                         return;
12870
12871                 }
12872
12873                 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
12874
12875                 const data = buffers.get( attribute );
12876
12877                 if ( data === undefined ) {
12878
12879                         buffers.set( attribute, createBuffer( attribute, bufferType ) );
12880
12881                 } else if ( data.version < attribute.version ) {
12882
12883                         updateBuffer( data.buffer, attribute, bufferType );
12884
12885                         data.version = attribute.version;
12886
12887                 }
12888
12889         }
12890
12891         return {
12892
12893                 get: get,
12894                 remove: remove,
12895                 update: update
12896
12897         };
12898
12899 }
12900
12901 class PlaneBufferGeometry extends BufferGeometry {
12902
12903         constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
12904
12905                 super();
12906                 this.type = 'PlaneBufferGeometry';
12907
12908                 this.parameters = {
12909                         width: width,
12910                         height: height,
12911                         widthSegments: widthSegments,
12912                         heightSegments: heightSegments
12913                 };
12914
12915                 const width_half = width / 2;
12916                 const height_half = height / 2;
12917
12918                 const gridX = Math.floor( widthSegments );
12919                 const gridY = Math.floor( heightSegments );
12920
12921                 const gridX1 = gridX + 1;
12922                 const gridY1 = gridY + 1;
12923
12924                 const segment_width = width / gridX;
12925                 const segment_height = height / gridY;
12926
12927                 //
12928
12929                 const indices = [];
12930                 const vertices = [];
12931                 const normals = [];
12932                 const uvs = [];
12933
12934                 for ( let iy = 0; iy < gridY1; iy ++ ) {
12935
12936                         const y = iy * segment_height - height_half;
12937
12938                         for ( let ix = 0; ix < gridX1; ix ++ ) {
12939
12940                                 const x = ix * segment_width - width_half;
12941
12942                                 vertices.push( x, - y, 0 );
12943
12944                                 normals.push( 0, 0, 1 );
12945
12946                                 uvs.push( ix / gridX );
12947                                 uvs.push( 1 - ( iy / gridY ) );
12948
12949                         }
12950
12951                 }
12952
12953                 for ( let iy = 0; iy < gridY; iy ++ ) {
12954
12955                         for ( let ix = 0; ix < gridX; ix ++ ) {
12956
12957                                 const a = ix + gridX1 * iy;
12958                                 const b = ix + gridX1 * ( iy + 1 );
12959                                 const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
12960                                 const d = ( ix + 1 ) + gridX1 * iy;
12961
12962                                 indices.push( a, b, d );
12963                                 indices.push( b, c, d );
12964
12965                         }
12966
12967                 }
12968
12969                 this.setIndex( indices );
12970                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
12971                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
12972                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
12973
12974         }
12975
12976 }
12977
12978 var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
12979
12980 var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
12981
12982 var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif";
12983
12984 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";
12985
12986 var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
12987
12988 var begin_vertex = "vec3 transformed = vec3( position );";
12989
12990 var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
12991
12992 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";
12993
12994 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";
12995
12996 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";
12997
12998 var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
12999
13000 var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
13001
13002 var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
13003
13004 var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
13005
13006 var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
13007
13008 var color_pars_vertex = "#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";
13009
13010 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";
13011
13012 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}";
13013
13014 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";
13015
13016 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";
13017
13018 var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
13019
13020 var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif";
13021
13022 var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
13023
13024 var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
13025
13026 var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
13027
13028 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}";
13029
13030 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";
13031
13032 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";
13033
13034 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";
13035
13036 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";
13037
13038 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";
13039
13040 var fog_vertex = "#ifdef USE_FOG\n\tfogDepth = - mvPosition.z;\n#endif";
13041
13042 var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif";
13043
13044 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";
13045
13046 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";
13047
13048 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}";
13049
13050 var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n#endif";
13051
13052 var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
13053
13054 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";
13055
13056 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";
13057
13058 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";
13059
13060 var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
13061
13062 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)";
13063
13064 var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
13065
13066 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)";
13067
13068 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";
13069
13070 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}";
13071
13072 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";
13073
13074 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";
13075
13076 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";
13077
13078 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";
13079
13080 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";
13081
13082 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";
13083
13084 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";
13085
13086 var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif";
13087
13088 var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
13089
13090 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";
13091
13092 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";
13093
13094 var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
13095
13096 var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
13097
13098 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";
13099
13100 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";
13101
13102 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";
13103
13104 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;";
13105
13106 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";
13107
13108 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";
13109
13110 var clearcoat_normal_fragment_begin = "#ifdef CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif";
13111
13112 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";
13113
13114 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";
13115
13116 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}";
13117
13118 var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
13119
13120 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;";
13121
13122 var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
13123
13124 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";
13125
13126 var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
13127
13128 var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
13129
13130 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";
13131
13132 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";
13133
13134 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";
13135
13136 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}";
13137
13138 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";
13139
13140 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";
13141
13142 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";
13143
13144 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";
13145
13146 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";
13147
13148 var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
13149
13150 var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
13151
13152 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; }";
13153
13154 var transmissionmap_fragment = "#ifdef USE_TRANSMISSIONMAP\n\ttotalTransmission *= texture2D( transmissionMap, vUv ).r;\n#endif";
13155
13156 var transmissionmap_pars_fragment = "#ifdef USE_TRANSMISSIONMAP\n\tuniform sampler2D transmissionMap;\n#endif";
13157
13158 var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif";
13159
13160 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";
13161
13162 var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
13163
13164 var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
13165
13166 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";
13167
13168 var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif";
13169
13170 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";
13171
13172 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}";
13173
13174 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}";
13175
13176 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}";
13177
13178 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}";
13179
13180 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}";
13181
13182 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}";
13183
13184 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}";
13185
13186 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}";
13187
13188 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}";
13189
13190 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}";
13191
13192 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}";
13193
13194 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}";
13195
13196 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}";
13197
13198 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}";
13199
13200 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}";
13201
13202 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}";
13203
13204 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}";
13205
13206 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}";
13207
13208 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}";
13209
13210 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}";
13211
13212 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}";
13213
13214 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}";
13215
13216 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}";
13217
13218 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}";
13219
13220 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}";
13221
13222 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}";
13223
13224 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}";
13225
13226 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}";
13227
13228 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}";
13229
13230 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}";
13231
13232 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}";
13233
13234 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}";
13235
13236 const ShaderChunk = {
13237         alphamap_fragment: alphamap_fragment,
13238         alphamap_pars_fragment: alphamap_pars_fragment,
13239         alphatest_fragment: alphatest_fragment,
13240         aomap_fragment: aomap_fragment,
13241         aomap_pars_fragment: aomap_pars_fragment,
13242         begin_vertex: begin_vertex,
13243         beginnormal_vertex: beginnormal_vertex,
13244         bsdfs: bsdfs,
13245         bumpmap_pars_fragment: bumpmap_pars_fragment,
13246         clipping_planes_fragment: clipping_planes_fragment,
13247         clipping_planes_pars_fragment: clipping_planes_pars_fragment,
13248         clipping_planes_pars_vertex: clipping_planes_pars_vertex,
13249         clipping_planes_vertex: clipping_planes_vertex,
13250         color_fragment: color_fragment,
13251         color_pars_fragment: color_pars_fragment,
13252         color_pars_vertex: color_pars_vertex,
13253         color_vertex: color_vertex,
13254         common: common,
13255         cube_uv_reflection_fragment: cube_uv_reflection_fragment,
13256         defaultnormal_vertex: defaultnormal_vertex,
13257         displacementmap_pars_vertex: displacementmap_pars_vertex,
13258         displacementmap_vertex: displacementmap_vertex,
13259         emissivemap_fragment: emissivemap_fragment,
13260         emissivemap_pars_fragment: emissivemap_pars_fragment,
13261         encodings_fragment: encodings_fragment,
13262         encodings_pars_fragment: encodings_pars_fragment,
13263         envmap_fragment: envmap_fragment,
13264         envmap_common_pars_fragment: envmap_common_pars_fragment,
13265         envmap_pars_fragment: envmap_pars_fragment,
13266         envmap_pars_vertex: envmap_pars_vertex,
13267         envmap_physical_pars_fragment: envmap_physical_pars_fragment,
13268         envmap_vertex: envmap_vertex,
13269         fog_vertex: fog_vertex,
13270         fog_pars_vertex: fog_pars_vertex,
13271         fog_fragment: fog_fragment,
13272         fog_pars_fragment: fog_pars_fragment,
13273         gradientmap_pars_fragment: gradientmap_pars_fragment,
13274         lightmap_fragment: lightmap_fragment,
13275         lightmap_pars_fragment: lightmap_pars_fragment,
13276         lights_lambert_vertex: lights_lambert_vertex,
13277         lights_pars_begin: lights_pars_begin,
13278         lights_toon_fragment: lights_toon_fragment,
13279         lights_toon_pars_fragment: lights_toon_pars_fragment,
13280         lights_phong_fragment: lights_phong_fragment,
13281         lights_phong_pars_fragment: lights_phong_pars_fragment,
13282         lights_physical_fragment: lights_physical_fragment,
13283         lights_physical_pars_fragment: lights_physical_pars_fragment,
13284         lights_fragment_begin: lights_fragment_begin,
13285         lights_fragment_maps: lights_fragment_maps,
13286         lights_fragment_end: lights_fragment_end,
13287         logdepthbuf_fragment: logdepthbuf_fragment,
13288         logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
13289         logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
13290         logdepthbuf_vertex: logdepthbuf_vertex,
13291         map_fragment: map_fragment,
13292         map_pars_fragment: map_pars_fragment,
13293         map_particle_fragment: map_particle_fragment,
13294         map_particle_pars_fragment: map_particle_pars_fragment,
13295         metalnessmap_fragment: metalnessmap_fragment,
13296         metalnessmap_pars_fragment: metalnessmap_pars_fragment,
13297         morphnormal_vertex: morphnormal_vertex,
13298         morphtarget_pars_vertex: morphtarget_pars_vertex,
13299         morphtarget_vertex: morphtarget_vertex,
13300         normal_fragment_begin: normal_fragment_begin,
13301         normal_fragment_maps: normal_fragment_maps,
13302         normalmap_pars_fragment: normalmap_pars_fragment,
13303         clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
13304         clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
13305         clearcoat_pars_fragment: clearcoat_pars_fragment,
13306         packing: packing,
13307         premultiplied_alpha_fragment: premultiplied_alpha_fragment,
13308         project_vertex: project_vertex,
13309         dithering_fragment: dithering_fragment,
13310         dithering_pars_fragment: dithering_pars_fragment,
13311         roughnessmap_fragment: roughnessmap_fragment,
13312         roughnessmap_pars_fragment: roughnessmap_pars_fragment,
13313         shadowmap_pars_fragment: shadowmap_pars_fragment,
13314         shadowmap_pars_vertex: shadowmap_pars_vertex,
13315         shadowmap_vertex: shadowmap_vertex,
13316         shadowmask_pars_fragment: shadowmask_pars_fragment,
13317         skinbase_vertex: skinbase_vertex,
13318         skinning_pars_vertex: skinning_pars_vertex,
13319         skinning_vertex: skinning_vertex,
13320         skinnormal_vertex: skinnormal_vertex,
13321         specularmap_fragment: specularmap_fragment,
13322         specularmap_pars_fragment: specularmap_pars_fragment,
13323         tonemapping_fragment: tonemapping_fragment,
13324         tonemapping_pars_fragment: tonemapping_pars_fragment,
13325         transmissionmap_fragment: transmissionmap_fragment,
13326         transmissionmap_pars_fragment: transmissionmap_pars_fragment,
13327         uv_pars_fragment: uv_pars_fragment,
13328         uv_pars_vertex: uv_pars_vertex,
13329         uv_vertex: uv_vertex,
13330         uv2_pars_fragment: uv2_pars_fragment,
13331         uv2_pars_vertex: uv2_pars_vertex,
13332         uv2_vertex: uv2_vertex,
13333         worldpos_vertex: worldpos_vertex,
13334
13335         background_frag: background_frag,
13336         background_vert: background_vert,
13337         cube_frag: cube_frag,
13338         cube_vert: cube_vert,
13339         depth_frag: depth_frag,
13340         depth_vert: depth_vert,
13341         distanceRGBA_frag: distanceRGBA_frag,
13342         distanceRGBA_vert: distanceRGBA_vert,
13343         equirect_frag: equirect_frag,
13344         equirect_vert: equirect_vert,
13345         linedashed_frag: linedashed_frag,
13346         linedashed_vert: linedashed_vert,
13347         meshbasic_frag: meshbasic_frag,
13348         meshbasic_vert: meshbasic_vert,
13349         meshlambert_frag: meshlambert_frag,
13350         meshlambert_vert: meshlambert_vert,
13351         meshmatcap_frag: meshmatcap_frag,
13352         meshmatcap_vert: meshmatcap_vert,
13353         meshtoon_frag: meshtoon_frag,
13354         meshtoon_vert: meshtoon_vert,
13355         meshphong_frag: meshphong_frag,
13356         meshphong_vert: meshphong_vert,
13357         meshphysical_frag: meshphysical_frag,
13358         meshphysical_vert: meshphysical_vert,
13359         normal_frag: normal_frag,
13360         normal_vert: normal_vert,
13361         points_frag: points_frag,
13362         points_vert: points_vert,
13363         shadow_frag: shadow_frag,
13364         shadow_vert: shadow_vert,
13365         sprite_frag: sprite_frag,
13366         sprite_vert: sprite_vert
13367 };
13368
13369 /**
13370  * Uniforms library for shared webgl shaders
13371  */
13372
13373 const UniformsLib = {
13374
13375         common: {
13376
13377                 diffuse: { value: new Color( 0xeeeeee ) },
13378                 opacity: { value: 1.0 },
13379
13380                 map: { value: null },
13381                 uvTransform: { value: new Matrix3() },
13382                 uv2Transform: { value: new Matrix3() },
13383
13384                 alphaMap: { value: null },
13385
13386         },
13387
13388         specularmap: {
13389
13390                 specularMap: { value: null },
13391
13392         },
13393
13394         envmap: {
13395
13396                 envMap: { value: null },
13397                 flipEnvMap: { value: - 1 },
13398                 reflectivity: { value: 1.0 },
13399                 refractionRatio: { value: 0.98 },
13400                 maxMipLevel: { value: 0 }
13401
13402         },
13403
13404         aomap: {
13405
13406                 aoMap: { value: null },
13407                 aoMapIntensity: { value: 1 }
13408
13409         },
13410
13411         lightmap: {
13412
13413                 lightMap: { value: null },
13414                 lightMapIntensity: { value: 1 }
13415
13416         },
13417
13418         emissivemap: {
13419
13420                 emissiveMap: { value: null }
13421
13422         },
13423
13424         bumpmap: {
13425
13426                 bumpMap: { value: null },
13427                 bumpScale: { value: 1 }
13428
13429         },
13430
13431         normalmap: {
13432
13433                 normalMap: { value: null },
13434                 normalScale: { value: new Vector2( 1, 1 ) }
13435
13436         },
13437
13438         displacementmap: {
13439
13440                 displacementMap: { value: null },
13441                 displacementScale: { value: 1 },
13442                 displacementBias: { value: 0 }
13443
13444         },
13445
13446         roughnessmap: {
13447
13448                 roughnessMap: { value: null }
13449
13450         },
13451
13452         metalnessmap: {
13453
13454                 metalnessMap: { value: null }
13455
13456         },
13457
13458         gradientmap: {
13459
13460                 gradientMap: { value: null }
13461
13462         },
13463
13464         fog: {
13465
13466                 fogDensity: { value: 0.00025 },
13467                 fogNear: { value: 1 },
13468                 fogFar: { value: 2000 },
13469                 fogColor: { value: new Color( 0xffffff ) }
13470
13471         },
13472
13473         lights: {
13474
13475                 ambientLightColor: { value: [] },
13476
13477                 lightProbe: { value: [] },
13478
13479                 directionalLights: { value: [], properties: {
13480                         direction: {},
13481                         color: {}
13482                 } },
13483
13484                 directionalLightShadows: { value: [], properties: {
13485                         shadowBias: {},
13486                         shadowNormalBias: {},
13487                         shadowRadius: {},
13488                         shadowMapSize: {}
13489                 } },
13490
13491                 directionalShadowMap: { value: [] },
13492                 directionalShadowMatrix: { value: [] },
13493
13494                 spotLights: { value: [], properties: {
13495                         color: {},
13496                         position: {},
13497                         direction: {},
13498                         distance: {},
13499                         coneCos: {},
13500                         penumbraCos: {},
13501                         decay: {}
13502                 } },
13503
13504                 spotLightShadows: { value: [], properties: {
13505                         shadowBias: {},
13506                         shadowNormalBias: {},
13507                         shadowRadius: {},
13508                         shadowMapSize: {}
13509                 } },
13510
13511                 spotShadowMap: { value: [] },
13512                 spotShadowMatrix: { value: [] },
13513
13514                 pointLights: { value: [], properties: {
13515                         color: {},
13516                         position: {},
13517                         decay: {},
13518                         distance: {}
13519                 } },
13520
13521                 pointLightShadows: { value: [], properties: {
13522                         shadowBias: {},
13523                         shadowNormalBias: {},
13524                         shadowRadius: {},
13525                         shadowMapSize: {},
13526                         shadowCameraNear: {},
13527                         shadowCameraFar: {}
13528                 } },
13529
13530                 pointShadowMap: { value: [] },
13531                 pointShadowMatrix: { value: [] },
13532
13533                 hemisphereLights: { value: [], properties: {
13534                         direction: {},
13535                         skyColor: {},
13536                         groundColor: {}
13537                 } },
13538
13539                 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
13540                 rectAreaLights: { value: [], properties: {
13541                         color: {},
13542                         position: {},
13543                         width: {},
13544                         height: {}
13545                 } },
13546
13547                 ltc_1: { value: null },
13548                 ltc_2: { value: null }
13549
13550         },
13551
13552         points: {
13553
13554                 diffuse: { value: new Color( 0xeeeeee ) },
13555                 opacity: { value: 1.0 },
13556                 size: { value: 1.0 },
13557                 scale: { value: 1.0 },
13558                 map: { value: null },
13559                 alphaMap: { value: null },
13560                 uvTransform: { value: new Matrix3() }
13561
13562         },
13563
13564         sprite: {
13565
13566                 diffuse: { value: new Color( 0xeeeeee ) },
13567                 opacity: { value: 1.0 },
13568                 center: { value: new Vector2( 0.5, 0.5 ) },
13569                 rotation: { value: 0.0 },
13570                 map: { value: null },
13571                 alphaMap: { value: null },
13572                 uvTransform: { value: new Matrix3() }
13573
13574         }
13575
13576 };
13577
13578 const ShaderLib = {
13579
13580         basic: {
13581
13582                 uniforms: mergeUniforms( [
13583                         UniformsLib.common,
13584                         UniformsLib.specularmap,
13585                         UniformsLib.envmap,
13586                         UniformsLib.aomap,
13587                         UniformsLib.lightmap,
13588                         UniformsLib.fog
13589                 ] ),
13590
13591                 vertexShader: ShaderChunk.meshbasic_vert,
13592                 fragmentShader: ShaderChunk.meshbasic_frag
13593
13594         },
13595
13596         lambert: {
13597
13598                 uniforms: mergeUniforms( [
13599                         UniformsLib.common,
13600                         UniformsLib.specularmap,
13601                         UniformsLib.envmap,
13602                         UniformsLib.aomap,
13603                         UniformsLib.lightmap,
13604                         UniformsLib.emissivemap,
13605                         UniformsLib.fog,
13606                         UniformsLib.lights,
13607                         {
13608                                 emissive: { value: new Color( 0x000000 ) }
13609                         }
13610                 ] ),
13611
13612                 vertexShader: ShaderChunk.meshlambert_vert,
13613                 fragmentShader: ShaderChunk.meshlambert_frag
13614
13615         },
13616
13617         phong: {
13618
13619                 uniforms: mergeUniforms( [
13620                         UniformsLib.common,
13621                         UniformsLib.specularmap,
13622                         UniformsLib.envmap,
13623                         UniformsLib.aomap,
13624                         UniformsLib.lightmap,
13625                         UniformsLib.emissivemap,
13626                         UniformsLib.bumpmap,
13627                         UniformsLib.normalmap,
13628                         UniformsLib.displacementmap,
13629                         UniformsLib.fog,
13630                         UniformsLib.lights,
13631                         {
13632                                 emissive: { value: new Color( 0x000000 ) },
13633                                 specular: { value: new Color( 0x111111 ) },
13634                                 shininess: { value: 30 }
13635                         }
13636                 ] ),
13637
13638                 vertexShader: ShaderChunk.meshphong_vert,
13639                 fragmentShader: ShaderChunk.meshphong_frag
13640
13641         },
13642
13643         standard: {
13644
13645                 uniforms: mergeUniforms( [
13646                         UniformsLib.common,
13647                         UniformsLib.envmap,
13648                         UniformsLib.aomap,
13649                         UniformsLib.lightmap,
13650                         UniformsLib.emissivemap,
13651                         UniformsLib.bumpmap,
13652                         UniformsLib.normalmap,
13653                         UniformsLib.displacementmap,
13654                         UniformsLib.roughnessmap,
13655                         UniformsLib.metalnessmap,
13656                         UniformsLib.fog,
13657                         UniformsLib.lights,
13658                         {
13659                                 emissive: { value: new Color( 0x000000 ) },
13660                                 roughness: { value: 1.0 },
13661                                 metalness: { value: 0.0 },
13662                                 envMapIntensity: { value: 1 } // temporary
13663                         }
13664                 ] ),
13665
13666                 vertexShader: ShaderChunk.meshphysical_vert,
13667                 fragmentShader: ShaderChunk.meshphysical_frag
13668
13669         },
13670
13671         toon: {
13672
13673                 uniforms: mergeUniforms( [
13674                         UniformsLib.common,
13675                         UniformsLib.aomap,
13676                         UniformsLib.lightmap,
13677                         UniformsLib.emissivemap,
13678                         UniformsLib.bumpmap,
13679                         UniformsLib.normalmap,
13680                         UniformsLib.displacementmap,
13681                         UniformsLib.gradientmap,
13682                         UniformsLib.fog,
13683                         UniformsLib.lights,
13684                         {
13685                                 emissive: { value: new Color( 0x000000 ) }
13686                         }
13687                 ] ),
13688
13689                 vertexShader: ShaderChunk.meshtoon_vert,
13690                 fragmentShader: ShaderChunk.meshtoon_frag
13691
13692         },
13693
13694         matcap: {
13695
13696                 uniforms: mergeUniforms( [
13697                         UniformsLib.common,
13698                         UniformsLib.bumpmap,
13699                         UniformsLib.normalmap,
13700                         UniformsLib.displacementmap,
13701                         UniformsLib.fog,
13702                         {
13703                                 matcap: { value: null }
13704                         }
13705                 ] ),
13706
13707                 vertexShader: ShaderChunk.meshmatcap_vert,
13708                 fragmentShader: ShaderChunk.meshmatcap_frag
13709
13710         },
13711
13712         points: {
13713
13714                 uniforms: mergeUniforms( [
13715                         UniformsLib.points,
13716                         UniformsLib.fog
13717                 ] ),
13718
13719                 vertexShader: ShaderChunk.points_vert,
13720                 fragmentShader: ShaderChunk.points_frag
13721
13722         },
13723
13724         dashed: {
13725
13726                 uniforms: mergeUniforms( [
13727                         UniformsLib.common,
13728                         UniformsLib.fog,
13729                         {
13730                                 scale: { value: 1 },
13731                                 dashSize: { value: 1 },
13732                                 totalSize: { value: 2 }
13733                         }
13734                 ] ),
13735
13736                 vertexShader: ShaderChunk.linedashed_vert,
13737                 fragmentShader: ShaderChunk.linedashed_frag
13738
13739         },
13740
13741         depth: {
13742
13743                 uniforms: mergeUniforms( [
13744                         UniformsLib.common,
13745                         UniformsLib.displacementmap
13746                 ] ),
13747
13748                 vertexShader: ShaderChunk.depth_vert,
13749                 fragmentShader: ShaderChunk.depth_frag
13750
13751         },
13752
13753         normal: {
13754
13755                 uniforms: mergeUniforms( [
13756                         UniformsLib.common,
13757                         UniformsLib.bumpmap,
13758                         UniformsLib.normalmap,
13759                         UniformsLib.displacementmap,
13760                         {
13761                                 opacity: { value: 1.0 }
13762                         }
13763                 ] ),
13764
13765                 vertexShader: ShaderChunk.normal_vert,
13766                 fragmentShader: ShaderChunk.normal_frag
13767
13768         },
13769
13770         sprite: {
13771
13772                 uniforms: mergeUniforms( [
13773                         UniformsLib.sprite,
13774                         UniformsLib.fog
13775                 ] ),
13776
13777                 vertexShader: ShaderChunk.sprite_vert,
13778                 fragmentShader: ShaderChunk.sprite_frag
13779
13780         },
13781
13782         background: {
13783
13784                 uniforms: {
13785                         uvTransform: { value: new Matrix3() },
13786                         t2D: { value: null },
13787                 },
13788
13789                 vertexShader: ShaderChunk.background_vert,
13790                 fragmentShader: ShaderChunk.background_frag
13791
13792         },
13793         /* -------------------------------------------------------------------------
13794         //      Cube map shader
13795          ------------------------------------------------------------------------- */
13796
13797         cube: {
13798
13799                 uniforms: mergeUniforms( [
13800                         UniformsLib.envmap,
13801                         {
13802                                 opacity: { value: 1.0 }
13803                         }
13804                 ] ),
13805
13806                 vertexShader: ShaderChunk.cube_vert,
13807                 fragmentShader: ShaderChunk.cube_frag
13808
13809         },
13810
13811         equirect: {
13812
13813                 uniforms: {
13814                         tEquirect: { value: null },
13815                 },
13816
13817                 vertexShader: ShaderChunk.equirect_vert,
13818                 fragmentShader: ShaderChunk.equirect_frag
13819
13820         },
13821
13822         distanceRGBA: {
13823
13824                 uniforms: mergeUniforms( [
13825                         UniformsLib.common,
13826                         UniformsLib.displacementmap,
13827                         {
13828                                 referencePosition: { value: new Vector3() },
13829                                 nearDistance: { value: 1 },
13830                                 farDistance: { value: 1000 }
13831                         }
13832                 ] ),
13833
13834                 vertexShader: ShaderChunk.distanceRGBA_vert,
13835                 fragmentShader: ShaderChunk.distanceRGBA_frag
13836
13837         },
13838
13839         shadow: {
13840
13841                 uniforms: mergeUniforms( [
13842                         UniformsLib.lights,
13843                         UniformsLib.fog,
13844                         {
13845                                 color: { value: new Color( 0x00000 ) },
13846                                 opacity: { value: 1.0 }
13847                         },
13848                 ] ),
13849
13850                 vertexShader: ShaderChunk.shadow_vert,
13851                 fragmentShader: ShaderChunk.shadow_frag
13852
13853         }
13854
13855 };
13856
13857 ShaderLib.physical = {
13858
13859         uniforms: mergeUniforms( [
13860                 ShaderLib.standard.uniforms,
13861                 {
13862                         clearcoat: { value: 0 },
13863                         clearcoatMap: { value: null },
13864                         clearcoatRoughness: { value: 0 },
13865                         clearcoatRoughnessMap: { value: null },
13866                         clearcoatNormalScale: { value: new Vector2( 1, 1 ) },
13867                         clearcoatNormalMap: { value: null },
13868                         sheen: { value: new Color( 0x000000 ) },
13869                         transmission: { value: 0 },
13870                         transmissionMap: { value: null },
13871                 }
13872         ] ),
13873
13874         vertexShader: ShaderChunk.meshphysical_vert,
13875         fragmentShader: ShaderChunk.meshphysical_frag
13876
13877 };
13878
13879 function WebGLBackground( renderer, cubemaps, state, objects, premultipliedAlpha ) {
13880
13881         const clearColor = new Color( 0x000000 );
13882         let clearAlpha = 0;
13883
13884         let planeMesh;
13885         let boxMesh;
13886
13887         let currentBackground = null;
13888         let currentBackgroundVersion = 0;
13889         let currentTonemapping = null;
13890
13891         function render( renderList, scene, camera, forceClear ) {
13892
13893                 let background = scene.isScene === true ? scene.background : null;
13894
13895                 if ( background && background.isTexture ) {
13896
13897                         background = cubemaps.get( background );
13898
13899                 }
13900
13901                 // Ignore background in AR
13902                 // TODO: Reconsider this.
13903
13904                 const xr = renderer.xr;
13905                 const session = xr.getSession && xr.getSession();
13906
13907                 if ( session && session.environmentBlendMode === 'additive' ) {
13908
13909                         background = null;
13910
13911                 }
13912
13913                 if ( background === null ) {
13914
13915                         setClear( clearColor, clearAlpha );
13916
13917                 } else if ( background && background.isColor ) {
13918
13919                         setClear( background, 1 );
13920                         forceClear = true;
13921
13922                 }
13923
13924                 if ( renderer.autoClear || forceClear ) {
13925
13926                         renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
13927
13928                 }
13929
13930                 if ( background && ( background.isCubeTexture || background.isWebGLCubeRenderTarget || background.mapping === CubeUVReflectionMapping ) ) {
13931
13932                         if ( boxMesh === undefined ) {
13933
13934                                 boxMesh = new Mesh(
13935                                         new BoxBufferGeometry( 1, 1, 1 ),
13936                                         new ShaderMaterial( {
13937                                                 name: 'BackgroundCubeMaterial',
13938                                                 uniforms: cloneUniforms( ShaderLib.cube.uniforms ),
13939                                                 vertexShader: ShaderLib.cube.vertexShader,
13940                                                 fragmentShader: ShaderLib.cube.fragmentShader,
13941                                                 side: BackSide,
13942                                                 depthTest: false,
13943                                                 depthWrite: false,
13944                                                 fog: false
13945                                         } )
13946                                 );
13947
13948                                 boxMesh.geometry.deleteAttribute( 'normal' );
13949                                 boxMesh.geometry.deleteAttribute( 'uv' );
13950
13951                                 boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
13952
13953                                         this.matrixWorld.copyPosition( camera.matrixWorld );
13954
13955                                 };
13956
13957                                 // enable code injection for non-built-in material
13958                                 Object.defineProperty( boxMesh.material, 'envMap', {
13959
13960                                         get: function () {
13961
13962                                                 return this.uniforms.envMap.value;
13963
13964                                         }
13965
13966                                 } );
13967
13968                                 objects.update( boxMesh );
13969
13970                         }
13971
13972                         if ( background.isWebGLCubeRenderTarget ) {
13973
13974                                 // TODO Deprecate
13975
13976                                 background = background.texture;
13977
13978                         }
13979
13980                         boxMesh.material.uniforms.envMap.value = background;
13981                         boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background._needsFlipEnvMap ) ? - 1 : 1;
13982
13983                         if ( currentBackground !== background ||
13984                                 currentBackgroundVersion !== background.version ||
13985                                 currentTonemapping !== renderer.toneMapping ) {
13986
13987                                 boxMesh.material.needsUpdate = true;
13988
13989                                 currentBackground = background;
13990                                 currentBackgroundVersion = background.version;
13991                                 currentTonemapping = renderer.toneMapping;
13992
13993                         }
13994
13995                         // push to the pre-sorted opaque render list
13996                         renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
13997
13998                 } else if ( background && background.isTexture ) {
13999
14000                         if ( planeMesh === undefined ) {
14001
14002                                 planeMesh = new Mesh(
14003                                         new PlaneBufferGeometry( 2, 2 ),
14004                                         new ShaderMaterial( {
14005                                                 name: 'BackgroundMaterial',
14006                                                 uniforms: cloneUniforms( ShaderLib.background.uniforms ),
14007                                                 vertexShader: ShaderLib.background.vertexShader,
14008                                                 fragmentShader: ShaderLib.background.fragmentShader,
14009                                                 side: FrontSide,
14010                                                 depthTest: false,
14011                                                 depthWrite: false,
14012                                                 fog: false
14013                                         } )
14014                                 );
14015
14016                                 planeMesh.geometry.deleteAttribute( 'normal' );
14017
14018                                 // enable code injection for non-built-in material
14019                                 Object.defineProperty( planeMesh.material, 'map', {
14020
14021                                         get: function () {
14022
14023                                                 return this.uniforms.t2D.value;
14024
14025                                         }
14026
14027                                 } );
14028
14029                                 objects.update( planeMesh );
14030
14031                         }
14032
14033                         planeMesh.material.uniforms.t2D.value = background;
14034
14035                         if ( background.matrixAutoUpdate === true ) {
14036
14037                                 background.updateMatrix();
14038
14039                         }
14040
14041                         planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
14042
14043                         if ( currentBackground !== background ||
14044                                 currentBackgroundVersion !== background.version ||
14045                                 currentTonemapping !== renderer.toneMapping ) {
14046
14047                                 planeMesh.material.needsUpdate = true;
14048
14049                                 currentBackground = background;
14050                                 currentBackgroundVersion = background.version;
14051                                 currentTonemapping = renderer.toneMapping;
14052
14053                         }
14054
14055
14056                         // push to the pre-sorted opaque render list
14057                         renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
14058
14059                 }
14060
14061         }
14062
14063         function setClear( color, alpha ) {
14064
14065                 state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
14066
14067         }
14068
14069         return {
14070
14071                 getClearColor: function () {
14072
14073                         return clearColor;
14074
14075                 },
14076                 setClearColor: function ( color, alpha = 1 ) {
14077
14078                         clearColor.set( color );
14079                         clearAlpha = alpha;
14080                         setClear( clearColor, clearAlpha );
14081
14082                 },
14083                 getClearAlpha: function () {
14084
14085                         return clearAlpha;
14086
14087                 },
14088                 setClearAlpha: function ( alpha ) {
14089
14090                         clearAlpha = alpha;
14091                         setClear( clearColor, clearAlpha );
14092
14093                 },
14094                 render: render
14095
14096         };
14097
14098 }
14099
14100 function WebGLBindingStates( gl, extensions, attributes, capabilities ) {
14101
14102         const maxVertexAttributes = gl.getParameter( 34921 );
14103
14104         const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' );
14105         const vaoAvailable = capabilities.isWebGL2 || extension !== null;
14106
14107         const bindingStates = {};
14108
14109         const defaultState = createBindingState( null );
14110         let currentState = defaultState;
14111
14112         function setup( object, material, program, geometry, index ) {
14113
14114                 let updateBuffers = false;
14115
14116                 if ( vaoAvailable ) {
14117
14118                         const state = getBindingState( geometry, program, material );
14119
14120                         if ( currentState !== state ) {
14121
14122                                 currentState = state;
14123                                 bindVertexArrayObject( currentState.object );
14124
14125                         }
14126
14127                         updateBuffers = needsUpdate( geometry, index );
14128
14129                         if ( updateBuffers ) saveCache( geometry, index );
14130
14131                 } else {
14132
14133                         const wireframe = ( material.wireframe === true );
14134
14135                         if ( currentState.geometry !== geometry.id ||
14136                                 currentState.program !== program.id ||
14137                                 currentState.wireframe !== wireframe ) {
14138
14139                                 currentState.geometry = geometry.id;
14140                                 currentState.program = program.id;
14141                                 currentState.wireframe = wireframe;
14142
14143                                 updateBuffers = true;
14144
14145                         }
14146
14147                 }
14148
14149                 if ( object.isInstancedMesh === true ) {
14150
14151                         updateBuffers = true;
14152
14153                 }
14154
14155                 if ( index !== null ) {
14156
14157                         attributes.update( index, 34963 );
14158
14159                 }
14160
14161                 if ( updateBuffers ) {
14162
14163                         setupVertexAttributes( object, material, program, geometry );
14164
14165                         if ( index !== null ) {
14166
14167                                 gl.bindBuffer( 34963, attributes.get( index ).buffer );
14168
14169                         }
14170
14171                 }
14172
14173         }
14174
14175         function createVertexArrayObject() {
14176
14177                 if ( capabilities.isWebGL2 ) return gl.createVertexArray();
14178
14179                 return extension.createVertexArrayOES();
14180
14181         }
14182
14183         function bindVertexArrayObject( vao ) {
14184
14185                 if ( capabilities.isWebGL2 ) return gl.bindVertexArray( vao );
14186
14187                 return extension.bindVertexArrayOES( vao );
14188
14189         }
14190
14191         function deleteVertexArrayObject( vao ) {
14192
14193                 if ( capabilities.isWebGL2 ) return gl.deleteVertexArray( vao );
14194
14195                 return extension.deleteVertexArrayOES( vao );
14196
14197         }
14198
14199         function getBindingState( geometry, program, material ) {
14200
14201                 const wireframe = ( material.wireframe === true );
14202
14203                 let programMap = bindingStates[ geometry.id ];
14204
14205                 if ( programMap === undefined ) {
14206
14207                         programMap = {};
14208                         bindingStates[ geometry.id ] = programMap;
14209
14210                 }
14211
14212                 let stateMap = programMap[ program.id ];
14213
14214                 if ( stateMap === undefined ) {
14215
14216                         stateMap = {};
14217                         programMap[ program.id ] = stateMap;
14218
14219                 }
14220
14221                 let state = stateMap[ wireframe ];
14222
14223                 if ( state === undefined ) {
14224
14225                         state = createBindingState( createVertexArrayObject() );
14226                         stateMap[ wireframe ] = state;
14227
14228                 }
14229
14230                 return state;
14231
14232         }
14233
14234         function createBindingState( vao ) {
14235
14236                 const newAttributes = [];
14237                 const enabledAttributes = [];
14238                 const attributeDivisors = [];
14239
14240                 for ( let i = 0; i < maxVertexAttributes; i ++ ) {
14241
14242                         newAttributes[ i ] = 0;
14243                         enabledAttributes[ i ] = 0;
14244                         attributeDivisors[ i ] = 0;
14245
14246                 }
14247
14248                 return {
14249
14250                         // for backward compatibility on non-VAO support browser
14251                         geometry: null,
14252                         program: null,
14253                         wireframe: false,
14254
14255                         newAttributes: newAttributes,
14256                         enabledAttributes: enabledAttributes,
14257                         attributeDivisors: attributeDivisors,
14258                         object: vao,
14259                         attributes: {},
14260                         index: null
14261
14262                 };
14263
14264         }
14265
14266         function needsUpdate( geometry, index ) {
14267
14268                 const cachedAttributes = currentState.attributes;
14269                 const geometryAttributes = geometry.attributes;
14270
14271                 let attributesNum = 0;
14272
14273                 for ( const key in geometryAttributes ) {
14274
14275                         const cachedAttribute = cachedAttributes[ key ];
14276                         const geometryAttribute = geometryAttributes[ key ];
14277
14278                         if ( cachedAttribute === undefined ) return true;
14279
14280                         if ( cachedAttribute.attribute !== geometryAttribute ) return true;
14281
14282                         if ( cachedAttribute.data !== geometryAttribute.data ) return true;
14283
14284                         attributesNum ++;
14285
14286                 }
14287
14288                 if ( currentState.attributesNum !== attributesNum ) return true;
14289
14290                 if ( currentState.index !== index ) return true;
14291
14292                 return false;
14293
14294         }
14295
14296         function saveCache( geometry, index ) {
14297
14298                 const cache = {};
14299                 const attributes = geometry.attributes;
14300                 let attributesNum = 0;
14301
14302                 for ( const key in attributes ) {
14303
14304                         const attribute = attributes[ key ];
14305
14306                         const data = {};
14307                         data.attribute = attribute;
14308
14309                         if ( attribute.data ) {
14310
14311                                 data.data = attribute.data;
14312
14313                         }
14314
14315                         cache[ key ] = data;
14316
14317                         attributesNum ++;
14318
14319                 }
14320
14321                 currentState.attributes = cache;
14322                 currentState.attributesNum = attributesNum;
14323
14324                 currentState.index = index;
14325
14326         }
14327
14328         function initAttributes() {
14329
14330                 const newAttributes = currentState.newAttributes;
14331
14332                 for ( let i = 0, il = newAttributes.length; i < il; i ++ ) {
14333
14334                         newAttributes[ i ] = 0;
14335
14336                 }
14337
14338         }
14339
14340         function enableAttribute( attribute ) {
14341
14342                 enableAttributeAndDivisor( attribute, 0 );
14343
14344         }
14345
14346         function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
14347
14348                 const newAttributes = currentState.newAttributes;
14349                 const enabledAttributes = currentState.enabledAttributes;
14350                 const attributeDivisors = currentState.attributeDivisors;
14351
14352                 newAttributes[ attribute ] = 1;
14353
14354                 if ( enabledAttributes[ attribute ] === 0 ) {
14355
14356                         gl.enableVertexAttribArray( attribute );
14357                         enabledAttributes[ attribute ] = 1;
14358
14359                 }
14360
14361                 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
14362
14363                         const extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
14364
14365                         extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
14366                         attributeDivisors[ attribute ] = meshPerAttribute;
14367
14368                 }
14369
14370         }
14371
14372         function disableUnusedAttributes() {
14373
14374                 const newAttributes = currentState.newAttributes;
14375                 const enabledAttributes = currentState.enabledAttributes;
14376
14377                 for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) {
14378
14379                         if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
14380
14381                                 gl.disableVertexAttribArray( i );
14382                                 enabledAttributes[ i ] = 0;
14383
14384                         }
14385
14386                 }
14387
14388         }
14389
14390         function vertexAttribPointer( index, size, type, normalized, stride, offset ) {
14391
14392                 if ( capabilities.isWebGL2 === true && ( type === 5124 || type === 5125 ) ) {
14393
14394                         gl.vertexAttribIPointer( index, size, type, stride, offset );
14395
14396                 } else {
14397
14398                         gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
14399
14400                 }
14401
14402         }
14403
14404         function setupVertexAttributes( object, material, program, geometry ) {
14405
14406                 if ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {
14407
14408                         if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return;
14409
14410                 }
14411
14412                 initAttributes();
14413
14414                 const geometryAttributes = geometry.attributes;
14415
14416                 const programAttributes = program.getAttributes();
14417
14418                 const materialDefaultAttributeValues = material.defaultAttributeValues;
14419
14420                 for ( const name in programAttributes ) {
14421
14422                         const programAttribute = programAttributes[ name ];
14423
14424                         if ( programAttribute >= 0 ) {
14425
14426                                 const geometryAttribute = geometryAttributes[ name ];
14427
14428                                 if ( geometryAttribute !== undefined ) {
14429
14430                                         const normalized = geometryAttribute.normalized;
14431                                         const size = geometryAttribute.itemSize;
14432
14433                                         const attribute = attributes.get( geometryAttribute );
14434
14435                                         // TODO Attribute may not be available on context restore
14436
14437                                         if ( attribute === undefined ) continue;
14438
14439                                         const buffer = attribute.buffer;
14440                                         const type = attribute.type;
14441                                         const bytesPerElement = attribute.bytesPerElement;
14442
14443                                         if ( geometryAttribute.isInterleavedBufferAttribute ) {
14444
14445                                                 const data = geometryAttribute.data;
14446                                                 const stride = data.stride;
14447                                                 const offset = geometryAttribute.offset;
14448
14449                                                 if ( data && data.isInstancedInterleavedBuffer ) {
14450
14451                                                         enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
14452
14453                                                         if ( geometry._maxInstanceCount === undefined ) {
14454
14455                                                                 geometry._maxInstanceCount = data.meshPerAttribute * data.count;
14456
14457                                                         }
14458
14459                                                 } else {
14460
14461                                                         enableAttribute( programAttribute );
14462
14463                                                 }
14464
14465                                                 gl.bindBuffer( 34962, buffer );
14466                                                 vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
14467
14468                                         } else {
14469
14470                                                 if ( geometryAttribute.isInstancedBufferAttribute ) {
14471
14472                                                         enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
14473
14474                                                         if ( geometry._maxInstanceCount === undefined ) {
14475
14476                                                                 geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
14477
14478                                                         }
14479
14480                                                 } else {
14481
14482                                                         enableAttribute( programAttribute );
14483
14484                                                 }
14485
14486                                                 gl.bindBuffer( 34962, buffer );
14487                                                 vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
14488
14489                                         }
14490
14491                                 } else if ( name === 'instanceMatrix' ) {
14492
14493                                         const attribute = attributes.get( object.instanceMatrix );
14494
14495                                         // TODO Attribute may not be available on context restore
14496
14497                                         if ( attribute === undefined ) continue;
14498
14499                                         const buffer = attribute.buffer;
14500                                         const type = attribute.type;
14501
14502                                         enableAttributeAndDivisor( programAttribute + 0, 1 );
14503                                         enableAttributeAndDivisor( programAttribute + 1, 1 );
14504                                         enableAttributeAndDivisor( programAttribute + 2, 1 );
14505                                         enableAttributeAndDivisor( programAttribute + 3, 1 );
14506
14507                                         gl.bindBuffer( 34962, buffer );
14508
14509                                         gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );
14510                                         gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );
14511                                         gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );
14512                                         gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );
14513
14514                                 } else if ( name === 'instanceColor' ) {
14515
14516                                         const attribute = attributes.get( object.instanceColor );
14517
14518                                         // TODO Attribute may not be available on context restore
14519
14520                                         if ( attribute === undefined ) continue;
14521
14522                                         const buffer = attribute.buffer;
14523                                         const type = attribute.type;
14524
14525                                         enableAttributeAndDivisor( programAttribute, 1 );
14526
14527                                         gl.bindBuffer( 34962, buffer );
14528
14529                                         gl.vertexAttribPointer( programAttribute, 3, type, false, 12, 0 );
14530
14531                                 } else if ( materialDefaultAttributeValues !== undefined ) {
14532
14533                                         const value = materialDefaultAttributeValues[ name ];
14534
14535                                         if ( value !== undefined ) {
14536
14537                                                 switch ( value.length ) {
14538
14539                                                         case 2:
14540                                                                 gl.vertexAttrib2fv( programAttribute, value );
14541                                                                 break;
14542
14543                                                         case 3:
14544                                                                 gl.vertexAttrib3fv( programAttribute, value );
14545                                                                 break;
14546
14547                                                         case 4:
14548                                                                 gl.vertexAttrib4fv( programAttribute, value );
14549                                                                 break;
14550
14551                                                         default:
14552                                                                 gl.vertexAttrib1fv( programAttribute, value );
14553
14554                                                 }
14555
14556                                         }
14557
14558                                 }
14559
14560                         }
14561
14562                 }
14563
14564                 disableUnusedAttributes();
14565
14566         }
14567
14568         function dispose() {
14569
14570                 reset();
14571
14572                 for ( const geometryId in bindingStates ) {
14573
14574                         const programMap = bindingStates[ geometryId ];
14575
14576                         for ( const programId in programMap ) {
14577
14578                                 const stateMap = programMap[ programId ];
14579
14580                                 for ( const wireframe in stateMap ) {
14581
14582                                         deleteVertexArrayObject( stateMap[ wireframe ].object );
14583
14584                                         delete stateMap[ wireframe ];
14585
14586                                 }
14587
14588                                 delete programMap[ programId ];
14589
14590                         }
14591
14592                         delete bindingStates[ geometryId ];
14593
14594                 }
14595
14596         }
14597
14598         function releaseStatesOfGeometry( geometry ) {
14599
14600                 if ( bindingStates[ geometry.id ] === undefined ) return;
14601
14602                 const programMap = bindingStates[ geometry.id ];
14603
14604                 for ( const programId in programMap ) {
14605
14606                         const stateMap = programMap[ programId ];
14607
14608                         for ( const wireframe in stateMap ) {
14609
14610                                 deleteVertexArrayObject( stateMap[ wireframe ].object );
14611
14612                                 delete stateMap[ wireframe ];
14613
14614                         }
14615
14616                         delete programMap[ programId ];
14617
14618                 }
14619
14620                 delete bindingStates[ geometry.id ];
14621
14622         }
14623
14624         function releaseStatesOfProgram( program ) {
14625
14626                 for ( const geometryId in bindingStates ) {
14627
14628                         const programMap = bindingStates[ geometryId ];
14629
14630                         if ( programMap[ program.id ] === undefined ) continue;
14631
14632                         const stateMap = programMap[ program.id ];
14633
14634                         for ( const wireframe in stateMap ) {
14635
14636                                 deleteVertexArrayObject( stateMap[ wireframe ].object );
14637
14638                                 delete stateMap[ wireframe ];
14639
14640                         }
14641
14642                         delete programMap[ program.id ];
14643
14644                 }
14645
14646         }
14647
14648         function reset() {
14649
14650                 resetDefaultState();
14651
14652                 if ( currentState === defaultState ) return;
14653
14654                 currentState = defaultState;
14655                 bindVertexArrayObject( currentState.object );
14656
14657         }
14658
14659         // for backward-compatilibity
14660
14661         function resetDefaultState() {
14662
14663                 defaultState.geometry = null;
14664                 defaultState.program = null;
14665                 defaultState.wireframe = false;
14666
14667         }
14668
14669         return {
14670
14671                 setup: setup,
14672                 reset: reset,
14673                 resetDefaultState: resetDefaultState,
14674                 dispose: dispose,
14675                 releaseStatesOfGeometry: releaseStatesOfGeometry,
14676                 releaseStatesOfProgram: releaseStatesOfProgram,
14677
14678                 initAttributes: initAttributes,
14679                 enableAttribute: enableAttribute,
14680                 disableUnusedAttributes: disableUnusedAttributes
14681
14682         };
14683
14684 }
14685
14686 function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
14687
14688         const isWebGL2 = capabilities.isWebGL2;
14689
14690         let mode;
14691
14692         function setMode( value ) {
14693
14694                 mode = value;
14695
14696         }
14697
14698         function render( start, count ) {
14699
14700                 gl.drawArrays( mode, start, count );
14701
14702                 info.update( count, mode, 1 );
14703
14704         }
14705
14706         function renderInstances( start, count, primcount ) {
14707
14708                 if ( primcount === 0 ) return;
14709
14710                 let extension, methodName;
14711
14712                 if ( isWebGL2 ) {
14713
14714                         extension = gl;
14715                         methodName = 'drawArraysInstanced';
14716
14717                 } else {
14718
14719                         extension = extensions.get( 'ANGLE_instanced_arrays' );
14720                         methodName = 'drawArraysInstancedANGLE';
14721
14722                         if ( extension === null ) {
14723
14724                                 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
14725                                 return;
14726
14727                         }
14728
14729                 }
14730
14731                 extension[ methodName ]( mode, start, count, primcount );
14732
14733                 info.update( count, mode, primcount );
14734
14735         }
14736
14737         //
14738
14739         this.setMode = setMode;
14740         this.render = render;
14741         this.renderInstances = renderInstances;
14742
14743 }
14744
14745 function WebGLCapabilities( gl, extensions, parameters ) {
14746
14747         let maxAnisotropy;
14748
14749         function getMaxAnisotropy() {
14750
14751                 if ( maxAnisotropy !== undefined ) return maxAnisotropy;
14752
14753                 const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
14754
14755                 if ( extension !== null ) {
14756
14757                         maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
14758
14759                 } else {
14760
14761                         maxAnisotropy = 0;
14762
14763                 }
14764
14765                 return maxAnisotropy;
14766
14767         }
14768
14769         function getMaxPrecision( precision ) {
14770
14771                 if ( precision === 'highp' ) {
14772
14773                         if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&
14774                                 gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {
14775
14776                                 return 'highp';
14777
14778                         }
14779
14780                         precision = 'mediump';
14781
14782                 }
14783
14784                 if ( precision === 'mediump' ) {
14785
14786                         if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&
14787                                 gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {
14788
14789                                 return 'mediump';
14790
14791                         }
14792
14793                 }
14794
14795                 return 'lowp';
14796
14797         }
14798
14799         /* eslint-disable no-undef */
14800         const isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||
14801                 ( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );
14802         /* eslint-enable no-undef */
14803
14804         let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
14805         const maxPrecision = getMaxPrecision( precision );
14806
14807         if ( maxPrecision !== precision ) {
14808
14809                 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
14810                 precision = maxPrecision;
14811
14812         }
14813
14814         const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
14815
14816         const maxTextures = gl.getParameter( 34930 );
14817         const maxVertexTextures = gl.getParameter( 35660 );
14818         const maxTextureSize = gl.getParameter( 3379 );
14819         const maxCubemapSize = gl.getParameter( 34076 );
14820
14821         const maxAttributes = gl.getParameter( 34921 );
14822         const maxVertexUniforms = gl.getParameter( 36347 );
14823         const maxVaryings = gl.getParameter( 36348 );
14824         const maxFragmentUniforms = gl.getParameter( 36349 );
14825
14826         const vertexTextures = maxVertexTextures > 0;
14827         const floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
14828         const floatVertexTextures = vertexTextures && floatFragmentTextures;
14829
14830         const maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;
14831
14832         return {
14833
14834                 isWebGL2: isWebGL2,
14835
14836                 getMaxAnisotropy: getMaxAnisotropy,
14837                 getMaxPrecision: getMaxPrecision,
14838
14839                 precision: precision,
14840                 logarithmicDepthBuffer: logarithmicDepthBuffer,
14841
14842                 maxTextures: maxTextures,
14843                 maxVertexTextures: maxVertexTextures,
14844                 maxTextureSize: maxTextureSize,
14845                 maxCubemapSize: maxCubemapSize,
14846
14847                 maxAttributes: maxAttributes,
14848                 maxVertexUniforms: maxVertexUniforms,
14849                 maxVaryings: maxVaryings,
14850                 maxFragmentUniforms: maxFragmentUniforms,
14851
14852                 vertexTextures: vertexTextures,
14853                 floatFragmentTextures: floatFragmentTextures,
14854                 floatVertexTextures: floatVertexTextures,
14855
14856                 maxSamples: maxSamples
14857
14858         };
14859
14860 }
14861
14862 function WebGLClipping( properties ) {
14863
14864         const scope = this;
14865
14866         let globalState = null,
14867                 numGlobalPlanes = 0,
14868                 localClippingEnabled = false,
14869                 renderingShadows = false;
14870
14871         const plane = new Plane(),
14872                 viewNormalMatrix = new Matrix3(),
14873
14874                 uniform = { value: null, needsUpdate: false };
14875
14876         this.uniform = uniform;
14877         this.numPlanes = 0;
14878         this.numIntersection = 0;
14879
14880         this.init = function ( planes, enableLocalClipping, camera ) {
14881
14882                 const enabled =
14883                         planes.length !== 0 ||
14884                         enableLocalClipping ||
14885                         // enable state of previous frame - the clipping code has to
14886                         // run another frame in order to reset the state:
14887                         numGlobalPlanes !== 0 ||
14888                         localClippingEnabled;
14889
14890                 localClippingEnabled = enableLocalClipping;
14891
14892                 globalState = projectPlanes( planes, camera, 0 );
14893                 numGlobalPlanes = planes.length;
14894
14895                 return enabled;
14896
14897         };
14898
14899         this.beginShadows = function () {
14900
14901                 renderingShadows = true;
14902                 projectPlanes( null );
14903
14904         };
14905
14906         this.endShadows = function () {
14907
14908                 renderingShadows = false;
14909                 resetGlobalState();
14910
14911         };
14912
14913         this.setState = function ( material, camera, useCache ) {
14914
14915                 const planes = material.clippingPlanes,
14916                         clipIntersection = material.clipIntersection,
14917                         clipShadows = material.clipShadows;
14918
14919                 const materialProperties = properties.get( material );
14920
14921                 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
14922
14923                         // there's no local clipping
14924
14925                         if ( renderingShadows ) {
14926
14927                                 // there's no global clipping
14928
14929                                 projectPlanes( null );
14930
14931                         } else {
14932
14933                                 resetGlobalState();
14934
14935                         }
14936
14937                 } else {
14938
14939                         const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
14940                                 lGlobal = nGlobal * 4;
14941
14942                         let dstArray = materialProperties.clippingState || null;
14943
14944                         uniform.value = dstArray; // ensure unique state
14945
14946                         dstArray = projectPlanes( planes, camera, lGlobal, useCache );
14947
14948                         for ( let i = 0; i !== lGlobal; ++ i ) {
14949
14950                                 dstArray[ i ] = globalState[ i ];
14951
14952                         }
14953
14954                         materialProperties.clippingState = dstArray;
14955                         this.numIntersection = clipIntersection ? this.numPlanes : 0;
14956                         this.numPlanes += nGlobal;
14957
14958                 }
14959
14960
14961         };
14962
14963         function resetGlobalState() {
14964
14965                 if ( uniform.value !== globalState ) {
14966
14967                         uniform.value = globalState;
14968                         uniform.needsUpdate = numGlobalPlanes > 0;
14969
14970                 }
14971
14972                 scope.numPlanes = numGlobalPlanes;
14973                 scope.numIntersection = 0;
14974
14975         }
14976
14977         function projectPlanes( planes, camera, dstOffset, skipTransform ) {
14978
14979                 const nPlanes = planes !== null ? planes.length : 0;
14980                 let dstArray = null;
14981
14982                 if ( nPlanes !== 0 ) {
14983
14984                         dstArray = uniform.value;
14985
14986                         if ( skipTransform !== true || dstArray === null ) {
14987
14988                                 const flatSize = dstOffset + nPlanes * 4,
14989                                         viewMatrix = camera.matrixWorldInverse;
14990
14991                                 viewNormalMatrix.getNormalMatrix( viewMatrix );
14992
14993                                 if ( dstArray === null || dstArray.length < flatSize ) {
14994
14995                                         dstArray = new Float32Array( flatSize );
14996
14997                                 }
14998
14999                                 for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
15000
15001                                         plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
15002
15003                                         plane.normal.toArray( dstArray, i4 );
15004                                         dstArray[ i4 + 3 ] = plane.constant;
15005
15006                                 }
15007
15008                         }
15009
15010                         uniform.value = dstArray;
15011                         uniform.needsUpdate = true;
15012
15013                 }
15014
15015                 scope.numPlanes = nPlanes;
15016                 scope.numIntersection = 0;
15017
15018                 return dstArray;
15019
15020         }
15021
15022 }
15023
15024 function WebGLCubeMaps( renderer ) {
15025
15026         let cubemaps = new WeakMap();
15027
15028         function mapTextureMapping( texture, mapping ) {
15029
15030                 if ( mapping === EquirectangularReflectionMapping ) {
15031
15032                         texture.mapping = CubeReflectionMapping;
15033
15034                 } else if ( mapping === EquirectangularRefractionMapping ) {
15035
15036                         texture.mapping = CubeRefractionMapping;
15037
15038                 }
15039
15040                 return texture;
15041
15042         }
15043
15044         function get( texture ) {
15045
15046                 if ( texture && texture.isTexture ) {
15047
15048                         const mapping = texture.mapping;
15049
15050                         if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
15051
15052                                 if ( cubemaps.has( texture ) ) {
15053
15054                                         const cubemap = cubemaps.get( texture ).texture;
15055                                         return mapTextureMapping( cubemap, texture.mapping );
15056
15057                                 } else {
15058
15059                                         const image = texture.image;
15060
15061                                         if ( image && image.height > 0 ) {
15062
15063                                                 const currentRenderList = renderer.getRenderList();
15064                                                 const currentRenderTarget = renderer.getRenderTarget();
15065                                                 const currentRenderState = renderer.getRenderState();
15066
15067                                                 const renderTarget = new WebGLCubeRenderTarget( image.height / 2 );
15068                                                 renderTarget.fromEquirectangularTexture( renderer, texture );
15069                                                 cubemaps.set( texture, renderTarget );
15070
15071                                                 renderer.setRenderTarget( currentRenderTarget );
15072                                                 renderer.setRenderList( currentRenderList );
15073                                                 renderer.setRenderState( currentRenderState );
15074
15075                                                 texture.addEventListener( 'dispose', onTextureDispose );
15076
15077                                                 return mapTextureMapping( renderTarget.texture, texture.mapping );
15078
15079                                         } else {
15080
15081                                                 // image not yet ready. try the conversion next frame
15082
15083                                                 return null;
15084
15085                                         }
15086
15087                                 }
15088
15089                         }
15090
15091                 }
15092
15093                 return texture;
15094
15095         }
15096
15097         function onTextureDispose( event ) {
15098
15099                 const texture = event.target;
15100
15101                 texture.removeEventListener( 'dispose', onTextureDispose );
15102
15103                 const cubemap = cubemaps.get( texture );
15104
15105                 if ( cubemap !== undefined ) {
15106
15107                         cubemaps.delete( texture );
15108                         cubemap.dispose();
15109
15110                 }
15111
15112         }
15113
15114         function dispose() {
15115
15116                 cubemaps = new WeakMap();
15117
15118         }
15119
15120         return {
15121                 get: get,
15122                 dispose: dispose
15123         };
15124
15125 }
15126
15127 function WebGLExtensions( gl ) {
15128
15129         const extensions = {};
15130
15131         return {
15132
15133                 has: function ( name ) {
15134
15135                         if ( extensions[ name ] !== undefined ) {
15136
15137                                 return extensions[ name ] !== null;
15138
15139                         }
15140
15141                         let extension;
15142
15143                         switch ( name ) {
15144
15145                                 case 'WEBGL_depth_texture':
15146                                         extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
15147                                         break;
15148
15149                                 case 'EXT_texture_filter_anisotropic':
15150                                         extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
15151                                         break;
15152
15153                                 case 'WEBGL_compressed_texture_s3tc':
15154                                         extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
15155                                         break;
15156
15157                                 case 'WEBGL_compressed_texture_pvrtc':
15158                                         extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
15159                                         break;
15160
15161                                 default:
15162                                         extension = gl.getExtension( name );
15163
15164                         }
15165
15166                         extensions[ name ] = extension;
15167
15168                         return extension !== null;
15169
15170                 },
15171
15172                 get: function ( name ) {
15173
15174                         if ( ! this.has( name ) ) {
15175
15176                                 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
15177
15178                         }
15179
15180                         return extensions[ name ];
15181
15182                 }
15183
15184         };
15185
15186 }
15187
15188 function WebGLGeometries( gl, attributes, info, bindingStates ) {
15189
15190         const geometries = new WeakMap();
15191         const wireframeAttributes = new WeakMap();
15192
15193         function onGeometryDispose( event ) {
15194
15195                 const geometry = event.target;
15196                 const buffergeometry = geometries.get( geometry );
15197
15198                 if ( buffergeometry.index !== null ) {
15199
15200                         attributes.remove( buffergeometry.index );
15201
15202                 }
15203
15204                 for ( const name in buffergeometry.attributes ) {
15205
15206                         attributes.remove( buffergeometry.attributes[ name ] );
15207
15208                 }
15209
15210                 geometry.removeEventListener( 'dispose', onGeometryDispose );
15211
15212                 geometries.delete( geometry );
15213
15214                 const attribute = wireframeAttributes.get( buffergeometry );
15215
15216                 if ( attribute ) {
15217
15218                         attributes.remove( attribute );
15219                         wireframeAttributes.delete( buffergeometry );
15220
15221                 }
15222
15223                 bindingStates.releaseStatesOfGeometry( buffergeometry );
15224
15225                 if ( geometry.isInstancedBufferGeometry === true ) {
15226
15227                         delete geometry._maxInstanceCount;
15228
15229                 }
15230
15231                 //
15232
15233                 info.memory.geometries --;
15234
15235         }
15236
15237         function get( object, geometry ) {
15238
15239                 let buffergeometry = geometries.get( geometry );
15240
15241                 if ( buffergeometry ) return buffergeometry;
15242
15243                 geometry.addEventListener( 'dispose', onGeometryDispose );
15244
15245                 if ( geometry.isBufferGeometry ) {
15246
15247                         buffergeometry = geometry;
15248
15249                 } else if ( geometry.isGeometry ) {
15250
15251                         if ( geometry._bufferGeometry === undefined ) {
15252
15253                                 geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
15254
15255                         }
15256
15257                         buffergeometry = geometry._bufferGeometry;
15258
15259                 }
15260
15261                 geometries.set( geometry, buffergeometry );
15262
15263                 info.memory.geometries ++;
15264
15265                 return buffergeometry;
15266
15267         }
15268
15269         function update( geometry ) {
15270
15271                 const geometryAttributes = geometry.attributes;
15272
15273                 // Updating index buffer in VAO now. See WebGLBindingStates.
15274
15275                 for ( const name in geometryAttributes ) {
15276
15277                         attributes.update( geometryAttributes[ name ], 34962 );
15278
15279                 }
15280
15281                 // morph targets
15282
15283                 const morphAttributes = geometry.morphAttributes;
15284
15285                 for ( const name in morphAttributes ) {
15286
15287                         const array = morphAttributes[ name ];
15288
15289                         for ( let i = 0, l = array.length; i < l; i ++ ) {
15290
15291                                 attributes.update( array[ i ], 34962 );
15292
15293                         }
15294
15295                 }
15296
15297         }
15298
15299         function updateWireframeAttribute( geometry ) {
15300
15301                 const indices = [];
15302
15303                 const geometryIndex = geometry.index;
15304                 const geometryPosition = geometry.attributes.position;
15305                 let version = 0;
15306
15307                 if ( geometryIndex !== null ) {
15308
15309                         const array = geometryIndex.array;
15310                         version = geometryIndex.version;
15311
15312                         for ( let i = 0, l = array.length; i < l; i += 3 ) {
15313
15314                                 const a = array[ i + 0 ];
15315                                 const b = array[ i + 1 ];
15316                                 const c = array[ i + 2 ];
15317
15318                                 indices.push( a, b, b, c, c, a );
15319
15320                         }
15321
15322                 } else {
15323
15324                         const array = geometryPosition.array;
15325                         version = geometryPosition.version;
15326
15327                         for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
15328
15329                                 const a = i + 0;
15330                                 const b = i + 1;
15331                                 const c = i + 2;
15332
15333                                 indices.push( a, b, b, c, c, a );
15334
15335                         }
15336
15337                 }
15338
15339                 const attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
15340                 attribute.version = version;
15341
15342                 // Updating index buffer in VAO now. See WebGLBindingStates
15343
15344                 //
15345
15346                 const previousAttribute = wireframeAttributes.get( geometry );
15347
15348                 if ( previousAttribute ) attributes.remove( previousAttribute );
15349
15350                 //
15351
15352                 wireframeAttributes.set( geometry, attribute );
15353
15354         }
15355
15356         function getWireframeAttribute( geometry ) {
15357
15358                 const currentAttribute = wireframeAttributes.get( geometry );
15359
15360                 if ( currentAttribute ) {
15361
15362                         const geometryIndex = geometry.index;
15363
15364                         if ( geometryIndex !== null ) {
15365
15366                                 // if the attribute is obsolete, create a new one
15367
15368                                 if ( currentAttribute.version < geometryIndex.version ) {
15369
15370                                         updateWireframeAttribute( geometry );
15371
15372                                 }
15373
15374                         }
15375
15376                 } else {
15377
15378                         updateWireframeAttribute( geometry );
15379
15380                 }
15381
15382                 return wireframeAttributes.get( geometry );
15383
15384         }
15385
15386         return {
15387
15388                 get: get,
15389                 update: update,
15390
15391                 getWireframeAttribute: getWireframeAttribute
15392
15393         };
15394
15395 }
15396
15397 function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
15398
15399         const isWebGL2 = capabilities.isWebGL2;
15400
15401         let mode;
15402
15403         function setMode( value ) {
15404
15405                 mode = value;
15406
15407         }
15408
15409         let type, bytesPerElement;
15410
15411         function setIndex( value ) {
15412
15413                 type = value.type;
15414                 bytesPerElement = value.bytesPerElement;
15415
15416         }
15417
15418         function render( start, count ) {
15419
15420                 gl.drawElements( mode, count, type, start * bytesPerElement );
15421
15422                 info.update( count, mode, 1 );
15423
15424         }
15425
15426         function renderInstances( start, count, primcount ) {
15427
15428                 if ( primcount === 0 ) return;
15429
15430                 let extension, methodName;
15431
15432                 if ( isWebGL2 ) {
15433
15434                         extension = gl;
15435                         methodName = 'drawElementsInstanced';
15436
15437                 } else {
15438
15439                         extension = extensions.get( 'ANGLE_instanced_arrays' );
15440                         methodName = 'drawElementsInstancedANGLE';
15441
15442                         if ( extension === null ) {
15443
15444                                 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
15445                                 return;
15446
15447                         }
15448
15449                 }
15450
15451                 extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );
15452
15453                 info.update( count, mode, primcount );
15454
15455         }
15456
15457         //
15458
15459         this.setMode = setMode;
15460         this.setIndex = setIndex;
15461         this.render = render;
15462         this.renderInstances = renderInstances;
15463
15464 }
15465
15466 function WebGLInfo( gl ) {
15467
15468         const memory = {
15469                 geometries: 0,
15470                 textures: 0
15471         };
15472
15473         const render = {
15474                 frame: 0,
15475                 calls: 0,
15476                 triangles: 0,
15477                 points: 0,
15478                 lines: 0
15479         };
15480
15481         function update( count, mode, instanceCount ) {
15482
15483                 render.calls ++;
15484
15485                 switch ( mode ) {
15486
15487                         case 4:
15488                                 render.triangles += instanceCount * ( count / 3 );
15489                                 break;
15490
15491                         case 1:
15492                                 render.lines += instanceCount * ( count / 2 );
15493                                 break;
15494
15495                         case 3:
15496                                 render.lines += instanceCount * ( count - 1 );
15497                                 break;
15498
15499                         case 2:
15500                                 render.lines += instanceCount * count;
15501                                 break;
15502
15503                         case 0:
15504                                 render.points += instanceCount * count;
15505                                 break;
15506
15507                         default:
15508                                 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
15509                                 break;
15510
15511                 }
15512
15513         }
15514
15515         function reset() {
15516
15517                 render.frame ++;
15518                 render.calls = 0;
15519                 render.triangles = 0;
15520                 render.points = 0;
15521                 render.lines = 0;
15522
15523         }
15524
15525         return {
15526                 memory: memory,
15527                 render: render,
15528                 programs: null,
15529                 autoReset: true,
15530                 reset: reset,
15531                 update: update
15532         };
15533
15534 }
15535
15536 function numericalSort( a, b ) {
15537
15538         return a[ 0 ] - b[ 0 ];
15539
15540 }
15541
15542 function absNumericalSort( a, b ) {
15543
15544         return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
15545
15546 }
15547
15548 function WebGLMorphtargets( gl ) {
15549
15550         const influencesList = {};
15551         const morphInfluences = new Float32Array( 8 );
15552
15553         const workInfluences = [];
15554
15555         for ( let i = 0; i < 8; i ++ ) {
15556
15557                 workInfluences[ i ] = [ i, 0 ];
15558
15559         }
15560
15561         function update( object, geometry, material, program ) {
15562
15563                 const objectInfluences = object.morphTargetInfluences;
15564
15565                 // When object doesn't have morph target influences defined, we treat it as a 0-length array
15566                 // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
15567
15568                 const length = objectInfluences === undefined ? 0 : objectInfluences.length;
15569
15570                 let influences = influencesList[ geometry.id ];
15571
15572                 if ( influences === undefined ) {
15573
15574                         // initialise list
15575
15576                         influences = [];
15577
15578                         for ( let i = 0; i < length; i ++ ) {
15579
15580                                 influences[ i ] = [ i, 0 ];
15581
15582                         }
15583
15584                         influencesList[ geometry.id ] = influences;
15585
15586                 }
15587
15588                 // Collect influences
15589
15590                 for ( let i = 0; i < length; i ++ ) {
15591
15592                         const influence = influences[ i ];
15593
15594                         influence[ 0 ] = i;
15595                         influence[ 1 ] = objectInfluences[ i ];
15596
15597                 }
15598
15599                 influences.sort( absNumericalSort );
15600
15601                 for ( let i = 0; i < 8; i ++ ) {
15602
15603                         if ( i < length && influences[ i ][ 1 ] ) {
15604
15605                                 workInfluences[ i ][ 0 ] = influences[ i ][ 0 ];
15606                                 workInfluences[ i ][ 1 ] = influences[ i ][ 1 ];
15607
15608                         } else {
15609
15610                                 workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER;
15611                                 workInfluences[ i ][ 1 ] = 0;
15612
15613                         }
15614
15615                 }
15616
15617                 workInfluences.sort( numericalSort );
15618
15619                 const morphTargets = material.morphTargets && geometry.morphAttributes.position;
15620                 const morphNormals = material.morphNormals && geometry.morphAttributes.normal;
15621
15622                 let morphInfluencesSum = 0;
15623
15624                 for ( let i = 0; i < 8; i ++ ) {
15625
15626                         const influence = workInfluences[ i ];
15627                         const index = influence[ 0 ];
15628                         const value = influence[ 1 ];
15629
15630                         if ( index !== Number.MAX_SAFE_INTEGER && value ) {
15631
15632                                 if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) {
15633
15634                                         geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );
15635
15636                                 }
15637
15638                                 if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) {
15639
15640                                         geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );
15641
15642                                 }
15643
15644                                 morphInfluences[ i ] = value;
15645                                 morphInfluencesSum += value;
15646
15647                         } else {
15648
15649                                 if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) {
15650
15651                                         geometry.deleteAttribute( 'morphTarget' + i );
15652
15653                                 }
15654
15655                                 if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) {
15656
15657                                         geometry.deleteAttribute( 'morphNormal' + i );
15658
15659                                 }
15660
15661                                 morphInfluences[ i ] = 0;
15662
15663                         }
15664
15665                 }
15666
15667                 // GLSL shader uses formula baseinfluence * base + sum(target * influence)
15668                 // This allows us to switch between absolute morphs and relative morphs without changing shader code
15669                 // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
15670                 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
15671
15672                 program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
15673                 program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
15674
15675         }
15676
15677         return {
15678
15679                 update: update
15680
15681         };
15682
15683 }
15684
15685 function WebGLObjects( gl, geometries, attributes, info ) {
15686
15687         let updateMap = new WeakMap();
15688
15689         function update( object ) {
15690
15691                 const frame = info.render.frame;
15692
15693                 const geometry = object.geometry;
15694                 const buffergeometry = geometries.get( object, geometry );
15695
15696                 // Update once per frame
15697
15698                 if ( updateMap.get( buffergeometry ) !== frame ) {
15699
15700                         if ( geometry.isGeometry ) {
15701
15702                                 buffergeometry.updateFromObject( object );
15703
15704                         }
15705
15706                         geometries.update( buffergeometry );
15707
15708                         updateMap.set( buffergeometry, frame );
15709
15710                 }
15711
15712                 if ( object.isInstancedMesh ) {
15713
15714                         attributes.update( object.instanceMatrix, 34962 );
15715
15716                         if ( object.instanceColor !== null ) {
15717
15718                                 attributes.update( object.instanceColor, 34962 );
15719
15720                         }
15721
15722                 }
15723
15724                 return buffergeometry;
15725
15726         }
15727
15728         function dispose() {
15729
15730                 updateMap = new WeakMap();
15731
15732         }
15733
15734         return {
15735
15736                 update: update,
15737                 dispose: dispose
15738
15739         };
15740
15741 }
15742
15743 function DataTexture2DArray( data = null, width = 1, height = 1, depth = 1 ) {
15744
15745         Texture.call( this, null );
15746
15747         this.image = { data, width, height, depth };
15748
15749         this.magFilter = NearestFilter;
15750         this.minFilter = NearestFilter;
15751
15752         this.wrapR = ClampToEdgeWrapping;
15753
15754         this.generateMipmaps = false;
15755         this.flipY = false;
15756
15757         this.needsUpdate = true;
15758
15759 }
15760
15761 DataTexture2DArray.prototype = Object.create( Texture.prototype );
15762 DataTexture2DArray.prototype.constructor = DataTexture2DArray;
15763 DataTexture2DArray.prototype.isDataTexture2DArray = true;
15764
15765 function DataTexture3D( data = null, width = 1, height = 1, depth = 1 ) {
15766
15767         // We're going to add .setXXX() methods for setting properties later.
15768         // Users can still set in DataTexture3D directly.
15769         //
15770         //      const texture = new THREE.DataTexture3D( data, width, height, depth );
15771         //      texture.anisotropy = 16;
15772         //
15773         // See #14839
15774
15775         Texture.call( this, null );
15776
15777         this.image = { data, width, height, depth };
15778
15779         this.magFilter = NearestFilter;
15780         this.minFilter = NearestFilter;
15781
15782         this.wrapR = ClampToEdgeWrapping;
15783
15784         this.generateMipmaps = false;
15785         this.flipY = false;
15786
15787         this.needsUpdate = true;
15788
15789
15790 }
15791
15792 DataTexture3D.prototype = Object.create( Texture.prototype );
15793 DataTexture3D.prototype.constructor = DataTexture3D;
15794 DataTexture3D.prototype.isDataTexture3D = true;
15795
15796 /**
15797  * Uniforms of a program.
15798  * Those form a tree structure with a special top-level container for the root,
15799  * which you get by calling 'new WebGLUniforms( gl, program )'.
15800  *
15801  *
15802  * Properties of inner nodes including the top-level container:
15803  *
15804  * .seq - array of nested uniforms
15805  * .map - nested uniforms by name
15806  *
15807  *
15808  * Methods of all nodes except the top-level container:
15809  *
15810  * .setValue( gl, value, [textures] )
15811  *
15812  *              uploads a uniform value(s)
15813  *      the 'textures' parameter is needed for sampler uniforms
15814  *
15815  *
15816  * Static methods of the top-level container (textures factorizations):
15817  *
15818  * .upload( gl, seq, values, textures )
15819  *
15820  *              sets uniforms in 'seq' to 'values[id].value'
15821  *
15822  * .seqWithValue( seq, values ) : filteredSeq
15823  *
15824  *              filters 'seq' entries with corresponding entry in values
15825  *
15826  *
15827  * Methods of the top-level container (textures factorizations):
15828  *
15829  * .setValue( gl, name, value, textures )
15830  *
15831  *              sets uniform with  name 'name' to 'value'
15832  *
15833  * .setOptional( gl, obj, prop )
15834  *
15835  *              like .set for an optional property of the object
15836  *
15837  */
15838
15839 const emptyTexture = new Texture();
15840 const emptyTexture2dArray = new DataTexture2DArray();
15841 const emptyTexture3d = new DataTexture3D();
15842 const emptyCubeTexture = new CubeTexture();
15843
15844 // --- Utilities ---
15845
15846 // Array Caches (provide typed arrays for temporary by size)
15847
15848 const arrayCacheF32 = [];
15849 const arrayCacheI32 = [];
15850
15851 // Float32Array caches used for uploading Matrix uniforms
15852
15853 const mat4array = new Float32Array( 16 );
15854 const mat3array = new Float32Array( 9 );
15855 const mat2array = new Float32Array( 4 );
15856
15857 // Flattening for arrays of vectors and matrices
15858
15859 function flatten( array, nBlocks, blockSize ) {
15860
15861         const firstElem = array[ 0 ];
15862
15863         if ( firstElem <= 0 || firstElem > 0 ) return array;
15864         // unoptimized: ! isNaN( firstElem )
15865         // see http://jacksondunstan.com/articles/983
15866
15867         const n = nBlocks * blockSize;
15868         let r = arrayCacheF32[ n ];
15869
15870         if ( r === undefined ) {
15871
15872                 r = new Float32Array( n );
15873                 arrayCacheF32[ n ] = r;
15874
15875         }
15876
15877         if ( nBlocks !== 0 ) {
15878
15879                 firstElem.toArray( r, 0 );
15880
15881                 for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) {
15882
15883                         offset += blockSize;
15884                         array[ i ].toArray( r, offset );
15885
15886                 }
15887
15888         }
15889
15890         return r;
15891
15892 }
15893
15894 function arraysEqual( a, b ) {
15895
15896         if ( a.length !== b.length ) return false;
15897
15898         for ( let i = 0, l = a.length; i < l; i ++ ) {
15899
15900                 if ( a[ i ] !== b[ i ] ) return false;
15901
15902         }
15903
15904         return true;
15905
15906 }
15907
15908 function copyArray( a, b ) {
15909
15910         for ( let i = 0, l = b.length; i < l; i ++ ) {
15911
15912                 a[ i ] = b[ i ];
15913
15914         }
15915
15916 }
15917
15918 // Texture unit allocation
15919
15920 function allocTexUnits( textures, n ) {
15921
15922         let r = arrayCacheI32[ n ];
15923
15924         if ( r === undefined ) {
15925
15926                 r = new Int32Array( n );
15927                 arrayCacheI32[ n ] = r;
15928
15929         }
15930
15931         for ( let i = 0; i !== n; ++ i ) {
15932
15933                 r[ i ] = textures.allocateTextureUnit();
15934
15935         }
15936
15937         return r;
15938
15939 }
15940
15941 // --- Setters ---
15942
15943 // Note: Defining these methods externally, because they come in a bunch
15944 // and this way their names minify.
15945
15946 // Single scalar
15947
15948 function setValueV1f( gl, v ) {
15949
15950         const cache = this.cache;
15951
15952         if ( cache[ 0 ] === v ) return;
15953
15954         gl.uniform1f( this.addr, v );
15955
15956         cache[ 0 ] = v;
15957
15958 }
15959
15960 // Single float vector (from flat array or THREE.VectorN)
15961
15962 function setValueV2f( gl, v ) {
15963
15964         const cache = this.cache;
15965
15966         if ( v.x !== undefined ) {
15967
15968                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
15969
15970                         gl.uniform2f( this.addr, v.x, v.y );
15971
15972                         cache[ 0 ] = v.x;
15973                         cache[ 1 ] = v.y;
15974
15975                 }
15976
15977         } else {
15978
15979                 if ( arraysEqual( cache, v ) ) return;
15980
15981                 gl.uniform2fv( this.addr, v );
15982
15983                 copyArray( cache, v );
15984
15985         }
15986
15987 }
15988
15989 function setValueV3f( gl, v ) {
15990
15991         const cache = this.cache;
15992
15993         if ( v.x !== undefined ) {
15994
15995                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
15996
15997                         gl.uniform3f( this.addr, v.x, v.y, v.z );
15998
15999                         cache[ 0 ] = v.x;
16000                         cache[ 1 ] = v.y;
16001                         cache[ 2 ] = v.z;
16002
16003                 }
16004
16005         } else if ( v.r !== undefined ) {
16006
16007                 if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
16008
16009                         gl.uniform3f( this.addr, v.r, v.g, v.b );
16010
16011                         cache[ 0 ] = v.r;
16012                         cache[ 1 ] = v.g;
16013                         cache[ 2 ] = v.b;
16014
16015                 }
16016
16017         } else {
16018
16019                 if ( arraysEqual( cache, v ) ) return;
16020
16021                 gl.uniform3fv( this.addr, v );
16022
16023                 copyArray( cache, v );
16024
16025         }
16026
16027 }
16028
16029 function setValueV4f( gl, v ) {
16030
16031         const cache = this.cache;
16032
16033         if ( v.x !== undefined ) {
16034
16035                 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
16036
16037                         gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
16038
16039                         cache[ 0 ] = v.x;
16040                         cache[ 1 ] = v.y;
16041                         cache[ 2 ] = v.z;
16042                         cache[ 3 ] = v.w;
16043
16044                 }
16045
16046         } else {
16047
16048                 if ( arraysEqual( cache, v ) ) return;
16049
16050                 gl.uniform4fv( this.addr, v );
16051
16052                 copyArray( cache, v );
16053
16054         }
16055
16056 }
16057
16058 // Single matrix (from flat array or MatrixN)
16059
16060 function setValueM2( gl, v ) {
16061
16062         const cache = this.cache;
16063         const elements = v.elements;
16064
16065         if ( elements === undefined ) {
16066
16067                 if ( arraysEqual( cache, v ) ) return;
16068
16069                 gl.uniformMatrix2fv( this.addr, false, v );
16070
16071                 copyArray( cache, v );
16072
16073         } else {
16074
16075                 if ( arraysEqual( cache, elements ) ) return;
16076
16077                 mat2array.set( elements );
16078
16079                 gl.uniformMatrix2fv( this.addr, false, mat2array );
16080
16081                 copyArray( cache, elements );
16082
16083         }
16084
16085 }
16086
16087 function setValueM3( gl, v ) {
16088
16089         const cache = this.cache;
16090         const elements = v.elements;
16091
16092         if ( elements === undefined ) {
16093
16094                 if ( arraysEqual( cache, v ) ) return;
16095
16096                 gl.uniformMatrix3fv( this.addr, false, v );
16097
16098                 copyArray( cache, v );
16099
16100         } else {
16101
16102                 if ( arraysEqual( cache, elements ) ) return;
16103
16104                 mat3array.set( elements );
16105
16106                 gl.uniformMatrix3fv( this.addr, false, mat3array );
16107
16108                 copyArray( cache, elements );
16109
16110         }
16111
16112 }
16113
16114 function setValueM4( gl, v ) {
16115
16116         const cache = this.cache;
16117         const elements = v.elements;
16118
16119         if ( elements === undefined ) {
16120
16121                 if ( arraysEqual( cache, v ) ) return;
16122
16123                 gl.uniformMatrix4fv( this.addr, false, v );
16124
16125                 copyArray( cache, v );
16126
16127         } else {
16128
16129                 if ( arraysEqual( cache, elements ) ) return;
16130
16131                 mat4array.set( elements );
16132
16133                 gl.uniformMatrix4fv( this.addr, false, mat4array );
16134
16135                 copyArray( cache, elements );
16136
16137         }
16138
16139 }
16140
16141 // Single texture (2D / Cube)
16142
16143 function setValueT1( gl, v, textures ) {
16144
16145         const cache = this.cache;
16146         const unit = textures.allocateTextureUnit();
16147
16148         if ( cache[ 0 ] !== unit ) {
16149
16150                 gl.uniform1i( this.addr, unit );
16151                 cache[ 0 ] = unit;
16152
16153         }
16154
16155         textures.safeSetTexture2D( v || emptyTexture, unit );
16156
16157 }
16158
16159 function setValueT2DArray1( gl, v, textures ) {
16160
16161         const cache = this.cache;
16162         const unit = textures.allocateTextureUnit();
16163
16164         if ( cache[ 0 ] !== unit ) {
16165
16166                 gl.uniform1i( this.addr, unit );
16167                 cache[ 0 ] = unit;
16168
16169         }
16170
16171         textures.setTexture2DArray( v || emptyTexture2dArray, unit );
16172
16173 }
16174
16175 function setValueT3D1( gl, v, textures ) {
16176
16177         const cache = this.cache;
16178         const unit = textures.allocateTextureUnit();
16179
16180         if ( cache[ 0 ] !== unit ) {
16181
16182                 gl.uniform1i( this.addr, unit );
16183                 cache[ 0 ] = unit;
16184
16185         }
16186
16187         textures.setTexture3D( v || emptyTexture3d, unit );
16188
16189 }
16190
16191 function setValueT6( gl, v, textures ) {
16192
16193         const cache = this.cache;
16194         const unit = textures.allocateTextureUnit();
16195
16196         if ( cache[ 0 ] !== unit ) {
16197
16198                 gl.uniform1i( this.addr, unit );
16199                 cache[ 0 ] = unit;
16200
16201         }
16202
16203         textures.safeSetTextureCube( v || emptyCubeTexture, unit );
16204
16205 }
16206
16207 // Integer / Boolean vectors or arrays thereof (always flat arrays)
16208
16209 function setValueV1i( gl, v ) {
16210
16211         const cache = this.cache;
16212
16213         if ( cache[ 0 ] === v ) return;
16214
16215         gl.uniform1i( this.addr, v );
16216
16217         cache[ 0 ] = v;
16218
16219 }
16220
16221 function setValueV2i( gl, v ) {
16222
16223         const cache = this.cache;
16224
16225         if ( arraysEqual( cache, v ) ) return;
16226
16227         gl.uniform2iv( this.addr, v );
16228
16229         copyArray( cache, v );
16230
16231 }
16232
16233 function setValueV3i( gl, v ) {
16234
16235         const cache = this.cache;
16236
16237         if ( arraysEqual( cache, v ) ) return;
16238
16239         gl.uniform3iv( this.addr, v );
16240
16241         copyArray( cache, v );
16242
16243 }
16244
16245 function setValueV4i( gl, v ) {
16246
16247         const cache = this.cache;
16248
16249         if ( arraysEqual( cache, v ) ) return;
16250
16251         gl.uniform4iv( this.addr, v );
16252
16253         copyArray( cache, v );
16254
16255 }
16256
16257 // uint
16258
16259 function setValueV1ui( gl, v ) {
16260
16261         const cache = this.cache;
16262
16263         if ( cache[ 0 ] === v ) return;
16264
16265         gl.uniform1ui( this.addr, v );
16266
16267         cache[ 0 ] = v;
16268
16269 }
16270
16271 // Helper to pick the right setter for the singular case
16272
16273 function getSingularSetter( type ) {
16274
16275         switch ( type ) {
16276
16277                 case 0x1406: return setValueV1f; // FLOAT
16278                 case 0x8b50: return setValueV2f; // _VEC2
16279                 case 0x8b51: return setValueV3f; // _VEC3
16280                 case 0x8b52: return setValueV4f; // _VEC4
16281
16282                 case 0x8b5a: return setValueM2; // _MAT2
16283                 case 0x8b5b: return setValueM3; // _MAT3
16284                 case 0x8b5c: return setValueM4; // _MAT4
16285
16286                 case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
16287                 case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
16288                 case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
16289                 case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
16290
16291                 case 0x1405: return setValueV1ui; // UINT
16292
16293                 case 0x8b5e: // SAMPLER_2D
16294                 case 0x8d66: // SAMPLER_EXTERNAL_OES
16295                 case 0x8dca: // INT_SAMPLER_2D
16296                 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
16297                 case 0x8b62: // SAMPLER_2D_SHADOW
16298                         return setValueT1;
16299
16300                 case 0x8b5f: // SAMPLER_3D
16301                 case 0x8dcb: // INT_SAMPLER_3D
16302                 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
16303                         return setValueT3D1;
16304
16305                 case 0x8b60: // SAMPLER_CUBE
16306                 case 0x8dcc: // INT_SAMPLER_CUBE
16307                 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
16308                 case 0x8dc5: // SAMPLER_CUBE_SHADOW
16309                         return setValueT6;
16310
16311                 case 0x8dc1: // SAMPLER_2D_ARRAY
16312                 case 0x8dcf: // INT_SAMPLER_2D_ARRAY
16313                 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
16314                 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
16315                         return setValueT2DArray1;
16316
16317         }
16318
16319 }
16320
16321 // Array of scalars
16322 function setValueV1fArray( gl, v ) {
16323
16324         gl.uniform1fv( this.addr, v );
16325
16326 }
16327
16328 // Integer / Boolean vectors or arrays thereof (always flat arrays)
16329 function setValueV1iArray( gl, v ) {
16330
16331         gl.uniform1iv( this.addr, v );
16332
16333 }
16334
16335 function setValueV2iArray( gl, v ) {
16336
16337         gl.uniform2iv( this.addr, v );
16338
16339 }
16340
16341 function setValueV3iArray( gl, v ) {
16342
16343         gl.uniform3iv( this.addr, v );
16344
16345 }
16346
16347 function setValueV4iArray( gl, v ) {
16348
16349         gl.uniform4iv( this.addr, v );
16350
16351 }
16352
16353
16354 // Array of vectors (flat or from THREE classes)
16355
16356 function setValueV2fArray( gl, v ) {
16357
16358         const data = flatten( v, this.size, 2 );
16359
16360         gl.uniform2fv( this.addr, data );
16361
16362 }
16363
16364 function setValueV3fArray( gl, v ) {
16365
16366         const data = flatten( v, this.size, 3 );
16367
16368         gl.uniform3fv( this.addr, data );
16369
16370 }
16371
16372 function setValueV4fArray( gl, v ) {
16373
16374         const data = flatten( v, this.size, 4 );
16375
16376         gl.uniform4fv( this.addr, data );
16377
16378 }
16379
16380 // Array of matrices (flat or from THREE clases)
16381
16382 function setValueM2Array( gl, v ) {
16383
16384         const data = flatten( v, this.size, 4 );
16385
16386         gl.uniformMatrix2fv( this.addr, false, data );
16387
16388 }
16389
16390 function setValueM3Array( gl, v ) {
16391
16392         const data = flatten( v, this.size, 9 );
16393
16394         gl.uniformMatrix3fv( this.addr, false, data );
16395
16396 }
16397
16398 function setValueM4Array( gl, v ) {
16399
16400         const data = flatten( v, this.size, 16 );
16401
16402         gl.uniformMatrix4fv( this.addr, false, data );
16403
16404 }
16405
16406 // Array of textures (2D / Cube)
16407
16408 function setValueT1Array( gl, v, textures ) {
16409
16410         const n = v.length;
16411
16412         const units = allocTexUnits( textures, n );
16413
16414         gl.uniform1iv( this.addr, units );
16415
16416         for ( let i = 0; i !== n; ++ i ) {
16417
16418                 textures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );
16419
16420         }
16421
16422 }
16423
16424 function setValueT6Array( gl, v, textures ) {
16425
16426         const n = v.length;
16427
16428         const units = allocTexUnits( textures, n );
16429
16430         gl.uniform1iv( this.addr, units );
16431
16432         for ( let i = 0; i !== n; ++ i ) {
16433
16434                 textures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
16435
16436         }
16437
16438 }
16439
16440 // Helper to pick the right setter for a pure (bottom-level) array
16441
16442 function getPureArraySetter( type ) {
16443
16444         switch ( type ) {
16445
16446                 case 0x1406: return setValueV1fArray; // FLOAT
16447                 case 0x8b50: return setValueV2fArray; // _VEC2
16448                 case 0x8b51: return setValueV3fArray; // _VEC3
16449                 case 0x8b52: return setValueV4fArray; // _VEC4
16450
16451                 case 0x8b5a: return setValueM2Array; // _MAT2
16452                 case 0x8b5b: return setValueM3Array; // _MAT3
16453                 case 0x8b5c: return setValueM4Array; // _MAT4
16454
16455                 case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
16456                 case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
16457                 case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
16458                 case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
16459
16460                 case 0x8b5e: // SAMPLER_2D
16461                 case 0x8d66: // SAMPLER_EXTERNAL_OES
16462                 case 0x8dca: // INT_SAMPLER_2D
16463                 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
16464                 case 0x8b62: // SAMPLER_2D_SHADOW
16465                         return setValueT1Array;
16466
16467                 case 0x8b60: // SAMPLER_CUBE
16468                 case 0x8dcc: // INT_SAMPLER_CUBE
16469                 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
16470                 case 0x8dc5: // SAMPLER_CUBE_SHADOW
16471                         return setValueT6Array;
16472
16473         }
16474
16475 }
16476
16477 // --- Uniform Classes ---
16478
16479 function SingleUniform( id, activeInfo, addr ) {
16480
16481         this.id = id;
16482         this.addr = addr;
16483         this.cache = [];
16484         this.setValue = getSingularSetter( activeInfo.type );
16485
16486         // this.path = activeInfo.name; // DEBUG
16487
16488 }
16489
16490 function PureArrayUniform( id, activeInfo, addr ) {
16491
16492         this.id = id;
16493         this.addr = addr;
16494         this.cache = [];
16495         this.size = activeInfo.size;
16496         this.setValue = getPureArraySetter( activeInfo.type );
16497
16498         // this.path = activeInfo.name; // DEBUG
16499
16500 }
16501
16502 PureArrayUniform.prototype.updateCache = function ( data ) {
16503
16504         const cache = this.cache;
16505
16506         if ( data instanceof Float32Array && cache.length !== data.length ) {
16507
16508                 this.cache = new Float32Array( data.length );
16509
16510         }
16511
16512         copyArray( cache, data );
16513
16514 };
16515
16516 function StructuredUniform( id ) {
16517
16518         this.id = id;
16519
16520         this.seq = [];
16521         this.map = {};
16522
16523 }
16524
16525 StructuredUniform.prototype.setValue = function ( gl, value, textures ) {
16526
16527         const seq = this.seq;
16528
16529         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
16530
16531                 const u = seq[ i ];
16532                 u.setValue( gl, value[ u.id ], textures );
16533
16534         }
16535
16536 };
16537
16538 // --- Top-level ---
16539
16540 // Parser - builds up the property tree from the path strings
16541
16542 const RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
16543
16544 // extracts
16545 //      - the identifier (member name or array index)
16546 //  - followed by an optional right bracket (found when array index)
16547 //  - followed by an optional left bracket or dot (type of subscript)
16548 //
16549 // Note: These portions can be read in a non-overlapping fashion and
16550 // allow straightforward parsing of the hierarchy that WebGL encodes
16551 // in the uniform names.
16552
16553 function addUniform( container, uniformObject ) {
16554
16555         container.seq.push( uniformObject );
16556         container.map[ uniformObject.id ] = uniformObject;
16557
16558 }
16559
16560 function parseUniform( activeInfo, addr, container ) {
16561
16562         const path = activeInfo.name,
16563                 pathLength = path.length;
16564
16565         // reset RegExp object, because of the early exit of a previous run
16566         RePathPart.lastIndex = 0;
16567
16568         while ( true ) {
16569
16570                 const match = RePathPart.exec( path ),
16571                         matchEnd = RePathPart.lastIndex;
16572
16573                 let id = match[ 1 ];
16574                 const idIsIndex = match[ 2 ] === ']',
16575                         subscript = match[ 3 ];
16576
16577                 if ( idIsIndex ) id = id | 0; // convert to integer
16578
16579                 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
16580
16581                         // bare name or "pure" bottom-level array "[0]" suffix
16582
16583                         addUniform( container, subscript === undefined ?
16584                                 new SingleUniform( id, activeInfo, addr ) :
16585                                 new PureArrayUniform( id, activeInfo, addr ) );
16586
16587                         break;
16588
16589                 } else {
16590
16591                         // step into inner node / create it in case it doesn't exist
16592
16593                         const map = container.map;
16594                         let next = map[ id ];
16595
16596                         if ( next === undefined ) {
16597
16598                                 next = new StructuredUniform( id );
16599                                 addUniform( container, next );
16600
16601                         }
16602
16603                         container = next;
16604
16605                 }
16606
16607         }
16608
16609 }
16610
16611 // Root Container
16612
16613 function WebGLUniforms( gl, program ) {
16614
16615         this.seq = [];
16616         this.map = {};
16617
16618         const n = gl.getProgramParameter( program, 35718 );
16619
16620         for ( let i = 0; i < n; ++ i ) {
16621
16622                 const info = gl.getActiveUniform( program, i ),
16623                         addr = gl.getUniformLocation( program, info.name );
16624
16625                 parseUniform( info, addr, this );
16626
16627         }
16628
16629 }
16630
16631 WebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {
16632
16633         const u = this.map[ name ];
16634
16635         if ( u !== undefined ) u.setValue( gl, value, textures );
16636
16637 };
16638
16639 WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
16640
16641         const v = object[ name ];
16642
16643         if ( v !== undefined ) this.setValue( gl, name, v );
16644
16645 };
16646
16647
16648 // Static interface
16649
16650 WebGLUniforms.upload = function ( gl, seq, values, textures ) {
16651
16652         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
16653
16654                 const u = seq[ i ],
16655                         v = values[ u.id ];
16656
16657                 if ( v.needsUpdate !== false ) {
16658
16659                         // note: always updating when .needsUpdate is undefined
16660                         u.setValue( gl, v.value, textures );
16661
16662                 }
16663
16664         }
16665
16666 };
16667
16668 WebGLUniforms.seqWithValue = function ( seq, values ) {
16669
16670         const r = [];
16671
16672         for ( let i = 0, n = seq.length; i !== n; ++ i ) {
16673
16674                 const u = seq[ i ];
16675                 if ( u.id in values ) r.push( u );
16676
16677         }
16678
16679         return r;
16680
16681 };
16682
16683 function WebGLShader( gl, type, string ) {
16684
16685         const shader = gl.createShader( type );
16686
16687         gl.shaderSource( shader, string );
16688         gl.compileShader( shader );
16689
16690         return shader;
16691
16692 }
16693
16694 let programIdCount = 0;
16695
16696 function addLineNumbers( string ) {
16697
16698         const lines = string.split( '\n' );
16699
16700         for ( let i = 0; i < lines.length; i ++ ) {
16701
16702                 lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
16703
16704         }
16705
16706         return lines.join( '\n' );
16707
16708 }
16709
16710 function getEncodingComponents( encoding ) {
16711
16712         switch ( encoding ) {
16713
16714                 case LinearEncoding:
16715                         return [ 'Linear', '( value )' ];
16716                 case sRGBEncoding:
16717                         return [ 'sRGB', '( value )' ];
16718                 case RGBEEncoding:
16719                         return [ 'RGBE', '( value )' ];
16720                 case RGBM7Encoding:
16721                         return [ 'RGBM', '( value, 7.0 )' ];
16722                 case RGBM16Encoding:
16723                         return [ 'RGBM', '( value, 16.0 )' ];
16724                 case RGBDEncoding:
16725                         return [ 'RGBD', '( value, 256.0 )' ];
16726                 case GammaEncoding:
16727                         return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
16728                 case LogLuvEncoding:
16729                         return [ 'LogLuv', '( value )' ];
16730                 default:
16731                         console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding );
16732                         return [ 'Linear', '( value )' ];
16733
16734         }
16735
16736 }
16737
16738 function getShaderErrors( gl, shader, type ) {
16739
16740         const status = gl.getShaderParameter( shader, 35713 );
16741         const log = gl.getShaderInfoLog( shader ).trim();
16742
16743         if ( status && log === '' ) return '';
16744
16745         // --enable-privileged-webgl-extension
16746         // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
16747
16748         const source = gl.getShaderSource( shader );
16749
16750         return 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\n' + log + addLineNumbers( source );
16751
16752 }
16753
16754 function getTexelDecodingFunction( functionName, encoding ) {
16755
16756         const components = getEncodingComponents( encoding );
16757         return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
16758
16759 }
16760
16761 function getTexelEncodingFunction( functionName, encoding ) {
16762
16763         const components = getEncodingComponents( encoding );
16764         return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
16765
16766 }
16767
16768 function getToneMappingFunction( functionName, toneMapping ) {
16769
16770         let toneMappingName;
16771
16772         switch ( toneMapping ) {
16773
16774                 case LinearToneMapping:
16775                         toneMappingName = 'Linear';
16776                         break;
16777
16778                 case ReinhardToneMapping:
16779                         toneMappingName = 'Reinhard';
16780                         break;
16781
16782                 case CineonToneMapping:
16783                         toneMappingName = 'OptimizedCineon';
16784                         break;
16785
16786                 case ACESFilmicToneMapping:
16787                         toneMappingName = 'ACESFilmic';
16788                         break;
16789
16790                 case CustomToneMapping:
16791                         toneMappingName = 'Custom';
16792                         break;
16793
16794                 default:
16795                         console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping );
16796                         toneMappingName = 'Linear';
16797
16798         }
16799
16800         return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
16801
16802 }
16803
16804 function generateExtensions( parameters ) {
16805
16806         const chunks = [
16807                 ( parameters.extensionDerivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '',
16808                 ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',
16809                 ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '',
16810                 ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''
16811         ];
16812
16813         return chunks.filter( filterEmptyLine ).join( '\n' );
16814
16815 }
16816
16817 function generateDefines( defines ) {
16818
16819         const chunks = [];
16820
16821         for ( const name in defines ) {
16822
16823                 const value = defines[ name ];
16824
16825                 if ( value === false ) continue;
16826
16827                 chunks.push( '#define ' + name + ' ' + value );
16828
16829         }
16830
16831         return chunks.join( '\n' );
16832
16833 }
16834
16835 function fetchAttributeLocations( gl, program ) {
16836
16837         const attributes = {};
16838
16839         const n = gl.getProgramParameter( program, 35721 );
16840
16841         for ( let i = 0; i < n; i ++ ) {
16842
16843                 const info = gl.getActiveAttrib( program, i );
16844                 const name = info.name;
16845
16846                 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
16847
16848                 attributes[ name ] = gl.getAttribLocation( program, name );
16849
16850         }
16851
16852         return attributes;
16853
16854 }
16855
16856 function filterEmptyLine( string ) {
16857
16858         return string !== '';
16859
16860 }
16861
16862 function replaceLightNums( string, parameters ) {
16863
16864         return string
16865                 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
16866                 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
16867                 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
16868                 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
16869                 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
16870                 .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
16871                 .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
16872                 .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
16873
16874 }
16875
16876 function replaceClippingPlaneNums( string, parameters ) {
16877
16878         return string
16879                 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
16880                 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
16881
16882 }
16883
16884 // Resolve Includes
16885
16886 const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
16887
16888 function resolveIncludes( string ) {
16889
16890         return string.replace( includePattern, includeReplacer );
16891
16892 }
16893
16894 function includeReplacer( match, include ) {
16895
16896         const string = ShaderChunk[ include ];
16897
16898         if ( string === undefined ) {
16899
16900                 throw new Error( 'Can not resolve #include <' + include + '>' );
16901
16902         }
16903
16904         return resolveIncludes( string );
16905
16906 }
16907
16908 // Unroll Loops
16909
16910 const deprecatedUnrollLoopPattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
16911 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;
16912
16913 function unrollLoops( string ) {
16914
16915         return string
16916                 .replace( unrollLoopPattern, loopReplacer )
16917                 .replace( deprecatedUnrollLoopPattern, deprecatedLoopReplacer );
16918
16919 }
16920
16921 function deprecatedLoopReplacer( match, start, end, snippet ) {
16922
16923         console.warn( 'WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.' );
16924         return loopReplacer( match, start, end, snippet );
16925
16926 }
16927
16928 function loopReplacer( match, start, end, snippet ) {
16929
16930         let string = '';
16931
16932         for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) {
16933
16934                 string += snippet
16935                         .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' )
16936                         .replace( /UNROLLED_LOOP_INDEX/g, i );
16937
16938         }
16939
16940         return string;
16941
16942 }
16943
16944 //
16945
16946 function generatePrecision( parameters ) {
16947
16948         let precisionstring = "precision " + parameters.precision + " float;\nprecision " + parameters.precision + " int;";
16949
16950         if ( parameters.precision === "highp" ) {
16951
16952                 precisionstring += "\n#define HIGH_PRECISION";
16953
16954         } else if ( parameters.precision === "mediump" ) {
16955
16956                 precisionstring += "\n#define MEDIUM_PRECISION";
16957
16958         } else if ( parameters.precision === "lowp" ) {
16959
16960                 precisionstring += "\n#define LOW_PRECISION";
16961
16962         }
16963
16964         return precisionstring;
16965
16966 }
16967
16968 function generateShadowMapTypeDefine( parameters ) {
16969
16970         let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
16971
16972         if ( parameters.shadowMapType === PCFShadowMap ) {
16973
16974                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
16975
16976         } else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
16977
16978                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
16979
16980         } else if ( parameters.shadowMapType === VSMShadowMap ) {
16981
16982                 shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
16983
16984         }
16985
16986         return shadowMapTypeDefine;
16987
16988 }
16989
16990 function generateEnvMapTypeDefine( parameters ) {
16991
16992         let envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
16993
16994         if ( parameters.envMap ) {
16995
16996                 switch ( parameters.envMapMode ) {
16997
16998                         case CubeReflectionMapping:
16999                         case CubeRefractionMapping:
17000                                 envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
17001                                 break;
17002
17003                         case CubeUVReflectionMapping:
17004                         case CubeUVRefractionMapping:
17005                                 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
17006                                 break;
17007
17008                 }
17009
17010         }
17011
17012         return envMapTypeDefine;
17013
17014 }
17015
17016 function generateEnvMapModeDefine( parameters ) {
17017
17018         let envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
17019
17020         if ( parameters.envMap ) {
17021
17022                 switch ( parameters.envMapMode ) {
17023
17024                         case CubeRefractionMapping:
17025                         case CubeUVRefractionMapping:
17026
17027                                 envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
17028                                 break;
17029
17030                 }
17031
17032         }
17033
17034         return envMapModeDefine;
17035
17036 }
17037
17038 function generateEnvMapBlendingDefine( parameters ) {
17039
17040         let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
17041
17042         if ( parameters.envMap ) {
17043
17044                 switch ( parameters.combine ) {
17045
17046                         case MultiplyOperation:
17047                                 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
17048                                 break;
17049
17050                         case MixOperation:
17051                                 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
17052                                 break;
17053
17054                         case AddOperation:
17055                                 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
17056                                 break;
17057
17058                 }
17059
17060         }
17061
17062         return envMapBlendingDefine;
17063
17064 }
17065
17066 function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
17067
17068         const gl = renderer.getContext();
17069
17070         const defines = parameters.defines;
17071
17072         let vertexShader = parameters.vertexShader;
17073         let fragmentShader = parameters.fragmentShader;
17074
17075         const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
17076         const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
17077         const envMapModeDefine = generateEnvMapModeDefine( parameters );
17078         const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
17079
17080
17081         const gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
17082
17083         const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );
17084
17085         const customDefines = generateDefines( defines );
17086
17087         const program = gl.createProgram();
17088
17089         let prefixVertex, prefixFragment;
17090         let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + "\n" : '';
17091
17092         if ( parameters.isRawShaderMaterial ) {
17093
17094                 prefixVertex = [
17095
17096                         customDefines
17097
17098                 ].filter( filterEmptyLine ).join( '\n' );
17099
17100                 if ( prefixVertex.length > 0 ) {
17101
17102                         prefixVertex += '\n';
17103
17104                 }
17105
17106                 prefixFragment = [
17107
17108                         customExtensions,
17109                         customDefines
17110
17111                 ].filter( filterEmptyLine ).join( '\n' );
17112
17113                 if ( prefixFragment.length > 0 ) {
17114
17115                         prefixFragment += '\n';
17116
17117                 }
17118
17119         } else {
17120
17121                 prefixVertex = [
17122
17123                         generatePrecision( parameters ),
17124
17125                         '#define SHADER_NAME ' + parameters.shaderName,
17126
17127                         customDefines,
17128
17129                         parameters.instancing ? '#define USE_INSTANCING' : '',
17130                         parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
17131
17132                         parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
17133
17134                         '#define GAMMA_FACTOR ' + gammaFactorDefine,
17135
17136                         '#define MAX_BONES ' + parameters.maxBones,
17137                         ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
17138                         ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
17139
17140                         parameters.map ? '#define USE_MAP' : '',
17141                         parameters.envMap ? '#define USE_ENVMAP' : '',
17142                         parameters.envMap ? '#define ' + envMapModeDefine : '',
17143                         parameters.lightMap ? '#define USE_LIGHTMAP' : '',
17144                         parameters.aoMap ? '#define USE_AOMAP' : '',
17145                         parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
17146                         parameters.bumpMap ? '#define USE_BUMPMAP' : '',
17147                         parameters.normalMap ? '#define USE_NORMALMAP' : '',
17148                         ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
17149                         ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
17150
17151                         parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
17152                         parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
17153                         parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
17154                         parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
17155                         parameters.specularMap ? '#define USE_SPECULARMAP' : '',
17156                         parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
17157                         parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
17158                         parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
17159                         parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
17160
17161                         parameters.vertexTangents ? '#define USE_TANGENT' : '',
17162                         parameters.vertexColors ? '#define USE_COLOR' : '',
17163                         parameters.vertexUvs ? '#define USE_UV' : '',
17164                         parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
17165
17166                         parameters.flatShading ? '#define FLAT_SHADED' : '',
17167
17168                         parameters.skinning ? '#define USE_SKINNING' : '',
17169                         parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
17170
17171                         parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
17172                         parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
17173                         parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
17174                         parameters.flipSided ? '#define FLIP_SIDED' : '',
17175
17176                         parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
17177                         parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
17178
17179                         parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
17180
17181                         parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
17182                         ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
17183
17184                         'uniform mat4 modelMatrix;',
17185                         'uniform mat4 modelViewMatrix;',
17186                         'uniform mat4 projectionMatrix;',
17187                         'uniform mat4 viewMatrix;',
17188                         'uniform mat3 normalMatrix;',
17189                         'uniform vec3 cameraPosition;',
17190                         'uniform bool isOrthographic;',
17191
17192                         '#ifdef USE_INSTANCING',
17193
17194                         '       attribute mat4 instanceMatrix;',
17195
17196                         '#endif',
17197
17198                         '#ifdef USE_INSTANCING_COLOR',
17199
17200                         '       attribute vec3 instanceColor;',
17201
17202                         '#endif',
17203
17204                         'attribute vec3 position;',
17205                         'attribute vec3 normal;',
17206                         'attribute vec2 uv;',
17207
17208                         '#ifdef USE_TANGENT',
17209
17210                         '       attribute vec4 tangent;',
17211
17212                         '#endif',
17213
17214                         '#ifdef USE_COLOR',
17215
17216                         '       attribute vec3 color;',
17217
17218                         '#endif',
17219
17220                         '#ifdef USE_MORPHTARGETS',
17221
17222                         '       attribute vec3 morphTarget0;',
17223                         '       attribute vec3 morphTarget1;',
17224                         '       attribute vec3 morphTarget2;',
17225                         '       attribute vec3 morphTarget3;',
17226
17227                         '       #ifdef USE_MORPHNORMALS',
17228
17229                         '               attribute vec3 morphNormal0;',
17230                         '               attribute vec3 morphNormal1;',
17231                         '               attribute vec3 morphNormal2;',
17232                         '               attribute vec3 morphNormal3;',
17233
17234                         '       #else',
17235
17236                         '               attribute vec3 morphTarget4;',
17237                         '               attribute vec3 morphTarget5;',
17238                         '               attribute vec3 morphTarget6;',
17239                         '               attribute vec3 morphTarget7;',
17240
17241                         '       #endif',
17242
17243                         '#endif',
17244
17245                         '#ifdef USE_SKINNING',
17246
17247                         '       attribute vec4 skinIndex;',
17248                         '       attribute vec4 skinWeight;',
17249
17250                         '#endif',
17251
17252                         '\n'
17253
17254                 ].filter( filterEmptyLine ).join( '\n' );
17255
17256                 prefixFragment = [
17257
17258                         customExtensions,
17259
17260                         generatePrecision( parameters ),
17261
17262                         '#define SHADER_NAME ' + parameters.shaderName,
17263
17264                         customDefines,
17265
17266                         parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer
17267
17268                         '#define GAMMA_FACTOR ' + gammaFactorDefine,
17269
17270                         ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
17271                         ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
17272
17273                         parameters.map ? '#define USE_MAP' : '',
17274                         parameters.matcap ? '#define USE_MATCAP' : '',
17275                         parameters.envMap ? '#define USE_ENVMAP' : '',
17276                         parameters.envMap ? '#define ' + envMapTypeDefine : '',
17277                         parameters.envMap ? '#define ' + envMapModeDefine : '',
17278                         parameters.envMap ? '#define ' + envMapBlendingDefine : '',
17279                         parameters.lightMap ? '#define USE_LIGHTMAP' : '',
17280                         parameters.aoMap ? '#define USE_AOMAP' : '',
17281                         parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
17282                         parameters.bumpMap ? '#define USE_BUMPMAP' : '',
17283                         parameters.normalMap ? '#define USE_NORMALMAP' : '',
17284                         ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
17285                         ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
17286                         parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
17287                         parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
17288                         parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
17289                         parameters.specularMap ? '#define USE_SPECULARMAP' : '',
17290                         parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
17291                         parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
17292                         parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
17293
17294                         parameters.sheen ? '#define USE_SHEEN' : '',
17295                         parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
17296
17297                         parameters.vertexTangents ? '#define USE_TANGENT' : '',
17298                         parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
17299                         parameters.vertexUvs ? '#define USE_UV' : '',
17300                         parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
17301
17302                         parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
17303
17304                         parameters.flatShading ? '#define FLAT_SHADED' : '',
17305
17306                         parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
17307                         parameters.flipSided ? '#define FLIP_SIDED' : '',
17308
17309                         parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
17310                         parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
17311
17312                         parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
17313
17314                         parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
17315
17316                         parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
17317                         ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
17318
17319                         ( ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ) ? '#define TEXTURE_LOD_EXT' : '',
17320
17321                         'uniform mat4 viewMatrix;',
17322                         'uniform vec3 cameraPosition;',
17323                         'uniform bool isOrthographic;',
17324
17325                         ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
17326                         ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
17327                         ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
17328
17329                         parameters.dithering ? '#define DITHERING' : '',
17330
17331                         ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below
17332                         parameters.map ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
17333                         parameters.matcap ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
17334                         parameters.envMap ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
17335                         parameters.emissiveMap ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
17336                         parameters.lightMap ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',
17337                         getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ),
17338
17339                         parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
17340
17341                         '\n'
17342
17343                 ].filter( filterEmptyLine ).join( '\n' );
17344
17345         }
17346
17347         vertexShader = resolveIncludes( vertexShader );
17348         vertexShader = replaceLightNums( vertexShader, parameters );
17349         vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
17350
17351         fragmentShader = resolveIncludes( fragmentShader );
17352         fragmentShader = replaceLightNums( fragmentShader, parameters );
17353         fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
17354
17355         vertexShader = unrollLoops( vertexShader );
17356         fragmentShader = unrollLoops( fragmentShader );
17357
17358         if ( parameters.isWebGL2 && parameters.isRawShaderMaterial !== true ) {
17359
17360                 // GLSL 3.0 conversion for built-in materials and ShaderMaterial
17361
17362                 versionString = '#version 300 es\n';
17363
17364                 prefixVertex = [
17365                         '#define attribute in',
17366                         '#define varying out',
17367                         '#define texture2D texture'
17368                 ].join( '\n' ) + '\n' + prefixVertex;
17369
17370                 prefixFragment = [
17371                         '#define varying in',
17372                         ( parameters.glslVersion === GLSL3 ) ? '' : 'out highp vec4 pc_fragColor;',
17373                         ( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor',
17374                         '#define gl_FragDepthEXT gl_FragDepth',
17375                         '#define texture2D texture',
17376                         '#define textureCube texture',
17377                         '#define texture2DProj textureProj',
17378                         '#define texture2DLodEXT textureLod',
17379                         '#define texture2DProjLodEXT textureProjLod',
17380                         '#define textureCubeLodEXT textureLod',
17381                         '#define texture2DGradEXT textureGrad',
17382                         '#define texture2DProjGradEXT textureProjGrad',
17383                         '#define textureCubeGradEXT textureGrad'
17384                 ].join( '\n' ) + '\n' + prefixFragment;
17385
17386         }
17387
17388         const vertexGlsl = versionString + prefixVertex + vertexShader;
17389         const fragmentGlsl = versionString + prefixFragment + fragmentShader;
17390
17391         // console.log( '*VERTEX*', vertexGlsl );
17392         // console.log( '*FRAGMENT*', fragmentGlsl );
17393
17394         const glVertexShader = WebGLShader( gl, 35633, vertexGlsl );
17395         const glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );
17396
17397         gl.attachShader( program, glVertexShader );
17398         gl.attachShader( program, glFragmentShader );
17399
17400         // Force a particular attribute to index 0.
17401
17402         if ( parameters.index0AttributeName !== undefined ) {
17403
17404                 gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
17405
17406         } else if ( parameters.morphTargets === true ) {
17407
17408                 // programs with morphTargets displace position out of attribute 0
17409                 gl.bindAttribLocation( program, 0, 'position' );
17410
17411         }
17412
17413         gl.linkProgram( program );
17414
17415         // check for link errors
17416         if ( renderer.debug.checkShaderErrors ) {
17417
17418                 const programLog = gl.getProgramInfoLog( program ).trim();
17419                 const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
17420                 const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
17421
17422                 let runnable = true;
17423                 let haveDiagnostics = true;
17424
17425                 if ( gl.getProgramParameter( program, 35714 ) === false ) {
17426
17427                         runnable = false;
17428
17429                         const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
17430                         const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
17431
17432                         console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), '35715', gl.getProgramParameter( program, 35715 ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );
17433
17434                 } else if ( programLog !== '' ) {
17435
17436                         console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
17437
17438                 } else if ( vertexLog === '' || fragmentLog === '' ) {
17439
17440                         haveDiagnostics = false;
17441
17442                 }
17443
17444                 if ( haveDiagnostics ) {
17445
17446                         this.diagnostics = {
17447
17448                                 runnable: runnable,
17449
17450                                 programLog: programLog,
17451
17452                                 vertexShader: {
17453
17454                                         log: vertexLog,
17455                                         prefix: prefixVertex
17456
17457                                 },
17458
17459                                 fragmentShader: {
17460
17461                                         log: fragmentLog,
17462                                         prefix: prefixFragment
17463
17464                                 }
17465
17466                         };
17467
17468                 }
17469
17470         }
17471
17472         // Clean up
17473
17474         // Crashes in iOS9 and iOS10. #18402
17475         // gl.detachShader( program, glVertexShader );
17476         // gl.detachShader( program, glFragmentShader );
17477
17478         gl.deleteShader( glVertexShader );
17479         gl.deleteShader( glFragmentShader );
17480
17481         // set up caching for uniform locations
17482
17483         let cachedUniforms;
17484
17485         this.getUniforms = function () {
17486
17487                 if ( cachedUniforms === undefined ) {
17488
17489                         cachedUniforms = new WebGLUniforms( gl, program );
17490
17491                 }
17492
17493                 return cachedUniforms;
17494
17495         };
17496
17497         // set up caching for attribute locations
17498
17499         let cachedAttributes;
17500
17501         this.getAttributes = function () {
17502
17503                 if ( cachedAttributes === undefined ) {
17504
17505                         cachedAttributes = fetchAttributeLocations( gl, program );
17506
17507                 }
17508
17509                 return cachedAttributes;
17510
17511         };
17512
17513         // free resource
17514
17515         this.destroy = function () {
17516
17517                 bindingStates.releaseStatesOfProgram( this );
17518
17519                 gl.deleteProgram( program );
17520                 this.program = undefined;
17521
17522         };
17523
17524         //
17525
17526         this.name = parameters.shaderName;
17527         this.id = programIdCount ++;
17528         this.cacheKey = cacheKey;
17529         this.usedTimes = 1;
17530         this.program = program;
17531         this.vertexShader = glVertexShader;
17532         this.fragmentShader = glFragmentShader;
17533
17534         return this;
17535
17536 }
17537
17538 function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingStates, clipping ) {
17539
17540         const programs = [];
17541
17542         const isWebGL2 = capabilities.isWebGL2;
17543         const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
17544         const floatVertexTextures = capabilities.floatVertexTextures;
17545         const maxVertexUniforms = capabilities.maxVertexUniforms;
17546         const vertexTextures = capabilities.vertexTextures;
17547
17548         let precision = capabilities.precision;
17549
17550         const shaderIDs = {
17551                 MeshDepthMaterial: 'depth',
17552                 MeshDistanceMaterial: 'distanceRGBA',
17553                 MeshNormalMaterial: 'normal',
17554                 MeshBasicMaterial: 'basic',
17555                 MeshLambertMaterial: 'lambert',
17556                 MeshPhongMaterial: 'phong',
17557                 MeshToonMaterial: 'toon',
17558                 MeshStandardMaterial: 'physical',
17559                 MeshPhysicalMaterial: 'physical',
17560                 MeshMatcapMaterial: 'matcap',
17561                 LineBasicMaterial: 'basic',
17562                 LineDashedMaterial: 'dashed',
17563                 PointsMaterial: 'points',
17564                 ShadowMaterial: 'shadow',
17565                 SpriteMaterial: 'sprite'
17566         };
17567
17568         const parameterNames = [
17569                 "precision", "isWebGL2", "supportsVertexTextures", "outputEncoding", "instancing", "instancingColor",
17570                 "map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding", "envMapCubeUV",
17571                 "lightMap", "lightMapEncoding", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "tangentSpaceNormalMap", "clearcoatMap", "clearcoatRoughnessMap", "clearcoatNormalMap", "displacementMap", "specularMap",
17572                 "roughnessMap", "metalnessMap", "gradientMap",
17573                 "alphaMap", "combine", "vertexColors", "vertexTangents", "vertexUvs", "uvsVertexOnly", "fog", "useFog", "fogExp2",
17574                 "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
17575                 "maxBones", "useVertexTexture", "morphTargets", "morphNormals",
17576                 "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
17577                 "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
17578                 "numDirLightShadows", "numPointLightShadows", "numSpotLightShadows",
17579                 "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
17580                 "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering",
17581                 "sheen", "transmissionMap"
17582         ];
17583
17584         function getMaxBones( object ) {
17585
17586                 const skeleton = object.skeleton;
17587                 const bones = skeleton.bones;
17588
17589                 if ( floatVertexTextures ) {
17590
17591                         return 1024;
17592
17593                 } else {
17594
17595                         // default for when object is not specified
17596                         // ( for example when prebuilding shader to be used with multiple objects )
17597                         //
17598                         //  - leave some extra space for other uniforms
17599                         //  - limit here is ANGLE's 254 max uniform vectors
17600                         //    (up to 54 should be safe)
17601
17602                         const nVertexUniforms = maxVertexUniforms;
17603                         const nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
17604
17605                         const maxBones = Math.min( nVertexMatrices, bones.length );
17606
17607                         if ( maxBones < bones.length ) {
17608
17609                                 console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
17610                                 return 0;
17611
17612                         }
17613
17614                         return maxBones;
17615
17616                 }
17617
17618         }
17619
17620         function getTextureEncodingFromMap( map ) {
17621
17622                 let encoding;
17623
17624                 if ( ! map ) {
17625
17626                         encoding = LinearEncoding;
17627
17628                 } else if ( map.isTexture ) {
17629
17630                         encoding = map.encoding;
17631
17632                 } else if ( map.isWebGLRenderTarget ) {
17633
17634                         console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
17635                         encoding = map.texture.encoding;
17636
17637                 }
17638
17639                 return encoding;
17640
17641         }
17642
17643         function getParameters( material, lights, shadows, scene, object ) {
17644
17645                 const fog = scene.fog;
17646                 const environment = material.isMeshStandardMaterial ? scene.environment : null;
17647
17648                 const envMap = cubemaps.get( material.envMap || environment );
17649
17650                 const shaderID = shaderIDs[ material.type ];
17651
17652                 // heuristics to create shader parameters according to lights in the scene
17653                 // (not to blow over maxLights budget)
17654
17655                 const maxBones = object.isSkinnedMesh ? getMaxBones( object ) : 0;
17656
17657                 if ( material.precision !== null ) {
17658
17659                         precision = capabilities.getMaxPrecision( material.precision );
17660
17661                         if ( precision !== material.precision ) {
17662
17663                                 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
17664
17665                         }
17666
17667                 }
17668
17669                 let vertexShader, fragmentShader;
17670
17671                 if ( shaderID ) {
17672
17673                         const shader = ShaderLib[ shaderID ];
17674
17675                         vertexShader = shader.vertexShader;
17676                         fragmentShader = shader.fragmentShader;
17677
17678                 } else {
17679
17680                         vertexShader = material.vertexShader;
17681                         fragmentShader = material.fragmentShader;
17682
17683                 }
17684
17685                 const currentRenderTarget = renderer.getRenderTarget();
17686
17687                 const parameters = {
17688
17689                         isWebGL2: isWebGL2,
17690
17691                         shaderID: shaderID,
17692                         shaderName: material.type,
17693
17694                         vertexShader: vertexShader,
17695                         fragmentShader: fragmentShader,
17696                         defines: material.defines,
17697
17698                         isRawShaderMaterial: material.isRawShaderMaterial === true,
17699                         glslVersion: material.glslVersion,
17700
17701                         precision: precision,
17702
17703                         instancing: object.isInstancedMesh === true,
17704                         instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
17705
17706                         supportsVertexTextures: vertexTextures,
17707                         outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,
17708                         map: !! material.map,
17709                         mapEncoding: getTextureEncodingFromMap( material.map ),
17710                         matcap: !! material.matcap,
17711                         matcapEncoding: getTextureEncodingFromMap( material.matcap ),
17712                         envMap: !! envMap,
17713                         envMapMode: envMap && envMap.mapping,
17714                         envMapEncoding: getTextureEncodingFromMap( envMap ),
17715                         envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),
17716                         lightMap: !! material.lightMap,
17717                         lightMapEncoding: getTextureEncodingFromMap( material.lightMap ),
17718                         aoMap: !! material.aoMap,
17719                         emissiveMap: !! material.emissiveMap,
17720                         emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),
17721                         bumpMap: !! material.bumpMap,
17722                         normalMap: !! material.normalMap,
17723                         objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
17724                         tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
17725                         clearcoatMap: !! material.clearcoatMap,
17726                         clearcoatRoughnessMap: !! material.clearcoatRoughnessMap,
17727                         clearcoatNormalMap: !! material.clearcoatNormalMap,
17728                         displacementMap: !! material.displacementMap,
17729                         roughnessMap: !! material.roughnessMap,
17730                         metalnessMap: !! material.metalnessMap,
17731                         specularMap: !! material.specularMap,
17732                         alphaMap: !! material.alphaMap,
17733
17734                         gradientMap: !! material.gradientMap,
17735
17736                         sheen: !! material.sheen,
17737
17738                         transmissionMap: !! material.transmissionMap,
17739
17740                         combine: material.combine,
17741
17742                         vertexTangents: ( material.normalMap && material.vertexTangents ),
17743                         vertexColors: material.vertexColors,
17744                         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,
17745                         uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.transmissionMap ) && !! material.displacementMap,
17746
17747                         fog: !! fog,
17748                         useFog: material.fog,
17749                         fogExp2: ( fog && fog.isFogExp2 ),
17750
17751                         flatShading: material.flatShading,
17752
17753                         sizeAttenuation: material.sizeAttenuation,
17754                         logarithmicDepthBuffer: logarithmicDepthBuffer,
17755
17756                         skinning: material.skinning && maxBones > 0,
17757                         maxBones: maxBones,
17758                         useVertexTexture: floatVertexTextures,
17759
17760                         morphTargets: material.morphTargets,
17761                         morphNormals: material.morphNormals,
17762                         maxMorphTargets: renderer.maxMorphTargets,
17763                         maxMorphNormals: renderer.maxMorphNormals,
17764
17765                         numDirLights: lights.directional.length,
17766                         numPointLights: lights.point.length,
17767                         numSpotLights: lights.spot.length,
17768                         numRectAreaLights: lights.rectArea.length,
17769                         numHemiLights: lights.hemi.length,
17770
17771                         numDirLightShadows: lights.directionalShadowMap.length,
17772                         numPointLightShadows: lights.pointShadowMap.length,
17773                         numSpotLightShadows: lights.spotShadowMap.length,
17774
17775                         numClippingPlanes: clipping.numPlanes,
17776                         numClipIntersection: clipping.numIntersection,
17777
17778                         dithering: material.dithering,
17779
17780                         shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
17781                         shadowMapType: renderer.shadowMap.type,
17782
17783                         toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
17784                         physicallyCorrectLights: renderer.physicallyCorrectLights,
17785
17786                         premultipliedAlpha: material.premultipliedAlpha,
17787
17788                         alphaTest: material.alphaTest,
17789                         doubleSided: material.side === DoubleSide,
17790                         flipSided: material.side === BackSide,
17791
17792                         depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,
17793
17794                         index0AttributeName: material.index0AttributeName,
17795
17796                         extensionDerivatives: material.extensions && material.extensions.derivatives,
17797                         extensionFragDepth: material.extensions && material.extensions.fragDepth,
17798                         extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
17799                         extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,
17800
17801                         rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ),
17802                         rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ),
17803                         rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ),
17804
17805                         customProgramCacheKey: material.customProgramCacheKey()
17806
17807                 };
17808
17809                 return parameters;
17810
17811         }
17812
17813         function getProgramCacheKey( parameters ) {
17814
17815                 const array = [];
17816
17817                 if ( parameters.shaderID ) {
17818
17819                         array.push( parameters.shaderID );
17820
17821                 } else {
17822
17823                         array.push( parameters.fragmentShader );
17824                         array.push( parameters.vertexShader );
17825
17826                 }
17827
17828                 if ( parameters.defines !== undefined ) {
17829
17830                         for ( const name in parameters.defines ) {
17831
17832                                 array.push( name );
17833                                 array.push( parameters.defines[ name ] );
17834
17835                         }
17836
17837                 }
17838
17839                 if ( parameters.isRawShaderMaterial === false ) {
17840
17841                         for ( let i = 0; i < parameterNames.length; i ++ ) {
17842
17843                                 array.push( parameters[ parameterNames[ i ] ] );
17844
17845                         }
17846
17847                         array.push( renderer.outputEncoding );
17848                         array.push( renderer.gammaFactor );
17849
17850                 }
17851
17852                 array.push( parameters.customProgramCacheKey );
17853
17854                 return array.join();
17855
17856         }
17857
17858         function getUniforms( material ) {
17859
17860                 const shaderID = shaderIDs[ material.type ];
17861                 let uniforms;
17862
17863                 if ( shaderID ) {
17864
17865                         const shader = ShaderLib[ shaderID ];
17866                         uniforms = UniformsUtils.clone( shader.uniforms );
17867
17868                 } else {
17869
17870                         uniforms = material.uniforms;
17871
17872                 }
17873
17874                 return uniforms;
17875
17876         }
17877
17878         function acquireProgram( parameters, cacheKey ) {
17879
17880                 let program;
17881
17882                 // Check if code has been already compiled
17883                 for ( let p = 0, pl = programs.length; p < pl; p ++ ) {
17884
17885                         const preexistingProgram = programs[ p ];
17886
17887                         if ( preexistingProgram.cacheKey === cacheKey ) {
17888
17889                                 program = preexistingProgram;
17890                                 ++ program.usedTimes;
17891
17892                                 break;
17893
17894                         }
17895
17896                 }
17897
17898                 if ( program === undefined ) {
17899
17900                         program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
17901                         programs.push( program );
17902
17903                 }
17904
17905                 return program;
17906
17907         }
17908
17909         function releaseProgram( program ) {
17910
17911                 if ( -- program.usedTimes === 0 ) {
17912
17913                         // Remove from unordered set
17914                         const i = programs.indexOf( program );
17915                         programs[ i ] = programs[ programs.length - 1 ];
17916                         programs.pop();
17917
17918                         // Free WebGL resources
17919                         program.destroy();
17920
17921                 }
17922
17923         }
17924
17925         return {
17926                 getParameters: getParameters,
17927                 getProgramCacheKey: getProgramCacheKey,
17928                 getUniforms: getUniforms,
17929                 acquireProgram: acquireProgram,
17930                 releaseProgram: releaseProgram,
17931                 // Exposed for resource monitoring & error feedback via renderer.info:
17932                 programs: programs
17933         };
17934
17935 }
17936
17937 function WebGLProperties() {
17938
17939         let properties = new WeakMap();
17940
17941         function get( object ) {
17942
17943                 let map = properties.get( object );
17944
17945                 if ( map === undefined ) {
17946
17947                         map = {};
17948                         properties.set( object, map );
17949
17950                 }
17951
17952                 return map;
17953
17954         }
17955
17956         function remove( object ) {
17957
17958                 properties.delete( object );
17959
17960         }
17961
17962         function update( object, key, value ) {
17963
17964                 properties.get( object )[ key ] = value;
17965
17966         }
17967
17968         function dispose() {
17969
17970                 properties = new WeakMap();
17971
17972         }
17973
17974         return {
17975                 get: get,
17976                 remove: remove,
17977                 update: update,
17978                 dispose: dispose
17979         };
17980
17981 }
17982
17983 function painterSortStable( a, b ) {
17984
17985         if ( a.groupOrder !== b.groupOrder ) {
17986
17987                 return a.groupOrder - b.groupOrder;
17988
17989         } else if ( a.renderOrder !== b.renderOrder ) {
17990
17991                 return a.renderOrder - b.renderOrder;
17992
17993         } else if ( a.program !== b.program ) {
17994
17995                 return a.program.id - b.program.id;
17996
17997         } else if ( a.material.id !== b.material.id ) {
17998
17999                 return a.material.id - b.material.id;
18000
18001         } else if ( a.z !== b.z ) {
18002
18003                 return a.z - b.z;
18004
18005         } else {
18006
18007                 return a.id - b.id;
18008
18009         }
18010
18011 }
18012
18013 function reversePainterSortStable( a, b ) {
18014
18015         if ( a.groupOrder !== b.groupOrder ) {
18016
18017                 return a.groupOrder - b.groupOrder;
18018
18019         } else if ( a.renderOrder !== b.renderOrder ) {
18020
18021                 return a.renderOrder - b.renderOrder;
18022
18023         } else if ( a.z !== b.z ) {
18024
18025                 return b.z - a.z;
18026
18027         } else {
18028
18029                 return a.id - b.id;
18030
18031         }
18032
18033 }
18034
18035
18036 function WebGLRenderList( properties ) {
18037
18038         const renderItems = [];
18039         let renderItemsIndex = 0;
18040
18041         const opaque = [];
18042         const transparent = [];
18043
18044         const defaultProgram = { id: - 1 };
18045
18046         function init() {
18047
18048                 renderItemsIndex = 0;
18049
18050                 opaque.length = 0;
18051                 transparent.length = 0;
18052
18053         }
18054
18055         function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
18056
18057                 let renderItem = renderItems[ renderItemsIndex ];
18058                 const materialProperties = properties.get( material );
18059
18060                 if ( renderItem === undefined ) {
18061
18062                         renderItem = {
18063                                 id: object.id,
18064                                 object: object,
18065                                 geometry: geometry,
18066                                 material: material,
18067                                 program: materialProperties.program || defaultProgram,
18068                                 groupOrder: groupOrder,
18069                                 renderOrder: object.renderOrder,
18070                                 z: z,
18071                                 group: group
18072                         };
18073
18074                         renderItems[ renderItemsIndex ] = renderItem;
18075
18076                 } else {
18077
18078                         renderItem.id = object.id;
18079                         renderItem.object = object;
18080                         renderItem.geometry = geometry;
18081                         renderItem.material = material;
18082                         renderItem.program = materialProperties.program || defaultProgram;
18083                         renderItem.groupOrder = groupOrder;
18084                         renderItem.renderOrder = object.renderOrder;
18085                         renderItem.z = z;
18086                         renderItem.group = group;
18087
18088                 }
18089
18090                 renderItemsIndex ++;
18091
18092                 return renderItem;
18093
18094         }
18095
18096         function push( object, geometry, material, groupOrder, z, group ) {
18097
18098                 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
18099
18100                 ( material.transparent === true ? transparent : opaque ).push( renderItem );
18101
18102         }
18103
18104         function unshift( object, geometry, material, groupOrder, z, group ) {
18105
18106                 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
18107
18108                 ( material.transparent === true ? transparent : opaque ).unshift( renderItem );
18109
18110         }
18111
18112         function sort( customOpaqueSort, customTransparentSort ) {
18113
18114                 if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
18115                 if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
18116
18117         }
18118
18119         function finish() {
18120
18121                 // Clear references from inactive renderItems in the list
18122
18123                 for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
18124
18125                         const renderItem = renderItems[ i ];
18126
18127                         if ( renderItem.id === null ) break;
18128
18129                         renderItem.id = null;
18130                         renderItem.object = null;
18131                         renderItem.geometry = null;
18132                         renderItem.material = null;
18133                         renderItem.program = null;
18134                         renderItem.group = null;
18135
18136                 }
18137
18138         }
18139
18140         return {
18141
18142                 opaque: opaque,
18143                 transparent: transparent,
18144
18145                 init: init,
18146                 push: push,
18147                 unshift: unshift,
18148                 finish: finish,
18149
18150                 sort: sort
18151         };
18152
18153 }
18154
18155 function WebGLRenderLists( properties ) {
18156
18157         let lists = new WeakMap();
18158
18159         function get( scene, camera ) {
18160
18161                 const cameras = lists.get( scene );
18162                 let list;
18163
18164                 if ( cameras === undefined ) {
18165
18166                         list = new WebGLRenderList( properties );
18167                         lists.set( scene, new WeakMap() );
18168                         lists.get( scene ).set( camera, list );
18169
18170                 } else {
18171
18172                         list = cameras.get( camera );
18173                         if ( list === undefined ) {
18174
18175                                 list = new WebGLRenderList( properties );
18176                                 cameras.set( camera, list );
18177
18178                         }
18179
18180                 }
18181
18182                 return list;
18183
18184         }
18185
18186         function dispose() {
18187
18188                 lists = new WeakMap();
18189
18190         }
18191
18192         return {
18193                 get: get,
18194                 dispose: dispose
18195         };
18196
18197 }
18198
18199 function UniformsCache() {
18200
18201         const lights = {};
18202
18203         return {
18204
18205                 get: function ( light ) {
18206
18207                         if ( lights[ light.id ] !== undefined ) {
18208
18209                                 return lights[ light.id ];
18210
18211                         }
18212
18213                         let uniforms;
18214
18215                         switch ( light.type ) {
18216
18217                                 case 'DirectionalLight':
18218                                         uniforms = {
18219                                                 direction: new Vector3(),
18220                                                 color: new Color()
18221                                         };
18222                                         break;
18223
18224                                 case 'SpotLight':
18225                                         uniforms = {
18226                                                 position: new Vector3(),
18227                                                 direction: new Vector3(),
18228                                                 color: new Color(),
18229                                                 distance: 0,
18230                                                 coneCos: 0,
18231                                                 penumbraCos: 0,
18232                                                 decay: 0
18233                                         };
18234                                         break;
18235
18236                                 case 'PointLight':
18237                                         uniforms = {
18238                                                 position: new Vector3(),
18239                                                 color: new Color(),
18240                                                 distance: 0,
18241                                                 decay: 0
18242                                         };
18243                                         break;
18244
18245                                 case 'HemisphereLight':
18246                                         uniforms = {
18247                                                 direction: new Vector3(),
18248                                                 skyColor: new Color(),
18249                                                 groundColor: new Color()
18250                                         };
18251                                         break;
18252
18253                                 case 'RectAreaLight':
18254                                         uniforms = {
18255                                                 color: new Color(),
18256                                                 position: new Vector3(),
18257                                                 halfWidth: new Vector3(),
18258                                                 halfHeight: new Vector3()
18259                                         };
18260                                         break;
18261
18262                         }
18263
18264                         lights[ light.id ] = uniforms;
18265
18266                         return uniforms;
18267
18268                 }
18269
18270         };
18271
18272 }
18273
18274 function ShadowUniformsCache() {
18275
18276         const lights = {};
18277
18278         return {
18279
18280                 get: function ( light ) {
18281
18282                         if ( lights[ light.id ] !== undefined ) {
18283
18284                                 return lights[ light.id ];
18285
18286                         }
18287
18288                         let uniforms;
18289
18290                         switch ( light.type ) {
18291
18292                                 case 'DirectionalLight':
18293                                         uniforms = {
18294                                                 shadowBias: 0,
18295                                                 shadowNormalBias: 0,
18296                                                 shadowRadius: 1,
18297                                                 shadowMapSize: new Vector2()
18298                                         };
18299                                         break;
18300
18301                                 case 'SpotLight':
18302                                         uniforms = {
18303                                                 shadowBias: 0,
18304                                                 shadowNormalBias: 0,
18305                                                 shadowRadius: 1,
18306                                                 shadowMapSize: new Vector2()
18307                                         };
18308                                         break;
18309
18310                                 case 'PointLight':
18311                                         uniforms = {
18312                                                 shadowBias: 0,
18313                                                 shadowNormalBias: 0,
18314                                                 shadowRadius: 1,
18315                                                 shadowMapSize: new Vector2(),
18316                                                 shadowCameraNear: 1,
18317                                                 shadowCameraFar: 1000
18318                                         };
18319                                         break;
18320
18321                                 // TODO (abelnation): set RectAreaLight shadow uniforms
18322
18323                         }
18324
18325                         lights[ light.id ] = uniforms;
18326
18327                         return uniforms;
18328
18329                 }
18330
18331         };
18332
18333 }
18334
18335
18336
18337 let nextVersion = 0;
18338
18339 function shadowCastingLightsFirst( lightA, lightB ) {
18340
18341         return ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );
18342
18343 }
18344
18345 function WebGLLights( extensions, capabilities ) {
18346
18347         const cache = new UniformsCache();
18348
18349         const shadowCache = ShadowUniformsCache();
18350
18351         const state = {
18352
18353                 version: 0,
18354
18355                 hash: {
18356                         directionalLength: - 1,
18357                         pointLength: - 1,
18358                         spotLength: - 1,
18359                         rectAreaLength: - 1,
18360                         hemiLength: - 1,
18361
18362                         numDirectionalShadows: - 1,
18363                         numPointShadows: - 1,
18364                         numSpotShadows: - 1
18365                 },
18366
18367                 ambient: [ 0, 0, 0 ],
18368                 probe: [],
18369                 directional: [],
18370                 directionalShadow: [],
18371                 directionalShadowMap: [],
18372                 directionalShadowMatrix: [],
18373                 spot: [],
18374                 spotShadow: [],
18375                 spotShadowMap: [],
18376                 spotShadowMatrix: [],
18377                 rectArea: [],
18378                 rectAreaLTC1: null,
18379                 rectAreaLTC2: null,
18380                 point: [],
18381                 pointShadow: [],
18382                 pointShadowMap: [],
18383                 pointShadowMatrix: [],
18384                 hemi: []
18385
18386         };
18387
18388         for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
18389
18390         const vector3 = new Vector3();
18391         const matrix4 = new Matrix4();
18392         const matrix42 = new Matrix4();
18393
18394         function setup( lights, shadows, camera ) {
18395
18396                 let r = 0, g = 0, b = 0;
18397
18398                 for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
18399
18400                 let directionalLength = 0;
18401                 let pointLength = 0;
18402                 let spotLength = 0;
18403                 let rectAreaLength = 0;
18404                 let hemiLength = 0;
18405
18406                 let numDirectionalShadows = 0;
18407                 let numPointShadows = 0;
18408                 let numSpotShadows = 0;
18409
18410                 const viewMatrix = camera.matrixWorldInverse;
18411
18412                 lights.sort( shadowCastingLightsFirst );
18413
18414                 for ( let i = 0, l = lights.length; i < l; i ++ ) {
18415
18416                         const light = lights[ i ];
18417
18418                         const color = light.color;
18419                         const intensity = light.intensity;
18420                         const distance = light.distance;
18421
18422                         const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
18423
18424                         if ( light.isAmbientLight ) {
18425
18426                                 r += color.r * intensity;
18427                                 g += color.g * intensity;
18428                                 b += color.b * intensity;
18429
18430                         } else if ( light.isLightProbe ) {
18431
18432                                 for ( let j = 0; j < 9; j ++ ) {
18433
18434                                         state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
18435
18436                                 }
18437
18438                         } else if ( light.isDirectionalLight ) {
18439
18440                                 const uniforms = cache.get( light );
18441
18442                                 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
18443                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
18444                                 vector3.setFromMatrixPosition( light.target.matrixWorld );
18445                                 uniforms.direction.sub( vector3 );
18446                                 uniforms.direction.transformDirection( viewMatrix );
18447
18448                                 if ( light.castShadow ) {
18449
18450                                         const shadow = light.shadow;
18451
18452                                         const shadowUniforms = shadowCache.get( light );
18453
18454                                         shadowUniforms.shadowBias = shadow.bias;
18455                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
18456                                         shadowUniforms.shadowRadius = shadow.radius;
18457                                         shadowUniforms.shadowMapSize = shadow.mapSize;
18458
18459                                         state.directionalShadow[ directionalLength ] = shadowUniforms;
18460                                         state.directionalShadowMap[ directionalLength ] = shadowMap;
18461                                         state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
18462
18463                                         numDirectionalShadows ++;
18464
18465                                 }
18466
18467                                 state.directional[ directionalLength ] = uniforms;
18468
18469                                 directionalLength ++;
18470
18471                         } else if ( light.isSpotLight ) {
18472
18473                                 const uniforms = cache.get( light );
18474
18475                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
18476                                 uniforms.position.applyMatrix4( viewMatrix );
18477
18478                                 uniforms.color.copy( color ).multiplyScalar( intensity );
18479                                 uniforms.distance = distance;
18480
18481                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
18482                                 vector3.setFromMatrixPosition( light.target.matrixWorld );
18483                                 uniforms.direction.sub( vector3 );
18484                                 uniforms.direction.transformDirection( viewMatrix );
18485
18486                                 uniforms.coneCos = Math.cos( light.angle );
18487                                 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
18488                                 uniforms.decay = light.decay;
18489
18490                                 if ( light.castShadow ) {
18491
18492                                         const shadow = light.shadow;
18493
18494                                         const shadowUniforms = shadowCache.get( light );
18495
18496                                         shadowUniforms.shadowBias = shadow.bias;
18497                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
18498                                         shadowUniforms.shadowRadius = shadow.radius;
18499                                         shadowUniforms.shadowMapSize = shadow.mapSize;
18500
18501                                         state.spotShadow[ spotLength ] = shadowUniforms;
18502                                         state.spotShadowMap[ spotLength ] = shadowMap;
18503                                         state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
18504
18505                                         numSpotShadows ++;
18506
18507                                 }
18508
18509                                 state.spot[ spotLength ] = uniforms;
18510
18511                                 spotLength ++;
18512
18513                         } else if ( light.isRectAreaLight ) {
18514
18515                                 const uniforms = cache.get( light );
18516
18517                                 // (a) intensity is the total visible light emitted
18518                                 //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
18519
18520                                 // (b) intensity is the brightness of the light
18521                                 uniforms.color.copy( color ).multiplyScalar( intensity );
18522
18523                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
18524                                 uniforms.position.applyMatrix4( viewMatrix );
18525
18526                                 // extract local rotation of light to derive width/height half vectors
18527                                 matrix42.identity();
18528                                 matrix4.copy( light.matrixWorld );
18529                                 matrix4.premultiply( viewMatrix );
18530                                 matrix42.extractRotation( matrix4 );
18531
18532                                 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
18533                                 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
18534
18535                                 uniforms.halfWidth.applyMatrix4( matrix42 );
18536                                 uniforms.halfHeight.applyMatrix4( matrix42 );
18537
18538                                 // TODO (abelnation): RectAreaLight distance?
18539                                 // uniforms.distance = distance;
18540
18541                                 state.rectArea[ rectAreaLength ] = uniforms;
18542
18543                                 rectAreaLength ++;
18544
18545                         } else if ( light.isPointLight ) {
18546
18547                                 const uniforms = cache.get( light );
18548
18549                                 uniforms.position.setFromMatrixPosition( light.matrixWorld );
18550                                 uniforms.position.applyMatrix4( viewMatrix );
18551
18552                                 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
18553                                 uniforms.distance = light.distance;
18554                                 uniforms.decay = light.decay;
18555
18556                                 if ( light.castShadow ) {
18557
18558                                         const shadow = light.shadow;
18559
18560                                         const shadowUniforms = shadowCache.get( light );
18561
18562                                         shadowUniforms.shadowBias = shadow.bias;
18563                                         shadowUniforms.shadowNormalBias = shadow.normalBias;
18564                                         shadowUniforms.shadowRadius = shadow.radius;
18565                                         shadowUniforms.shadowMapSize = shadow.mapSize;
18566                                         shadowUniforms.shadowCameraNear = shadow.camera.near;
18567                                         shadowUniforms.shadowCameraFar = shadow.camera.far;
18568
18569                                         state.pointShadow[ pointLength ] = shadowUniforms;
18570                                         state.pointShadowMap[ pointLength ] = shadowMap;
18571                                         state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
18572
18573                                         numPointShadows ++;
18574
18575                                 }
18576
18577                                 state.point[ pointLength ] = uniforms;
18578
18579                                 pointLength ++;
18580
18581                         } else if ( light.isHemisphereLight ) {
18582
18583                                 const uniforms = cache.get( light );
18584
18585                                 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
18586                                 uniforms.direction.transformDirection( viewMatrix );
18587                                 uniforms.direction.normalize();
18588
18589                                 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
18590                                 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
18591
18592                                 state.hemi[ hemiLength ] = uniforms;
18593
18594                                 hemiLength ++;
18595
18596                         }
18597
18598                 }
18599
18600                 if ( rectAreaLength > 0 ) {
18601
18602                         if ( capabilities.isWebGL2 ) {
18603
18604                                 // WebGL 2
18605
18606                                 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
18607                                 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
18608
18609                         } else {
18610
18611                                 // WebGL 1
18612
18613                                 if ( extensions.has( 'OES_texture_float_linear' ) === true ) {
18614
18615                                         state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
18616                                         state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
18617
18618                                 } else if ( extensions.has( 'OES_texture_half_float_linear' ) === true ) {
18619
18620                                         state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
18621                                         state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
18622
18623                                 } else {
18624
18625                                         console.error( 'THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.' );
18626
18627                                 }
18628
18629                         }
18630
18631                 }
18632
18633                 state.ambient[ 0 ] = r;
18634                 state.ambient[ 1 ] = g;
18635                 state.ambient[ 2 ] = b;
18636
18637                 const hash = state.hash;
18638
18639                 if ( hash.directionalLength !== directionalLength ||
18640                         hash.pointLength !== pointLength ||
18641                         hash.spotLength !== spotLength ||
18642                         hash.rectAreaLength !== rectAreaLength ||
18643                         hash.hemiLength !== hemiLength ||
18644                         hash.numDirectionalShadows !== numDirectionalShadows ||
18645                         hash.numPointShadows !== numPointShadows ||
18646                         hash.numSpotShadows !== numSpotShadows ) {
18647
18648                         state.directional.length = directionalLength;
18649                         state.spot.length = spotLength;
18650                         state.rectArea.length = rectAreaLength;
18651                         state.point.length = pointLength;
18652                         state.hemi.length = hemiLength;
18653
18654                         state.directionalShadow.length = numDirectionalShadows;
18655                         state.directionalShadowMap.length = numDirectionalShadows;
18656                         state.pointShadow.length = numPointShadows;
18657                         state.pointShadowMap.length = numPointShadows;
18658                         state.spotShadow.length = numSpotShadows;
18659                         state.spotShadowMap.length = numSpotShadows;
18660                         state.directionalShadowMatrix.length = numDirectionalShadows;
18661                         state.pointShadowMatrix.length = numPointShadows;
18662                         state.spotShadowMatrix.length = numSpotShadows;
18663
18664                         hash.directionalLength = directionalLength;
18665                         hash.pointLength = pointLength;
18666                         hash.spotLength = spotLength;
18667                         hash.rectAreaLength = rectAreaLength;
18668                         hash.hemiLength = hemiLength;
18669
18670                         hash.numDirectionalShadows = numDirectionalShadows;
18671                         hash.numPointShadows = numPointShadows;
18672                         hash.numSpotShadows = numSpotShadows;
18673
18674                         state.version = nextVersion ++;
18675
18676                 }
18677
18678         }
18679
18680         return {
18681                 setup: setup,
18682                 state: state
18683         };
18684
18685 }
18686
18687 function WebGLRenderState( extensions, capabilities ) {
18688
18689         const lights = new WebGLLights( extensions, capabilities );
18690
18691         const lightsArray = [];
18692         const shadowsArray = [];
18693
18694         function init() {
18695
18696                 lightsArray.length = 0;
18697                 shadowsArray.length = 0;
18698
18699         }
18700
18701         function pushLight( light ) {
18702
18703                 lightsArray.push( light );
18704
18705         }
18706
18707         function pushShadow( shadowLight ) {
18708
18709                 shadowsArray.push( shadowLight );
18710
18711         }
18712
18713         function setupLights( camera ) {
18714
18715                 lights.setup( lightsArray, shadowsArray, camera );
18716
18717         }
18718
18719         const state = {
18720                 lightsArray: lightsArray,
18721                 shadowsArray: shadowsArray,
18722
18723                 lights: lights
18724         };
18725
18726         return {
18727                 init: init,
18728                 state: state,
18729                 setupLights: setupLights,
18730
18731                 pushLight: pushLight,
18732                 pushShadow: pushShadow
18733         };
18734
18735 }
18736
18737 function WebGLRenderStates( extensions, capabilities ) {
18738
18739         let renderStates = new WeakMap();
18740
18741         function get( scene, camera ) {
18742
18743                 let renderState;
18744
18745                 if ( renderStates.has( scene ) === false ) {
18746
18747                         renderState = new WebGLRenderState( extensions, capabilities );
18748                         renderStates.set( scene, new WeakMap() );
18749                         renderStates.get( scene ).set( camera, renderState );
18750
18751                 } else {
18752
18753                         if ( renderStates.get( scene ).has( camera ) === false ) {
18754
18755                                 renderState = new WebGLRenderState( extensions, capabilities );
18756                                 renderStates.get( scene ).set( camera, renderState );
18757
18758                         } else {
18759
18760                                 renderState = renderStates.get( scene ).get( camera );
18761
18762                         }
18763
18764                 }
18765
18766                 return renderState;
18767
18768         }
18769
18770         function dispose() {
18771
18772                 renderStates = new WeakMap();
18773
18774         }
18775
18776         return {
18777                 get: get,
18778                 dispose: dispose
18779         };
18780
18781 }
18782
18783 /**
18784  * parameters = {
18785  *
18786  *  opacity: <float>,
18787  *
18788  *  map: new THREE.Texture( <Image> ),
18789  *
18790  *  alphaMap: new THREE.Texture( <Image> ),
18791  *
18792  *  displacementMap: new THREE.Texture( <Image> ),
18793  *  displacementScale: <float>,
18794  *  displacementBias: <float>,
18795  *
18796  *  wireframe: <boolean>,
18797  *  wireframeLinewidth: <float>
18798  * }
18799  */
18800
18801 function MeshDepthMaterial( parameters ) {
18802
18803         Material.call( this );
18804
18805         this.type = 'MeshDepthMaterial';
18806
18807         this.depthPacking = BasicDepthPacking;
18808
18809         this.skinning = false;
18810         this.morphTargets = false;
18811
18812         this.map = null;
18813
18814         this.alphaMap = null;
18815
18816         this.displacementMap = null;
18817         this.displacementScale = 1;
18818         this.displacementBias = 0;
18819
18820         this.wireframe = false;
18821         this.wireframeLinewidth = 1;
18822
18823         this.fog = false;
18824
18825         this.setValues( parameters );
18826
18827 }
18828
18829 MeshDepthMaterial.prototype = Object.create( Material.prototype );
18830 MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
18831
18832 MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
18833
18834 MeshDepthMaterial.prototype.copy = function ( source ) {
18835
18836         Material.prototype.copy.call( this, source );
18837
18838         this.depthPacking = source.depthPacking;
18839
18840         this.skinning = source.skinning;
18841         this.morphTargets = source.morphTargets;
18842
18843         this.map = source.map;
18844
18845         this.alphaMap = source.alphaMap;
18846
18847         this.displacementMap = source.displacementMap;
18848         this.displacementScale = source.displacementScale;
18849         this.displacementBias = source.displacementBias;
18850
18851         this.wireframe = source.wireframe;
18852         this.wireframeLinewidth = source.wireframeLinewidth;
18853
18854         return this;
18855
18856 };
18857
18858 /**
18859  * parameters = {
18860  *
18861  *  referencePosition: <float>,
18862  *  nearDistance: <float>,
18863  *  farDistance: <float>,
18864  *
18865  *  skinning: <bool>,
18866  *  morphTargets: <bool>,
18867  *
18868  *  map: new THREE.Texture( <Image> ),
18869  *
18870  *  alphaMap: new THREE.Texture( <Image> ),
18871  *
18872  *  displacementMap: new THREE.Texture( <Image> ),
18873  *  displacementScale: <float>,
18874  *  displacementBias: <float>
18875  *
18876  * }
18877  */
18878
18879 function MeshDistanceMaterial( parameters ) {
18880
18881         Material.call( this );
18882
18883         this.type = 'MeshDistanceMaterial';
18884
18885         this.referencePosition = new Vector3();
18886         this.nearDistance = 1;
18887         this.farDistance = 1000;
18888
18889         this.skinning = false;
18890         this.morphTargets = false;
18891
18892         this.map = null;
18893
18894         this.alphaMap = null;
18895
18896         this.displacementMap = null;
18897         this.displacementScale = 1;
18898         this.displacementBias = 0;
18899
18900         this.fog = false;
18901
18902         this.setValues( parameters );
18903
18904 }
18905
18906 MeshDistanceMaterial.prototype = Object.create( Material.prototype );
18907 MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
18908
18909 MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
18910
18911 MeshDistanceMaterial.prototype.copy = function ( source ) {
18912
18913         Material.prototype.copy.call( this, source );
18914
18915         this.referencePosition.copy( source.referencePosition );
18916         this.nearDistance = source.nearDistance;
18917         this.farDistance = source.farDistance;
18918
18919         this.skinning = source.skinning;
18920         this.morphTargets = source.morphTargets;
18921
18922         this.map = source.map;
18923
18924         this.alphaMap = source.alphaMap;
18925
18926         this.displacementMap = source.displacementMap;
18927         this.displacementScale = source.displacementScale;
18928         this.displacementBias = source.displacementBias;
18929
18930         return this;
18931
18932 };
18933
18934 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 HORIZONAL_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}";
18935
18936 var vsm_vert = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
18937
18938 function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
18939
18940         let _frustum = new Frustum();
18941
18942         const _shadowMapSize = new Vector2(),
18943                 _viewportSize = new Vector2(),
18944
18945                 _viewport = new Vector4(),
18946
18947                 _depthMaterials = [],
18948                 _distanceMaterials = [],
18949
18950                 _materialCache = {};
18951
18952         const shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
18953
18954         const shadowMaterialVertical = new ShaderMaterial( {
18955
18956                 defines: {
18957                         SAMPLE_RATE: 2.0 / 8.0,
18958                         HALF_SAMPLE_RATE: 1.0 / 8.0
18959                 },
18960
18961                 uniforms: {
18962                         shadow_pass: { value: null },
18963                         resolution: { value: new Vector2() },
18964                         radius: { value: 4.0 }
18965                 },
18966
18967                 vertexShader: vsm_vert,
18968
18969                 fragmentShader: vsm_frag
18970
18971         } );
18972
18973         const shadowMaterialHorizonal = shadowMaterialVertical.clone();
18974         shadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;
18975
18976         const fullScreenTri = new BufferGeometry();
18977         fullScreenTri.setAttribute(
18978                 "position",
18979                 new BufferAttribute(
18980                         new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
18981                         3
18982                 )
18983         );
18984
18985         const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
18986
18987         const scope = this;
18988
18989         this.enabled = false;
18990
18991         this.autoUpdate = true;
18992         this.needsUpdate = false;
18993
18994         this.type = PCFShadowMap;
18995
18996         this.render = function ( lights, scene, camera ) {
18997
18998                 if ( scope.enabled === false ) return;
18999                 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
19000
19001                 if ( lights.length === 0 ) return;
19002
19003                 const currentRenderTarget = _renderer.getRenderTarget();
19004                 const activeCubeFace = _renderer.getActiveCubeFace();
19005                 const activeMipmapLevel = _renderer.getActiveMipmapLevel();
19006
19007                 const _state = _renderer.state;
19008
19009                 // Set GL state for depth map.
19010                 _state.setBlending( NoBlending );
19011                 _state.buffers.color.setClear( 1, 1, 1, 1 );
19012                 _state.buffers.depth.setTest( true );
19013                 _state.setScissorTest( false );
19014
19015                 // render depth map
19016
19017                 for ( let i = 0, il = lights.length; i < il; i ++ ) {
19018
19019                         const light = lights[ i ];
19020                         const shadow = light.shadow;
19021
19022                         if ( shadow === undefined ) {
19023
19024                                 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
19025                                 continue;
19026
19027                         }
19028
19029                         if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue;
19030
19031                         _shadowMapSize.copy( shadow.mapSize );
19032
19033                         const shadowFrameExtents = shadow.getFrameExtents();
19034
19035                         _shadowMapSize.multiply( shadowFrameExtents );
19036
19037                         _viewportSize.copy( shadow.mapSize );
19038
19039                         if ( _shadowMapSize.x > maxTextureSize || _shadowMapSize.y > maxTextureSize ) {
19040
19041                                 if ( _shadowMapSize.x > maxTextureSize ) {
19042
19043                                         _viewportSize.x = Math.floor( maxTextureSize / shadowFrameExtents.x );
19044                                         _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
19045                                         shadow.mapSize.x = _viewportSize.x;
19046
19047                                 }
19048
19049                                 if ( _shadowMapSize.y > maxTextureSize ) {
19050
19051                                         _viewportSize.y = Math.floor( maxTextureSize / shadowFrameExtents.y );
19052                                         _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
19053                                         shadow.mapSize.y = _viewportSize.y;
19054
19055                                 }
19056
19057                         }
19058
19059                         if ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
19060
19061                                 const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
19062
19063                                 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
19064                                 shadow.map.texture.name = light.name + ".shadowMap";
19065
19066                                 shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
19067
19068                                 shadow.camera.updateProjectionMatrix();
19069
19070                         }
19071
19072                         if ( shadow.map === null ) {
19073
19074                                 const pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
19075
19076                                 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
19077                                 shadow.map.texture.name = light.name + ".shadowMap";
19078
19079                                 shadow.camera.updateProjectionMatrix();
19080
19081                         }
19082
19083                         _renderer.setRenderTarget( shadow.map );
19084                         _renderer.clear();
19085
19086                         const viewportCount = shadow.getViewportCount();
19087
19088                         for ( let vp = 0; vp < viewportCount; vp ++ ) {
19089
19090                                 const viewport = shadow.getViewport( vp );
19091
19092                                 _viewport.set(
19093                                         _viewportSize.x * viewport.x,
19094                                         _viewportSize.y * viewport.y,
19095                                         _viewportSize.x * viewport.z,
19096                                         _viewportSize.y * viewport.w
19097                                 );
19098
19099                                 _state.viewport( _viewport );
19100
19101                                 shadow.updateMatrices( light, vp );
19102
19103                                 _frustum = shadow.getFrustum();
19104
19105                                 renderObject( scene, camera, shadow.camera, light, this.type );
19106
19107                         }
19108
19109                         // do blur pass for VSM
19110
19111                         if ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
19112
19113                                 VSMPass( shadow, camera );
19114
19115                         }
19116
19117                         shadow.needsUpdate = false;
19118
19119                 }
19120
19121                 scope.needsUpdate = false;
19122
19123                 _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
19124
19125         };
19126
19127         function VSMPass( shadow, camera ) {
19128
19129                 const geometry = _objects.update( fullScreenMesh );
19130
19131                 // vertical pass
19132
19133                 shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
19134                 shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
19135                 shadowMaterialVertical.uniforms.radius.value = shadow.radius;
19136                 _renderer.setRenderTarget( shadow.mapPass );
19137                 _renderer.clear();
19138                 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
19139
19140                 // horizonal pass
19141
19142                 shadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;
19143                 shadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;
19144                 shadowMaterialHorizonal.uniforms.radius.value = shadow.radius;
19145                 _renderer.setRenderTarget( shadow.map );
19146                 _renderer.clear();
19147                 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null );
19148
19149         }
19150
19151         function getDepthMaterialVariant( useMorphing, useSkinning, useInstancing ) {
19152
19153                 const index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
19154
19155                 let material = _depthMaterials[ index ];
19156
19157                 if ( material === undefined ) {
19158
19159                         material = new MeshDepthMaterial( {
19160
19161                                 depthPacking: RGBADepthPacking,
19162
19163                                 morphTargets: useMorphing,
19164                                 skinning: useSkinning
19165
19166                         } );
19167
19168                         _depthMaterials[ index ] = material;
19169
19170                 }
19171
19172                 return material;
19173
19174         }
19175
19176         function getDistanceMaterialVariant( useMorphing, useSkinning, useInstancing ) {
19177
19178                 const index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
19179
19180                 let material = _distanceMaterials[ index ];
19181
19182                 if ( material === undefined ) {
19183
19184                         material = new MeshDistanceMaterial( {
19185
19186                                 morphTargets: useMorphing,
19187                                 skinning: useSkinning
19188
19189                         } );
19190
19191                         _distanceMaterials[ index ] = material;
19192
19193                 }
19194
19195                 return material;
19196
19197         }
19198
19199         function getDepthMaterial( object, geometry, material, light, shadowCameraNear, shadowCameraFar, type ) {
19200
19201                 let result = null;
19202
19203                 let getMaterialVariant = getDepthMaterialVariant;
19204                 let customMaterial = object.customDepthMaterial;
19205
19206                 if ( light.isPointLight === true ) {
19207
19208                         getMaterialVariant = getDistanceMaterialVariant;
19209                         customMaterial = object.customDistanceMaterial;
19210
19211                 }
19212
19213                 if ( customMaterial === undefined ) {
19214
19215                         let useMorphing = false;
19216
19217                         if ( material.morphTargets === true ) {
19218
19219                                 useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
19220
19221                         }
19222
19223                         let useSkinning = false;
19224
19225                         if ( object.isSkinnedMesh === true ) {
19226
19227                                 if ( material.skinning === true ) {
19228
19229                                         useSkinning = true;
19230
19231                                 } else {
19232
19233                                         console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
19234
19235                                 }
19236
19237                         }
19238
19239                         const useInstancing = object.isInstancedMesh === true;
19240
19241                         result = getMaterialVariant( useMorphing, useSkinning, useInstancing );
19242
19243                 } else {
19244
19245                         result = customMaterial;
19246
19247                 }
19248
19249                 if ( _renderer.localClippingEnabled &&
19250                                 material.clipShadows === true &&
19251                                 material.clippingPlanes.length !== 0 ) {
19252
19253                         // in this case we need a unique material instance reflecting the
19254                         // appropriate state
19255
19256                         const keyA = result.uuid, keyB = material.uuid;
19257
19258                         let materialsForVariant = _materialCache[ keyA ];
19259
19260                         if ( materialsForVariant === undefined ) {
19261
19262                                 materialsForVariant = {};
19263                                 _materialCache[ keyA ] = materialsForVariant;
19264
19265                         }
19266
19267                         let cachedMaterial = materialsForVariant[ keyB ];
19268
19269                         if ( cachedMaterial === undefined ) {
19270
19271                                 cachedMaterial = result.clone();
19272                                 materialsForVariant[ keyB ] = cachedMaterial;
19273
19274                         }
19275
19276                         result = cachedMaterial;
19277
19278                 }
19279
19280                 result.visible = material.visible;
19281                 result.wireframe = material.wireframe;
19282
19283                 if ( type === VSMShadowMap ) {
19284
19285                         result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
19286
19287                 } else {
19288
19289                         result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
19290
19291                 }
19292
19293                 result.clipShadows = material.clipShadows;
19294                 result.clippingPlanes = material.clippingPlanes;
19295                 result.clipIntersection = material.clipIntersection;
19296
19297                 result.wireframeLinewidth = material.wireframeLinewidth;
19298                 result.linewidth = material.linewidth;
19299
19300                 if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
19301
19302                         result.referencePosition.setFromMatrixPosition( light.matrixWorld );
19303                         result.nearDistance = shadowCameraNear;
19304                         result.farDistance = shadowCameraFar;
19305
19306                 }
19307
19308                 return result;
19309
19310         }
19311
19312         function renderObject( object, camera, shadowCamera, light, type ) {
19313
19314                 if ( object.visible === false ) return;
19315
19316                 const visible = object.layers.test( camera.layers );
19317
19318                 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
19319
19320                         if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
19321
19322                                 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
19323
19324                                 const geometry = _objects.update( object );
19325                                 const material = object.material;
19326
19327                                 if ( Array.isArray( material ) ) {
19328
19329                                         const groups = geometry.groups;
19330
19331                                         for ( let k = 0, kl = groups.length; k < kl; k ++ ) {
19332
19333                                                 const group = groups[ k ];
19334                                                 const groupMaterial = material[ group.materialIndex ];
19335
19336                                                 if ( groupMaterial && groupMaterial.visible ) {
19337
19338                                                         const depthMaterial = getDepthMaterial( object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );
19339
19340                                                         _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
19341
19342                                                 }
19343
19344                                         }
19345
19346                                 } else if ( material.visible ) {
19347
19348                                         const depthMaterial = getDepthMaterial( object, geometry, material, light, shadowCamera.near, shadowCamera.far, type );
19349
19350                                         _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
19351
19352                                 }
19353
19354                         }
19355
19356                 }
19357
19358                 const children = object.children;
19359
19360                 for ( let i = 0, l = children.length; i < l; i ++ ) {
19361
19362                         renderObject( children[ i ], camera, shadowCamera, light, type );
19363
19364                 }
19365
19366         }
19367
19368 }
19369
19370 function WebGLState( gl, extensions, capabilities ) {
19371
19372         const isWebGL2 = capabilities.isWebGL2;
19373
19374         function ColorBuffer() {
19375
19376                 let locked = false;
19377
19378                 const color = new Vector4();
19379                 let currentColorMask = null;
19380                 const currentColorClear = new Vector4( 0, 0, 0, 0 );
19381
19382                 return {
19383
19384                         setMask: function ( colorMask ) {
19385
19386                                 if ( currentColorMask !== colorMask && ! locked ) {
19387
19388                                         gl.colorMask( colorMask, colorMask, colorMask, colorMask );
19389                                         currentColorMask = colorMask;
19390
19391                                 }
19392
19393                         },
19394
19395                         setLocked: function ( lock ) {
19396
19397                                 locked = lock;
19398
19399                         },
19400
19401                         setClear: function ( r, g, b, a, premultipliedAlpha ) {
19402
19403                                 if ( premultipliedAlpha === true ) {
19404
19405                                         r *= a; g *= a; b *= a;
19406
19407                                 }
19408
19409                                 color.set( r, g, b, a );
19410
19411                                 if ( currentColorClear.equals( color ) === false ) {
19412
19413                                         gl.clearColor( r, g, b, a );
19414                                         currentColorClear.copy( color );
19415
19416                                 }
19417
19418                         },
19419
19420                         reset: function () {
19421
19422                                 locked = false;
19423
19424                                 currentColorMask = null;
19425                                 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
19426
19427                         }
19428
19429                 };
19430
19431         }
19432
19433         function DepthBuffer() {
19434
19435                 let locked = false;
19436
19437                 let currentDepthMask = null;
19438                 let currentDepthFunc = null;
19439                 let currentDepthClear = null;
19440
19441                 return {
19442
19443                         setTest: function ( depthTest ) {
19444
19445                                 if ( depthTest ) {
19446
19447                                         enable( 2929 );
19448
19449                                 } else {
19450
19451                                         disable( 2929 );
19452
19453                                 }
19454
19455                         },
19456
19457                         setMask: function ( depthMask ) {
19458
19459                                 if ( currentDepthMask !== depthMask && ! locked ) {
19460
19461                                         gl.depthMask( depthMask );
19462                                         currentDepthMask = depthMask;
19463
19464                                 }
19465
19466                         },
19467
19468                         setFunc: function ( depthFunc ) {
19469
19470                                 if ( currentDepthFunc !== depthFunc ) {
19471
19472                                         if ( depthFunc ) {
19473
19474                                                 switch ( depthFunc ) {
19475
19476                                                         case NeverDepth:
19477
19478                                                                 gl.depthFunc( 512 );
19479                                                                 break;
19480
19481                                                         case AlwaysDepth:
19482
19483                                                                 gl.depthFunc( 519 );
19484                                                                 break;
19485
19486                                                         case LessDepth:
19487
19488                                                                 gl.depthFunc( 513 );
19489                                                                 break;
19490
19491                                                         case LessEqualDepth:
19492
19493                                                                 gl.depthFunc( 515 );
19494                                                                 break;
19495
19496                                                         case EqualDepth:
19497
19498                                                                 gl.depthFunc( 514 );
19499                                                                 break;
19500
19501                                                         case GreaterEqualDepth:
19502
19503                                                                 gl.depthFunc( 518 );
19504                                                                 break;
19505
19506                                                         case GreaterDepth:
19507
19508                                                                 gl.depthFunc( 516 );
19509                                                                 break;
19510
19511                                                         case NotEqualDepth:
19512
19513                                                                 gl.depthFunc( 517 );
19514                                                                 break;
19515
19516                                                         default:
19517
19518                                                                 gl.depthFunc( 515 );
19519
19520                                                 }
19521
19522                                         } else {
19523
19524                                                 gl.depthFunc( 515 );
19525
19526                                         }
19527
19528                                         currentDepthFunc = depthFunc;
19529
19530                                 }
19531
19532                         },
19533
19534                         setLocked: function ( lock ) {
19535
19536                                 locked = lock;
19537
19538                         },
19539
19540                         setClear: function ( depth ) {
19541
19542                                 if ( currentDepthClear !== depth ) {
19543
19544                                         gl.clearDepth( depth );
19545                                         currentDepthClear = depth;
19546
19547                                 }
19548
19549                         },
19550
19551                         reset: function () {
19552
19553                                 locked = false;
19554
19555                                 currentDepthMask = null;
19556                                 currentDepthFunc = null;
19557                                 currentDepthClear = null;
19558
19559                         }
19560
19561                 };
19562
19563         }
19564
19565         function StencilBuffer() {
19566
19567                 let locked = false;
19568
19569                 let currentStencilMask = null;
19570                 let currentStencilFunc = null;
19571                 let currentStencilRef = null;
19572                 let currentStencilFuncMask = null;
19573                 let currentStencilFail = null;
19574                 let currentStencilZFail = null;
19575                 let currentStencilZPass = null;
19576                 let currentStencilClear = null;
19577
19578                 return {
19579
19580                         setTest: function ( stencilTest ) {
19581
19582                                 if ( ! locked ) {
19583
19584                                         if ( stencilTest ) {
19585
19586                                                 enable( 2960 );
19587
19588                                         } else {
19589
19590                                                 disable( 2960 );
19591
19592                                         }
19593
19594                                 }
19595
19596                         },
19597
19598                         setMask: function ( stencilMask ) {
19599
19600                                 if ( currentStencilMask !== stencilMask && ! locked ) {
19601
19602                                         gl.stencilMask( stencilMask );
19603                                         currentStencilMask = stencilMask;
19604
19605                                 }
19606
19607                         },
19608
19609                         setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
19610
19611                                 if ( currentStencilFunc !== stencilFunc ||
19612                                      currentStencilRef !== stencilRef ||
19613                                      currentStencilFuncMask !== stencilMask ) {
19614
19615                                         gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
19616
19617                                         currentStencilFunc = stencilFunc;
19618                                         currentStencilRef = stencilRef;
19619                                         currentStencilFuncMask = stencilMask;
19620
19621                                 }
19622
19623                         },
19624
19625                         setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
19626
19627                                 if ( currentStencilFail !== stencilFail ||
19628                                      currentStencilZFail !== stencilZFail ||
19629                                      currentStencilZPass !== stencilZPass ) {
19630
19631                                         gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
19632
19633                                         currentStencilFail = stencilFail;
19634                                         currentStencilZFail = stencilZFail;
19635                                         currentStencilZPass = stencilZPass;
19636
19637                                 }
19638
19639                         },
19640
19641                         setLocked: function ( lock ) {
19642
19643                                 locked = lock;
19644
19645                         },
19646
19647                         setClear: function ( stencil ) {
19648
19649                                 if ( currentStencilClear !== stencil ) {
19650
19651                                         gl.clearStencil( stencil );
19652                                         currentStencilClear = stencil;
19653
19654                                 }
19655
19656                         },
19657
19658                         reset: function () {
19659
19660                                 locked = false;
19661
19662                                 currentStencilMask = null;
19663                                 currentStencilFunc = null;
19664                                 currentStencilRef = null;
19665                                 currentStencilFuncMask = null;
19666                                 currentStencilFail = null;
19667                                 currentStencilZFail = null;
19668                                 currentStencilZPass = null;
19669                                 currentStencilClear = null;
19670
19671                         }
19672
19673                 };
19674
19675         }
19676
19677         //
19678
19679         const colorBuffer = new ColorBuffer();
19680         const depthBuffer = new DepthBuffer();
19681         const stencilBuffer = new StencilBuffer();
19682
19683         let enabledCapabilities = {};
19684
19685         let currentProgram = null;
19686
19687         let currentBlendingEnabled = null;
19688         let currentBlending = null;
19689         let currentBlendEquation = null;
19690         let currentBlendSrc = null;
19691         let currentBlendDst = null;
19692         let currentBlendEquationAlpha = null;
19693         let currentBlendSrcAlpha = null;
19694         let currentBlendDstAlpha = null;
19695         let currentPremultipledAlpha = false;
19696
19697         let currentFlipSided = null;
19698         let currentCullFace = null;
19699
19700         let currentLineWidth = null;
19701
19702         let currentPolygonOffsetFactor = null;
19703         let currentPolygonOffsetUnits = null;
19704
19705         const maxTextures = gl.getParameter( 35661 );
19706
19707         let lineWidthAvailable = false;
19708         let version = 0;
19709         const glVersion = gl.getParameter( 7938 );
19710
19711         if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
19712
19713                 version = parseFloat( /^WebGL\ ([0-9])/.exec( glVersion )[ 1 ] );
19714                 lineWidthAvailable = ( version >= 1.0 );
19715
19716         } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
19717
19718                 version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] );
19719                 lineWidthAvailable = ( version >= 2.0 );
19720
19721         }
19722
19723         let currentTextureSlot = null;
19724         let currentBoundTextures = {};
19725
19726         const currentScissor = new Vector4();
19727         const currentViewport = new Vector4();
19728
19729         function createTexture( type, target, count ) {
19730
19731                 const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
19732                 const texture = gl.createTexture();
19733
19734                 gl.bindTexture( type, texture );
19735                 gl.texParameteri( type, 10241, 9728 );
19736                 gl.texParameteri( type, 10240, 9728 );
19737
19738                 for ( let i = 0; i < count; i ++ ) {
19739
19740                         gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );
19741
19742                 }
19743
19744                 return texture;
19745
19746         }
19747
19748         const emptyTextures = {};
19749         emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );
19750         emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );
19751
19752         // init
19753
19754         colorBuffer.setClear( 0, 0, 0, 1 );
19755         depthBuffer.setClear( 1 );
19756         stencilBuffer.setClear( 0 );
19757
19758         enable( 2929 );
19759         depthBuffer.setFunc( LessEqualDepth );
19760
19761         setFlipSided( false );
19762         setCullFace( CullFaceBack );
19763         enable( 2884 );
19764
19765         setBlending( NoBlending );
19766
19767         //
19768
19769         function enable( id ) {
19770
19771                 if ( enabledCapabilities[ id ] !== true ) {
19772
19773                         gl.enable( id );
19774                         enabledCapabilities[ id ] = true;
19775
19776                 }
19777
19778         }
19779
19780         function disable( id ) {
19781
19782                 if ( enabledCapabilities[ id ] !== false ) {
19783
19784                         gl.disable( id );
19785                         enabledCapabilities[ id ] = false;
19786
19787                 }
19788
19789         }
19790
19791         function useProgram( program ) {
19792
19793                 if ( currentProgram !== program ) {
19794
19795                         gl.useProgram( program );
19796
19797                         currentProgram = program;
19798
19799                         return true;
19800
19801                 }
19802
19803                 return false;
19804
19805         }
19806
19807         const equationToGL = {
19808                 [ AddEquation ]: 32774,
19809                 [ SubtractEquation ]: 32778,
19810                 [ ReverseSubtractEquation ]: 32779
19811         };
19812
19813         if ( isWebGL2 ) {
19814
19815                 equationToGL[ MinEquation ] = 32775;
19816                 equationToGL[ MaxEquation ] = 32776;
19817
19818         } else {
19819
19820                 const extension = extensions.get( 'EXT_blend_minmax' );
19821
19822                 if ( extension !== null ) {
19823
19824                         equationToGL[ MinEquation ] = extension.MIN_EXT;
19825                         equationToGL[ MaxEquation ] = extension.MAX_EXT;
19826
19827                 }
19828
19829         }
19830
19831         const factorToGL = {
19832                 [ ZeroFactor ]: 0,
19833                 [ OneFactor ]: 1,
19834                 [ SrcColorFactor ]: 768,
19835                 [ SrcAlphaFactor ]: 770,
19836                 [ SrcAlphaSaturateFactor ]: 776,
19837                 [ DstColorFactor ]: 774,
19838                 [ DstAlphaFactor ]: 772,
19839                 [ OneMinusSrcColorFactor ]: 769,
19840                 [ OneMinusSrcAlphaFactor ]: 771,
19841                 [ OneMinusDstColorFactor ]: 775,
19842                 [ OneMinusDstAlphaFactor ]: 773
19843         };
19844
19845         function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
19846
19847                 if ( blending === NoBlending ) {
19848
19849                         if ( currentBlendingEnabled ) {
19850
19851                                 disable( 3042 );
19852                                 currentBlendingEnabled = false;
19853
19854                         }
19855
19856                         return;
19857
19858                 }
19859
19860                 if ( ! currentBlendingEnabled ) {
19861
19862                         enable( 3042 );
19863                         currentBlendingEnabled = true;
19864
19865                 }
19866
19867                 if ( blending !== CustomBlending ) {
19868
19869                         if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
19870
19871                                 if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
19872
19873                                         gl.blendEquation( 32774 );
19874
19875                                         currentBlendEquation = AddEquation;
19876                                         currentBlendEquationAlpha = AddEquation;
19877
19878                                 }
19879
19880                                 if ( premultipliedAlpha ) {
19881
19882                                         switch ( blending ) {
19883
19884                                                 case NormalBlending:
19885                                                         gl.blendFuncSeparate( 1, 771, 1, 771 );
19886                                                         break;
19887
19888                                                 case AdditiveBlending:
19889                                                         gl.blendFunc( 1, 1 );
19890                                                         break;
19891
19892                                                 case SubtractiveBlending:
19893                                                         gl.blendFuncSeparate( 0, 0, 769, 771 );
19894                                                         break;
19895
19896                                                 case MultiplyBlending:
19897                                                         gl.blendFuncSeparate( 0, 768, 0, 770 );
19898                                                         break;
19899
19900                                                 default:
19901                                                         console.error( 'THREE.WebGLState: Invalid blending: ', blending );
19902                                                         break;
19903
19904                                         }
19905
19906                                 } else {
19907
19908                                         switch ( blending ) {
19909
19910                                                 case NormalBlending:
19911                                                         gl.blendFuncSeparate( 770, 771, 1, 771 );
19912                                                         break;
19913
19914                                                 case AdditiveBlending:
19915                                                         gl.blendFunc( 770, 1 );
19916                                                         break;
19917
19918                                                 case SubtractiveBlending:
19919                                                         gl.blendFunc( 0, 769 );
19920                                                         break;
19921
19922                                                 case MultiplyBlending:
19923                                                         gl.blendFunc( 0, 768 );
19924                                                         break;
19925
19926                                                 default:
19927                                                         console.error( 'THREE.WebGLState: Invalid blending: ', blending );
19928                                                         break;
19929
19930                                         }
19931
19932                                 }
19933
19934                                 currentBlendSrc = null;
19935                                 currentBlendDst = null;
19936                                 currentBlendSrcAlpha = null;
19937                                 currentBlendDstAlpha = null;
19938
19939                                 currentBlending = blending;
19940                                 currentPremultipledAlpha = premultipliedAlpha;
19941
19942                         }
19943
19944                         return;
19945
19946                 }
19947
19948                 // custom blending
19949
19950                 blendEquationAlpha = blendEquationAlpha || blendEquation;
19951                 blendSrcAlpha = blendSrcAlpha || blendSrc;
19952                 blendDstAlpha = blendDstAlpha || blendDst;
19953
19954                 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
19955
19956                         gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
19957
19958                         currentBlendEquation = blendEquation;
19959                         currentBlendEquationAlpha = blendEquationAlpha;
19960
19961                 }
19962
19963                 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
19964
19965                         gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
19966
19967                         currentBlendSrc = blendSrc;
19968                         currentBlendDst = blendDst;
19969                         currentBlendSrcAlpha = blendSrcAlpha;
19970                         currentBlendDstAlpha = blendDstAlpha;
19971
19972                 }
19973
19974                 currentBlending = blending;
19975                 currentPremultipledAlpha = null;
19976
19977         }
19978
19979         function setMaterial( material, frontFaceCW ) {
19980
19981                 material.side === DoubleSide
19982                         ? disable( 2884 )
19983                         : enable( 2884 );
19984
19985                 let flipSided = ( material.side === BackSide );
19986                 if ( frontFaceCW ) flipSided = ! flipSided;
19987
19988                 setFlipSided( flipSided );
19989
19990                 ( material.blending === NormalBlending && material.transparent === false )
19991                         ? setBlending( NoBlending )
19992                         : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
19993
19994                 depthBuffer.setFunc( material.depthFunc );
19995                 depthBuffer.setTest( material.depthTest );
19996                 depthBuffer.setMask( material.depthWrite );
19997                 colorBuffer.setMask( material.colorWrite );
19998
19999                 const stencilWrite = material.stencilWrite;
20000                 stencilBuffer.setTest( stencilWrite );
20001                 if ( stencilWrite ) {
20002
20003                         stencilBuffer.setMask( material.stencilWriteMask );
20004                         stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
20005                         stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
20006
20007                 }
20008
20009                 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
20010
20011         }
20012
20013         //
20014
20015         function setFlipSided( flipSided ) {
20016
20017                 if ( currentFlipSided !== flipSided ) {
20018
20019                         if ( flipSided ) {
20020
20021                                 gl.frontFace( 2304 );
20022
20023                         } else {
20024
20025                                 gl.frontFace( 2305 );
20026
20027                         }
20028
20029                         currentFlipSided = flipSided;
20030
20031                 }
20032
20033         }
20034
20035         function setCullFace( cullFace ) {
20036
20037                 if ( cullFace !== CullFaceNone ) {
20038
20039                         enable( 2884 );
20040
20041                         if ( cullFace !== currentCullFace ) {
20042
20043                                 if ( cullFace === CullFaceBack ) {
20044
20045                                         gl.cullFace( 1029 );
20046
20047                                 } else if ( cullFace === CullFaceFront ) {
20048
20049                                         gl.cullFace( 1028 );
20050
20051                                 } else {
20052
20053                                         gl.cullFace( 1032 );
20054
20055                                 }
20056
20057                         }
20058
20059                 } else {
20060
20061                         disable( 2884 );
20062
20063                 }
20064
20065                 currentCullFace = cullFace;
20066
20067         }
20068
20069         function setLineWidth( width ) {
20070
20071                 if ( width !== currentLineWidth ) {
20072
20073                         if ( lineWidthAvailable ) gl.lineWidth( width );
20074
20075                         currentLineWidth = width;
20076
20077                 }
20078
20079         }
20080
20081         function setPolygonOffset( polygonOffset, factor, units ) {
20082
20083                 if ( polygonOffset ) {
20084
20085                         enable( 32823 );
20086
20087                         if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
20088
20089                                 gl.polygonOffset( factor, units );
20090
20091                                 currentPolygonOffsetFactor = factor;
20092                                 currentPolygonOffsetUnits = units;
20093
20094                         }
20095
20096                 } else {
20097
20098                         disable( 32823 );
20099
20100                 }
20101
20102         }
20103
20104         function setScissorTest( scissorTest ) {
20105
20106                 if ( scissorTest ) {
20107
20108                         enable( 3089 );
20109
20110                 } else {
20111
20112                         disable( 3089 );
20113
20114                 }
20115
20116         }
20117
20118         // texture
20119
20120         function activeTexture( webglSlot ) {
20121
20122                 if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1;
20123
20124                 if ( currentTextureSlot !== webglSlot ) {
20125
20126                         gl.activeTexture( webglSlot );
20127                         currentTextureSlot = webglSlot;
20128
20129                 }
20130
20131         }
20132
20133         function bindTexture( webglType, webglTexture ) {
20134
20135                 if ( currentTextureSlot === null ) {
20136
20137                         activeTexture();
20138
20139                 }
20140
20141                 let boundTexture = currentBoundTextures[ currentTextureSlot ];
20142
20143                 if ( boundTexture === undefined ) {
20144
20145                         boundTexture = { type: undefined, texture: undefined };
20146                         currentBoundTextures[ currentTextureSlot ] = boundTexture;
20147
20148                 }
20149
20150                 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
20151
20152                         gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
20153
20154                         boundTexture.type = webglType;
20155                         boundTexture.texture = webglTexture;
20156
20157                 }
20158
20159         }
20160
20161         function unbindTexture() {
20162
20163                 const boundTexture = currentBoundTextures[ currentTextureSlot ];
20164
20165                 if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
20166
20167                         gl.bindTexture( boundTexture.type, null );
20168
20169                         boundTexture.type = undefined;
20170                         boundTexture.texture = undefined;
20171
20172                 }
20173
20174         }
20175
20176         function compressedTexImage2D() {
20177
20178                 try {
20179
20180                         gl.compressedTexImage2D.apply( gl, arguments );
20181
20182                 } catch ( error ) {
20183
20184                         console.error( 'THREE.WebGLState:', error );
20185
20186                 }
20187
20188         }
20189
20190         function texImage2D() {
20191
20192                 try {
20193
20194                         gl.texImage2D.apply( gl, arguments );
20195
20196                 } catch ( error ) {
20197
20198                         console.error( 'THREE.WebGLState:', error );
20199
20200                 }
20201
20202         }
20203
20204         function texImage3D() {
20205
20206                 try {
20207
20208                         gl.texImage3D.apply( gl, arguments );
20209
20210                 } catch ( error ) {
20211
20212                         console.error( 'THREE.WebGLState:', error );
20213
20214                 }
20215
20216         }
20217
20218         //
20219
20220         function scissor( scissor ) {
20221
20222                 if ( currentScissor.equals( scissor ) === false ) {
20223
20224                         gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
20225                         currentScissor.copy( scissor );
20226
20227                 }
20228
20229         }
20230
20231         function viewport( viewport ) {
20232
20233                 if ( currentViewport.equals( viewport ) === false ) {
20234
20235                         gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
20236                         currentViewport.copy( viewport );
20237
20238                 }
20239
20240         }
20241
20242         //
20243
20244         function reset() {
20245
20246                 enabledCapabilities = {};
20247
20248                 currentTextureSlot = null;
20249                 currentBoundTextures = {};
20250
20251                 currentProgram = null;
20252
20253                 currentBlendingEnabled = null;
20254                 currentBlending = null;
20255                 currentBlendEquation = null;
20256                 currentBlendSrc = null;
20257                 currentBlendDst = null;
20258                 currentBlendEquationAlpha = null;
20259                 currentBlendSrcAlpha = null;
20260                 currentBlendDstAlpha = null;
20261                 currentPremultipledAlpha = false;
20262
20263                 currentFlipSided = null;
20264                 currentCullFace = null;
20265
20266                 currentLineWidth = null;
20267
20268                 currentPolygonOffsetFactor = null;
20269                 currentPolygonOffsetUnits = null;
20270
20271                 colorBuffer.reset();
20272                 depthBuffer.reset();
20273                 stencilBuffer.reset();
20274
20275         }
20276
20277         return {
20278
20279                 buffers: {
20280                         color: colorBuffer,
20281                         depth: depthBuffer,
20282                         stencil: stencilBuffer
20283                 },
20284
20285                 enable: enable,
20286                 disable: disable,
20287
20288                 useProgram: useProgram,
20289
20290                 setBlending: setBlending,
20291                 setMaterial: setMaterial,
20292
20293                 setFlipSided: setFlipSided,
20294                 setCullFace: setCullFace,
20295
20296                 setLineWidth: setLineWidth,
20297                 setPolygonOffset: setPolygonOffset,
20298
20299                 setScissorTest: setScissorTest,
20300
20301                 activeTexture: activeTexture,
20302                 bindTexture: bindTexture,
20303                 unbindTexture: unbindTexture,
20304                 compressedTexImage2D: compressedTexImage2D,
20305                 texImage2D: texImage2D,
20306                 texImage3D: texImage3D,
20307
20308                 scissor: scissor,
20309                 viewport: viewport,
20310
20311                 reset: reset
20312
20313         };
20314
20315 }
20316
20317 function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
20318
20319         const isWebGL2 = capabilities.isWebGL2;
20320         const maxTextures = capabilities.maxTextures;
20321         const maxCubemapSize = capabilities.maxCubemapSize;
20322         const maxTextureSize = capabilities.maxTextureSize;
20323         const maxSamples = capabilities.maxSamples;
20324
20325         const _videoTextures = new WeakMap();
20326         let _canvas;
20327
20328         // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
20329         // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
20330         // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
20331
20332         let useOffscreenCanvas = false;
20333
20334         try {
20335
20336                 useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
20337                         && ( new OffscreenCanvas( 1, 1 ).getContext( "2d" ) ) !== null;
20338
20339         } catch ( err ) {
20340
20341                 // Ignore any errors
20342
20343         }
20344
20345         function createCanvas( width, height ) {
20346
20347                 // Use OffscreenCanvas when available. Specially needed in web workers
20348
20349                 return useOffscreenCanvas ?
20350                         new OffscreenCanvas( width, height ) :
20351                         document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
20352
20353         }
20354
20355         function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {
20356
20357                 let scale = 1;
20358
20359                 // handle case if texture exceeds max size
20360
20361                 if ( image.width > maxSize || image.height > maxSize ) {
20362
20363                         scale = maxSize / Math.max( image.width, image.height );
20364
20365                 }
20366
20367                 // only perform resize if necessary
20368
20369                 if ( scale < 1 || needsPowerOfTwo === true ) {
20370
20371                         // only perform resize for certain image types
20372
20373                         if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
20374                                 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
20375                                 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
20376
20377                                 const floor = needsPowerOfTwo ? MathUtils.floorPowerOfTwo : Math.floor;
20378
20379                                 const width = floor( scale * image.width );
20380                                 const height = floor( scale * image.height );
20381
20382                                 if ( _canvas === undefined ) _canvas = createCanvas( width, height );
20383
20384                                 // cube textures can't reuse the same canvas
20385
20386                                 const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
20387
20388                                 canvas.width = width;
20389                                 canvas.height = height;
20390
20391                                 const context = canvas.getContext( '2d' );
20392                                 context.drawImage( image, 0, 0, width, height );
20393
20394                                 console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );
20395
20396                                 return canvas;
20397
20398                         } else {
20399
20400                                 if ( 'data' in image ) {
20401
20402                                         console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
20403
20404                                 }
20405
20406                                 return image;
20407
20408                         }
20409
20410                 }
20411
20412                 return image;
20413
20414         }
20415
20416         function isPowerOfTwo( image ) {
20417
20418                 return MathUtils.isPowerOfTwo( image.width ) && MathUtils.isPowerOfTwo( image.height );
20419
20420         }
20421
20422         function textureNeedsPowerOfTwo( texture ) {
20423
20424                 if ( isWebGL2 ) return false;
20425
20426                 return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
20427                         ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
20428
20429         }
20430
20431         function textureNeedsGenerateMipmaps( texture, supportsMips ) {
20432
20433                 return texture.generateMipmaps && supportsMips &&
20434                         texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
20435
20436         }
20437
20438         function generateMipmap( target, texture, width, height ) {
20439
20440                 _gl.generateMipmap( target );
20441
20442                 const textureProperties = properties.get( texture );
20443
20444                 // Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
20445                 textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
20446
20447         }
20448
20449         function getInternalFormat( internalFormatName, glFormat, glType ) {
20450
20451                 if ( isWebGL2 === false ) return glFormat;
20452
20453                 if ( internalFormatName !== null ) {
20454
20455                         if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
20456
20457                         console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
20458
20459                 }
20460
20461                 let internalFormat = glFormat;
20462
20463                 if ( glFormat === 6403 ) {
20464
20465                         if ( glType === 5126 ) internalFormat = 33326;
20466                         if ( glType === 5131 ) internalFormat = 33325;
20467                         if ( glType === 5121 ) internalFormat = 33321;
20468
20469                 }
20470
20471                 if ( glFormat === 6407 ) {
20472
20473                         if ( glType === 5126 ) internalFormat = 34837;
20474                         if ( glType === 5131 ) internalFormat = 34843;
20475                         if ( glType === 5121 ) internalFormat = 32849;
20476
20477                 }
20478
20479                 if ( glFormat === 6408 ) {
20480
20481                         if ( glType === 5126 ) internalFormat = 34836;
20482                         if ( glType === 5131 ) internalFormat = 34842;
20483                         if ( glType === 5121 ) internalFormat = 32856;
20484
20485                 }
20486
20487                 if ( internalFormat === 33325 || internalFormat === 33326 ||
20488                         internalFormat === 34842 || internalFormat === 34836 ) {
20489
20490                         extensions.get( 'EXT_color_buffer_float' );
20491
20492                 }
20493
20494                 return internalFormat;
20495
20496         }
20497
20498         // Fallback filters for non-power-of-2 textures
20499
20500         function filterFallback( f ) {
20501
20502                 if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {
20503
20504                         return 9728;
20505
20506                 }
20507
20508                 return 9729;
20509
20510         }
20511
20512         //
20513
20514         function onTextureDispose( event ) {
20515
20516                 const texture = event.target;
20517
20518                 texture.removeEventListener( 'dispose', onTextureDispose );
20519
20520                 deallocateTexture( texture );
20521
20522                 if ( texture.isVideoTexture ) {
20523
20524                         _videoTextures.delete( texture );
20525
20526                 }
20527
20528                 info.memory.textures --;
20529
20530         }
20531
20532         function onRenderTargetDispose( event ) {
20533
20534                 const renderTarget = event.target;
20535
20536                 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
20537
20538                 deallocateRenderTarget( renderTarget );
20539
20540                 info.memory.textures --;
20541
20542         }
20543
20544         //
20545
20546         function deallocateTexture( texture ) {
20547
20548                 const textureProperties = properties.get( texture );
20549
20550                 if ( textureProperties.__webglInit === undefined ) return;
20551
20552                 _gl.deleteTexture( textureProperties.__webglTexture );
20553
20554                 properties.remove( texture );
20555
20556         }
20557
20558         function deallocateRenderTarget( renderTarget ) {
20559
20560                 const renderTargetProperties = properties.get( renderTarget );
20561                 const textureProperties = properties.get( renderTarget.texture );
20562
20563                 if ( ! renderTarget ) return;
20564
20565                 if ( textureProperties.__webglTexture !== undefined ) {
20566
20567                         _gl.deleteTexture( textureProperties.__webglTexture );
20568
20569                 }
20570
20571                 if ( renderTarget.depthTexture ) {
20572
20573                         renderTarget.depthTexture.dispose();
20574
20575                 }
20576
20577                 if ( renderTarget.isWebGLCubeRenderTarget ) {
20578
20579                         for ( let i = 0; i < 6; i ++ ) {
20580
20581                                 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
20582                                 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
20583
20584                         }
20585
20586                 } else {
20587
20588                         _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
20589                         if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
20590                         if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
20591                         if ( renderTargetProperties.__webglColorRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer );
20592                         if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
20593
20594                 }
20595
20596                 properties.remove( renderTarget.texture );
20597                 properties.remove( renderTarget );
20598
20599         }
20600
20601         //
20602
20603         let textureUnits = 0;
20604
20605         function resetTextureUnits() {
20606
20607                 textureUnits = 0;
20608
20609         }
20610
20611         function allocateTextureUnit() {
20612
20613                 const textureUnit = textureUnits;
20614
20615                 if ( textureUnit >= maxTextures ) {
20616
20617                         console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );
20618
20619                 }
20620
20621                 textureUnits += 1;
20622
20623                 return textureUnit;
20624
20625         }
20626
20627         //
20628
20629         function setTexture2D( texture, slot ) {
20630
20631                 const textureProperties = properties.get( texture );
20632
20633                 if ( texture.isVideoTexture ) updateVideoTexture( texture );
20634
20635                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20636
20637                         const image = texture.image;
20638
20639                         if ( image === undefined ) {
20640
20641                                 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );
20642
20643                         } else if ( image.complete === false ) {
20644
20645                                 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
20646
20647                         } else {
20648
20649                                 uploadTexture( textureProperties, texture, slot );
20650                                 return;
20651
20652                         }
20653
20654                 }
20655
20656                 state.activeTexture( 33984 + slot );
20657                 state.bindTexture( 3553, textureProperties.__webglTexture );
20658
20659         }
20660
20661         function setTexture2DArray( texture, slot ) {
20662
20663                 const textureProperties = properties.get( texture );
20664
20665                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20666
20667                         uploadTexture( textureProperties, texture, slot );
20668                         return;
20669
20670                 }
20671
20672                 state.activeTexture( 33984 + slot );
20673                 state.bindTexture( 35866, textureProperties.__webglTexture );
20674
20675         }
20676
20677         function setTexture3D( texture, slot ) {
20678
20679                 const textureProperties = properties.get( texture );
20680
20681                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20682
20683                         uploadTexture( textureProperties, texture, slot );
20684                         return;
20685
20686                 }
20687
20688                 state.activeTexture( 33984 + slot );
20689                 state.bindTexture( 32879, textureProperties.__webglTexture );
20690
20691         }
20692
20693         function setTextureCube( texture, slot ) {
20694
20695                 const textureProperties = properties.get( texture );
20696
20697                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20698
20699                         uploadCubeTexture( textureProperties, texture, slot );
20700                         return;
20701
20702                 }
20703
20704                 state.activeTexture( 33984 + slot );
20705                 state.bindTexture( 34067, textureProperties.__webglTexture );
20706
20707         }
20708
20709         const wrappingToGL = {
20710                 [ RepeatWrapping ]: 10497,
20711                 [ ClampToEdgeWrapping ]: 33071,
20712                 [ MirroredRepeatWrapping ]: 33648
20713         };
20714
20715         const filterToGL = {
20716                 [ NearestFilter ]: 9728,
20717                 [ NearestMipmapNearestFilter ]: 9984,
20718                 [ NearestMipmapLinearFilter ]: 9986,
20719
20720                 [ LinearFilter ]: 9729,
20721                 [ LinearMipmapNearestFilter ]: 9985,
20722                 [ LinearMipmapLinearFilter ]: 9987
20723         };
20724
20725         function setTextureParameters( textureType, texture, supportsMips ) {
20726
20727                 if ( supportsMips ) {
20728
20729                         _gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] );
20730                         _gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] );
20731
20732                         if ( textureType === 32879 || textureType === 35866 ) {
20733
20734                                 _gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] );
20735
20736                         }
20737
20738                         _gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] );
20739                         _gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] );
20740
20741                 } else {
20742
20743                         _gl.texParameteri( textureType, 10242, 33071 );
20744                         _gl.texParameteri( textureType, 10243, 33071 );
20745
20746                         if ( textureType === 32879 || textureType === 35866 ) {
20747
20748                                 _gl.texParameteri( textureType, 32882, 33071 );
20749
20750                         }
20751
20752                         if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
20753
20754                                 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
20755
20756                         }
20757
20758                         _gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );
20759                         _gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );
20760
20761                         if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
20762
20763                                 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
20764
20765                         }
20766
20767                 }
20768
20769                 const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
20770
20771                 if ( extension ) {
20772
20773                         if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
20774                         if ( texture.type === HalfFloatType && ( isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
20775
20776                         if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
20777
20778                                 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
20779                                 properties.get( texture ).__currentAnisotropy = texture.anisotropy;
20780
20781                         }
20782
20783                 }
20784
20785         }
20786
20787         function initTexture( textureProperties, texture ) {
20788
20789                 if ( textureProperties.__webglInit === undefined ) {
20790
20791                         textureProperties.__webglInit = true;
20792
20793                         texture.addEventListener( 'dispose', onTextureDispose );
20794
20795                         textureProperties.__webglTexture = _gl.createTexture();
20796
20797                         info.memory.textures ++;
20798
20799                 }
20800
20801         }
20802
20803         function uploadTexture( textureProperties, texture, slot ) {
20804
20805                 let textureType = 3553;
20806
20807                 if ( texture.isDataTexture2DArray ) textureType = 35866;
20808                 if ( texture.isDataTexture3D ) textureType = 32879;
20809
20810                 initTexture( textureProperties, texture );
20811
20812                 state.activeTexture( 33984 + slot );
20813                 state.bindTexture( textureType, textureProperties.__webglTexture );
20814
20815                 _gl.pixelStorei( 37440, texture.flipY );
20816                 _gl.pixelStorei( 37441, texture.premultiplyAlpha );
20817                 _gl.pixelStorei( 3317, texture.unpackAlignment );
20818
20819                 const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;
20820                 const image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );
20821
20822                 const supportsMips = isPowerOfTwo( image ) || isWebGL2,
20823                         glFormat = utils.convert( texture.format );
20824
20825                 let glType = utils.convert( texture.type ),
20826                         glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
20827
20828                 setTextureParameters( textureType, texture, supportsMips );
20829
20830                 let mipmap;
20831                 const mipmaps = texture.mipmaps;
20832
20833                 if ( texture.isDepthTexture ) {
20834
20835                         // populate depth texture with dummy data
20836
20837                         glInternalFormat = 6402;
20838
20839                         if ( isWebGL2 ) {
20840
20841                                 if ( texture.type === FloatType ) {
20842
20843                                         glInternalFormat = 36012;
20844
20845                                 } else if ( texture.type === UnsignedIntType ) {
20846
20847                                         glInternalFormat = 33190;
20848
20849                                 } else if ( texture.type === UnsignedInt248Type ) {
20850
20851                                         glInternalFormat = 35056;
20852
20853                                 } else {
20854
20855                                         glInternalFormat = 33189; // WebGL2 requires sized internalformat for glTexImage2D
20856
20857                                 }
20858
20859                         } else {
20860
20861                                 if ( texture.type === FloatType ) {
20862
20863                                         console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );
20864
20865                                 }
20866
20867                         }
20868
20869                         // validation checks for WebGL 1
20870
20871                         if ( texture.format === DepthFormat && glInternalFormat === 6402 ) {
20872
20873                                 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20874                                 // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
20875                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20876                                 if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
20877
20878                                         console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
20879
20880                                         texture.type = UnsignedShortType;
20881                                         glType = utils.convert( texture.type );
20882
20883                                 }
20884
20885                         }
20886
20887                         if ( texture.format === DepthStencilFormat && glInternalFormat === 6402 ) {
20888
20889                                 // Depth stencil textures need the DEPTH_STENCIL internal format
20890                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20891                                 glInternalFormat = 34041;
20892
20893                                 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20894                                 // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
20895                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20896                                 if ( texture.type !== UnsignedInt248Type ) {
20897
20898                                         console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
20899
20900                                         texture.type = UnsignedInt248Type;
20901                                         glType = utils.convert( texture.type );
20902
20903                                 }
20904
20905                         }
20906
20907                         //
20908
20909                         state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
20910
20911                 } else if ( texture.isDataTexture ) {
20912
20913                         // use manually created mipmaps if available
20914                         // if there are no manual mipmaps
20915                         // set 0 level mipmap and then use GL to generate other mipmap levels
20916
20917                         if ( mipmaps.length > 0 && supportsMips ) {
20918
20919                                 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
20920
20921                                         mipmap = mipmaps[ i ];
20922                                         state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20923
20924                                 }
20925
20926                                 texture.generateMipmaps = false;
20927                                 textureProperties.__maxMipLevel = mipmaps.length - 1;
20928
20929                         } else {
20930
20931                                 state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
20932                                 textureProperties.__maxMipLevel = 0;
20933
20934                         }
20935
20936                 } else if ( texture.isCompressedTexture ) {
20937
20938                         for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
20939
20940                                 mipmap = mipmaps[ i ];
20941
20942                                 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
20943
20944                                         if ( glFormat !== null ) {
20945
20946                                                 state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
20947
20948                                         } else {
20949
20950                                                 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
20951
20952                                         }
20953
20954                                 } else {
20955
20956                                         state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20957
20958                                 }
20959
20960                         }
20961
20962                         textureProperties.__maxMipLevel = mipmaps.length - 1;
20963
20964                 } else if ( texture.isDataTexture2DArray ) {
20965
20966                         state.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
20967                         textureProperties.__maxMipLevel = 0;
20968
20969                 } else if ( texture.isDataTexture3D ) {
20970
20971                         state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
20972                         textureProperties.__maxMipLevel = 0;
20973
20974                 } else {
20975
20976                         // regular Texture (image, video, canvas)
20977
20978                         // use manually created mipmaps if available
20979                         // if there are no manual mipmaps
20980                         // set 0 level mipmap and then use GL to generate other mipmap levels
20981
20982                         if ( mipmaps.length > 0 && supportsMips ) {
20983
20984                                 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
20985
20986                                         mipmap = mipmaps[ i ];
20987                                         state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );
20988
20989                                 }
20990
20991                                 texture.generateMipmaps = false;
20992                                 textureProperties.__maxMipLevel = mipmaps.length - 1;
20993
20994                         } else {
20995
20996                                 state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );
20997                                 textureProperties.__maxMipLevel = 0;
20998
20999                         }
21000
21001                 }
21002
21003                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
21004
21005                         generateMipmap( textureType, texture, image.width, image.height );
21006
21007                 }
21008
21009                 textureProperties.__version = texture.version;
21010
21011                 if ( texture.onUpdate ) texture.onUpdate( texture );
21012
21013         }
21014
21015         function uploadCubeTexture( textureProperties, texture, slot ) {
21016
21017                 if ( texture.image.length !== 6 ) return;
21018
21019                 initTexture( textureProperties, texture );
21020
21021                 state.activeTexture( 33984 + slot );
21022                 state.bindTexture( 34067, textureProperties.__webglTexture );
21023
21024                 _gl.pixelStorei( 37440, texture.flipY );
21025
21026                 const isCompressed = ( texture && ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ) );
21027                 const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
21028
21029                 const cubeImage = [];
21030
21031                 for ( let i = 0; i < 6; i ++ ) {
21032
21033                         if ( ! isCompressed && ! isDataTexture ) {
21034
21035                                 cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );
21036
21037                         } else {
21038
21039                                 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
21040
21041                         }
21042
21043                 }
21044
21045                 const image = cubeImage[ 0 ],
21046                         supportsMips = isPowerOfTwo( image ) || isWebGL2,
21047                         glFormat = utils.convert( texture.format ),
21048                         glType = utils.convert( texture.type ),
21049                         glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
21050
21051                 setTextureParameters( 34067, texture, supportsMips );
21052
21053                 let mipmaps;
21054
21055                 if ( isCompressed ) {
21056
21057                         for ( let i = 0; i < 6; i ++ ) {
21058
21059                                 mipmaps = cubeImage[ i ].mipmaps;
21060
21061                                 for ( let j = 0; j < mipmaps.length; j ++ ) {
21062
21063                                         const mipmap = mipmaps[ j ];
21064
21065                                         if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
21066
21067                                                 if ( glFormat !== null ) {
21068
21069                                                         state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
21070
21071                                                 } else {
21072
21073                                                         console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
21074
21075                                                 }
21076
21077                                         } else {
21078
21079                                                 state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
21080
21081                                         }
21082
21083                                 }
21084
21085                         }
21086
21087                         textureProperties.__maxMipLevel = mipmaps.length - 1;
21088
21089                 } else {
21090
21091                         mipmaps = texture.mipmaps;
21092
21093                         for ( let i = 0; i < 6; i ++ ) {
21094
21095                                 if ( isDataTexture ) {
21096
21097                                         state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
21098
21099                                         for ( let j = 0; j < mipmaps.length; j ++ ) {
21100
21101                                                 const mipmap = mipmaps[ j ];
21102                                                 const mipmapImage = mipmap.image[ i ].image;
21103
21104                                                 state.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
21105
21106                                         }
21107
21108                                 } else {
21109
21110                                         state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
21111
21112                                         for ( let j = 0; j < mipmaps.length; j ++ ) {
21113
21114                                                 const mipmap = mipmaps[ j ];
21115
21116                                                 state.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
21117
21118                                         }
21119
21120                                 }
21121
21122                         }
21123
21124                         textureProperties.__maxMipLevel = mipmaps.length;
21125
21126                 }
21127
21128                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
21129
21130                         // We assume images for cube map have the same size.
21131                         generateMipmap( 34067, texture, image.width, image.height );
21132
21133                 }
21134
21135                 textureProperties.__version = texture.version;
21136
21137                 if ( texture.onUpdate ) texture.onUpdate( texture );
21138
21139         }
21140
21141         // Render targets
21142
21143         // Setup storage for target texture and bind it to correct framebuffer
21144         function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
21145
21146                 const glFormat = utils.convert( renderTarget.texture.format );
21147                 const glType = utils.convert( renderTarget.texture.type );
21148                 const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
21149                 state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
21150                 _gl.bindFramebuffer( 36160, framebuffer );
21151                 _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
21152                 _gl.bindFramebuffer( 36160, null );
21153
21154         }
21155
21156         // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
21157         function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
21158
21159                 _gl.bindRenderbuffer( 36161, renderbuffer );
21160
21161                 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
21162
21163                         let glInternalFormat = 33189;
21164
21165                         if ( isMultisample ) {
21166
21167                                 const depthTexture = renderTarget.depthTexture;
21168
21169                                 if ( depthTexture && depthTexture.isDepthTexture ) {
21170
21171                                         if ( depthTexture.type === FloatType ) {
21172
21173                                                 glInternalFormat = 36012;
21174
21175                                         } else if ( depthTexture.type === UnsignedIntType ) {
21176
21177                                                 glInternalFormat = 33190;
21178
21179                                         }
21180
21181                                 }
21182
21183                                 const samples = getRenderTargetSamples( renderTarget );
21184
21185                                 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
21186
21187                         } else {
21188
21189                                 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
21190
21191                         }
21192
21193                         _gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );
21194
21195                 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
21196
21197                         if ( isMultisample ) {
21198
21199                                 const samples = getRenderTargetSamples( renderTarget );
21200
21201                                 _gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height );
21202
21203                         } else {
21204
21205                                 _gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );
21206
21207                         }
21208
21209
21210                         _gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );
21211
21212                 } else {
21213
21214                         const glFormat = utils.convert( renderTarget.texture.format );
21215                         const glType = utils.convert( renderTarget.texture.type );
21216                         const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
21217
21218                         if ( isMultisample ) {
21219
21220                                 const samples = getRenderTargetSamples( renderTarget );
21221
21222                                 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
21223
21224                         } else {
21225
21226                                 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
21227
21228                         }
21229
21230                 }
21231
21232                 _gl.bindRenderbuffer( 36161, null );
21233
21234         }
21235
21236         // Setup resources for a Depth Texture for a FBO (needs an extension)
21237         function setupDepthTexture( framebuffer, renderTarget ) {
21238
21239                 const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
21240                 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
21241
21242                 _gl.bindFramebuffer( 36160, framebuffer );
21243
21244                 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
21245
21246                         throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
21247
21248                 }
21249
21250                 // upload an empty depth texture with framebuffer size
21251                 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
21252                                 renderTarget.depthTexture.image.width !== renderTarget.width ||
21253                                 renderTarget.depthTexture.image.height !== renderTarget.height ) {
21254
21255                         renderTarget.depthTexture.image.width = renderTarget.width;
21256                         renderTarget.depthTexture.image.height = renderTarget.height;
21257                         renderTarget.depthTexture.needsUpdate = true;
21258
21259                 }
21260
21261                 setTexture2D( renderTarget.depthTexture, 0 );
21262
21263                 const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
21264
21265                 if ( renderTarget.depthTexture.format === DepthFormat ) {
21266
21267                         _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );
21268
21269                 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
21270
21271                         _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );
21272
21273                 } else {
21274
21275                         throw new Error( 'Unknown depthTexture format' );
21276
21277                 }
21278
21279         }
21280
21281         // Setup GL resources for a non-texture depth buffer
21282         function setupDepthRenderbuffer( renderTarget ) {
21283
21284                 const renderTargetProperties = properties.get( renderTarget );
21285
21286                 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
21287
21288                 if ( renderTarget.depthTexture ) {
21289
21290                         if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
21291
21292                         setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
21293
21294                 } else {
21295
21296                         if ( isCube ) {
21297
21298                                 renderTargetProperties.__webglDepthbuffer = [];
21299
21300                                 for ( let i = 0; i < 6; i ++ ) {
21301
21302                                         _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );
21303                                         renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
21304                                         setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );
21305
21306                                 }
21307
21308                         } else {
21309
21310                                 _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
21311                                 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
21312                                 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );
21313
21314                         }
21315
21316                 }
21317
21318                 _gl.bindFramebuffer( 36160, null );
21319
21320         }
21321
21322         // Set up GL resources for the render target
21323         function setupRenderTarget( renderTarget ) {
21324
21325                 const renderTargetProperties = properties.get( renderTarget );
21326                 const textureProperties = properties.get( renderTarget.texture );
21327
21328                 renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
21329
21330                 textureProperties.__webglTexture = _gl.createTexture();
21331
21332                 info.memory.textures ++;
21333
21334                 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
21335                 const isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );
21336                 const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
21337
21338                 // Handles WebGL2 RGBFormat fallback - #18858
21339
21340                 if ( isWebGL2 && renderTarget.texture.format === RGBFormat && ( renderTarget.texture.type === FloatType || renderTarget.texture.type === HalfFloatType ) ) {
21341
21342                         renderTarget.texture.format = RGBAFormat;
21343
21344                         console.warn( 'THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.' );
21345
21346                 }
21347
21348                 // Setup framebuffer
21349
21350                 if ( isCube ) {
21351
21352                         renderTargetProperties.__webglFramebuffer = [];
21353
21354                         for ( let i = 0; i < 6; i ++ ) {
21355
21356                                 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
21357
21358                         }
21359
21360                 } else {
21361
21362                         renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
21363
21364                         if ( isMultisample ) {
21365
21366                                 if ( isWebGL2 ) {
21367
21368                                         renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
21369                                         renderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();
21370
21371                                         _gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer );
21372
21373                                         const glFormat = utils.convert( renderTarget.texture.format );
21374                                         const glType = utils.convert( renderTarget.texture.type );
21375                                         const glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
21376                                         const samples = getRenderTargetSamples( renderTarget );
21377                                         _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
21378
21379                                         _gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
21380                                         _gl.framebufferRenderbuffer( 36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer );
21381                                         _gl.bindRenderbuffer( 36161, null );
21382
21383                                         if ( renderTarget.depthBuffer ) {
21384
21385                                                 renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
21386                                                 setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
21387
21388                                         }
21389
21390                                         _gl.bindFramebuffer( 36160, null );
21391
21392
21393                                 } else {
21394
21395                                         console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
21396
21397                                 }
21398
21399                         }
21400
21401                 }
21402
21403                 // Setup color buffer
21404
21405                 if ( isCube ) {
21406
21407                         state.bindTexture( 34067, textureProperties.__webglTexture );
21408                         setTextureParameters( 34067, renderTarget.texture, supportsMips );
21409
21410                         for ( let i = 0; i < 6; i ++ ) {
21411
21412                                 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, 36064, 34069 + i );
21413
21414                         }
21415
21416                         if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
21417
21418                                 generateMipmap( 34067, renderTarget.texture, renderTarget.width, renderTarget.height );
21419
21420                         }
21421
21422                         state.bindTexture( 34067, null );
21423
21424                 } else {
21425
21426                         state.bindTexture( 3553, textureProperties.__webglTexture );
21427                         setTextureParameters( 3553, renderTarget.texture, supportsMips );
21428                         setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, 36064, 3553 );
21429
21430                         if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
21431
21432                                 generateMipmap( 3553, renderTarget.texture, renderTarget.width, renderTarget.height );
21433
21434                         }
21435
21436                         state.bindTexture( 3553, null );
21437
21438                 }
21439
21440                 // Setup depth and stencil buffers
21441
21442                 if ( renderTarget.depthBuffer ) {
21443
21444                         setupDepthRenderbuffer( renderTarget );
21445
21446                 }
21447
21448         }
21449
21450         function updateRenderTargetMipmap( renderTarget ) {
21451
21452                 const texture = renderTarget.texture;
21453                 const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
21454
21455                 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
21456
21457                         const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553;
21458                         const webglTexture = properties.get( texture ).__webglTexture;
21459
21460                         state.bindTexture( target, webglTexture );
21461                         generateMipmap( target, texture, renderTarget.width, renderTarget.height );
21462                         state.bindTexture( target, null );
21463
21464                 }
21465
21466         }
21467
21468         function updateMultisampleRenderTarget( renderTarget ) {
21469
21470                 if ( renderTarget.isWebGLMultisampleRenderTarget ) {
21471
21472                         if ( isWebGL2 ) {
21473
21474                                 const renderTargetProperties = properties.get( renderTarget );
21475
21476                                 _gl.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );
21477                                 _gl.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );
21478
21479                                 const width = renderTarget.width;
21480                                 const height = renderTarget.height;
21481                                 let mask = 16384;
21482
21483                                 if ( renderTarget.depthBuffer ) mask |= 256;
21484                                 if ( renderTarget.stencilBuffer ) mask |= 1024;
21485
21486                                 _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );
21487
21488                                 _gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); // see #18905
21489
21490                         } else {
21491
21492                                 console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
21493
21494                         }
21495
21496                 }
21497
21498         }
21499
21500         function getRenderTargetSamples( renderTarget ) {
21501
21502                 return ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?
21503                         Math.min( maxSamples, renderTarget.samples ) : 0;
21504
21505         }
21506
21507         function updateVideoTexture( texture ) {
21508
21509                 const frame = info.render.frame;
21510
21511                 // Check the last frame we updated the VideoTexture
21512
21513                 if ( _videoTextures.get( texture ) !== frame ) {
21514
21515                         _videoTextures.set( texture, frame );
21516                         texture.update();
21517
21518                 }
21519
21520         }
21521
21522         // backwards compatibility
21523
21524         let warnedTexture2D = false;
21525         let warnedTextureCube = false;
21526
21527         function safeSetTexture2D( texture, slot ) {
21528
21529                 if ( texture && texture.isWebGLRenderTarget ) {
21530
21531                         if ( warnedTexture2D === false ) {
21532
21533                                 console.warn( "THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead." );
21534                                 warnedTexture2D = true;
21535
21536                         }
21537
21538                         texture = texture.texture;
21539
21540                 }
21541
21542                 setTexture2D( texture, slot );
21543
21544         }
21545
21546         function safeSetTextureCube( texture, slot ) {
21547
21548                 if ( texture && texture.isWebGLCubeRenderTarget ) {
21549
21550                         if ( warnedTextureCube === false ) {
21551
21552                                 console.warn( "THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead." );
21553                                 warnedTextureCube = true;
21554
21555                         }
21556
21557                         texture = texture.texture;
21558
21559                 }
21560
21561
21562                 setTextureCube( texture, slot );
21563
21564         }
21565
21566         //
21567
21568         this.allocateTextureUnit = allocateTextureUnit;
21569         this.resetTextureUnits = resetTextureUnits;
21570
21571         this.setTexture2D = setTexture2D;
21572         this.setTexture2DArray = setTexture2DArray;
21573         this.setTexture3D = setTexture3D;
21574         this.setTextureCube = setTextureCube;
21575         this.setupRenderTarget = setupRenderTarget;
21576         this.updateRenderTargetMipmap = updateRenderTargetMipmap;
21577         this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
21578
21579         this.safeSetTexture2D = safeSetTexture2D;
21580         this.safeSetTextureCube = safeSetTextureCube;
21581
21582 }
21583
21584 function WebGLUtils( gl, extensions, capabilities ) {
21585
21586         const isWebGL2 = capabilities.isWebGL2;
21587
21588         function convert( p ) {
21589
21590                 let extension;
21591
21592                 if ( p === UnsignedByteType ) return 5121;
21593                 if ( p === UnsignedShort4444Type ) return 32819;
21594                 if ( p === UnsignedShort5551Type ) return 32820;
21595                 if ( p === UnsignedShort565Type ) return 33635;
21596
21597                 if ( p === ByteType ) return 5120;
21598                 if ( p === ShortType ) return 5122;
21599                 if ( p === UnsignedShortType ) return 5123;
21600                 if ( p === IntType ) return 5124;
21601                 if ( p === UnsignedIntType ) return 5125;
21602                 if ( p === FloatType ) return 5126;
21603
21604                 if ( p === HalfFloatType ) {
21605
21606                         if ( isWebGL2 ) return 5131;
21607
21608                         extension = extensions.get( 'OES_texture_half_float' );
21609
21610                         if ( extension !== null ) {
21611
21612                                 return extension.HALF_FLOAT_OES;
21613
21614                         } else {
21615
21616                                 return null;
21617
21618                         }
21619
21620                 }
21621
21622                 if ( p === AlphaFormat ) return 6406;
21623                 if ( p === RGBFormat ) return 6407;
21624                 if ( p === RGBAFormat ) return 6408;
21625                 if ( p === LuminanceFormat ) return 6409;
21626                 if ( p === LuminanceAlphaFormat ) return 6410;
21627                 if ( p === DepthFormat ) return 6402;
21628                 if ( p === DepthStencilFormat ) return 34041;
21629                 if ( p === RedFormat ) return 6403;
21630
21631                 // WebGL2 formats.
21632
21633                 if ( p === RedIntegerFormat ) return 36244;
21634                 if ( p === RGFormat ) return 33319;
21635                 if ( p === RGIntegerFormat ) return 33320;
21636                 if ( p === RGBIntegerFormat ) return 36248;
21637                 if ( p === RGBAIntegerFormat ) return 36249;
21638
21639                 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
21640                         p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
21641
21642                         extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
21643
21644                         if ( extension !== null ) {
21645
21646                                 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
21647                                 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
21648                                 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
21649                                 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
21650
21651                         } else {
21652
21653                                 return null;
21654
21655                         }
21656
21657                 }
21658
21659                 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
21660                         p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
21661
21662                         extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
21663
21664                         if ( extension !== null ) {
21665
21666                                 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
21667                                 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
21668                                 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
21669                                 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
21670
21671                         } else {
21672
21673                                 return null;
21674
21675                         }
21676
21677                 }
21678
21679                 if ( p === RGB_ETC1_Format ) {
21680
21681                         extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
21682
21683                         if ( extension !== null ) {
21684
21685                                 return extension.COMPRESSED_RGB_ETC1_WEBGL;
21686
21687                         } else {
21688
21689                                 return null;
21690
21691                         }
21692
21693                 }
21694
21695                 if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {
21696
21697                         extension = extensions.get( 'WEBGL_compressed_texture_etc' );
21698
21699                         if ( extension !== null ) {
21700
21701                                 if ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2;
21702                                 if ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC;
21703
21704                         }
21705
21706                 }
21707
21708                 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
21709                         p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
21710                         p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
21711                         p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
21712                         p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ||
21713                         p === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format ||
21714                         p === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format ||
21715                         p === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format ||
21716                         p === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format ||
21717                         p === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) {
21718
21719                         extension = extensions.get( 'WEBGL_compressed_texture_astc' );
21720
21721                         if ( extension !== null ) {
21722
21723                                 // TODO Complete?
21724
21725                                 return p;
21726
21727                         } else {
21728
21729                                 return null;
21730
21731                         }
21732
21733                 }
21734
21735                 if ( p === RGBA_BPTC_Format ) {
21736
21737                         extension = extensions.get( 'EXT_texture_compression_bptc' );
21738
21739                         if ( extension !== null ) {
21740
21741                                 // TODO Complete?
21742
21743                                 return p;
21744
21745                         } else {
21746
21747                                 return null;
21748
21749                         }
21750
21751                 }
21752
21753                 if ( p === UnsignedInt248Type ) {
21754
21755                         if ( isWebGL2 ) return 34042;
21756
21757                         extension = extensions.get( 'WEBGL_depth_texture' );
21758
21759                         if ( extension !== null ) {
21760
21761                                 return extension.UNSIGNED_INT_24_8_WEBGL;
21762
21763                         } else {
21764
21765                                 return null;
21766
21767                         }
21768
21769                 }
21770
21771         }
21772
21773         return { convert: convert };
21774
21775 }
21776
21777 function ArrayCamera( array = [] ) {
21778
21779         PerspectiveCamera.call( this );
21780
21781         this.cameras = array;
21782
21783 }
21784
21785 ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
21786
21787         constructor: ArrayCamera,
21788
21789         isArrayCamera: true
21790
21791 } );
21792
21793 function Group() {
21794
21795         Object3D.call( this );
21796
21797         this.type = 'Group';
21798
21799 }
21800
21801 Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
21802
21803         constructor: Group,
21804
21805         isGroup: true
21806
21807 } );
21808
21809 function WebXRController() {
21810
21811         this._targetRay = null;
21812         this._grip = null;
21813         this._hand = null;
21814
21815 }
21816
21817 Object.assign( WebXRController.prototype, {
21818
21819         constructor: WebXRController,
21820
21821         getHandSpace: function () {
21822
21823                 if ( this._hand === null ) {
21824
21825                         this._hand = new Group();
21826                         this._hand.matrixAutoUpdate = false;
21827                         this._hand.visible = false;
21828
21829                         this._hand.joints = [];
21830                         this._hand.inputState = { pinching: false };
21831
21832                         if ( window.XRHand ) {
21833
21834                                 for ( let i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i ++ ) {
21835
21836                                         // The transform of this joint will be updated with the joint pose on each frame
21837                                         const joint = new Group();
21838                                         joint.matrixAutoUpdate = false;
21839                                         joint.visible = false;
21840                                         this._hand.joints.push( joint );
21841                                         // ??
21842                                         this._hand.add( joint );
21843
21844                                 }
21845
21846                         }
21847
21848                 }
21849
21850                 return this._hand;
21851
21852         },
21853
21854         getTargetRaySpace: function () {
21855
21856                 if ( this._targetRay === null ) {
21857
21858                         this._targetRay = new Group();
21859                         this._targetRay.matrixAutoUpdate = false;
21860                         this._targetRay.visible = false;
21861
21862                 }
21863
21864                 return this._targetRay;
21865
21866         },
21867
21868         getGripSpace: function () {
21869
21870                 if ( this._grip === null ) {
21871
21872                         this._grip = new Group();
21873                         this._grip.matrixAutoUpdate = false;
21874                         this._grip.visible = false;
21875
21876                 }
21877
21878                 return this._grip;
21879
21880         },
21881
21882         dispatchEvent: function ( event ) {
21883
21884                 if ( this._targetRay !== null ) {
21885
21886                         this._targetRay.dispatchEvent( event );
21887
21888                 }
21889
21890                 if ( this._grip !== null ) {
21891
21892                         this._grip.dispatchEvent( event );
21893
21894                 }
21895
21896                 if ( this._hand !== null ) {
21897
21898                         this._hand.dispatchEvent( event );
21899
21900                 }
21901
21902                 return this;
21903
21904         },
21905
21906         disconnect: function ( inputSource ) {
21907
21908                 this.dispatchEvent( { type: 'disconnected', data: inputSource } );
21909
21910                 if ( this._targetRay !== null ) {
21911
21912                         this._targetRay.visible = false;
21913
21914                 }
21915
21916                 if ( this._grip !== null ) {
21917
21918                         this._grip.visible = false;
21919
21920                 }
21921
21922                 if ( this._hand !== null ) {
21923
21924                         this._hand.visible = false;
21925
21926                 }
21927
21928                 return this;
21929
21930         },
21931
21932         update: function ( inputSource, frame, referenceSpace ) {
21933
21934                 let inputPose = null;
21935                 let gripPose = null;
21936                 let handPose = null;
21937
21938                 const targetRay = this._targetRay;
21939                 const grip = this._grip;
21940                 const hand = this._hand;
21941
21942                 if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
21943
21944                         if ( hand && inputSource.hand ) {
21945
21946                                 handPose = true;
21947
21948                                 for ( let i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i ++ ) {
21949
21950                                         if ( inputSource.hand[ i ] ) {
21951
21952                                                 // Update the joints groups with the XRJoint poses
21953                                                 const jointPose = frame.getJointPose( inputSource.hand[ i ], referenceSpace );
21954                                                 const joint = hand.joints[ i ];
21955
21956                                                 if ( jointPose !== null ) {
21957
21958                                                         joint.matrix.fromArray( jointPose.transform.matrix );
21959                                                         joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
21960                                                         joint.jointRadius = jointPose.radius;
21961
21962                                                 }
21963
21964                                                 joint.visible = jointPose !== null;
21965
21966                                                 // Custom events
21967
21968                                                 // Check pinch
21969                                                 const indexTip = hand.joints[ window.XRHand.INDEX_PHALANX_TIP ];
21970                                                 const thumbTip = hand.joints[ window.XRHand.THUMB_PHALANX_TIP ];
21971                                                 const distance = indexTip.position.distanceTo( thumbTip.position );
21972
21973                                                 const distanceToPinch = 0.02;
21974                                                 const threshold = 0.005;
21975
21976                                                 if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
21977
21978                                                         hand.inputState.pinching = false;
21979                                                         this.dispatchEvent( {
21980                                                                 type: "pinchend",
21981                                                                 handedness: inputSource.handedness,
21982                                                                 target: this
21983                                                         } );
21984
21985                                                 } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
21986
21987                                                         hand.inputState.pinching = true;
21988                                                         this.dispatchEvent( {
21989                                                                 type: "pinchstart",
21990                                                                 handedness: inputSource.handedness,
21991                                                                 target: this
21992                                                         } );
21993
21994                                                 }
21995
21996                                         }
21997
21998                                 }
21999
22000                         } else {
22001
22002                                 if ( targetRay !== null ) {
22003
22004                                         inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
22005
22006                                         if ( inputPose !== null ) {
22007
22008                                                 targetRay.matrix.fromArray( inputPose.transform.matrix );
22009                                                 targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
22010
22011                                         }
22012
22013                                 }
22014
22015                                 if ( grip !== null && inputSource.gripSpace ) {
22016
22017                                         gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
22018
22019                                         if ( gripPose !== null ) {
22020
22021                                                 grip.matrix.fromArray( gripPose.transform.matrix );
22022                                                 grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
22023
22024                                         }
22025
22026                                 }
22027
22028                         }
22029
22030                 }
22031
22032                 if ( targetRay !== null ) {
22033
22034                         targetRay.visible = ( inputPose !== null );
22035
22036                 }
22037
22038                 if ( grip !== null ) {
22039
22040                         grip.visible = ( gripPose !== null );
22041
22042                 }
22043
22044                 if ( hand !== null ) {
22045
22046                         hand.visible = ( handPose !== null );
22047
22048                 }
22049
22050                 return this;
22051
22052         }
22053
22054 } );
22055
22056 function WebXRManager( renderer, gl ) {
22057
22058         const scope = this;
22059
22060         let session = null;
22061
22062         let framebufferScaleFactor = 1.0;
22063
22064         let referenceSpace = null;
22065         let referenceSpaceType = 'local-floor';
22066
22067         let pose = null;
22068
22069         const controllers = [];
22070         const inputSourcesMap = new Map();
22071
22072         //
22073
22074         const cameraL = new PerspectiveCamera();
22075         cameraL.layers.enable( 1 );
22076         cameraL.viewport = new Vector4();
22077
22078         const cameraR = new PerspectiveCamera();
22079         cameraR.layers.enable( 2 );
22080         cameraR.viewport = new Vector4();
22081
22082         const cameras = [ cameraL, cameraR ];
22083
22084         const cameraVR = new ArrayCamera();
22085         cameraVR.layers.enable( 1 );
22086         cameraVR.layers.enable( 2 );
22087
22088         let _currentDepthNear = null;
22089         let _currentDepthFar = null;
22090
22091         //
22092
22093         this.enabled = false;
22094
22095         this.isPresenting = false;
22096
22097         this.getController = function ( index ) {
22098
22099                 let controller = controllers[ index ];
22100
22101                 if ( controller === undefined ) {
22102
22103                         controller = new WebXRController();
22104                         controllers[ index ] = controller;
22105
22106                 }
22107
22108                 return controller.getTargetRaySpace();
22109
22110         };
22111
22112         this.getControllerGrip = function ( index ) {
22113
22114                 let controller = controllers[ index ];
22115
22116                 if ( controller === undefined ) {
22117
22118                         controller = new WebXRController();
22119                         controllers[ index ] = controller;
22120
22121                 }
22122
22123                 return controller.getGripSpace();
22124
22125         };
22126
22127         this.getHand = function ( index ) {
22128
22129                 let controller = controllers[ index ];
22130
22131                 if ( controller === undefined ) {
22132
22133                         controller = new WebXRController();
22134                         controllers[ index ] = controller;
22135
22136                 }
22137
22138                 return controller.getHandSpace();
22139
22140         };
22141
22142         //
22143
22144         function onSessionEvent( event ) {
22145
22146                 const controller = inputSourcesMap.get( event.inputSource );
22147
22148                 if ( controller ) {
22149
22150                         controller.dispatchEvent( { type: event.type, data: event.inputSource } );
22151
22152                 }
22153
22154         }
22155
22156         function onSessionEnd() {
22157
22158                 inputSourcesMap.forEach( function ( controller, inputSource ) {
22159
22160                         controller.disconnect( inputSource );
22161
22162                 } );
22163
22164                 inputSourcesMap.clear();
22165
22166                 //
22167
22168                 renderer.setFramebuffer( null );
22169                 renderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830
22170                 animation.stop();
22171
22172                 scope.isPresenting = false;
22173
22174                 scope.dispatchEvent( { type: 'sessionend' } );
22175
22176         }
22177
22178         function onRequestReferenceSpace( value ) {
22179
22180                 referenceSpace = value;
22181
22182                 animation.setContext( session );
22183                 animation.start();
22184
22185                 scope.isPresenting = true;
22186
22187                 scope.dispatchEvent( { type: 'sessionstart' } );
22188
22189         }
22190
22191         this.setFramebufferScaleFactor = function ( value ) {
22192
22193                 framebufferScaleFactor = value;
22194
22195                 if ( scope.isPresenting === true ) {
22196
22197                         console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
22198
22199                 }
22200
22201         };
22202
22203         this.setReferenceSpaceType = function ( value ) {
22204
22205                 referenceSpaceType = value;
22206
22207                 if ( scope.isPresenting === true ) {
22208
22209                         console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
22210
22211                 }
22212
22213         };
22214
22215         this.getReferenceSpace = function () {
22216
22217                 return referenceSpace;
22218
22219         };
22220
22221         this.getSession = function () {
22222
22223                 return session;
22224
22225         };
22226
22227         this.setSession = function ( value ) {
22228
22229                 session = value;
22230
22231                 if ( session !== null ) {
22232
22233                         session.addEventListener( 'select', onSessionEvent );
22234                         session.addEventListener( 'selectstart', onSessionEvent );
22235                         session.addEventListener( 'selectend', onSessionEvent );
22236                         session.addEventListener( 'squeeze', onSessionEvent );
22237                         session.addEventListener( 'squeezestart', onSessionEvent );
22238                         session.addEventListener( 'squeezeend', onSessionEvent );
22239                         session.addEventListener( 'end', onSessionEnd );
22240
22241                         const attributes = gl.getContextAttributes();
22242
22243                         if ( attributes.xrCompatible !== true ) {
22244
22245                                 gl.makeXRCompatible();
22246
22247                         }
22248
22249                         const layerInit = {
22250                                 antialias: attributes.antialias,
22251                                 alpha: attributes.alpha,
22252                                 depth: attributes.depth,
22253                                 stencil: attributes.stencil,
22254                                 framebufferScaleFactor: framebufferScaleFactor
22255                         };
22256
22257                         // eslint-disable-next-line no-undef
22258                         const baseLayer = new XRWebGLLayer( session, gl, layerInit );
22259
22260                         session.updateRenderState( { baseLayer: baseLayer } );
22261
22262                         session.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );
22263
22264                         //
22265
22266                         session.addEventListener( 'inputsourceschange', updateInputSources );
22267
22268                 }
22269
22270         };
22271
22272         function updateInputSources( event ) {
22273
22274                 const inputSources = session.inputSources;
22275
22276                 // Assign inputSources to available controllers
22277
22278                 for ( let i = 0; i < controllers.length; i ++ ) {
22279
22280                         inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
22281
22282                 }
22283
22284                 // Notify disconnected
22285
22286                 for ( let i = 0; i < event.removed.length; i ++ ) {
22287
22288                         const inputSource = event.removed[ i ];
22289                         const controller = inputSourcesMap.get( inputSource );
22290
22291                         if ( controller ) {
22292
22293                                 controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
22294                                 inputSourcesMap.delete( inputSource );
22295
22296                         }
22297
22298                 }
22299
22300                 // Notify connected
22301
22302                 for ( let i = 0; i < event.added.length; i ++ ) {
22303
22304                         const inputSource = event.added[ i ];
22305                         const controller = inputSourcesMap.get( inputSource );
22306
22307                         if ( controller ) {
22308
22309                                 controller.dispatchEvent( { type: 'connected', data: inputSource } );
22310
22311                         }
22312
22313                 }
22314
22315         }
22316
22317         //
22318
22319         const cameraLPos = new Vector3();
22320         const cameraRPos = new Vector3();
22321
22322         /**
22323          * Assumes 2 cameras that are parallel and share an X-axis, and that
22324          * the cameras' projection and world matrices have already been set.
22325          * And that near and far planes are identical for both cameras.
22326          * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
22327          */
22328         function setProjectionFromUnion( camera, cameraL, cameraR ) {
22329
22330                 cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
22331                 cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
22332
22333                 const ipd = cameraLPos.distanceTo( cameraRPos );
22334
22335                 const projL = cameraL.projectionMatrix.elements;
22336                 const projR = cameraR.projectionMatrix.elements;
22337
22338                 // VR systems will have identical far and near planes, and
22339                 // most likely identical top and bottom frustum extents.
22340                 // Use the left camera for these values.
22341                 const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
22342                 const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
22343                 const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
22344                 const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
22345
22346                 const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
22347                 const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
22348                 const left = near * leftFov;
22349                 const right = near * rightFov;
22350
22351                 // Calculate the new camera's position offset from the
22352                 // left camera. xOffset should be roughly half `ipd`.
22353                 const zOffset = ipd / ( - leftFov + rightFov );
22354                 const xOffset = zOffset * - leftFov;
22355
22356                 // TODO: Better way to apply this offset?
22357                 cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
22358                 camera.translateX( xOffset );
22359                 camera.translateZ( zOffset );
22360                 camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
22361                 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
22362
22363                 // Find the union of the frustum values of the cameras and scale
22364                 // the values so that the near plane's position does not change in world space,
22365                 // although must now be relative to the new union camera.
22366                 const near2 = near + zOffset;
22367                 const far2 = far + zOffset;
22368                 const left2 = left - xOffset;
22369                 const right2 = right + ( ipd - xOffset );
22370                 const top2 = topFov * far / far2 * near2;
22371                 const bottom2 = bottomFov * far / far2 * near2;
22372
22373                 camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
22374
22375         }
22376
22377         function updateCamera( camera, parent ) {
22378
22379                 if ( parent === null ) {
22380
22381                         camera.matrixWorld.copy( camera.matrix );
22382
22383                 } else {
22384
22385                         camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
22386
22387                 }
22388
22389                 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
22390
22391         }
22392
22393         this.getCamera = function ( camera ) {
22394
22395                 cameraVR.near = cameraR.near = cameraL.near = camera.near;
22396                 cameraVR.far = cameraR.far = cameraL.far = camera.far;
22397
22398                 if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
22399
22400                         // Note that the new renderState won't apply until the next frame. See #18320
22401
22402                         session.updateRenderState( {
22403                                 depthNear: cameraVR.near,
22404                                 depthFar: cameraVR.far
22405                         } );
22406
22407                         _currentDepthNear = cameraVR.near;
22408                         _currentDepthFar = cameraVR.far;
22409
22410                 }
22411
22412                 const parent = camera.parent;
22413                 const cameras = cameraVR.cameras;
22414
22415                 updateCamera( cameraVR, parent );
22416
22417                 for ( let i = 0; i < cameras.length; i ++ ) {
22418
22419                         updateCamera( cameras[ i ], parent );
22420
22421                 }
22422
22423                 // update camera and its children
22424
22425                 camera.matrixWorld.copy( cameraVR.matrixWorld );
22426
22427                 const children = camera.children;
22428
22429                 for ( let i = 0, l = children.length; i < l; i ++ ) {
22430
22431                         children[ i ].updateMatrixWorld( true );
22432
22433                 }
22434
22435                 // update projection matrix for proper view frustum culling
22436
22437                 if ( cameras.length === 2 ) {
22438
22439                         setProjectionFromUnion( cameraVR, cameraL, cameraR );
22440
22441                 } else {
22442
22443                         // assume single camera setup (AR)
22444
22445                         cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
22446
22447                 }
22448
22449                 return cameraVR;
22450
22451         };
22452
22453         // Animation Loop
22454
22455         let onAnimationFrameCallback = null;
22456
22457         function onAnimationFrame( time, frame ) {
22458
22459                 pose = frame.getViewerPose( referenceSpace );
22460
22461                 if ( pose !== null ) {
22462
22463                         const views = pose.views;
22464                         const baseLayer = session.renderState.baseLayer;
22465
22466                         renderer.setFramebuffer( baseLayer.framebuffer );
22467
22468                         let cameraVRNeedsUpdate = false;
22469
22470                         // check if it's necessary to rebuild cameraVR's camera list
22471
22472                         if ( views.length !== cameraVR.cameras.length ) {
22473
22474                                 cameraVR.cameras.length = 0;
22475                                 cameraVRNeedsUpdate = true;
22476
22477                         }
22478
22479                         for ( let i = 0; i < views.length; i ++ ) {
22480
22481                                 const view = views[ i ];
22482                                 const viewport = baseLayer.getViewport( view );
22483
22484                                 const camera = cameras[ i ];
22485                                 camera.matrix.fromArray( view.transform.matrix );
22486                                 camera.projectionMatrix.fromArray( view.projectionMatrix );
22487                                 camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
22488
22489                                 if ( i === 0 ) {
22490
22491                                         cameraVR.matrix.copy( camera.matrix );
22492
22493                                 }
22494
22495                                 if ( cameraVRNeedsUpdate === true ) {
22496
22497                                         cameraVR.cameras.push( camera );
22498
22499                                 }
22500
22501                         }
22502
22503                 }
22504
22505                 //
22506
22507                 const inputSources = session.inputSources;
22508
22509                 for ( let i = 0; i < controllers.length; i ++ ) {
22510
22511                         const controller = controllers[ i ];
22512                         const inputSource = inputSources[ i ];
22513
22514                         controller.update( inputSource, frame, referenceSpace );
22515
22516                 }
22517
22518                 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
22519
22520         }
22521
22522         const animation = new WebGLAnimation();
22523         animation.setAnimationLoop( onAnimationFrame );
22524
22525         this.setAnimationLoop = function ( callback ) {
22526
22527                 onAnimationFrameCallback = callback;
22528
22529         };
22530
22531         this.dispose = function () {};
22532
22533 }
22534
22535 Object.assign( WebXRManager.prototype, EventDispatcher.prototype );
22536
22537 function WebGLMaterials( properties ) {
22538
22539         function refreshFogUniforms( uniforms, fog ) {
22540
22541                 uniforms.fogColor.value.copy( fog.color );
22542
22543                 if ( fog.isFog ) {
22544
22545                         uniforms.fogNear.value = fog.near;
22546                         uniforms.fogFar.value = fog.far;
22547
22548                 } else if ( fog.isFogExp2 ) {
22549
22550                         uniforms.fogDensity.value = fog.density;
22551
22552                 }
22553
22554         }
22555
22556         function refreshMaterialUniforms( uniforms, material, pixelRatio, height ) {
22557
22558                 if ( material.isMeshBasicMaterial ) {
22559
22560                         refreshUniformsCommon( uniforms, material );
22561
22562                 } else if ( material.isMeshLambertMaterial ) {
22563
22564                         refreshUniformsCommon( uniforms, material );
22565                         refreshUniformsLambert( uniforms, material );
22566
22567                 } else if ( material.isMeshToonMaterial ) {
22568
22569                         refreshUniformsCommon( uniforms, material );
22570                         refreshUniformsToon( uniforms, material );
22571
22572                 } else if ( material.isMeshPhongMaterial ) {
22573
22574                         refreshUniformsCommon( uniforms, material );
22575                         refreshUniformsPhong( uniforms, material );
22576
22577                 } else if ( material.isMeshStandardMaterial ) {
22578
22579                         refreshUniformsCommon( uniforms, material );
22580
22581                         if ( material.isMeshPhysicalMaterial ) {
22582
22583                                 refreshUniformsPhysical( uniforms, material );
22584
22585                         } else {
22586
22587                                 refreshUniformsStandard( uniforms, material );
22588
22589                         }
22590
22591                 } else if ( material.isMeshMatcapMaterial ) {
22592
22593                         refreshUniformsCommon( uniforms, material );
22594                         refreshUniformsMatcap( uniforms, material );
22595
22596                 } else if ( material.isMeshDepthMaterial ) {
22597
22598                         refreshUniformsCommon( uniforms, material );
22599                         refreshUniformsDepth( uniforms, material );
22600
22601                 } else if ( material.isMeshDistanceMaterial ) {
22602
22603                         refreshUniformsCommon( uniforms, material );
22604                         refreshUniformsDistance( uniforms, material );
22605
22606                 } else if ( material.isMeshNormalMaterial ) {
22607
22608                         refreshUniformsCommon( uniforms, material );
22609                         refreshUniformsNormal( uniforms, material );
22610
22611                 } else if ( material.isLineBasicMaterial ) {
22612
22613                         refreshUniformsLine( uniforms, material );
22614
22615                         if ( material.isLineDashedMaterial ) {
22616
22617                                 refreshUniformsDash( uniforms, material );
22618
22619                         }
22620
22621                 } else if ( material.isPointsMaterial ) {
22622
22623                         refreshUniformsPoints( uniforms, material, pixelRatio, height );
22624
22625                 } else if ( material.isSpriteMaterial ) {
22626
22627                         refreshUniformsSprites( uniforms, material );
22628
22629                 } else if ( material.isShadowMaterial ) {
22630
22631                         uniforms.color.value.copy( material.color );
22632                         uniforms.opacity.value = material.opacity;
22633
22634                 } else if ( material.isShaderMaterial ) {
22635
22636                         material.uniformsNeedUpdate = false; // #15581
22637
22638                 }
22639
22640         }
22641
22642         function refreshUniformsCommon( uniforms, material ) {
22643
22644                 uniforms.opacity.value = material.opacity;
22645
22646                 if ( material.color ) {
22647
22648                         uniforms.diffuse.value.copy( material.color );
22649
22650                 }
22651
22652                 if ( material.emissive ) {
22653
22654                         uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
22655
22656                 }
22657
22658                 if ( material.map ) {
22659
22660                         uniforms.map.value = material.map;
22661
22662                 }
22663
22664                 if ( material.alphaMap ) {
22665
22666                         uniforms.alphaMap.value = material.alphaMap;
22667
22668                 }
22669
22670                 if ( material.specularMap ) {
22671
22672                         uniforms.specularMap.value = material.specularMap;
22673
22674                 }
22675
22676                 const envMap = properties.get( material ).envMap;
22677
22678                 if ( envMap ) {
22679
22680                         uniforms.envMap.value = envMap;
22681
22682                         uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap._needsFlipEnvMap ) ? - 1 : 1;
22683
22684                         uniforms.reflectivity.value = material.reflectivity;
22685                         uniforms.refractionRatio.value = material.refractionRatio;
22686
22687                         const maxMipLevel = properties.get( envMap ).__maxMipLevel;
22688
22689                         if ( maxMipLevel !== undefined ) {
22690
22691                                 uniforms.maxMipLevel.value = maxMipLevel;
22692
22693                         }
22694
22695                 }
22696
22697                 if ( material.lightMap ) {
22698
22699                         uniforms.lightMap.value = material.lightMap;
22700                         uniforms.lightMapIntensity.value = material.lightMapIntensity;
22701
22702                 }
22703
22704                 if ( material.aoMap ) {
22705
22706                         uniforms.aoMap.value = material.aoMap;
22707                         uniforms.aoMapIntensity.value = material.aoMapIntensity;
22708
22709                 }
22710
22711                 // uv repeat and offset setting priorities
22712                 // 1. color map
22713                 // 2. specular map
22714                 // 3. displacementMap map
22715                 // 4. normal map
22716                 // 5. bump map
22717                 // 6. roughnessMap map
22718                 // 7. metalnessMap map
22719                 // 8. alphaMap map
22720                 // 9. emissiveMap map
22721                 // 10. clearcoat map
22722                 // 11. clearcoat normal map
22723                 // 12. clearcoat roughnessMap map
22724
22725                 let uvScaleMap;
22726
22727                 if ( material.map ) {
22728
22729                         uvScaleMap = material.map;
22730
22731                 } else if ( material.specularMap ) {
22732
22733                         uvScaleMap = material.specularMap;
22734
22735                 } else if ( material.displacementMap ) {
22736
22737                         uvScaleMap = material.displacementMap;
22738
22739                 } else if ( material.normalMap ) {
22740
22741                         uvScaleMap = material.normalMap;
22742
22743                 } else if ( material.bumpMap ) {
22744
22745                         uvScaleMap = material.bumpMap;
22746
22747                 } else if ( material.roughnessMap ) {
22748
22749                         uvScaleMap = material.roughnessMap;
22750
22751                 } else if ( material.metalnessMap ) {
22752
22753                         uvScaleMap = material.metalnessMap;
22754
22755                 } else if ( material.alphaMap ) {
22756
22757                         uvScaleMap = material.alphaMap;
22758
22759                 } else if ( material.emissiveMap ) {
22760
22761                         uvScaleMap = material.emissiveMap;
22762
22763                 } else if ( material.clearcoatMap ) {
22764
22765                         uvScaleMap = material.clearcoatMap;
22766
22767                 } else if ( material.clearcoatNormalMap ) {
22768
22769                         uvScaleMap = material.clearcoatNormalMap;
22770
22771                 } else if ( material.clearcoatRoughnessMap ) {
22772
22773                         uvScaleMap = material.clearcoatRoughnessMap;
22774
22775                 }
22776
22777                 if ( uvScaleMap !== undefined ) {
22778
22779                         // backwards compatibility
22780                         if ( uvScaleMap.isWebGLRenderTarget ) {
22781
22782                                 uvScaleMap = uvScaleMap.texture;
22783
22784                         }
22785
22786                         if ( uvScaleMap.matrixAutoUpdate === true ) {
22787
22788                                 uvScaleMap.updateMatrix();
22789
22790                         }
22791
22792                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
22793
22794                 }
22795
22796                 // uv repeat and offset setting priorities for uv2
22797                 // 1. ao map
22798                 // 2. light map
22799
22800                 let uv2ScaleMap;
22801
22802                 if ( material.aoMap ) {
22803
22804                         uv2ScaleMap = material.aoMap;
22805
22806                 } else if ( material.lightMap ) {
22807
22808                         uv2ScaleMap = material.lightMap;
22809
22810                 }
22811
22812                 if ( uv2ScaleMap !== undefined ) {
22813
22814                         // backwards compatibility
22815                         if ( uv2ScaleMap.isWebGLRenderTarget ) {
22816
22817                                 uv2ScaleMap = uv2ScaleMap.texture;
22818
22819                         }
22820
22821                         if ( uv2ScaleMap.matrixAutoUpdate === true ) {
22822
22823                                 uv2ScaleMap.updateMatrix();
22824
22825                         }
22826
22827                         uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );
22828
22829                 }
22830
22831         }
22832
22833         function refreshUniformsLine( uniforms, material ) {
22834
22835                 uniforms.diffuse.value.copy( material.color );
22836                 uniforms.opacity.value = material.opacity;
22837
22838         }
22839
22840         function refreshUniformsDash( uniforms, material ) {
22841
22842                 uniforms.dashSize.value = material.dashSize;
22843                 uniforms.totalSize.value = material.dashSize + material.gapSize;
22844                 uniforms.scale.value = material.scale;
22845
22846         }
22847
22848         function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
22849
22850                 uniforms.diffuse.value.copy( material.color );
22851                 uniforms.opacity.value = material.opacity;
22852                 uniforms.size.value = material.size * pixelRatio;
22853                 uniforms.scale.value = height * 0.5;
22854
22855                 if ( material.map ) {
22856
22857                         uniforms.map.value = material.map;
22858
22859                 }
22860
22861                 if ( material.alphaMap ) {
22862
22863                         uniforms.alphaMap.value = material.alphaMap;
22864
22865                 }
22866
22867                 // uv repeat and offset setting priorities
22868                 // 1. color map
22869                 // 2. alpha map
22870
22871                 let uvScaleMap;
22872
22873                 if ( material.map ) {
22874
22875                         uvScaleMap = material.map;
22876
22877                 } else if ( material.alphaMap ) {
22878
22879                         uvScaleMap = material.alphaMap;
22880
22881                 }
22882
22883                 if ( uvScaleMap !== undefined ) {
22884
22885                         if ( uvScaleMap.matrixAutoUpdate === true ) {
22886
22887                                 uvScaleMap.updateMatrix();
22888
22889                         }
22890
22891                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
22892
22893                 }
22894
22895         }
22896
22897         function refreshUniformsSprites( uniforms, material ) {
22898
22899                 uniforms.diffuse.value.copy( material.color );
22900                 uniforms.opacity.value = material.opacity;
22901                 uniforms.rotation.value = material.rotation;
22902
22903                 if ( material.map ) {
22904
22905                         uniforms.map.value = material.map;
22906
22907                 }
22908
22909                 if ( material.alphaMap ) {
22910
22911                         uniforms.alphaMap.value = material.alphaMap;
22912
22913                 }
22914
22915                 // uv repeat and offset setting priorities
22916                 // 1. color map
22917                 // 2. alpha map
22918
22919                 let uvScaleMap;
22920
22921                 if ( material.map ) {
22922
22923                         uvScaleMap = material.map;
22924
22925                 } else if ( material.alphaMap ) {
22926
22927                         uvScaleMap = material.alphaMap;
22928
22929                 }
22930
22931                 if ( uvScaleMap !== undefined ) {
22932
22933                         if ( uvScaleMap.matrixAutoUpdate === true ) {
22934
22935                                 uvScaleMap.updateMatrix();
22936
22937                         }
22938
22939                         uniforms.uvTransform.value.copy( uvScaleMap.matrix );
22940
22941                 }
22942
22943         }
22944
22945         function refreshUniformsLambert( uniforms, material ) {
22946
22947                 if ( material.emissiveMap ) {
22948
22949                         uniforms.emissiveMap.value = material.emissiveMap;
22950
22951                 }
22952
22953         }
22954
22955         function refreshUniformsPhong( uniforms, material ) {
22956
22957                 uniforms.specular.value.copy( material.specular );
22958                 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
22959
22960                 if ( material.emissiveMap ) {
22961
22962                         uniforms.emissiveMap.value = material.emissiveMap;
22963
22964                 }
22965
22966                 if ( material.bumpMap ) {
22967
22968                         uniforms.bumpMap.value = material.bumpMap;
22969                         uniforms.bumpScale.value = material.bumpScale;
22970                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
22971
22972                 }
22973
22974                 if ( material.normalMap ) {
22975
22976                         uniforms.normalMap.value = material.normalMap;
22977                         uniforms.normalScale.value.copy( material.normalScale );
22978                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
22979
22980                 }
22981
22982                 if ( material.displacementMap ) {
22983
22984                         uniforms.displacementMap.value = material.displacementMap;
22985                         uniforms.displacementScale.value = material.displacementScale;
22986                         uniforms.displacementBias.value = material.displacementBias;
22987
22988                 }
22989
22990         }
22991
22992         function refreshUniformsToon( uniforms, material ) {
22993
22994                 if ( material.gradientMap ) {
22995
22996                         uniforms.gradientMap.value = material.gradientMap;
22997
22998                 }
22999
23000                 if ( material.emissiveMap ) {
23001
23002                         uniforms.emissiveMap.value = material.emissiveMap;
23003
23004                 }
23005
23006                 if ( material.bumpMap ) {
23007
23008                         uniforms.bumpMap.value = material.bumpMap;
23009                         uniforms.bumpScale.value = material.bumpScale;
23010                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
23011
23012                 }
23013
23014                 if ( material.normalMap ) {
23015
23016                         uniforms.normalMap.value = material.normalMap;
23017                         uniforms.normalScale.value.copy( material.normalScale );
23018                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
23019
23020                 }
23021
23022                 if ( material.displacementMap ) {
23023
23024                         uniforms.displacementMap.value = material.displacementMap;
23025                         uniforms.displacementScale.value = material.displacementScale;
23026                         uniforms.displacementBias.value = material.displacementBias;
23027
23028                 }
23029
23030         }
23031
23032         function refreshUniformsStandard( uniforms, material ) {
23033
23034                 uniforms.roughness.value = material.roughness;
23035                 uniforms.metalness.value = material.metalness;
23036
23037                 if ( material.roughnessMap ) {
23038
23039                         uniforms.roughnessMap.value = material.roughnessMap;
23040
23041                 }
23042
23043                 if ( material.metalnessMap ) {
23044
23045                         uniforms.metalnessMap.value = material.metalnessMap;
23046
23047                 }
23048
23049                 if ( material.emissiveMap ) {
23050
23051                         uniforms.emissiveMap.value = material.emissiveMap;
23052
23053                 }
23054
23055                 if ( material.bumpMap ) {
23056
23057                         uniforms.bumpMap.value = material.bumpMap;
23058                         uniforms.bumpScale.value = material.bumpScale;
23059                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
23060
23061                 }
23062
23063                 if ( material.normalMap ) {
23064
23065                         uniforms.normalMap.value = material.normalMap;
23066                         uniforms.normalScale.value.copy( material.normalScale );
23067                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
23068
23069                 }
23070
23071                 if ( material.displacementMap ) {
23072
23073                         uniforms.displacementMap.value = material.displacementMap;
23074                         uniforms.displacementScale.value = material.displacementScale;
23075                         uniforms.displacementBias.value = material.displacementBias;
23076
23077                 }
23078
23079                 const envMap = properties.get( material ).envMap;
23080
23081                 if ( envMap ) {
23082
23083                         //uniforms.envMap.value = material.envMap; // part of uniforms common
23084                         uniforms.envMapIntensity.value = material.envMapIntensity;
23085
23086                 }
23087
23088         }
23089
23090         function refreshUniformsPhysical( uniforms, material ) {
23091
23092                 refreshUniformsStandard( uniforms, material );
23093
23094                 uniforms.reflectivity.value = material.reflectivity; // also part of uniforms common
23095
23096                 uniforms.clearcoat.value = material.clearcoat;
23097                 uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
23098                 if ( material.sheen ) uniforms.sheen.value.copy( material.sheen );
23099
23100                 if ( material.clearcoatMap ) {
23101
23102                         uniforms.clearcoatMap.value = material.clearcoatMap;
23103
23104                 }
23105
23106                 if ( material.clearcoatRoughnessMap ) {
23107
23108                         uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
23109
23110                 }
23111
23112                 if ( material.clearcoatNormalMap ) {
23113
23114                         uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
23115                         uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
23116
23117                         if ( material.side === BackSide ) {
23118
23119                                 uniforms.clearcoatNormalScale.value.negate();
23120
23121                         }
23122
23123                 }
23124
23125                 uniforms.transmission.value = material.transmission;
23126
23127                 if ( material.transmissionMap ) {
23128
23129                         uniforms.transmissionMap.value = material.transmissionMap;
23130
23131                 }
23132
23133         }
23134
23135         function refreshUniformsMatcap( uniforms, material ) {
23136
23137                 if ( material.matcap ) {
23138
23139                         uniforms.matcap.value = material.matcap;
23140
23141                 }
23142
23143                 if ( material.bumpMap ) {
23144
23145                         uniforms.bumpMap.value = material.bumpMap;
23146                         uniforms.bumpScale.value = material.bumpScale;
23147                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
23148
23149                 }
23150
23151                 if ( material.normalMap ) {
23152
23153                         uniforms.normalMap.value = material.normalMap;
23154                         uniforms.normalScale.value.copy( material.normalScale );
23155                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
23156
23157                 }
23158
23159                 if ( material.displacementMap ) {
23160
23161                         uniforms.displacementMap.value = material.displacementMap;
23162                         uniforms.displacementScale.value = material.displacementScale;
23163                         uniforms.displacementBias.value = material.displacementBias;
23164
23165                 }
23166
23167         }
23168
23169         function refreshUniformsDepth( uniforms, material ) {
23170
23171                 if ( material.displacementMap ) {
23172
23173                         uniforms.displacementMap.value = material.displacementMap;
23174                         uniforms.displacementScale.value = material.displacementScale;
23175                         uniforms.displacementBias.value = material.displacementBias;
23176
23177                 }
23178
23179         }
23180
23181         function refreshUniformsDistance( uniforms, material ) {
23182
23183                 if ( material.displacementMap ) {
23184
23185                         uniforms.displacementMap.value = material.displacementMap;
23186                         uniforms.displacementScale.value = material.displacementScale;
23187                         uniforms.displacementBias.value = material.displacementBias;
23188
23189                 }
23190
23191                 uniforms.referencePosition.value.copy( material.referencePosition );
23192                 uniforms.nearDistance.value = material.nearDistance;
23193                 uniforms.farDistance.value = material.farDistance;
23194
23195         }
23196
23197         function refreshUniformsNormal( uniforms, material ) {
23198
23199                 if ( material.bumpMap ) {
23200
23201                         uniforms.bumpMap.value = material.bumpMap;
23202                         uniforms.bumpScale.value = material.bumpScale;
23203                         if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
23204
23205                 }
23206
23207                 if ( material.normalMap ) {
23208
23209                         uniforms.normalMap.value = material.normalMap;
23210                         uniforms.normalScale.value.copy( material.normalScale );
23211                         if ( material.side === BackSide ) uniforms.normalScale.value.negate();
23212
23213                 }
23214
23215                 if ( material.displacementMap ) {
23216
23217                         uniforms.displacementMap.value = material.displacementMap;
23218                         uniforms.displacementScale.value = material.displacementScale;
23219                         uniforms.displacementBias.value = material.displacementBias;
23220
23221                 }
23222
23223         }
23224
23225         return {
23226                 refreshFogUniforms: refreshFogUniforms,
23227                 refreshMaterialUniforms: refreshMaterialUniforms
23228         };
23229
23230 }
23231
23232 function createCanvasElement() {
23233
23234         const canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
23235         canvas.style.display = 'block';
23236         return canvas;
23237
23238 }
23239
23240 function WebGLRenderer( parameters ) {
23241
23242         parameters = parameters || {};
23243
23244         const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(),
23245                 _context = parameters.context !== undefined ? parameters.context : null,
23246
23247                 _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
23248                 _depth = parameters.depth !== undefined ? parameters.depth : true,
23249                 _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
23250                 _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
23251                 _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
23252                 _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
23253                 _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',
23254                 _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;
23255
23256         let currentRenderList = null;
23257         let currentRenderState = null;
23258
23259         // public properties
23260
23261         this.domElement = _canvas;
23262
23263         // Debug configuration container
23264         this.debug = {
23265
23266                 /**
23267                  * Enables error checking and reporting when shader programs are being compiled
23268                  * @type {boolean}
23269                  */
23270                 checkShaderErrors: true
23271         };
23272
23273         // clearing
23274
23275         this.autoClear = true;
23276         this.autoClearColor = true;
23277         this.autoClearDepth = true;
23278         this.autoClearStencil = true;
23279
23280         // scene graph
23281
23282         this.sortObjects = true;
23283
23284         // user-defined clipping
23285
23286         this.clippingPlanes = [];
23287         this.localClippingEnabled = false;
23288
23289         // physically based shading
23290
23291         this.gammaFactor = 2.0; // for backwards compatibility
23292         this.outputEncoding = LinearEncoding;
23293
23294         // physical lights
23295
23296         this.physicallyCorrectLights = false;
23297
23298         // tone mapping
23299
23300         this.toneMapping = NoToneMapping;
23301         this.toneMappingExposure = 1.0;
23302
23303         // morphs
23304
23305         this.maxMorphTargets = 8;
23306         this.maxMorphNormals = 4;
23307
23308         // internal properties
23309
23310         const _this = this;
23311
23312         let _isContextLost = false;
23313
23314         // internal state cache
23315
23316         let _framebuffer = null;
23317
23318         let _currentActiveCubeFace = 0;
23319         let _currentActiveMipmapLevel = 0;
23320         let _currentRenderTarget = null;
23321         let _currentFramebuffer = null;
23322         let _currentMaterialId = - 1;
23323
23324         let _currentCamera = null;
23325         let _currentArrayCamera = null;
23326
23327         const _currentViewport = new Vector4();
23328         const _currentScissor = new Vector4();
23329         let _currentScissorTest = null;
23330
23331         //
23332
23333         let _width = _canvas.width;
23334         let _height = _canvas.height;
23335
23336         let _pixelRatio = 1;
23337         let _opaqueSort = null;
23338         let _transparentSort = null;
23339
23340         const _viewport = new Vector4( 0, 0, _width, _height );
23341         const _scissor = new Vector4( 0, 0, _width, _height );
23342         let _scissorTest = false;
23343
23344         // frustum
23345
23346         const _frustum = new Frustum();
23347
23348         // clipping
23349
23350         let _clippingEnabled = false;
23351         let _localClippingEnabled = false;
23352
23353         // camera matrices cache
23354
23355         const _projScreenMatrix = new Matrix4();
23356
23357         const _vector3 = new Vector3();
23358
23359         const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
23360
23361         function getTargetPixelRatio() {
23362
23363                 return _currentRenderTarget === null ? _pixelRatio : 1;
23364
23365         }
23366
23367         // initialize
23368
23369         let _gl = _context;
23370
23371         function getContext( contextNames, contextAttributes ) {
23372
23373                 for ( let i = 0; i < contextNames.length; i ++ ) {
23374
23375                         const contextName = contextNames[ i ];
23376                         const context = _canvas.getContext( contextName, contextAttributes );
23377                         if ( context !== null ) return context;
23378
23379                 }
23380
23381                 return null;
23382
23383         }
23384
23385         try {
23386
23387                 const contextAttributes = {
23388                         alpha: _alpha,
23389                         depth: _depth,
23390                         stencil: _stencil,
23391                         antialias: _antialias,
23392                         premultipliedAlpha: _premultipliedAlpha,
23393                         preserveDrawingBuffer: _preserveDrawingBuffer,
23394                         powerPreference: _powerPreference,
23395                         failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat
23396                 };
23397
23398                 // event listeners must be registered before WebGL context is created, see #12753
23399
23400                 _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
23401                 _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
23402
23403                 if ( _gl === null ) {
23404
23405                         const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ];
23406
23407                         if ( _this.isWebGL1Renderer === true ) {
23408
23409                                 contextNames.shift();
23410
23411                         }
23412
23413                         _gl = getContext( contextNames, contextAttributes );
23414
23415                         if ( _gl === null ) {
23416
23417                                 if ( getContext( contextNames ) ) {
23418
23419                                         throw new Error( 'Error creating WebGL context with your selected attributes.' );
23420
23421                                 } else {
23422
23423                                         throw new Error( 'Error creating WebGL context.' );
23424
23425                                 }
23426
23427                         }
23428
23429                 }
23430
23431                 // Some experimental-webgl implementations do not have getShaderPrecisionFormat
23432
23433                 if ( _gl.getShaderPrecisionFormat === undefined ) {
23434
23435                         _gl.getShaderPrecisionFormat = function () {
23436
23437                                 return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
23438
23439                         };
23440
23441                 }
23442
23443         } catch ( error ) {
23444
23445                 console.error( 'THREE.WebGLRenderer: ' + error.message );
23446                 throw error;
23447
23448         }
23449
23450         let extensions, capabilities, state, info;
23451         let properties, textures, cubemaps, attributes, geometries, objects;
23452         let programCache, materials, renderLists, renderStates, clipping;
23453
23454         let background, morphtargets, bufferRenderer, indexedBufferRenderer;
23455
23456         let utils, bindingStates;
23457
23458         function initGLContext() {
23459
23460                 extensions = new WebGLExtensions( _gl );
23461
23462                 capabilities = new WebGLCapabilities( _gl, extensions, parameters );
23463
23464                 if ( capabilities.isWebGL2 === false ) {
23465
23466                         extensions.get( 'WEBGL_depth_texture' );
23467                         extensions.get( 'OES_texture_float' );
23468                         extensions.get( 'OES_texture_half_float' );
23469                         extensions.get( 'OES_texture_half_float_linear' );
23470                         extensions.get( 'OES_standard_derivatives' );
23471                         extensions.get( 'OES_element_index_uint' );
23472                         extensions.get( 'OES_vertex_array_object' );
23473                         extensions.get( 'ANGLE_instanced_arrays' );
23474
23475                 }
23476
23477                 extensions.get( 'OES_texture_float_linear' );
23478
23479                 utils = new WebGLUtils( _gl, extensions, capabilities );
23480
23481                 state = new WebGLState( _gl, extensions, capabilities );
23482                 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
23483                 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
23484
23485                 info = new WebGLInfo( _gl );
23486                 properties = new WebGLProperties();
23487                 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
23488                 cubemaps = new WebGLCubeMaps( _this );
23489                 attributes = new WebGLAttributes( _gl, capabilities );
23490                 bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities );
23491                 geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
23492                 objects = new WebGLObjects( _gl, geometries, attributes, info );
23493                 morphtargets = new WebGLMorphtargets( _gl );
23494                 clipping = new WebGLClipping( properties );
23495                 programCache = new WebGLPrograms( _this, cubemaps, extensions, capabilities, bindingStates, clipping );
23496                 materials = new WebGLMaterials( properties );
23497                 renderLists = new WebGLRenderLists( properties );
23498                 renderStates = new WebGLRenderStates( extensions, capabilities );
23499                 background = new WebGLBackground( _this, cubemaps, state, objects, _premultipliedAlpha );
23500
23501                 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
23502                 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
23503
23504                 info.programs = programCache.programs;
23505
23506                 _this.capabilities = capabilities;
23507                 _this.extensions = extensions;
23508                 _this.properties = properties;
23509                 _this.renderLists = renderLists;
23510                 _this.state = state;
23511                 _this.info = info;
23512
23513         }
23514
23515         initGLContext();
23516
23517         // xr
23518
23519         const xr = new WebXRManager( _this, _gl );
23520
23521         this.xr = xr;
23522
23523         // shadow map
23524
23525         const shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
23526
23527         this.shadowMap = shadowMap;
23528
23529         // API
23530
23531         this.getContext = function () {
23532
23533                 return _gl;
23534
23535         };
23536
23537         this.getContextAttributes = function () {
23538
23539                 return _gl.getContextAttributes();
23540
23541         };
23542
23543         this.forceContextLoss = function () {
23544
23545                 const extension = extensions.get( 'WEBGL_lose_context' );
23546                 if ( extension ) extension.loseContext();
23547
23548         };
23549
23550         this.forceContextRestore = function () {
23551
23552                 const extension = extensions.get( 'WEBGL_lose_context' );
23553                 if ( extension ) extension.restoreContext();
23554
23555         };
23556
23557         this.getPixelRatio = function () {
23558
23559                 return _pixelRatio;
23560
23561         };
23562
23563         this.setPixelRatio = function ( value ) {
23564
23565                 if ( value === undefined ) return;
23566
23567                 _pixelRatio = value;
23568
23569                 this.setSize( _width, _height, false );
23570
23571         };
23572
23573         this.getSize = function ( target ) {
23574
23575                 if ( target === undefined ) {
23576
23577                         console.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );
23578
23579                         target = new Vector2();
23580
23581                 }
23582
23583                 return target.set( _width, _height );
23584
23585         };
23586
23587         this.setSize = function ( width, height, updateStyle ) {
23588
23589                 if ( xr.isPresenting ) {
23590
23591                         console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
23592                         return;
23593
23594                 }
23595
23596                 _width = width;
23597                 _height = height;
23598
23599                 _canvas.width = Math.floor( width * _pixelRatio );
23600                 _canvas.height = Math.floor( height * _pixelRatio );
23601
23602                 if ( updateStyle !== false ) {
23603
23604                         _canvas.style.width = width + 'px';
23605                         _canvas.style.height = height + 'px';
23606
23607                 }
23608
23609                 this.setViewport( 0, 0, width, height );
23610
23611         };
23612
23613         this.getDrawingBufferSize = function ( target ) {
23614
23615                 if ( target === undefined ) {
23616
23617                         console.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );
23618
23619                         target = new Vector2();
23620
23621                 }
23622
23623                 return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
23624
23625         };
23626
23627         this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
23628
23629                 _width = width;
23630                 _height = height;
23631
23632                 _pixelRatio = pixelRatio;
23633
23634                 _canvas.width = Math.floor( width * pixelRatio );
23635                 _canvas.height = Math.floor( height * pixelRatio );
23636
23637                 this.setViewport( 0, 0, width, height );
23638
23639         };
23640
23641         this.getCurrentViewport = function ( target ) {
23642
23643                 if ( target === undefined ) {
23644
23645                         console.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );
23646
23647                         target = new Vector4();
23648
23649                 }
23650
23651                 return target.copy( _currentViewport );
23652
23653         };
23654
23655         this.getViewport = function ( target ) {
23656
23657                 return target.copy( _viewport );
23658
23659         };
23660
23661         this.setViewport = function ( x, y, width, height ) {
23662
23663                 if ( x.isVector4 ) {
23664
23665                         _viewport.set( x.x, x.y, x.z, x.w );
23666
23667                 } else {
23668
23669                         _viewport.set( x, y, width, height );
23670
23671                 }
23672
23673                 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
23674
23675         };
23676
23677         this.getScissor = function ( target ) {
23678
23679                 return target.copy( _scissor );
23680
23681         };
23682
23683         this.setScissor = function ( x, y, width, height ) {
23684
23685                 if ( x.isVector4 ) {
23686
23687                         _scissor.set( x.x, x.y, x.z, x.w );
23688
23689                 } else {
23690
23691                         _scissor.set( x, y, width, height );
23692
23693                 }
23694
23695                 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
23696
23697         };
23698
23699         this.getScissorTest = function () {
23700
23701                 return _scissorTest;
23702
23703         };
23704
23705         this.setScissorTest = function ( boolean ) {
23706
23707                 state.setScissorTest( _scissorTest = boolean );
23708
23709         };
23710
23711         this.setOpaqueSort = function ( method ) {
23712
23713                 _opaqueSort = method;
23714
23715         };
23716
23717         this.setTransparentSort = function ( method ) {
23718
23719                 _transparentSort = method;
23720
23721         };
23722
23723         // Clearing
23724
23725         this.getClearColor = function () {
23726
23727                 return background.getClearColor();
23728
23729         };
23730
23731         this.setClearColor = function () {
23732
23733                 background.setClearColor.apply( background, arguments );
23734
23735         };
23736
23737         this.getClearAlpha = function () {
23738
23739                 return background.getClearAlpha();
23740
23741         };
23742
23743         this.setClearAlpha = function () {
23744
23745                 background.setClearAlpha.apply( background, arguments );
23746
23747         };
23748
23749         this.clear = function ( color, depth, stencil ) {
23750
23751                 let bits = 0;
23752
23753                 if ( color === undefined || color ) bits |= 16384;
23754                 if ( depth === undefined || depth ) bits |= 256;
23755                 if ( stencil === undefined || stencil ) bits |= 1024;
23756
23757                 _gl.clear( bits );
23758
23759         };
23760
23761         this.clearColor = function () {
23762
23763                 this.clear( true, false, false );
23764
23765         };
23766
23767         this.clearDepth = function () {
23768
23769                 this.clear( false, true, false );
23770
23771         };
23772
23773         this.clearStencil = function () {
23774
23775                 this.clear( false, false, true );
23776
23777         };
23778
23779         //
23780
23781         this.dispose = function () {
23782
23783                 _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
23784                 _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
23785
23786                 renderLists.dispose();
23787                 renderStates.dispose();
23788                 properties.dispose();
23789                 cubemaps.dispose();
23790                 objects.dispose();
23791                 bindingStates.dispose();
23792
23793                 xr.dispose();
23794
23795                 animation.stop();
23796
23797         };
23798
23799         // Events
23800
23801         function onContextLost( event ) {
23802
23803                 event.preventDefault();
23804
23805                 console.log( 'THREE.WebGLRenderer: Context Lost.' );
23806
23807                 _isContextLost = true;
23808
23809         }
23810
23811         function onContextRestore( /* event */ ) {
23812
23813                 console.log( 'THREE.WebGLRenderer: Context Restored.' );
23814
23815                 _isContextLost = false;
23816
23817                 initGLContext();
23818
23819         }
23820
23821         function onMaterialDispose( event ) {
23822
23823                 const material = event.target;
23824
23825                 material.removeEventListener( 'dispose', onMaterialDispose );
23826
23827                 deallocateMaterial( material );
23828
23829         }
23830
23831         // Buffer deallocation
23832
23833         function deallocateMaterial( material ) {
23834
23835                 releaseMaterialProgramReference( material );
23836
23837                 properties.remove( material );
23838
23839         }
23840
23841
23842         function releaseMaterialProgramReference( material ) {
23843
23844                 const programInfo = properties.get( material ).program;
23845
23846                 if ( programInfo !== undefined ) {
23847
23848                         programCache.releaseProgram( programInfo );
23849
23850                 }
23851
23852         }
23853
23854         // Buffer rendering
23855
23856         function renderObjectImmediate( object, program ) {
23857
23858                 object.render( function ( object ) {
23859
23860                         _this.renderBufferImmediate( object, program );
23861
23862                 } );
23863
23864         }
23865
23866         this.renderBufferImmediate = function ( object, program ) {
23867
23868                 bindingStates.initAttributes();
23869
23870                 const buffers = properties.get( object );
23871
23872                 if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
23873                 if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
23874                 if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
23875                 if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
23876
23877                 const programAttributes = program.getAttributes();
23878
23879                 if ( object.hasPositions ) {
23880
23881                         _gl.bindBuffer( 34962, buffers.position );
23882                         _gl.bufferData( 34962, object.positionArray, 35048 );
23883
23884                         bindingStates.enableAttribute( programAttributes.position );
23885                         _gl.vertexAttribPointer( programAttributes.position, 3, 5126, false, 0, 0 );
23886
23887                 }
23888
23889                 if ( object.hasNormals ) {
23890
23891                         _gl.bindBuffer( 34962, buffers.normal );
23892                         _gl.bufferData( 34962, object.normalArray, 35048 );
23893
23894                         bindingStates.enableAttribute( programAttributes.normal );
23895                         _gl.vertexAttribPointer( programAttributes.normal, 3, 5126, false, 0, 0 );
23896
23897                 }
23898
23899                 if ( object.hasUvs ) {
23900
23901                         _gl.bindBuffer( 34962, buffers.uv );
23902                         _gl.bufferData( 34962, object.uvArray, 35048 );
23903
23904                         bindingStates.enableAttribute( programAttributes.uv );
23905                         _gl.vertexAttribPointer( programAttributes.uv, 2, 5126, false, 0, 0 );
23906
23907                 }
23908
23909                 if ( object.hasColors ) {
23910
23911                         _gl.bindBuffer( 34962, buffers.color );
23912                         _gl.bufferData( 34962, object.colorArray, 35048 );
23913
23914                         bindingStates.enableAttribute( programAttributes.color );
23915                         _gl.vertexAttribPointer( programAttributes.color, 3, 5126, false, 0, 0 );
23916
23917                 }
23918
23919                 bindingStates.disableUnusedAttributes();
23920
23921                 _gl.drawArrays( 4, 0, object.count );
23922
23923                 object.count = 0;
23924
23925         };
23926
23927         this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {
23928
23929                 if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null)
23930
23931                 const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
23932
23933                 const program = setProgram( camera, scene, material, object );
23934
23935                 state.setMaterial( material, frontFaceCW );
23936
23937                 //
23938
23939                 let index = geometry.index;
23940                 const position = geometry.attributes.position;
23941
23942                 //
23943
23944                 if ( index === null ) {
23945
23946                         if ( position === undefined || position.count === 0 ) return;
23947
23948                 } else if ( index.count === 0 ) {
23949
23950                         return;
23951
23952                 }
23953
23954                 //
23955
23956                 let rangeFactor = 1;
23957
23958                 if ( material.wireframe === true ) {
23959
23960                         index = geometries.getWireframeAttribute( geometry );
23961                         rangeFactor = 2;
23962
23963                 }
23964
23965                 if ( material.morphTargets || material.morphNormals ) {
23966
23967                         morphtargets.update( object, geometry, material, program );
23968
23969                 }
23970
23971                 bindingStates.setup( object, material, program, geometry, index );
23972
23973                 let attribute;
23974                 let renderer = bufferRenderer;
23975
23976                 if ( index !== null ) {
23977
23978                         attribute = attributes.get( index );
23979
23980                         renderer = indexedBufferRenderer;
23981                         renderer.setIndex( attribute );
23982
23983                 }
23984
23985                 //
23986
23987                 const dataCount = ( index !== null ) ? index.count : position.count;
23988
23989                 const rangeStart = geometry.drawRange.start * rangeFactor;
23990                 const rangeCount = geometry.drawRange.count * rangeFactor;
23991
23992                 const groupStart = group !== null ? group.start * rangeFactor : 0;
23993                 const groupCount = group !== null ? group.count * rangeFactor : Infinity;
23994
23995                 const drawStart = Math.max( rangeStart, groupStart );
23996                 const drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
23997
23998                 const drawCount = Math.max( 0, drawEnd - drawStart + 1 );
23999
24000                 if ( drawCount === 0 ) return;
24001
24002                 //
24003
24004                 if ( object.isMesh ) {
24005
24006                         if ( material.wireframe === true ) {
24007
24008                                 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
24009                                 renderer.setMode( 1 );
24010
24011                         } else {
24012
24013                                 renderer.setMode( 4 );
24014
24015                         }
24016
24017                 } else if ( object.isLine ) {
24018
24019                         let lineWidth = material.linewidth;
24020
24021                         if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
24022
24023                         state.setLineWidth( lineWidth * getTargetPixelRatio() );
24024
24025                         if ( object.isLineSegments ) {
24026
24027                                 renderer.setMode( 1 );
24028
24029                         } else if ( object.isLineLoop ) {
24030
24031                                 renderer.setMode( 2 );
24032
24033                         } else {
24034
24035                                 renderer.setMode( 3 );
24036
24037                         }
24038
24039                 } else if ( object.isPoints ) {
24040
24041                         renderer.setMode( 0 );
24042
24043                 } else if ( object.isSprite ) {
24044
24045                         renderer.setMode( 4 );
24046
24047                 }
24048
24049                 if ( object.isInstancedMesh ) {
24050
24051                         renderer.renderInstances( drawStart, drawCount, object.count );
24052
24053                 } else if ( geometry.isInstancedBufferGeometry ) {
24054
24055                         const instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );
24056
24057                         renderer.renderInstances( drawStart, drawCount, instanceCount );
24058
24059                 } else {
24060
24061                         renderer.render( drawStart, drawCount );
24062
24063                 }
24064
24065         };
24066
24067         // Compile
24068
24069         this.compile = function ( scene, camera ) {
24070
24071                 currentRenderState = renderStates.get( scene, camera );
24072                 currentRenderState.init();
24073
24074                 scene.traverseVisible( function ( object ) {
24075
24076                         if ( object.isLight && object.layers.test( camera.layers ) ) {
24077
24078                                 currentRenderState.pushLight( object );
24079
24080                                 if ( object.castShadow ) {
24081
24082                                         currentRenderState.pushShadow( object );
24083
24084                                 }
24085
24086                         }
24087
24088                 } );
24089
24090                 currentRenderState.setupLights( camera );
24091
24092                 const compiled = new WeakMap();
24093
24094                 scene.traverse( function ( object ) {
24095
24096                         const material = object.material;
24097
24098                         if ( material ) {
24099
24100                                 if ( Array.isArray( material ) ) {
24101
24102                                         for ( let i = 0; i < material.length; i ++ ) {
24103
24104                                                 const material2 = material[ i ];
24105
24106                                                 if ( compiled.has( material2 ) === false ) {
24107
24108                                                         initMaterial( material2, scene, object );
24109                                                         compiled.set( material2 );
24110
24111                                                 }
24112
24113                                         }
24114
24115                                 } else if ( compiled.has( material ) === false ) {
24116
24117                                         initMaterial( material, scene, object );
24118                                         compiled.set( material );
24119
24120                                 }
24121
24122                         }
24123
24124                 } );
24125
24126         };
24127
24128         // Animation Loop
24129
24130         let onAnimationFrameCallback = null;
24131
24132         function onAnimationFrame( time ) {
24133
24134                 if ( xr.isPresenting ) return;
24135                 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
24136
24137         }
24138
24139         const animation = new WebGLAnimation();
24140         animation.setAnimationLoop( onAnimationFrame );
24141
24142         if ( typeof window !== 'undefined' ) animation.setContext( window );
24143
24144         this.setAnimationLoop = function ( callback ) {
24145
24146                 onAnimationFrameCallback = callback;
24147                 xr.setAnimationLoop( callback );
24148
24149                 ( callback === null ) ? animation.stop() : animation.start();
24150
24151         };
24152
24153         // Rendering
24154
24155         this.render = function ( scene, camera ) {
24156
24157                 let renderTarget, forceClear;
24158
24159                 if ( arguments[ 2 ] !== undefined ) {
24160
24161                         console.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );
24162                         renderTarget = arguments[ 2 ];
24163
24164                 }
24165
24166                 if ( arguments[ 3 ] !== undefined ) {
24167
24168                         console.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );
24169                         forceClear = arguments[ 3 ];
24170
24171                 }
24172
24173                 if ( camera !== undefined && camera.isCamera !== true ) {
24174
24175                         console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
24176                         return;
24177
24178                 }
24179
24180                 if ( _isContextLost === true ) return;
24181
24182                 // reset caching for this frame
24183
24184                 bindingStates.resetDefaultState();
24185                 _currentMaterialId = - 1;
24186                 _currentCamera = null;
24187
24188                 // update scene graph
24189
24190                 if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
24191
24192                 // update camera matrices and frustum
24193
24194                 if ( camera.parent === null ) camera.updateMatrixWorld();
24195
24196                 if ( xr.enabled === true && xr.isPresenting === true ) {
24197
24198                         camera = xr.getCamera( camera );
24199
24200                 }
24201
24202                 //
24203                 if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );
24204
24205                 currentRenderState = renderStates.get( scene, camera );
24206                 currentRenderState.init();
24207
24208                 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
24209                 _frustum.setFromProjectionMatrix( _projScreenMatrix );
24210
24211                 _localClippingEnabled = this.localClippingEnabled;
24212                 _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
24213
24214                 currentRenderList = renderLists.get( scene, camera );
24215                 currentRenderList.init();
24216
24217                 projectObject( scene, camera, 0, _this.sortObjects );
24218
24219                 currentRenderList.finish();
24220
24221                 if ( _this.sortObjects === true ) {
24222
24223                         currentRenderList.sort( _opaqueSort, _transparentSort );
24224
24225                 }
24226
24227                 //
24228
24229                 if ( _clippingEnabled === true ) clipping.beginShadows();
24230
24231                 const shadowsArray = currentRenderState.state.shadowsArray;
24232
24233                 shadowMap.render( shadowsArray, scene, camera );
24234
24235                 currentRenderState.setupLights( camera );
24236
24237                 if ( _clippingEnabled === true ) clipping.endShadows();
24238
24239                 //
24240
24241                 if ( this.info.autoReset === true ) this.info.reset();
24242
24243                 if ( renderTarget !== undefined ) {
24244
24245                         this.setRenderTarget( renderTarget );
24246
24247                 }
24248
24249                 //
24250
24251                 background.render( currentRenderList, scene, camera, forceClear );
24252
24253                 // render scene
24254
24255                 const opaqueObjects = currentRenderList.opaque;
24256                 const transparentObjects = currentRenderList.transparent;
24257
24258                 if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
24259                 if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
24260
24261                 //
24262
24263                 if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );
24264
24265                 //
24266
24267                 if ( _currentRenderTarget !== null ) {
24268
24269                         // Generate mipmap if we're using any kind of mipmap filtering
24270
24271                         textures.updateRenderTargetMipmap( _currentRenderTarget );
24272
24273                         // resolve multisample renderbuffers to a single-sample texture if necessary
24274
24275                         textures.updateMultisampleRenderTarget( _currentRenderTarget );
24276
24277                 }
24278
24279                 // Ensure depth buffer writing is enabled so it can be cleared on next render
24280
24281                 state.buffers.depth.setTest( true );
24282                 state.buffers.depth.setMask( true );
24283                 state.buffers.color.setMask( true );
24284
24285                 state.setPolygonOffset( false );
24286
24287                 // _gl.finish();
24288
24289                 currentRenderList = null;
24290                 currentRenderState = null;
24291
24292         };
24293
24294         function projectObject( object, camera, groupOrder, sortObjects ) {
24295
24296                 if ( object.visible === false ) return;
24297
24298                 const visible = object.layers.test( camera.layers );
24299
24300                 if ( visible ) {
24301
24302                         if ( object.isGroup ) {
24303
24304                                 groupOrder = object.renderOrder;
24305
24306                         } else if ( object.isLOD ) {
24307
24308                                 if ( object.autoUpdate === true ) object.update( camera );
24309
24310                         } else if ( object.isLight ) {
24311
24312                                 currentRenderState.pushLight( object );
24313
24314                                 if ( object.castShadow ) {
24315
24316                                         currentRenderState.pushShadow( object );
24317
24318                                 }
24319
24320                         } else if ( object.isSprite ) {
24321
24322                                 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
24323
24324                                         if ( sortObjects ) {
24325
24326                                                 _vector3.setFromMatrixPosition( object.matrixWorld )
24327                                                         .applyMatrix4( _projScreenMatrix );
24328
24329                                         }
24330
24331                                         const geometry = objects.update( object );
24332                                         const material = object.material;
24333
24334                                         if ( material.visible ) {
24335
24336                                                 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
24337
24338                                         }
24339
24340                                 }
24341
24342                         } else if ( object.isImmediateRenderObject ) {
24343
24344                                 if ( sortObjects ) {
24345
24346                                         _vector3.setFromMatrixPosition( object.matrixWorld )
24347                                                 .applyMatrix4( _projScreenMatrix );
24348
24349                                 }
24350
24351                                 currentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );
24352
24353                         } else if ( object.isMesh || object.isLine || object.isPoints ) {
24354
24355                                 if ( object.isSkinnedMesh ) {
24356
24357                                         // update skeleton only once in a frame
24358
24359                                         if ( object.skeleton.frame !== info.render.frame ) {
24360
24361                                                 object.skeleton.update();
24362                                                 object.skeleton.frame = info.render.frame;
24363
24364                                         }
24365
24366                                 }
24367
24368                                 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
24369
24370                                         if ( sortObjects ) {
24371
24372                                                 _vector3.setFromMatrixPosition( object.matrixWorld )
24373                                                         .applyMatrix4( _projScreenMatrix );
24374
24375                                         }
24376
24377                                         const geometry = objects.update( object );
24378                                         const material = object.material;
24379
24380                                         if ( Array.isArray( material ) ) {
24381
24382                                                 const groups = geometry.groups;
24383
24384                                                 for ( let i = 0, l = groups.length; i < l; i ++ ) {
24385
24386                                                         const group = groups[ i ];
24387                                                         const groupMaterial = material[ group.materialIndex ];
24388
24389                                                         if ( groupMaterial && groupMaterial.visible ) {
24390
24391                                                                 currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
24392
24393                                                         }
24394
24395                                                 }
24396
24397                                         } else if ( material.visible ) {
24398
24399                                                 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
24400
24401                                         }
24402
24403                                 }
24404
24405                         }
24406
24407                 }
24408
24409                 const children = object.children;
24410
24411                 for ( let i = 0, l = children.length; i < l; i ++ ) {
24412
24413                         projectObject( children[ i ], camera, groupOrder, sortObjects );
24414
24415                 }
24416
24417         }
24418
24419         function renderObjects( renderList, scene, camera ) {
24420
24421                 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
24422
24423                 for ( let i = 0, l = renderList.length; i < l; i ++ ) {
24424
24425                         const renderItem = renderList[ i ];
24426
24427                         const object = renderItem.object;
24428                         const geometry = renderItem.geometry;
24429                         const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
24430                         const group = renderItem.group;
24431
24432                         if ( camera.isArrayCamera ) {
24433
24434                                 _currentArrayCamera = camera;
24435
24436                                 const cameras = camera.cameras;
24437
24438                                 for ( let j = 0, jl = cameras.length; j < jl; j ++ ) {
24439
24440                                         const camera2 = cameras[ j ];
24441
24442                                         if ( object.layers.test( camera2.layers ) ) {
24443
24444                                                 state.viewport( _currentViewport.copy( camera2.viewport ) );
24445
24446                                                 currentRenderState.setupLights( camera2 );
24447
24448                                                 renderObject( object, scene, camera2, geometry, material, group );
24449
24450                                         }
24451
24452                                 }
24453
24454                         } else {
24455
24456                                 _currentArrayCamera = null;
24457
24458                                 renderObject( object, scene, camera, geometry, material, group );
24459
24460                         }
24461
24462                 }
24463
24464         }
24465
24466         function renderObject( object, scene, camera, geometry, material, group ) {
24467
24468                 object.onBeforeRender( _this, scene, camera, geometry, material, group );
24469                 currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
24470
24471                 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
24472                 object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
24473
24474                 if ( object.isImmediateRenderObject ) {
24475
24476                         const program = setProgram( camera, scene, material, object );
24477
24478                         state.setMaterial( material );
24479
24480                         bindingStates.reset();
24481
24482                         renderObjectImmediate( object, program );
24483
24484                 } else {
24485
24486                         _this.renderBufferDirect( camera, scene, geometry, material, object, group );
24487
24488                 }
24489
24490                 object.onAfterRender( _this, scene, camera, geometry, material, group );
24491                 currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
24492
24493         }
24494
24495         function initMaterial( material, scene, object ) {
24496
24497                 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
24498
24499                 const materialProperties = properties.get( material );
24500
24501                 const lights = currentRenderState.state.lights;
24502                 const shadowsArray = currentRenderState.state.shadowsArray;
24503
24504                 const lightsStateVersion = lights.state.version;
24505
24506                 const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object );
24507                 const programCacheKey = programCache.getProgramCacheKey( parameters );
24508
24509                 let program = materialProperties.program;
24510                 let programChange = true;
24511
24512                 if ( program === undefined ) {
24513
24514                         // new material
24515                         material.addEventListener( 'dispose', onMaterialDispose );
24516
24517                 } else if ( program.cacheKey !== programCacheKey ) {
24518
24519                         // changed glsl or parameters
24520                         releaseMaterialProgramReference( material );
24521
24522                 } else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) {
24523
24524                         programChange = false;
24525
24526                 } else if ( parameters.shaderID !== undefined ) {
24527
24528                         // same glsl and uniform list, envMap still needs the update here to avoid a frame-late effect
24529
24530                         const environment = material.isMeshStandardMaterial ? scene.environment : null;
24531                         materialProperties.envMap = cubemaps.get( material.envMap || environment );
24532
24533                         return;
24534
24535                 } else {
24536
24537                         // only rebuild uniform list
24538                         programChange = false;
24539
24540                 }
24541
24542                 if ( programChange ) {
24543
24544                         parameters.uniforms = programCache.getUniforms( material );
24545
24546                         material.onBeforeCompile( parameters, _this );
24547
24548                         program = programCache.acquireProgram( parameters, programCacheKey );
24549
24550                         materialProperties.program = program;
24551                         materialProperties.uniforms = parameters.uniforms;
24552                         materialProperties.outputEncoding = parameters.outputEncoding;
24553
24554                 }
24555
24556                 const uniforms = materialProperties.uniforms;
24557
24558                 if ( ! material.isShaderMaterial &&
24559                         ! material.isRawShaderMaterial ||
24560                         material.clipping === true ) {
24561
24562                         materialProperties.numClippingPlanes = clipping.numPlanes;
24563                         materialProperties.numIntersection = clipping.numIntersection;
24564                         uniforms.clippingPlanes = clipping.uniform;
24565
24566                 }
24567
24568                 materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
24569                 materialProperties.fog = scene.fog;
24570                 materialProperties.envMap = cubemaps.get( material.envMap || materialProperties.environment );
24571
24572                 // store the light setup it was created for
24573
24574                 materialProperties.needsLights = materialNeedsLights( material );
24575                 materialProperties.lightsStateVersion = lightsStateVersion;
24576
24577                 if ( materialProperties.needsLights ) {
24578
24579                         // wire up the material to this renderer's lighting state
24580
24581                         uniforms.ambientLightColor.value = lights.state.ambient;
24582                         uniforms.lightProbe.value = lights.state.probe;
24583                         uniforms.directionalLights.value = lights.state.directional;
24584                         uniforms.directionalLightShadows.value = lights.state.directionalShadow;
24585                         uniforms.spotLights.value = lights.state.spot;
24586                         uniforms.spotLightShadows.value = lights.state.spotShadow;
24587                         uniforms.rectAreaLights.value = lights.state.rectArea;
24588                         uniforms.ltc_1.value = lights.state.rectAreaLTC1;
24589                         uniforms.ltc_2.value = lights.state.rectAreaLTC2;
24590                         uniforms.pointLights.value = lights.state.point;
24591                         uniforms.pointLightShadows.value = lights.state.pointShadow;
24592                         uniforms.hemisphereLights.value = lights.state.hemi;
24593
24594                         uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
24595                         uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
24596                         uniforms.spotShadowMap.value = lights.state.spotShadowMap;
24597                         uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
24598                         uniforms.pointShadowMap.value = lights.state.pointShadowMap;
24599                         uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
24600                         // TODO (abelnation): add area lights shadow info to uniforms
24601
24602                 }
24603
24604                 const progUniforms = materialProperties.program.getUniforms();
24605                 const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
24606
24607                 materialProperties.uniformsList = uniformsList;
24608
24609         }
24610
24611         function setProgram( camera, scene, material, object ) {
24612
24613                 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
24614
24615                 textures.resetTextureUnits();
24616
24617                 const fog = scene.fog;
24618                 const environment = material.isMeshStandardMaterial ? scene.environment : null;
24619                 const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding;
24620                 const envMap = cubemaps.get( material.envMap || environment );
24621
24622                 const materialProperties = properties.get( material );
24623                 const lights = currentRenderState.state.lights;
24624
24625                 if ( _clippingEnabled === true ) {
24626
24627                         if ( _localClippingEnabled === true || camera !== _currentCamera ) {
24628
24629                                 const useCache =
24630                                         camera === _currentCamera &&
24631                                         material.id === _currentMaterialId;
24632
24633                                 // we might want to call this function with some ClippingGroup
24634                                 // object instead of the material, once it becomes feasible
24635                                 // (#8465, #8379)
24636                                 clipping.setState( material, camera, useCache );
24637
24638                         }
24639
24640                 }
24641
24642                 if ( material.version === materialProperties.__version ) {
24643
24644                         if ( material.fog && materialProperties.fog !== fog ) {
24645
24646                                 initMaterial( material, scene, object );
24647
24648                         } else if ( materialProperties.environment !== environment ) {
24649
24650                                 initMaterial( material, scene, object );
24651
24652                         } else if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
24653
24654                                 initMaterial( material, scene, object );
24655
24656                         } else if ( materialProperties.numClippingPlanes !== undefined &&
24657                                 ( materialProperties.numClippingPlanes !== clipping.numPlanes ||
24658                                 materialProperties.numIntersection !== clipping.numIntersection ) ) {
24659
24660                                 initMaterial( material, scene, object );
24661
24662                         } else if ( materialProperties.outputEncoding !== encoding ) {
24663
24664                                 initMaterial( material, scene, object );
24665
24666                         } else if ( materialProperties.envMap !== envMap ) {
24667
24668                                 initMaterial( material, scene, object );
24669
24670                         }
24671
24672                 } else {
24673
24674                         initMaterial( material, scene, object );
24675                         materialProperties.__version = material.version;
24676
24677                 }
24678
24679                 let refreshProgram = false;
24680                 let refreshMaterial = false;
24681                 let refreshLights = false;
24682
24683                 const program = materialProperties.program,
24684                         p_uniforms = program.getUniforms(),
24685                         m_uniforms = materialProperties.uniforms;
24686
24687                 if ( state.useProgram( program.program ) ) {
24688
24689                         refreshProgram = true;
24690                         refreshMaterial = true;
24691                         refreshLights = true;
24692
24693                 }
24694
24695                 if ( material.id !== _currentMaterialId ) {
24696
24697                         _currentMaterialId = material.id;
24698
24699                         refreshMaterial = true;
24700
24701                 }
24702
24703                 if ( refreshProgram || _currentCamera !== camera ) {
24704
24705                         p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
24706
24707                         if ( capabilities.logarithmicDepthBuffer ) {
24708
24709                                 p_uniforms.setValue( _gl, 'logDepthBufFC',
24710                                         2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
24711
24712                         }
24713
24714                         if ( _currentCamera !== camera ) {
24715
24716                                 _currentCamera = camera;
24717
24718                                 // lighting uniforms depend on the camera so enforce an update
24719                                 // now, in case this material supports lights - or later, when
24720                                 // the next material that does gets activated:
24721
24722                                 refreshMaterial = true;         // set to true on material change
24723                                 refreshLights = true;           // remains set until update done
24724
24725                         }
24726
24727                         // load material specific uniforms
24728                         // (shader material also gets them for the sake of genericity)
24729
24730                         if ( material.isShaderMaterial ||
24731                                 material.isMeshPhongMaterial ||
24732                                 material.isMeshToonMaterial ||
24733                                 material.isMeshStandardMaterial ||
24734                                 material.envMap ) {
24735
24736                                 const uCamPos = p_uniforms.map.cameraPosition;
24737
24738                                 if ( uCamPos !== undefined ) {
24739
24740                                         uCamPos.setValue( _gl,
24741                                                 _vector3.setFromMatrixPosition( camera.matrixWorld ) );
24742
24743                                 }
24744
24745                         }
24746
24747                         if ( material.isMeshPhongMaterial ||
24748                                 material.isMeshToonMaterial ||
24749                                 material.isMeshLambertMaterial ||
24750                                 material.isMeshBasicMaterial ||
24751                                 material.isMeshStandardMaterial ||
24752                                 material.isShaderMaterial ) {
24753
24754                                 p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );
24755
24756                         }
24757
24758                         if ( material.isMeshPhongMaterial ||
24759                                 material.isMeshToonMaterial ||
24760                                 material.isMeshLambertMaterial ||
24761                                 material.isMeshBasicMaterial ||
24762                                 material.isMeshStandardMaterial ||
24763                                 material.isShaderMaterial ||
24764                                 material.isShadowMaterial ||
24765                                 material.skinning ) {
24766
24767                                 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
24768
24769                         }
24770
24771                 }
24772
24773                 // skinning uniforms must be set even if material didn't change
24774                 // auto-setting of texture unit for bone texture must go before other textures
24775                 // otherwise textures used for skinning can take over texture units reserved for other material textures
24776
24777                 if ( material.skinning ) {
24778
24779                         p_uniforms.setOptional( _gl, object, 'bindMatrix' );
24780                         p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
24781
24782                         const skeleton = object.skeleton;
24783
24784                         if ( skeleton ) {
24785
24786                                 const bones = skeleton.bones;
24787
24788                                 if ( capabilities.floatVertexTextures ) {
24789
24790                                         if ( skeleton.boneTexture === null ) {
24791
24792                                                 // layout (1 matrix = 4 pixels)
24793                                                 //      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
24794                                                 //  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
24795                                                 //       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
24796                                                 //       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
24797                                                 //       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
24798
24799
24800                                                 let size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
24801                                                 size = MathUtils.ceilPowerOfTwo( size );
24802                                                 size = Math.max( size, 4 );
24803
24804                                                 const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
24805                                                 boneMatrices.set( skeleton.boneMatrices ); // copy current values
24806
24807                                                 const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
24808
24809                                                 skeleton.boneMatrices = boneMatrices;
24810                                                 skeleton.boneTexture = boneTexture;
24811                                                 skeleton.boneTextureSize = size;
24812
24813                                         }
24814
24815                                         p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );
24816                                         p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
24817
24818                                 } else {
24819
24820                                         p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
24821
24822                                 }
24823
24824                         }
24825
24826                 }
24827
24828                 if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {
24829
24830                         materialProperties.receiveShadow = object.receiveShadow;
24831                         p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );
24832
24833                 }
24834
24835                 if ( refreshMaterial ) {
24836
24837                         p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
24838
24839                         if ( materialProperties.needsLights ) {
24840
24841                                 // the current material requires lighting info
24842
24843                                 // note: all lighting uniforms are always set correctly
24844                                 // they simply reference the renderer's state for their
24845                                 // values
24846                                 //
24847                                 // use the current material's .needsUpdate flags to set
24848                                 // the GL state when required
24849
24850                                 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
24851
24852                         }
24853
24854                         // refresh uniforms common to several materials
24855
24856                         if ( fog && material.fog ) {
24857
24858                                 materials.refreshFogUniforms( m_uniforms, fog );
24859
24860                         }
24861
24862                         materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height );
24863
24864                         WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
24865
24866                 }
24867
24868                 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
24869
24870                         WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
24871                         material.uniformsNeedUpdate = false;
24872
24873                 }
24874
24875                 if ( material.isSpriteMaterial ) {
24876
24877                         p_uniforms.setValue( _gl, 'center', object.center );
24878
24879                 }
24880
24881                 // common matrices
24882
24883                 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
24884                 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
24885                 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
24886
24887                 return program;
24888
24889         }
24890
24891         // If uniforms are marked as clean, they don't need to be loaded to the GPU.
24892
24893         function markUniformsLightsNeedsUpdate( uniforms, value ) {
24894
24895                 uniforms.ambientLightColor.needsUpdate = value;
24896                 uniforms.lightProbe.needsUpdate = value;
24897
24898                 uniforms.directionalLights.needsUpdate = value;
24899                 uniforms.directionalLightShadows.needsUpdate = value;
24900                 uniforms.pointLights.needsUpdate = value;
24901                 uniforms.pointLightShadows.needsUpdate = value;
24902                 uniforms.spotLights.needsUpdate = value;
24903                 uniforms.spotLightShadows.needsUpdate = value;
24904                 uniforms.rectAreaLights.needsUpdate = value;
24905                 uniforms.hemisphereLights.needsUpdate = value;
24906
24907         }
24908
24909         function materialNeedsLights( material ) {
24910
24911                 return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
24912                         material.isMeshStandardMaterial || material.isShadowMaterial ||
24913                         ( material.isShaderMaterial && material.lights === true );
24914
24915         }
24916
24917         //
24918         this.setFramebuffer = function ( value ) {
24919
24920                 if ( _framebuffer !== value && _currentRenderTarget === null ) _gl.bindFramebuffer( 36160, value );
24921
24922                 _framebuffer = value;
24923
24924         };
24925
24926         this.getActiveCubeFace = function () {
24927
24928                 return _currentActiveCubeFace;
24929
24930         };
24931
24932         this.getActiveMipmapLevel = function () {
24933
24934                 return _currentActiveMipmapLevel;
24935
24936         };
24937
24938         this.getRenderList = function () {
24939
24940                 return currentRenderList;
24941
24942         };
24943
24944         this.setRenderList = function ( renderList ) {
24945
24946                 currentRenderList = renderList;
24947
24948         };
24949
24950         this.getRenderState = function () {
24951
24952                 return currentRenderState;
24953
24954         };
24955
24956         this.setRenderState = function ( renderState ) {
24957
24958                 currentRenderState = renderState;
24959
24960         };
24961
24962         this.getRenderTarget = function () {
24963
24964                 return _currentRenderTarget;
24965
24966         };
24967
24968         this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) {
24969
24970                 _currentRenderTarget = renderTarget;
24971                 _currentActiveCubeFace = activeCubeFace;
24972                 _currentActiveMipmapLevel = activeMipmapLevel;
24973
24974                 if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
24975
24976                         textures.setupRenderTarget( renderTarget );
24977
24978                 }
24979
24980                 let framebuffer = _framebuffer;
24981                 let isCube = false;
24982
24983                 if ( renderTarget ) {
24984
24985                         const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
24986
24987                         if ( renderTarget.isWebGLCubeRenderTarget ) {
24988
24989                                 framebuffer = __webglFramebuffer[ activeCubeFace ];
24990                                 isCube = true;
24991
24992                         } else if ( renderTarget.isWebGLMultisampleRenderTarget ) {
24993
24994                                 framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
24995
24996                         } else {
24997
24998                                 framebuffer = __webglFramebuffer;
24999
25000                         }
25001
25002                         _currentViewport.copy( renderTarget.viewport );
25003                         _currentScissor.copy( renderTarget.scissor );
25004                         _currentScissorTest = renderTarget.scissorTest;
25005
25006                 } else {
25007
25008                         _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
25009                         _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
25010                         _currentScissorTest = _scissorTest;
25011
25012                 }
25013
25014                 if ( _currentFramebuffer !== framebuffer ) {
25015
25016                         _gl.bindFramebuffer( 36160, framebuffer );
25017                         _currentFramebuffer = framebuffer;
25018
25019                 }
25020
25021                 state.viewport( _currentViewport );
25022                 state.scissor( _currentScissor );
25023                 state.setScissorTest( _currentScissorTest );
25024
25025                 if ( isCube ) {
25026
25027                         const textureProperties = properties.get( renderTarget.texture );
25028                         _gl.framebufferTexture2D( 36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel );
25029
25030                 }
25031
25032         };
25033
25034         this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
25035
25036                 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
25037
25038                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
25039                         return;
25040
25041                 }
25042
25043                 let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
25044
25045                 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
25046
25047                         framebuffer = framebuffer[ activeCubeFaceIndex ];
25048
25049                 }
25050
25051                 if ( framebuffer ) {
25052
25053                         let restore = false;
25054
25055                         if ( framebuffer !== _currentFramebuffer ) {
25056
25057                                 _gl.bindFramebuffer( 36160, framebuffer );
25058
25059                                 restore = true;
25060
25061                         }
25062
25063                         try {
25064
25065                                 const texture = renderTarget.texture;
25066                                 const textureFormat = texture.format;
25067                                 const textureType = texture.type;
25068
25069                                 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {
25070
25071                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
25072                                         return;
25073
25074                                 }
25075
25076                                 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // IE11, Edge and Chrome Mac < 52 (#9513)
25077                                         ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
25078                                         ! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {
25079
25080                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
25081                                         return;
25082
25083                                 }
25084
25085                                 if ( _gl.checkFramebufferStatus( 36160 ) === 36053 ) {
25086
25087                                         // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
25088
25089                                         if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
25090
25091                                                 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
25092
25093                                         }
25094
25095                                 } else {
25096
25097                                         console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
25098
25099                                 }
25100
25101                         } finally {
25102
25103                                 if ( restore ) {
25104
25105                                         _gl.bindFramebuffer( 36160, _currentFramebuffer );
25106
25107                                 }
25108
25109                         }
25110
25111                 }
25112
25113         };
25114
25115         this.copyFramebufferToTexture = function ( position, texture, level = 0 ) {
25116
25117                 const levelScale = Math.pow( 2, - level );
25118                 const width = Math.floor( texture.image.width * levelScale );
25119                 const height = Math.floor( texture.image.height * levelScale );
25120                 const glFormat = utils.convert( texture.format );
25121
25122                 textures.setTexture2D( texture, 0 );
25123
25124                 _gl.copyTexImage2D( 3553, level, glFormat, position.x, position.y, width, height, 0 );
25125
25126                 state.unbindTexture();
25127
25128         };
25129
25130         this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) {
25131
25132                 const width = srcTexture.image.width;
25133                 const height = srcTexture.image.height;
25134                 const glFormat = utils.convert( dstTexture.format );
25135                 const glType = utils.convert( dstTexture.type );
25136
25137                 textures.setTexture2D( dstTexture, 0 );
25138
25139                 // As another texture upload may have changed pixelStorei
25140                 // parameters, make sure they are correct for the dstTexture
25141                 _gl.pixelStorei( 37440, dstTexture.flipY );
25142                 _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha );
25143                 _gl.pixelStorei( 3317, dstTexture.unpackAlignment );
25144
25145                 if ( srcTexture.isDataTexture ) {
25146
25147                         _gl.texSubImage2D( 3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
25148
25149                 } else {
25150
25151                         if ( srcTexture.isCompressedTexture ) {
25152
25153                                 _gl.compressedTexSubImage2D( 3553, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
25154
25155                         } else {
25156
25157                                 _gl.texSubImage2D( 3553, level, position.x, position.y, glFormat, glType, srcTexture.image );
25158
25159                         }
25160
25161                 }
25162
25163                 // Generate mipmaps only when copying level 0
25164                 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( 3553 );
25165
25166                 state.unbindTexture();
25167
25168         };
25169
25170         this.initTexture = function ( texture ) {
25171
25172                 textures.setTexture2D( texture, 0 );
25173
25174                 state.unbindTexture();
25175
25176         };
25177
25178         if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
25179
25180                 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
25181
25182         }
25183
25184 }
25185
25186 function WebGL1Renderer( parameters ) {
25187
25188         WebGLRenderer.call( this, parameters );
25189
25190 }
25191
25192 WebGL1Renderer.prototype = Object.assign( Object.create( WebGLRenderer.prototype ), {
25193
25194         constructor: WebGL1Renderer,
25195
25196         isWebGL1Renderer: true
25197
25198 } );
25199
25200 class FogExp2 {
25201
25202         constructor( color, density ) {
25203
25204                 Object.defineProperty( this, 'isFogExp2', { value: true } );
25205
25206                 this.name = '';
25207
25208                 this.color = new Color( color );
25209                 this.density = ( density !== undefined ) ? density : 0.00025;
25210
25211         }
25212
25213         clone() {
25214
25215                 return new FogExp2( this.color, this.density );
25216
25217         }
25218
25219         toJSON( /* meta */ ) {
25220
25221                 return {
25222                         type: 'FogExp2',
25223                         color: this.color.getHex(),
25224                         density: this.density
25225                 };
25226
25227         }
25228
25229 }
25230
25231 class Fog {
25232
25233         constructor( color, near, far ) {
25234
25235                 Object.defineProperty( this, 'isFog', { value: true } );
25236
25237                 this.name = '';
25238
25239                 this.color = new Color( color );
25240
25241                 this.near = ( near !== undefined ) ? near : 1;
25242                 this.far = ( far !== undefined ) ? far : 1000;
25243
25244         }
25245
25246         clone() {
25247
25248                 return new Fog( this.color, this.near, this.far );
25249
25250         }
25251
25252         toJSON( /* meta */ ) {
25253
25254                 return {
25255                         type: 'Fog',
25256                         color: this.color.getHex(),
25257                         near: this.near,
25258                         far: this.far
25259                 };
25260
25261         }
25262
25263 }
25264
25265 class Scene extends Object3D {
25266
25267         constructor() {
25268
25269                 super();
25270
25271                 Object.defineProperty( this, 'isScene', { value: true } );
25272
25273                 this.type = 'Scene';
25274
25275                 this.background = null;
25276                 this.environment = null;
25277                 this.fog = null;
25278
25279                 this.overrideMaterial = null;
25280
25281                 this.autoUpdate = true; // checked by the renderer
25282
25283                 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
25284
25285                         __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
25286
25287                 }
25288
25289         }
25290
25291         copy( source, recursive ) {
25292
25293                 super.copy( source, recursive );
25294
25295                 if ( source.background !== null ) this.background = source.background.clone();
25296                 if ( source.environment !== null ) this.environment = source.environment.clone();
25297                 if ( source.fog !== null ) this.fog = source.fog.clone();
25298
25299                 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
25300
25301                 this.autoUpdate = source.autoUpdate;
25302                 this.matrixAutoUpdate = source.matrixAutoUpdate;
25303
25304                 return this;
25305
25306         }
25307
25308         toJSON( meta ) {
25309
25310                 const data = super.toJSON( meta );
25311
25312                 if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
25313                 if ( this.environment !== null ) data.object.environment = this.environment.toJSON( meta );
25314                 if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
25315
25316                 return data;
25317
25318         }
25319
25320 }
25321
25322 function InterleavedBuffer( array, stride ) {
25323
25324         this.array = array;
25325         this.stride = stride;
25326         this.count = array !== undefined ? array.length / stride : 0;
25327
25328         this.usage = StaticDrawUsage;
25329         this.updateRange = { offset: 0, count: - 1 };
25330
25331         this.version = 0;
25332
25333         this.uuid = MathUtils.generateUUID();
25334
25335 }
25336
25337 Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
25338
25339         set: function ( value ) {
25340
25341                 if ( value === true ) this.version ++;
25342
25343         }
25344
25345 } );
25346
25347 Object.assign( InterleavedBuffer.prototype, {
25348
25349         isInterleavedBuffer: true,
25350
25351         onUploadCallback: function () {},
25352
25353         setUsage: function ( value ) {
25354
25355                 this.usage = value;
25356
25357                 return this;
25358
25359         },
25360
25361         copy: function ( source ) {
25362
25363                 this.array = new source.array.constructor( source.array );
25364                 this.count = source.count;
25365                 this.stride = source.stride;
25366                 this.usage = source.usage;
25367
25368                 return this;
25369
25370         },
25371
25372         copyAt: function ( index1, attribute, index2 ) {
25373
25374                 index1 *= this.stride;
25375                 index2 *= attribute.stride;
25376
25377                 for ( let i = 0, l = this.stride; i < l; i ++ ) {
25378
25379                         this.array[ index1 + i ] = attribute.array[ index2 + i ];
25380
25381                 }
25382
25383                 return this;
25384
25385         },
25386
25387         set: function ( value, offset = 0 ) {
25388
25389                 this.array.set( value, offset );
25390
25391                 return this;
25392
25393         },
25394
25395         clone: function ( data ) {
25396
25397                 if ( data.arrayBuffers === undefined ) {
25398
25399                         data.arrayBuffers = {};
25400
25401                 }
25402
25403                 if ( this.array.buffer._uuid === undefined ) {
25404
25405                         this.array.buffer._uuid = MathUtils.generateUUID();
25406
25407                 }
25408
25409                 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
25410
25411                         data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
25412
25413                 }
25414
25415                 const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
25416
25417                 const ib = new InterleavedBuffer( array, this.stride );
25418                 ib.setUsage( this.usage );
25419
25420                 return ib;
25421
25422         },
25423
25424         onUpload: function ( callback ) {
25425
25426                 this.onUploadCallback = callback;
25427
25428                 return this;
25429
25430         },
25431
25432         toJSON: function ( data ) {
25433
25434                 if ( data.arrayBuffers === undefined ) {
25435
25436                         data.arrayBuffers = {};
25437
25438                 }
25439
25440                 // generate UUID for array buffer if necessary
25441
25442                 if ( this.array.buffer._uuid === undefined ) {
25443
25444                         this.array.buffer._uuid = MathUtils.generateUUID();
25445
25446                 }
25447
25448                 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
25449
25450                         data.arrayBuffers[ this.array.buffer._uuid ] = Array.prototype.slice.call( new Uint32Array( this.array.buffer ) );
25451
25452                 }
25453
25454                 //
25455
25456                 return {
25457                         uuid: this.uuid,
25458                         buffer: this.array.buffer._uuid,
25459                         type: this.array.constructor.name,
25460                         stride: this.stride
25461                 };
25462
25463         }
25464
25465 } );
25466
25467 const _vector$6 = new Vector3();
25468
25469 function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
25470
25471         this.name = '';
25472
25473         this.data = interleavedBuffer;
25474         this.itemSize = itemSize;
25475         this.offset = offset;
25476
25477         this.normalized = normalized === true;
25478
25479 }
25480
25481 Object.defineProperties( InterleavedBufferAttribute.prototype, {
25482
25483         count: {
25484
25485                 get: function () {
25486
25487                         return this.data.count;
25488
25489                 }
25490
25491         },
25492
25493         array: {
25494
25495                 get: function () {
25496
25497                         return this.data.array;
25498
25499                 }
25500
25501         },
25502
25503         needsUpdate: {
25504
25505                 set: function ( value ) {
25506
25507                         this.data.needsUpdate = value;
25508
25509                 }
25510
25511         }
25512
25513 } );
25514
25515 Object.assign( InterleavedBufferAttribute.prototype, {
25516
25517         isInterleavedBufferAttribute: true,
25518
25519         applyMatrix4: function ( m ) {
25520
25521                 for ( let i = 0, l = this.data.count; i < l; i ++ ) {
25522
25523                         _vector$6.x = this.getX( i );
25524                         _vector$6.y = this.getY( i );
25525                         _vector$6.z = this.getZ( i );
25526
25527                         _vector$6.applyMatrix4( m );
25528
25529                         this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
25530
25531                 }
25532
25533                 return this;
25534
25535         },
25536
25537         setX: function ( index, x ) {
25538
25539                 this.data.array[ index * this.data.stride + this.offset ] = x;
25540
25541                 return this;
25542
25543         },
25544
25545         setY: function ( index, y ) {
25546
25547                 this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
25548
25549                 return this;
25550
25551         },
25552
25553         setZ: function ( index, z ) {
25554
25555                 this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
25556
25557                 return this;
25558
25559         },
25560
25561         setW: function ( index, w ) {
25562
25563                 this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
25564
25565                 return this;
25566
25567         },
25568
25569         getX: function ( index ) {
25570
25571                 return this.data.array[ index * this.data.stride + this.offset ];
25572
25573         },
25574
25575         getY: function ( index ) {
25576
25577                 return this.data.array[ index * this.data.stride + this.offset + 1 ];
25578
25579         },
25580
25581         getZ: function ( index ) {
25582
25583                 return this.data.array[ index * this.data.stride + this.offset + 2 ];
25584
25585         },
25586
25587         getW: function ( index ) {
25588
25589                 return this.data.array[ index * this.data.stride + this.offset + 3 ];
25590
25591         },
25592
25593         setXY: function ( index, x, y ) {
25594
25595                 index = index * this.data.stride + this.offset;
25596
25597                 this.data.array[ index + 0 ] = x;
25598                 this.data.array[ index + 1 ] = y;
25599
25600                 return this;
25601
25602         },
25603
25604         setXYZ: function ( index, x, y, z ) {
25605
25606                 index = index * this.data.stride + this.offset;
25607
25608                 this.data.array[ index + 0 ] = x;
25609                 this.data.array[ index + 1 ] = y;
25610                 this.data.array[ index + 2 ] = z;
25611
25612                 return this;
25613
25614         },
25615
25616         setXYZW: function ( index, x, y, z, w ) {
25617
25618                 index = index * this.data.stride + this.offset;
25619
25620                 this.data.array[ index + 0 ] = x;
25621                 this.data.array[ index + 1 ] = y;
25622                 this.data.array[ index + 2 ] = z;
25623                 this.data.array[ index + 3 ] = w;
25624
25625                 return this;
25626
25627         },
25628
25629         clone: function ( data ) {
25630
25631                 if ( data === undefined ) {
25632
25633                         console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interlaved buffer attribute will deinterleave buffer data.' );
25634
25635                         const array = [];
25636
25637                         for ( let i = 0; i < this.count; i ++ ) {
25638
25639                                 const index = i * this.data.stride + this.offset;
25640
25641                                 for ( let j = 0; j < this.itemSize; j ++ ) {
25642
25643                                         array.push( this.data.array[ index + j ] );
25644
25645                                 }
25646
25647                         }
25648
25649                         return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
25650
25651                 } else {
25652
25653                         if ( data.interleavedBuffers === undefined ) {
25654
25655                                 data.interleavedBuffers = {};
25656
25657                         }
25658
25659                         if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
25660
25661                                 data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
25662
25663                         }
25664
25665                         return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
25666
25667                 }
25668
25669         },
25670
25671         toJSON: function ( data ) {
25672
25673                 if ( data === undefined ) {
25674
25675                         console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.' );
25676
25677                         const array = [];
25678
25679                         for ( let i = 0; i < this.count; i ++ ) {
25680
25681                                 const index = i * this.data.stride + this.offset;
25682
25683                                 for ( let j = 0; j < this.itemSize; j ++ ) {
25684
25685                                         array.push( this.data.array[ index + j ] );
25686
25687                                 }
25688
25689                         }
25690
25691                         // deinterleave data and save it as an ordinary buffer attribute for now
25692
25693                         return {
25694                                 itemSize: this.itemSize,
25695                                 type: this.array.constructor.name,
25696                                 array: array,
25697                                 normalized: this.normalized
25698                         };
25699
25700                 } else {
25701
25702                         // save as true interlaved attribtue
25703
25704                         if ( data.interleavedBuffers === undefined ) {
25705
25706                                 data.interleavedBuffers = {};
25707
25708                         }
25709
25710                         if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
25711
25712                                 data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
25713
25714                         }
25715
25716                         return {
25717                                 isInterleavedBufferAttribute: true,
25718                                 itemSize: this.itemSize,
25719                                 data: this.data.uuid,
25720                                 offset: this.offset,
25721                                 normalized: this.normalized
25722                         };
25723
25724                 }
25725
25726         }
25727
25728 } );
25729
25730 /**
25731  * parameters = {
25732  *  color: <hex>,
25733  *  map: new THREE.Texture( <Image> ),
25734  *  alphaMap: new THREE.Texture( <Image> ),
25735  *  rotation: <float>,
25736  *  sizeAttenuation: <bool>
25737  * }
25738  */
25739
25740 function SpriteMaterial( parameters ) {
25741
25742         Material.call( this );
25743
25744         this.type = 'SpriteMaterial';
25745
25746         this.color = new Color( 0xffffff );
25747
25748         this.map = null;
25749
25750         this.alphaMap = null;
25751
25752         this.rotation = 0;
25753
25754         this.sizeAttenuation = true;
25755
25756         this.transparent = true;
25757
25758         this.setValues( parameters );
25759
25760 }
25761
25762 SpriteMaterial.prototype = Object.create( Material.prototype );
25763 SpriteMaterial.prototype.constructor = SpriteMaterial;
25764 SpriteMaterial.prototype.isSpriteMaterial = true;
25765
25766 SpriteMaterial.prototype.copy = function ( source ) {
25767
25768         Material.prototype.copy.call( this, source );
25769
25770         this.color.copy( source.color );
25771
25772         this.map = source.map;
25773
25774         this.alphaMap = source.alphaMap;
25775
25776         this.rotation = source.rotation;
25777
25778         this.sizeAttenuation = source.sizeAttenuation;
25779
25780         return this;
25781
25782 };
25783
25784 let _geometry;
25785
25786 const _intersectPoint = new Vector3();
25787 const _worldScale = new Vector3();
25788 const _mvPosition = new Vector3();
25789
25790 const _alignedPosition = new Vector2();
25791 const _rotatedPosition = new Vector2();
25792 const _viewWorldMatrix = new Matrix4();
25793
25794 const _vA$1 = new Vector3();
25795 const _vB$1 = new Vector3();
25796 const _vC$1 = new Vector3();
25797
25798 const _uvA$1 = new Vector2();
25799 const _uvB$1 = new Vector2();
25800 const _uvC$1 = new Vector2();
25801
25802 function Sprite( material ) {
25803
25804         Object3D.call( this );
25805
25806         this.type = 'Sprite';
25807
25808         if ( _geometry === undefined ) {
25809
25810                 _geometry = new BufferGeometry();
25811
25812                 const float32Array = new Float32Array( [
25813                         - 0.5, - 0.5, 0, 0, 0,
25814                         0.5, - 0.5, 0, 1, 0,
25815                         0.5, 0.5, 0, 1, 1,
25816                         - 0.5, 0.5, 0, 0, 1
25817                 ] );
25818
25819                 const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
25820
25821                 _geometry.setIndex( [ 0, 1, 2,  0, 2, 3 ] );
25822                 _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
25823                 _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
25824
25825         }
25826
25827         this.geometry = _geometry;
25828         this.material = ( material !== undefined ) ? material : new SpriteMaterial();
25829
25830         this.center = new Vector2( 0.5, 0.5 );
25831
25832 }
25833
25834 Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
25835
25836         constructor: Sprite,
25837
25838         isSprite: true,
25839
25840         raycast: function ( raycaster, intersects ) {
25841
25842                 if ( raycaster.camera === null ) {
25843
25844                         console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
25845
25846                 }
25847
25848                 _worldScale.setFromMatrixScale( this.matrixWorld );
25849
25850                 _viewWorldMatrix.copy( raycaster.camera.matrixWorld );
25851                 this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
25852
25853                 _mvPosition.setFromMatrixPosition( this.modelViewMatrix );
25854
25855                 if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
25856
25857                         _worldScale.multiplyScalar( - _mvPosition.z );
25858
25859                 }
25860
25861                 const rotation = this.material.rotation;
25862                 let sin, cos;
25863
25864                 if ( rotation !== 0 ) {
25865
25866                         cos = Math.cos( rotation );
25867                         sin = Math.sin( rotation );
25868
25869                 }
25870
25871                 const center = this.center;
25872
25873                 transformVertex( _vA$1.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
25874                 transformVertex( _vB$1.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
25875                 transformVertex( _vC$1.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
25876
25877                 _uvA$1.set( 0, 0 );
25878                 _uvB$1.set( 1, 0 );
25879                 _uvC$1.set( 1, 1 );
25880
25881                 // check first triangle
25882                 let intersect = raycaster.ray.intersectTriangle( _vA$1, _vB$1, _vC$1, false, _intersectPoint );
25883
25884                 if ( intersect === null ) {
25885
25886                         // check second triangle
25887                         transformVertex( _vB$1.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
25888                         _uvB$1.set( 0, 1 );
25889
25890                         intersect = raycaster.ray.intersectTriangle( _vA$1, _vC$1, _vB$1, false, _intersectPoint );
25891                         if ( intersect === null ) {
25892
25893                                 return;
25894
25895                         }
25896
25897                 }
25898
25899                 const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
25900
25901                 if ( distance < raycaster.near || distance > raycaster.far ) return;
25902
25903                 intersects.push( {
25904
25905                         distance: distance,
25906                         point: _intersectPoint.clone(),
25907                         uv: Triangle.getUV( _intersectPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ),
25908                         face: null,
25909                         object: this
25910
25911                 } );
25912
25913         },
25914
25915         copy: function ( source ) {
25916
25917                 Object3D.prototype.copy.call( this, source );
25918
25919                 if ( source.center !== undefined ) this.center.copy( source.center );
25920
25921                 this.material = source.material;
25922
25923                 return this;
25924
25925         }
25926
25927 } );
25928
25929 function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
25930
25931         // compute position in camera space
25932         _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
25933
25934         // to check if rotation is not zero
25935         if ( sin !== undefined ) {
25936
25937                 _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
25938                 _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
25939
25940         } else {
25941
25942                 _rotatedPosition.copy( _alignedPosition );
25943
25944         }
25945
25946
25947         vertexPosition.copy( mvPosition );
25948         vertexPosition.x += _rotatedPosition.x;
25949         vertexPosition.y += _rotatedPosition.y;
25950
25951         // transform to world space
25952         vertexPosition.applyMatrix4( _viewWorldMatrix );
25953
25954 }
25955
25956 const _v1$4 = new Vector3();
25957 const _v2$2 = new Vector3();
25958
25959 function LOD() {
25960
25961         Object3D.call( this );
25962
25963         this._currentLevel = 0;
25964
25965         this.type = 'LOD';
25966
25967         Object.defineProperties( this, {
25968                 levels: {
25969                         enumerable: true,
25970                         value: []
25971                 }
25972         } );
25973
25974         this.autoUpdate = true;
25975
25976 }
25977
25978 LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
25979
25980         constructor: LOD,
25981
25982         isLOD: true,
25983
25984         copy: function ( source ) {
25985
25986                 Object3D.prototype.copy.call( this, source, false );
25987
25988                 const levels = source.levels;
25989
25990                 for ( let i = 0, l = levels.length; i < l; i ++ ) {
25991
25992                         const level = levels[ i ];
25993
25994                         this.addLevel( level.object.clone(), level.distance );
25995
25996                 }
25997
25998                 this.autoUpdate = source.autoUpdate;
25999
26000                 return this;
26001
26002         },
26003
26004         addLevel: function ( object, distance = 0 ) {
26005
26006                 distance = Math.abs( distance );
26007
26008                 const levels = this.levels;
26009
26010                 let l;
26011
26012                 for ( l = 0; l < levels.length; l ++ ) {
26013
26014                         if ( distance < levels[ l ].distance ) {
26015
26016                                 break;
26017
26018                         }
26019
26020                 }
26021
26022                 levels.splice( l, 0, { distance: distance, object: object } );
26023
26024                 this.add( object );
26025
26026                 return this;
26027
26028         },
26029
26030         getCurrentLevel: function () {
26031
26032                 return this._currentLevel;
26033
26034         },
26035
26036         getObjectForDistance: function ( distance ) {
26037
26038                 const levels = this.levels;
26039
26040                 if ( levels.length > 0 ) {
26041
26042                         let i, l;
26043
26044                         for ( i = 1, l = levels.length; i < l; i ++ ) {
26045
26046                                 if ( distance < levels[ i ].distance ) {
26047
26048                                         break;
26049
26050                                 }
26051
26052                         }
26053
26054                         return levels[ i - 1 ].object;
26055
26056                 }
26057
26058                 return null;
26059
26060         },
26061
26062         raycast: function ( raycaster, intersects ) {
26063
26064                 const levels = this.levels;
26065
26066                 if ( levels.length > 0 ) {
26067
26068                         _v1$4.setFromMatrixPosition( this.matrixWorld );
26069
26070                         const distance = raycaster.ray.origin.distanceTo( _v1$4 );
26071
26072                         this.getObjectForDistance( distance ).raycast( raycaster, intersects );
26073
26074                 }
26075
26076         },
26077
26078         update: function ( camera ) {
26079
26080                 const levels = this.levels;
26081
26082                 if ( levels.length > 1 ) {
26083
26084                         _v1$4.setFromMatrixPosition( camera.matrixWorld );
26085                         _v2$2.setFromMatrixPosition( this.matrixWorld );
26086
26087                         const distance = _v1$4.distanceTo( _v2$2 ) / camera.zoom;
26088
26089                         levels[ 0 ].object.visible = true;
26090
26091                         let i, l;
26092
26093                         for ( i = 1, l = levels.length; i < l; i ++ ) {
26094
26095                                 if ( distance >= levels[ i ].distance ) {
26096
26097                                         levels[ i - 1 ].object.visible = false;
26098                                         levels[ i ].object.visible = true;
26099
26100                                 } else {
26101
26102                                         break;
26103
26104                                 }
26105
26106                         }
26107
26108                         this._currentLevel = i - 1;
26109
26110                         for ( ; i < l; i ++ ) {
26111
26112                                 levels[ i ].object.visible = false;
26113
26114                         }
26115
26116                 }
26117
26118         },
26119
26120         toJSON: function ( meta ) {
26121
26122                 const data = Object3D.prototype.toJSON.call( this, meta );
26123
26124                 if ( this.autoUpdate === false ) data.object.autoUpdate = false;
26125
26126                 data.object.levels = [];
26127
26128                 const levels = this.levels;
26129
26130                 for ( let i = 0, l = levels.length; i < l; i ++ ) {
26131
26132                         const level = levels[ i ];
26133
26134                         data.object.levels.push( {
26135                                 object: level.object.uuid,
26136                                 distance: level.distance
26137                         } );
26138
26139                 }
26140
26141                 return data;
26142
26143         }
26144
26145 } );
26146
26147 function SkinnedMesh( geometry, material ) {
26148
26149         if ( geometry && geometry.isGeometry ) {
26150
26151                 console.error( 'THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
26152
26153         }
26154
26155         Mesh.call( this, geometry, material );
26156
26157         this.type = 'SkinnedMesh';
26158
26159         this.bindMode = 'attached';
26160         this.bindMatrix = new Matrix4();
26161         this.bindMatrixInverse = new Matrix4();
26162
26163 }
26164
26165 SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
26166
26167         constructor: SkinnedMesh,
26168
26169         isSkinnedMesh: true,
26170
26171         copy: function ( source ) {
26172
26173                 Mesh.prototype.copy.call( this, source );
26174
26175                 this.bindMode = source.bindMode;
26176                 this.bindMatrix.copy( source.bindMatrix );
26177                 this.bindMatrixInverse.copy( source.bindMatrixInverse );
26178
26179                 this.skeleton = source.skeleton;
26180
26181                 return this;
26182
26183         },
26184
26185         bind: function ( skeleton, bindMatrix ) {
26186
26187                 this.skeleton = skeleton;
26188
26189                 if ( bindMatrix === undefined ) {
26190
26191                         this.updateMatrixWorld( true );
26192
26193                         this.skeleton.calculateInverses();
26194
26195                         bindMatrix = this.matrixWorld;
26196
26197                 }
26198
26199                 this.bindMatrix.copy( bindMatrix );
26200                 this.bindMatrixInverse.copy( bindMatrix ).invert();
26201
26202         },
26203
26204         pose: function () {
26205
26206                 this.skeleton.pose();
26207
26208         },
26209
26210         normalizeSkinWeights: function () {
26211
26212                 const vector = new Vector4();
26213
26214                 const skinWeight = this.geometry.attributes.skinWeight;
26215
26216                 for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
26217
26218                         vector.x = skinWeight.getX( i );
26219                         vector.y = skinWeight.getY( i );
26220                         vector.z = skinWeight.getZ( i );
26221                         vector.w = skinWeight.getW( i );
26222
26223                         const scale = 1.0 / vector.manhattanLength();
26224
26225                         if ( scale !== Infinity ) {
26226
26227                                 vector.multiplyScalar( scale );
26228
26229                         } else {
26230
26231                                 vector.set( 1, 0, 0, 0 ); // do something reasonable
26232
26233                         }
26234
26235                         skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
26236
26237                 }
26238
26239         },
26240
26241         updateMatrixWorld: function ( force ) {
26242
26243                 Mesh.prototype.updateMatrixWorld.call( this, force );
26244
26245                 if ( this.bindMode === 'attached' ) {
26246
26247                         this.bindMatrixInverse.copy( this.matrixWorld ).invert();
26248
26249                 } else if ( this.bindMode === 'detached' ) {
26250
26251                         this.bindMatrixInverse.copy( this.bindMatrix ).invert();
26252
26253                 } else {
26254
26255                         console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
26256
26257                 }
26258
26259         },
26260
26261         boneTransform: ( function () {
26262
26263                 const basePosition = new Vector3();
26264
26265                 const skinIndex = new Vector4();
26266                 const skinWeight = new Vector4();
26267
26268                 const vector = new Vector3();
26269                 const matrix = new Matrix4();
26270
26271                 return function ( index, target ) {
26272
26273                         const skeleton = this.skeleton;
26274                         const geometry = this.geometry;
26275
26276                         skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
26277                         skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
26278
26279                         basePosition.fromBufferAttribute( geometry.attributes.position, index ).applyMatrix4( this.bindMatrix );
26280
26281                         target.set( 0, 0, 0 );
26282
26283                         for ( let i = 0; i < 4; i ++ ) {
26284
26285                                 const weight = skinWeight.getComponent( i );
26286
26287                                 if ( weight !== 0 ) {
26288
26289                                         const boneIndex = skinIndex.getComponent( i );
26290
26291                                         matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
26292
26293                                         target.addScaledVector( vector.copy( basePosition ).applyMatrix4( matrix ), weight );
26294
26295                                 }
26296
26297                         }
26298
26299                         return target.applyMatrix4( this.bindMatrixInverse );
26300
26301                 };
26302
26303         }() )
26304
26305 } );
26306
26307 function Bone() {
26308
26309         Object3D.call( this );
26310
26311         this.type = 'Bone';
26312
26313 }
26314
26315 Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
26316
26317         constructor: Bone,
26318
26319         isBone: true
26320
26321 } );
26322
26323 const _offsetMatrix = new Matrix4();
26324 const _identityMatrix = new Matrix4();
26325
26326 function Skeleton( bones = [], boneInverses = [] ) {
26327
26328         this.uuid = MathUtils.generateUUID();
26329
26330         this.bones = bones.slice( 0 );
26331         this.boneInverses = boneInverses;
26332         this.boneMatrices = null;
26333
26334         this.boneTexture = null;
26335         this.boneTextureSize = 0;
26336
26337         this.frame = - 1;
26338
26339         this.init();
26340
26341 }
26342
26343 Object.assign( Skeleton.prototype, {
26344
26345         init: function () {
26346
26347                 const bones = this.bones;
26348                 const boneInverses = this.boneInverses;
26349
26350                 this.boneMatrices = new Float32Array( bones.length * 16 );
26351
26352                 // calculate inverse bone matrices if necessary
26353
26354                 if ( boneInverses.length === 0 ) {
26355
26356                         this.calculateInverses();
26357
26358                 } else {
26359
26360                         // handle special case
26361
26362                         if ( bones.length !== boneInverses.length ) {
26363
26364                                 console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' );
26365
26366                                 this.boneInverses = [];
26367
26368                                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26369
26370                                         this.boneInverses.push( new Matrix4() );
26371
26372                                 }
26373
26374                         }
26375
26376                 }
26377
26378         },
26379
26380         calculateInverses: function () {
26381
26382                 this.boneInverses.length = 0;
26383
26384                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26385
26386                         const inverse = new Matrix4();
26387
26388                         if ( this.bones[ i ] ) {
26389
26390                                 inverse.copy( this.bones[ i ].matrixWorld ).invert();
26391
26392                         }
26393
26394                         this.boneInverses.push( inverse );
26395
26396                 }
26397
26398         },
26399
26400         pose: function () {
26401
26402                 // recover the bind-time world matrices
26403
26404                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26405
26406                         const bone = this.bones[ i ];
26407
26408                         if ( bone ) {
26409
26410                                 bone.matrixWorld.copy( this.boneInverses[ i ] ).invert();
26411
26412                         }
26413
26414                 }
26415
26416                 // compute the local matrices, positions, rotations and scales
26417
26418                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26419
26420                         const bone = this.bones[ i ];
26421
26422                         if ( bone ) {
26423
26424                                 if ( bone.parent && bone.parent.isBone ) {
26425
26426                                         bone.matrix.copy( bone.parent.matrixWorld ).invert();
26427                                         bone.matrix.multiply( bone.matrixWorld );
26428
26429                                 } else {
26430
26431                                         bone.matrix.copy( bone.matrixWorld );
26432
26433                                 }
26434
26435                                 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
26436
26437                         }
26438
26439                 }
26440
26441         },
26442
26443         update: function () {
26444
26445                 const bones = this.bones;
26446                 const boneInverses = this.boneInverses;
26447                 const boneMatrices = this.boneMatrices;
26448                 const boneTexture = this.boneTexture;
26449
26450                 // flatten bone matrices to array
26451
26452                 for ( let i = 0, il = bones.length; i < il; i ++ ) {
26453
26454                         // compute the offset between the current and the original transform
26455
26456                         const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;
26457
26458                         _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
26459                         _offsetMatrix.toArray( boneMatrices, i * 16 );
26460
26461                 }
26462
26463                 if ( boneTexture !== null ) {
26464
26465                         boneTexture.needsUpdate = true;
26466
26467                 }
26468
26469         },
26470
26471         clone: function () {
26472
26473                 return new Skeleton( this.bones, this.boneInverses );
26474
26475         },
26476
26477         getBoneByName: function ( name ) {
26478
26479                 for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
26480
26481                         const bone = this.bones[ i ];
26482
26483                         if ( bone.name === name ) {
26484
26485                                 return bone;
26486
26487                         }
26488
26489                 }
26490
26491                 return undefined;
26492
26493         },
26494
26495         dispose: function ( ) {
26496
26497                 if ( this.boneTexture !== null ) {
26498
26499                         this.boneTexture.dispose();
26500
26501                         this.boneTexture = null;
26502
26503                 }
26504
26505         },
26506
26507         fromJSON: function ( json, bones ) {
26508
26509                 this.uuid = json.uuid;
26510
26511                 for ( let i = 0, l = json.bones.length; i < l; i ++ ) {
26512
26513                         const uuid = json.bones[ i ];
26514                         let bone = bones[ uuid ];
26515
26516                         if ( bone === undefined ) {
26517
26518                                 console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid );
26519                                 bone = new Bone();
26520
26521                         }
26522
26523                         this.bones.push( bone );
26524                         this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) );
26525
26526                 }
26527
26528                 this.init();
26529
26530                 return this;
26531
26532         },
26533
26534         toJSON: function () {
26535
26536                 const data = {
26537                         metadata: {
26538                                 version: 4.5,
26539                                 type: 'Skeleton',
26540                                 generator: 'Skeleton.toJSON'
26541                         },
26542                         bones: [],
26543                         boneInverses: []
26544                 };
26545
26546                 data.uuid = this.uuid;
26547
26548                 const bones = this.bones;
26549                 const boneInverses = this.boneInverses;
26550
26551                 for ( let i = 0, l = bones.length; i < l; i ++ ) {
26552
26553                         const bone = bones[ i ];
26554                         data.bones.push( bone.uuid );
26555
26556                         const boneInverse = boneInverses[ i ];
26557                         data.boneInverses.push( boneInverse.toArray() );
26558
26559                 }
26560
26561                 return data;
26562
26563         }
26564
26565 } );
26566
26567 const _instanceLocalMatrix = new Matrix4();
26568 const _instanceWorldMatrix = new Matrix4();
26569
26570 const _instanceIntersects = [];
26571
26572 const _mesh = new Mesh();
26573
26574 function InstancedMesh( geometry, material, count ) {
26575
26576         Mesh.call( this, geometry, material );
26577
26578         this.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 );
26579         this.instanceColor = null;
26580
26581         this.count = count;
26582
26583         this.frustumCulled = false;
26584
26585 }
26586
26587 InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
26588
26589         constructor: InstancedMesh,
26590
26591         isInstancedMesh: true,
26592
26593         copy: function ( source ) {
26594
26595                 Mesh.prototype.copy.call( this, source );
26596
26597                 this.instanceMatrix.copy( source.instanceMatrix );
26598                 this.count = source.count;
26599
26600                 return this;
26601
26602         },
26603
26604         getColorAt: function ( index, color ) {
26605
26606                 color.fromArray( this.instanceColor.array, index * 3 );
26607
26608         },
26609
26610         getMatrixAt: function ( index, matrix ) {
26611
26612                 matrix.fromArray( this.instanceMatrix.array, index * 16 );
26613
26614         },
26615
26616         raycast: function ( raycaster, intersects ) {
26617
26618                 const matrixWorld = this.matrixWorld;
26619                 const raycastTimes = this.count;
26620
26621                 _mesh.geometry = this.geometry;
26622                 _mesh.material = this.material;
26623
26624                 if ( _mesh.material === undefined ) return;
26625
26626                 for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
26627
26628                         // calculate the world matrix for each instance
26629
26630                         this.getMatrixAt( instanceId, _instanceLocalMatrix );
26631
26632                         _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
26633
26634                         // the mesh represents this single instance
26635
26636                         _mesh.matrixWorld = _instanceWorldMatrix;
26637
26638                         _mesh.raycast( raycaster, _instanceIntersects );
26639
26640                         // process the result of raycast
26641
26642                         for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
26643
26644                                 const intersect = _instanceIntersects[ i ];
26645                                 intersect.instanceId = instanceId;
26646                                 intersect.object = this;
26647                                 intersects.push( intersect );
26648
26649                         }
26650
26651                         _instanceIntersects.length = 0;
26652
26653                 }
26654
26655         },
26656
26657         setColorAt: function ( index, color ) {
26658
26659                 if ( this.instanceColor === null ) {
26660
26661                         this.instanceColor = new BufferAttribute( new Float32Array( this.count * 3 ), 3 );
26662
26663                 }
26664
26665                 color.toArray( this.instanceColor.array, index * 3 );
26666
26667         },
26668
26669         setMatrixAt: function ( index, matrix ) {
26670
26671                 matrix.toArray( this.instanceMatrix.array, index * 16 );
26672
26673         },
26674
26675         updateMorphTargets: function () {
26676
26677         }
26678
26679 } );
26680
26681 /**
26682  * parameters = {
26683  *  color: <hex>,
26684  *  opacity: <float>,
26685  *
26686  *  linewidth: <float>,
26687  *  linecap: "round",
26688  *  linejoin: "round"
26689  * }
26690  */
26691
26692 function LineBasicMaterial( parameters ) {
26693
26694         Material.call( this );
26695
26696         this.type = 'LineBasicMaterial';
26697
26698         this.color = new Color( 0xffffff );
26699
26700         this.linewidth = 1;
26701         this.linecap = 'round';
26702         this.linejoin = 'round';
26703
26704         this.morphTargets = false;
26705
26706         this.setValues( parameters );
26707
26708 }
26709
26710 LineBasicMaterial.prototype = Object.create( Material.prototype );
26711 LineBasicMaterial.prototype.constructor = LineBasicMaterial;
26712
26713 LineBasicMaterial.prototype.isLineBasicMaterial = true;
26714
26715 LineBasicMaterial.prototype.copy = function ( source ) {
26716
26717         Material.prototype.copy.call( this, source );
26718
26719         this.color.copy( source.color );
26720
26721         this.linewidth = source.linewidth;
26722         this.linecap = source.linecap;
26723         this.linejoin = source.linejoin;
26724
26725         this.morphTargets = source.morphTargets;
26726
26727         return this;
26728
26729 };
26730
26731 const _start = new Vector3();
26732 const _end = new Vector3();
26733 const _inverseMatrix$1 = new Matrix4();
26734 const _ray$1 = new Ray();
26735 const _sphere$2 = new Sphere();
26736
26737 function Line( geometry, material, mode ) {
26738
26739         if ( mode === 1 ) {
26740
26741                 console.error( 'THREE.Line: parameter THREE.LinePieces no longer supported. Use THREE.LineSegments instead.' );
26742
26743         }
26744
26745         Object3D.call( this );
26746
26747         this.type = 'Line';
26748
26749         this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
26750         this.material = material !== undefined ? material : new LineBasicMaterial();
26751
26752         this.updateMorphTargets();
26753
26754 }
26755
26756 Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
26757
26758         constructor: Line,
26759
26760         isLine: true,
26761
26762         copy: function ( source ) {
26763
26764                 Object3D.prototype.copy.call( this, source );
26765
26766                 this.material = source.material;
26767                 this.geometry = source.geometry;
26768
26769                 return this;
26770
26771         },
26772
26773         computeLineDistances: function () {
26774
26775                 const geometry = this.geometry;
26776
26777                 if ( geometry.isBufferGeometry ) {
26778
26779                         // we assume non-indexed geometry
26780
26781                         if ( geometry.index === null ) {
26782
26783                                 const positionAttribute = geometry.attributes.position;
26784                                 const lineDistances = [ 0 ];
26785
26786                                 for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
26787
26788                                         _start.fromBufferAttribute( positionAttribute, i - 1 );
26789                                         _end.fromBufferAttribute( positionAttribute, i );
26790
26791                                         lineDistances[ i ] = lineDistances[ i - 1 ];
26792                                         lineDistances[ i ] += _start.distanceTo( _end );
26793
26794                                 }
26795
26796                                 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
26797
26798                         } else {
26799
26800                                 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
26801
26802                         }
26803
26804                 } else if ( geometry.isGeometry ) {
26805
26806                         const vertices = geometry.vertices;
26807                         const lineDistances = geometry.lineDistances;
26808
26809                         lineDistances[ 0 ] = 0;
26810
26811                         for ( let i = 1, l = vertices.length; i < l; i ++ ) {
26812
26813                                 lineDistances[ i ] = lineDistances[ i - 1 ];
26814                                 lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
26815
26816                         }
26817
26818                 }
26819
26820                 return this;
26821
26822         },
26823
26824         raycast: function ( raycaster, intersects ) {
26825
26826                 const geometry = this.geometry;
26827                 const matrixWorld = this.matrixWorld;
26828                 const threshold = raycaster.params.Line.threshold;
26829
26830                 // Checking boundingSphere distance to ray
26831
26832                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
26833
26834                 _sphere$2.copy( geometry.boundingSphere );
26835                 _sphere$2.applyMatrix4( matrixWorld );
26836                 _sphere$2.radius += threshold;
26837
26838                 if ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) return;
26839
26840                 //
26841
26842                 _inverseMatrix$1.copy( matrixWorld ).invert();
26843                 _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
26844
26845                 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
26846                 const localThresholdSq = localThreshold * localThreshold;
26847
26848                 const vStart = new Vector3();
26849                 const vEnd = new Vector3();
26850                 const interSegment = new Vector3();
26851                 const interRay = new Vector3();
26852                 const step = this.isLineSegments ? 2 : 1;
26853
26854                 if ( geometry.isBufferGeometry ) {
26855
26856                         const index = geometry.index;
26857                         const attributes = geometry.attributes;
26858                         const positionAttribute = attributes.position;
26859
26860                         if ( index !== null ) {
26861
26862                                 const indices = index.array;
26863
26864                                 for ( let i = 0, l = indices.length - 1; i < l; i += step ) {
26865
26866                                         const a = indices[ i ];
26867                                         const b = indices[ i + 1 ];
26868
26869                                         vStart.fromBufferAttribute( positionAttribute, a );
26870                                         vEnd.fromBufferAttribute( positionAttribute, b );
26871
26872                                         const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
26873
26874                                         if ( distSq > localThresholdSq ) continue;
26875
26876                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
26877
26878                                         const distance = raycaster.ray.origin.distanceTo( interRay );
26879
26880                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
26881
26882                                         intersects.push( {
26883
26884                                                 distance: distance,
26885                                                 // What do we want? intersection point on the ray or on the segment??
26886                                                 // point: raycaster.ray.at( distance ),
26887                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
26888                                                 index: i,
26889                                                 face: null,
26890                                                 faceIndex: null,
26891                                                 object: this
26892
26893                                         } );
26894
26895                                 }
26896
26897                         } else {
26898
26899                                 for ( let i = 0, l = positionAttribute.count - 1; i < l; i += step ) {
26900
26901                                         vStart.fromBufferAttribute( positionAttribute, i );
26902                                         vEnd.fromBufferAttribute( positionAttribute, i + 1 );
26903
26904                                         const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
26905
26906                                         if ( distSq > localThresholdSq ) continue;
26907
26908                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
26909
26910                                         const distance = raycaster.ray.origin.distanceTo( interRay );
26911
26912                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
26913
26914                                         intersects.push( {
26915
26916                                                 distance: distance,
26917                                                 // What do we want? intersection point on the ray or on the segment??
26918                                                 // point: raycaster.ray.at( distance ),
26919                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
26920                                                 index: i,
26921                                                 face: null,
26922                                                 faceIndex: null,
26923                                                 object: this
26924
26925                                         } );
26926
26927                                 }
26928
26929                         }
26930
26931                 } else if ( geometry.isGeometry ) {
26932
26933                         const vertices = geometry.vertices;
26934                         const nbVertices = vertices.length;
26935
26936                         for ( let i = 0; i < nbVertices - 1; i += step ) {
26937
26938                                 const distSq = _ray$1.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
26939
26940                                 if ( distSq > localThresholdSq ) continue;
26941
26942                                 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
26943
26944                                 const distance = raycaster.ray.origin.distanceTo( interRay );
26945
26946                                 if ( distance < raycaster.near || distance > raycaster.far ) continue;
26947
26948                                 intersects.push( {
26949
26950                                         distance: distance,
26951                                         // What do we want? intersection point on the ray or on the segment??
26952                                         // point: raycaster.ray.at( distance ),
26953                                         point: interSegment.clone().applyMatrix4( this.matrixWorld ),
26954                                         index: i,
26955                                         face: null,
26956                                         faceIndex: null,
26957                                         object: this
26958
26959                                 } );
26960
26961                         }
26962
26963                 }
26964
26965         },
26966
26967         updateMorphTargets: function () {
26968
26969                 const geometry = this.geometry;
26970
26971                 if ( geometry.isBufferGeometry ) {
26972
26973                         const morphAttributes = geometry.morphAttributes;
26974                         const keys = Object.keys( morphAttributes );
26975
26976                         if ( keys.length > 0 ) {
26977
26978                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
26979
26980                                 if ( morphAttribute !== undefined ) {
26981
26982                                         this.morphTargetInfluences = [];
26983                                         this.morphTargetDictionary = {};
26984
26985                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
26986
26987                                                 const name = morphAttribute[ m ].name || String( m );
26988
26989                                                 this.morphTargetInfluences.push( 0 );
26990                                                 this.morphTargetDictionary[ name ] = m;
26991
26992                                         }
26993
26994                                 }
26995
26996                         }
26997
26998                 } else {
26999
27000                         const morphTargets = geometry.morphTargets;
27001
27002                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
27003
27004                                 console.error( 'THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
27005
27006                         }
27007
27008                 }
27009
27010         }
27011
27012 } );
27013
27014 const _start$1 = new Vector3();
27015 const _end$1 = new Vector3();
27016
27017 function LineSegments( geometry, material ) {
27018
27019         Line.call( this, geometry, material );
27020
27021         this.type = 'LineSegments';
27022
27023 }
27024
27025 LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
27026
27027         constructor: LineSegments,
27028
27029         isLineSegments: true,
27030
27031         computeLineDistances: function () {
27032
27033                 const geometry = this.geometry;
27034
27035                 if ( geometry.isBufferGeometry ) {
27036
27037                         // we assume non-indexed geometry
27038
27039                         if ( geometry.index === null ) {
27040
27041                                 const positionAttribute = geometry.attributes.position;
27042                                 const lineDistances = [];
27043
27044                                 for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
27045
27046                                         _start$1.fromBufferAttribute( positionAttribute, i );
27047                                         _end$1.fromBufferAttribute( positionAttribute, i + 1 );
27048
27049                                         lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
27050                                         lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
27051
27052                                 }
27053
27054                                 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
27055
27056                         } else {
27057
27058                                 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
27059
27060                         }
27061
27062                 } else if ( geometry.isGeometry ) {
27063
27064                         const vertices = geometry.vertices;
27065                         const lineDistances = geometry.lineDistances;
27066
27067                         for ( let i = 0, l = vertices.length; i < l; i += 2 ) {
27068
27069                                 _start$1.copy( vertices[ i ] );
27070                                 _end$1.copy( vertices[ i + 1 ] );
27071
27072                                 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
27073                                 lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
27074
27075                         }
27076
27077                 }
27078
27079                 return this;
27080
27081         }
27082
27083 } );
27084
27085 function LineLoop( geometry, material ) {
27086
27087         Line.call( this, geometry, material );
27088
27089         this.type = 'LineLoop';
27090
27091 }
27092
27093 LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
27094
27095         constructor: LineLoop,
27096
27097         isLineLoop: true,
27098
27099 } );
27100
27101 /**
27102  * parameters = {
27103  *  color: <hex>,
27104  *  opacity: <float>,
27105  *  map: new THREE.Texture( <Image> ),
27106  *  alphaMap: new THREE.Texture( <Image> ),
27107  *
27108  *  size: <float>,
27109  *  sizeAttenuation: <bool>
27110  *
27111  *  morphTargets: <bool>
27112  * }
27113  */
27114
27115 function PointsMaterial( parameters ) {
27116
27117         Material.call( this );
27118
27119         this.type = 'PointsMaterial';
27120
27121         this.color = new Color( 0xffffff );
27122
27123         this.map = null;
27124
27125         this.alphaMap = null;
27126
27127         this.size = 1;
27128         this.sizeAttenuation = true;
27129
27130         this.morphTargets = false;
27131
27132         this.setValues( parameters );
27133
27134 }
27135
27136 PointsMaterial.prototype = Object.create( Material.prototype );
27137 PointsMaterial.prototype.constructor = PointsMaterial;
27138
27139 PointsMaterial.prototype.isPointsMaterial = true;
27140
27141 PointsMaterial.prototype.copy = function ( source ) {
27142
27143         Material.prototype.copy.call( this, source );
27144
27145         this.color.copy( source.color );
27146
27147         this.map = source.map;
27148
27149         this.alphaMap = source.alphaMap;
27150
27151         this.size = source.size;
27152         this.sizeAttenuation = source.sizeAttenuation;
27153
27154         this.morphTargets = source.morphTargets;
27155
27156         return this;
27157
27158 };
27159
27160 const _inverseMatrix$2 = new Matrix4();
27161 const _ray$2 = new Ray();
27162 const _sphere$3 = new Sphere();
27163 const _position$1 = new Vector3();
27164
27165 function Points( geometry, material ) {
27166
27167         Object3D.call( this );
27168
27169         this.type = 'Points';
27170
27171         this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
27172         this.material = material !== undefined ? material : new PointsMaterial();
27173
27174         this.updateMorphTargets();
27175
27176 }
27177
27178 Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
27179
27180         constructor: Points,
27181
27182         isPoints: true,
27183
27184         copy: function ( source ) {
27185
27186                 Object3D.prototype.copy.call( this, source );
27187
27188                 this.material = source.material;
27189                 this.geometry = source.geometry;
27190
27191                 return this;
27192
27193         },
27194
27195         raycast: function ( raycaster, intersects ) {
27196
27197                 const geometry = this.geometry;
27198                 const matrixWorld = this.matrixWorld;
27199                 const threshold = raycaster.params.Points.threshold;
27200
27201                 // Checking boundingSphere distance to ray
27202
27203                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
27204
27205                 _sphere$3.copy( geometry.boundingSphere );
27206                 _sphere$3.applyMatrix4( matrixWorld );
27207                 _sphere$3.radius += threshold;
27208
27209                 if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
27210
27211                 //
27212
27213                 _inverseMatrix$2.copy( matrixWorld ).invert();
27214                 _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
27215
27216                 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
27217                 const localThresholdSq = localThreshold * localThreshold;
27218
27219                 if ( geometry.isBufferGeometry ) {
27220
27221                         const index = geometry.index;
27222                         const attributes = geometry.attributes;
27223                         const positionAttribute = attributes.position;
27224
27225                         if ( index !== null ) {
27226
27227                                 const indices = index.array;
27228
27229                                 for ( let i = 0, il = indices.length; i < il; i ++ ) {
27230
27231                                         const a = indices[ i ];
27232
27233                                         _position$1.fromBufferAttribute( positionAttribute, a );
27234
27235                                         testPoint( _position$1, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
27236
27237                                 }
27238
27239                         } else {
27240
27241                                 for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
27242
27243                                         _position$1.fromBufferAttribute( positionAttribute, i );
27244
27245                                         testPoint( _position$1, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
27246
27247                                 }
27248
27249                         }
27250
27251                 } else {
27252
27253                         const vertices = geometry.vertices;
27254
27255                         for ( let i = 0, l = vertices.length; i < l; i ++ ) {
27256
27257                                 testPoint( vertices[ i ], i, localThresholdSq, matrixWorld, raycaster, intersects, this );
27258
27259                         }
27260
27261                 }
27262
27263         },
27264
27265         updateMorphTargets: function () {
27266
27267                 const geometry = this.geometry;
27268
27269                 if ( geometry.isBufferGeometry ) {
27270
27271                         const morphAttributes = geometry.morphAttributes;
27272                         const keys = Object.keys( morphAttributes );
27273
27274                         if ( keys.length > 0 ) {
27275
27276                                 const morphAttribute = morphAttributes[ keys[ 0 ] ];
27277
27278                                 if ( morphAttribute !== undefined ) {
27279
27280                                         this.morphTargetInfluences = [];
27281                                         this.morphTargetDictionary = {};
27282
27283                                         for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
27284
27285                                                 const name = morphAttribute[ m ].name || String( m );
27286
27287                                                 this.morphTargetInfluences.push( 0 );
27288                                                 this.morphTargetDictionary[ name ] = m;
27289
27290                                         }
27291
27292                                 }
27293
27294                         }
27295
27296                 } else {
27297
27298                         const morphTargets = geometry.morphTargets;
27299
27300                         if ( morphTargets !== undefined && morphTargets.length > 0 ) {
27301
27302                                 console.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
27303
27304                         }
27305
27306                 }
27307
27308         }
27309
27310 } );
27311
27312 function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
27313
27314         const rayPointDistanceSq = _ray$2.distanceSqToPoint( point );
27315
27316         if ( rayPointDistanceSq < localThresholdSq ) {
27317
27318                 const intersectPoint = new Vector3();
27319
27320                 _ray$2.closestPointToPoint( point, intersectPoint );
27321                 intersectPoint.applyMatrix4( matrixWorld );
27322
27323                 const distance = raycaster.ray.origin.distanceTo( intersectPoint );
27324
27325                 if ( distance < raycaster.near || distance > raycaster.far ) return;
27326
27327                 intersects.push( {
27328
27329                         distance: distance,
27330                         distanceToRay: Math.sqrt( rayPointDistanceSq ),
27331                         point: intersectPoint,
27332                         index: index,
27333                         face: null,
27334                         object: object
27335
27336                 } );
27337
27338         }
27339
27340 }
27341
27342 function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
27343
27344         Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
27345
27346         this.format = format !== undefined ? format : RGBFormat;
27347
27348         this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
27349         this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
27350
27351         this.generateMipmaps = false;
27352
27353         const scope = this;
27354
27355         function updateVideo() {
27356
27357                 scope.needsUpdate = true;
27358                 video.requestVideoFrameCallback( updateVideo );
27359
27360         }
27361
27362         if ( 'requestVideoFrameCallback' in video ) {
27363
27364                 video.requestVideoFrameCallback( updateVideo );
27365
27366         }
27367
27368 }
27369
27370 VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
27371
27372         constructor: VideoTexture,
27373
27374         clone: function () {
27375
27376                 return new this.constructor( this.image ).copy( this );
27377
27378         },
27379
27380         isVideoTexture: true,
27381
27382         update: function () {
27383
27384                 const video = this.image;
27385                 const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
27386
27387                 if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
27388
27389                         this.needsUpdate = true;
27390
27391                 }
27392
27393         }
27394
27395 } );
27396
27397 function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
27398
27399         Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
27400
27401         this.image = { width: width, height: height };
27402         this.mipmaps = mipmaps;
27403
27404         // no flipping for cube textures
27405         // (also flipping doesn't work for compressed textures )
27406
27407         this.flipY = false;
27408
27409         // can't generate mipmaps for compressed textures
27410         // mips must be embedded in DDS files
27411
27412         this.generateMipmaps = false;
27413
27414 }
27415
27416 CompressedTexture.prototype = Object.create( Texture.prototype );
27417 CompressedTexture.prototype.constructor = CompressedTexture;
27418
27419 CompressedTexture.prototype.isCompressedTexture = true;
27420
27421 function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
27422
27423         Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
27424
27425         this.needsUpdate = true;
27426
27427 }
27428
27429 CanvasTexture.prototype = Object.create( Texture.prototype );
27430 CanvasTexture.prototype.constructor = CanvasTexture;
27431 CanvasTexture.prototype.isCanvasTexture = true;
27432
27433 function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
27434
27435         format = format !== undefined ? format : DepthFormat;
27436
27437         if ( format !== DepthFormat && format !== DepthStencilFormat ) {
27438
27439                 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
27440
27441         }
27442
27443         if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
27444         if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
27445
27446         Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
27447
27448         this.image = { width: width, height: height };
27449
27450         this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
27451         this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
27452
27453         this.flipY = false;
27454         this.generateMipmaps = false;
27455
27456 }
27457
27458 DepthTexture.prototype = Object.create( Texture.prototype );
27459 DepthTexture.prototype.constructor = DepthTexture;
27460 DepthTexture.prototype.isDepthTexture = true;
27461
27462 let _geometryId = 0; // Geometry uses even numbers as Id
27463 const _m1$3 = new Matrix4();
27464 const _obj$1 = new Object3D();
27465 const _offset$1 = new Vector3();
27466
27467 function Geometry() {
27468
27469         Object.defineProperty( this, 'id', { value: _geometryId += 2 } );
27470
27471         this.uuid = MathUtils.generateUUID();
27472
27473         this.name = '';
27474         this.type = 'Geometry';
27475
27476         this.vertices = [];
27477         this.colors = [];
27478         this.faces = [];
27479         this.faceVertexUvs = [[]];
27480
27481         this.morphTargets = [];
27482         this.morphNormals = [];
27483
27484         this.skinWeights = [];
27485         this.skinIndices = [];
27486
27487         this.lineDistances = [];
27488
27489         this.boundingBox = null;
27490         this.boundingSphere = null;
27491
27492         // update flags
27493
27494         this.elementsNeedUpdate = false;
27495         this.verticesNeedUpdate = false;
27496         this.uvsNeedUpdate = false;
27497         this.normalsNeedUpdate = false;
27498         this.colorsNeedUpdate = false;
27499         this.lineDistancesNeedUpdate = false;
27500         this.groupsNeedUpdate = false;
27501
27502 }
27503
27504 Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
27505
27506         constructor: Geometry,
27507
27508         isGeometry: true,
27509
27510         applyMatrix4: function ( matrix ) {
27511
27512                 const normalMatrix = new Matrix3().getNormalMatrix( matrix );
27513
27514                 for ( let i = 0, il = this.vertices.length; i < il; i ++ ) {
27515
27516                         const vertex = this.vertices[ i ];
27517                         vertex.applyMatrix4( matrix );
27518
27519                 }
27520
27521                 for ( let i = 0, il = this.faces.length; i < il; i ++ ) {
27522
27523                         const face = this.faces[ i ];
27524                         face.normal.applyMatrix3( normalMatrix ).normalize();
27525
27526                         for ( let j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
27527
27528                                 face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
27529
27530                         }
27531
27532                 }
27533
27534                 if ( this.boundingBox !== null ) {
27535
27536                         this.computeBoundingBox();
27537
27538                 }
27539
27540                 if ( this.boundingSphere !== null ) {
27541
27542                         this.computeBoundingSphere();
27543
27544                 }
27545
27546                 this.verticesNeedUpdate = true;
27547                 this.normalsNeedUpdate = true;
27548
27549                 return this;
27550
27551         },
27552
27553         rotateX: function ( angle ) {
27554
27555                 // rotate geometry around world x-axis
27556
27557                 _m1$3.makeRotationX( angle );
27558
27559                 this.applyMatrix4( _m1$3 );
27560
27561                 return this;
27562
27563         },
27564
27565         rotateY: function ( angle ) {
27566
27567                 // rotate geometry around world y-axis
27568
27569                 _m1$3.makeRotationY( angle );
27570
27571                 this.applyMatrix4( _m1$3 );
27572
27573                 return this;
27574
27575         },
27576
27577         rotateZ: function ( angle ) {
27578
27579                 // rotate geometry around world z-axis
27580
27581                 _m1$3.makeRotationZ( angle );
27582
27583                 this.applyMatrix4( _m1$3 );
27584
27585                 return this;
27586
27587         },
27588
27589         translate: function ( x, y, z ) {
27590
27591                 // translate geometry
27592
27593                 _m1$3.makeTranslation( x, y, z );
27594
27595                 this.applyMatrix4( _m1$3 );
27596
27597                 return this;
27598
27599         },
27600
27601         scale: function ( x, y, z ) {
27602
27603                 // scale geometry
27604
27605                 _m1$3.makeScale( x, y, z );
27606
27607                 this.applyMatrix4( _m1$3 );
27608
27609                 return this;
27610
27611         },
27612
27613         lookAt: function ( vector ) {
27614
27615                 _obj$1.lookAt( vector );
27616
27617                 _obj$1.updateMatrix();
27618
27619                 this.applyMatrix4( _obj$1.matrix );
27620
27621                 return this;
27622
27623         },
27624
27625         fromBufferGeometry: function ( geometry ) {
27626
27627                 const scope = this;
27628
27629                 const index = geometry.index !== null ? geometry.index : undefined;
27630                 const attributes = geometry.attributes;
27631
27632                 if ( attributes.position === undefined ) {
27633
27634                         console.error( 'THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.' );
27635                         return this;
27636
27637                 }
27638
27639                 const position = attributes.position;
27640                 const normal = attributes.normal;
27641                 const color = attributes.color;
27642                 const uv = attributes.uv;
27643                 const uv2 = attributes.uv2;
27644
27645                 if ( uv2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
27646
27647                 for ( let i = 0; i < position.count; i ++ ) {
27648
27649                         scope.vertices.push( new Vector3().fromBufferAttribute( position, i ) );
27650
27651                         if ( color !== undefined ) {
27652
27653                                 scope.colors.push( new Color().fromBufferAttribute( color, i ) );
27654
27655                         }
27656
27657                 }
27658
27659                 function addFace( a, b, c, materialIndex ) {
27660
27661                         const vertexColors = ( color === undefined ) ? [] : [
27662                                 scope.colors[ a ].clone(),
27663                                 scope.colors[ b ].clone(),
27664                                 scope.colors[ c ].clone()
27665                         ];
27666
27667                         const vertexNormals = ( normal === undefined ) ? [] : [
27668                                 new Vector3().fromBufferAttribute( normal, a ),
27669                                 new Vector3().fromBufferAttribute( normal, b ),
27670                                 new Vector3().fromBufferAttribute( normal, c )
27671                         ];
27672
27673                         const face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
27674
27675                         scope.faces.push( face );
27676
27677                         if ( uv !== undefined ) {
27678
27679                                 scope.faceVertexUvs[ 0 ].push( [
27680                                         new Vector2().fromBufferAttribute( uv, a ),
27681                                         new Vector2().fromBufferAttribute( uv, b ),
27682                                         new Vector2().fromBufferAttribute( uv, c )
27683                                 ] );
27684
27685                         }
27686
27687                         if ( uv2 !== undefined ) {
27688
27689                                 scope.faceVertexUvs[ 1 ].push( [
27690                                         new Vector2().fromBufferAttribute( uv2, a ),
27691                                         new Vector2().fromBufferAttribute( uv2, b ),
27692                                         new Vector2().fromBufferAttribute( uv2, c )
27693                                 ] );
27694
27695                         }
27696
27697                 }
27698
27699                 const groups = geometry.groups;
27700
27701                 if ( groups.length > 0 ) {
27702
27703                         for ( let i = 0; i < groups.length; i ++ ) {
27704
27705                                 const group = groups[ i ];
27706
27707                                 const start = group.start;
27708                                 const count = group.count;
27709
27710                                 for ( let j = start, jl = start + count; j < jl; j += 3 ) {
27711
27712                                         if ( index !== undefined ) {
27713
27714                                                 addFace( index.getX( j ), index.getX( j + 1 ), index.getX( j + 2 ), group.materialIndex );
27715
27716                                         } else {
27717
27718                                                 addFace( j, j + 1, j + 2, group.materialIndex );
27719
27720                                         }
27721
27722                                 }
27723
27724                         }
27725
27726                 } else {
27727
27728                         if ( index !== undefined ) {
27729
27730                                 for ( let i = 0; i < index.count; i += 3 ) {
27731
27732                                         addFace( index.getX( i ), index.getX( i + 1 ), index.getX( i + 2 ) );
27733
27734                                 }
27735
27736                         } else {
27737
27738                                 for ( let i = 0; i < position.count; i += 3 ) {
27739
27740                                         addFace( i, i + 1, i + 2 );
27741
27742                                 }
27743
27744                         }
27745
27746                 }
27747
27748                 this.computeFaceNormals();
27749
27750                 if ( geometry.boundingBox !== null ) {
27751
27752                         this.boundingBox = geometry.boundingBox.clone();
27753
27754                 }
27755
27756                 if ( geometry.boundingSphere !== null ) {
27757
27758                         this.boundingSphere = geometry.boundingSphere.clone();
27759
27760                 }
27761
27762                 return this;
27763
27764         },
27765
27766         center: function () {
27767
27768                 this.computeBoundingBox();
27769
27770                 this.boundingBox.getCenter( _offset$1 ).negate();
27771
27772                 this.translate( _offset$1.x, _offset$1.y, _offset$1.z );
27773
27774                 return this;
27775
27776         },
27777
27778         normalize: function () {
27779
27780                 this.computeBoundingSphere();
27781
27782                 const center = this.boundingSphere.center;
27783                 const radius = this.boundingSphere.radius;
27784
27785                 const s = radius === 0 ? 1 : 1.0 / radius;
27786
27787                 const matrix = new Matrix4();
27788                 matrix.set(
27789                         s, 0, 0, - s * center.x,
27790                         0, s, 0, - s * center.y,
27791                         0, 0, s, - s * center.z,
27792                         0, 0, 0, 1
27793                 );
27794
27795                 this.applyMatrix4( matrix );
27796
27797                 return this;
27798
27799         },
27800
27801         computeFaceNormals: function () {
27802
27803                 const cb = new Vector3(), ab = new Vector3();
27804
27805                 for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
27806
27807                         const face = this.faces[ f ];
27808
27809                         const vA = this.vertices[ face.a ];
27810                         const vB = this.vertices[ face.b ];
27811                         const vC = this.vertices[ face.c ];
27812
27813                         cb.subVectors( vC, vB );
27814                         ab.subVectors( vA, vB );
27815                         cb.cross( ab );
27816
27817                         cb.normalize();
27818
27819                         face.normal.copy( cb );
27820
27821                 }
27822
27823         },
27824
27825         computeVertexNormals: function ( areaWeighted = true ) {
27826
27827                 const vertices = new Array( this.vertices.length );
27828
27829                 for ( let v = 0, vl = this.vertices.length; v < vl; v ++ ) {
27830
27831                         vertices[ v ] = new Vector3();
27832
27833                 }
27834
27835                 if ( areaWeighted ) {
27836
27837                         // vertex normals weighted by triangle areas
27838                         // http://www.iquilezles.org/www/articles/normals/normals.htm
27839
27840                         const cb = new Vector3(), ab = new Vector3();
27841
27842                         for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
27843
27844                                 const face = this.faces[ f ];
27845
27846                                 const vA = this.vertices[ face.a ];
27847                                 const vB = this.vertices[ face.b ];
27848                                 const vC = this.vertices[ face.c ];
27849
27850                                 cb.subVectors( vC, vB );
27851                                 ab.subVectors( vA, vB );
27852                                 cb.cross( ab );
27853
27854                                 vertices[ face.a ].add( cb );
27855                                 vertices[ face.b ].add( cb );
27856                                 vertices[ face.c ].add( cb );
27857
27858                         }
27859
27860                 } else {
27861
27862                         this.computeFaceNormals();
27863
27864                         for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
27865
27866                                 const face = this.faces[ f ];
27867
27868                                 vertices[ face.a ].add( face.normal );
27869                                 vertices[ face.b ].add( face.normal );
27870                                 vertices[ face.c ].add( face.normal );
27871
27872                         }
27873
27874                 }
27875
27876                 for ( let v = 0, vl = this.vertices.length; v < vl; v ++ ) {
27877
27878                         vertices[ v ].normalize();
27879
27880                 }
27881
27882                 for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
27883
27884                         const face = this.faces[ f ];
27885
27886                         const vertexNormals = face.vertexNormals;
27887
27888                         if ( vertexNormals.length === 3 ) {
27889
27890                                 vertexNormals[ 0 ].copy( vertices[ face.a ] );
27891                                 vertexNormals[ 1 ].copy( vertices[ face.b ] );
27892                                 vertexNormals[ 2 ].copy( vertices[ face.c ] );
27893
27894                         } else {
27895
27896                                 vertexNormals[ 0 ] = vertices[ face.a ].clone();
27897                                 vertexNormals[ 1 ] = vertices[ face.b ].clone();
27898                                 vertexNormals[ 2 ] = vertices[ face.c ].clone();
27899
27900                         }
27901
27902                 }
27903
27904                 if ( this.faces.length > 0 ) {
27905
27906                         this.normalsNeedUpdate = true;
27907
27908                 }
27909
27910         },
27911
27912         computeFlatVertexNormals: function () {
27913
27914                 this.computeFaceNormals();
27915
27916                 for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
27917
27918                         const face = this.faces[ f ];
27919
27920                         const vertexNormals = face.vertexNormals;
27921
27922                         if ( vertexNormals.length === 3 ) {
27923
27924                                 vertexNormals[ 0 ].copy( face.normal );
27925                                 vertexNormals[ 1 ].copy( face.normal );
27926                                 vertexNormals[ 2 ].copy( face.normal );
27927
27928                         } else {
27929
27930                                 vertexNormals[ 0 ] = face.normal.clone();
27931                                 vertexNormals[ 1 ] = face.normal.clone();
27932                                 vertexNormals[ 2 ] = face.normal.clone();
27933
27934                         }
27935
27936                 }
27937
27938                 if ( this.faces.length > 0 ) {
27939
27940                         this.normalsNeedUpdate = true;
27941
27942                 }
27943
27944         },
27945
27946         computeMorphNormals: function () {
27947
27948                 // save original normals
27949                 // - create temp variables on first access
27950                 //   otherwise just copy (for faster repeated calls)
27951
27952                 for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
27953
27954                         const face = this.faces[ f ];
27955
27956                         if ( ! face.__originalFaceNormal ) {
27957
27958                                 face.__originalFaceNormal = face.normal.clone();
27959
27960                         } else {
27961
27962                                 face.__originalFaceNormal.copy( face.normal );
27963
27964                         }
27965
27966                         if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
27967
27968                         for ( let i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
27969
27970                                 if ( ! face.__originalVertexNormals[ i ] ) {
27971
27972                                         face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
27973
27974                                 } else {
27975
27976                                         face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
27977
27978                                 }
27979
27980                         }
27981
27982                 }
27983
27984                 // use temp geometry to compute face and vertex normals for each morph
27985
27986                 const tmpGeo = new Geometry();
27987                 tmpGeo.faces = this.faces;
27988
27989                 for ( let i = 0, il = this.morphTargets.length; i < il; i ++ ) {
27990
27991                         // create on first access
27992
27993                         if ( ! this.morphNormals[ i ] ) {
27994
27995                                 this.morphNormals[ i ] = {};
27996                                 this.morphNormals[ i ].faceNormals = [];
27997                                 this.morphNormals[ i ].vertexNormals = [];
27998
27999                                 const dstNormalsFace = this.morphNormals[ i ].faceNormals;
28000                                 const dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
28001
28002                                 for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
28003
28004                                         const faceNormal = new Vector3();
28005                                         const vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
28006
28007                                         dstNormalsFace.push( faceNormal );
28008                                         dstNormalsVertex.push( vertexNormals );
28009
28010                                 }
28011
28012                         }
28013
28014                         const morphNormals = this.morphNormals[ i ];
28015
28016                         // set vertices to morph target
28017
28018                         tmpGeo.vertices = this.morphTargets[ i ].vertices;
28019
28020                         // compute morph normals
28021
28022                         tmpGeo.computeFaceNormals();
28023                         tmpGeo.computeVertexNormals();
28024
28025                         // store morph normals
28026
28027                         for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
28028
28029                                 const face = this.faces[ f ];
28030
28031                                 const faceNormal = morphNormals.faceNormals[ f ];
28032                                 const vertexNormals = morphNormals.vertexNormals[ f ];
28033
28034                                 faceNormal.copy( face.normal );
28035
28036                                 vertexNormals.a.copy( face.vertexNormals[ 0 ] );
28037                                 vertexNormals.b.copy( face.vertexNormals[ 1 ] );
28038                                 vertexNormals.c.copy( face.vertexNormals[ 2 ] );
28039
28040                         }
28041
28042                 }
28043
28044                 // restore original normals
28045
28046                 for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
28047
28048                         const face = this.faces[ f ];
28049
28050                         face.normal = face.__originalFaceNormal;
28051                         face.vertexNormals = face.__originalVertexNormals;
28052
28053                 }
28054
28055         },
28056
28057         computeBoundingBox: function () {
28058
28059                 if ( this.boundingBox === null ) {
28060
28061                         this.boundingBox = new Box3();
28062
28063                 }
28064
28065                 this.boundingBox.setFromPoints( this.vertices );
28066
28067         },
28068
28069         computeBoundingSphere: function () {
28070
28071                 if ( this.boundingSphere === null ) {
28072
28073                         this.boundingSphere = new Sphere();
28074
28075                 }
28076
28077                 this.boundingSphere.setFromPoints( this.vertices );
28078
28079         },
28080
28081         merge: function ( geometry, matrix, materialIndexOffset = 0 ) {
28082
28083                 if ( ! ( geometry && geometry.isGeometry ) ) {
28084
28085                         console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
28086                         return;
28087
28088                 }
28089
28090                 let normalMatrix;
28091                 const vertexOffset = this.vertices.length,
28092                         vertices1 = this.vertices,
28093                         vertices2 = geometry.vertices,
28094                         faces1 = this.faces,
28095                         faces2 = geometry.faces,
28096                         colors1 = this.colors,
28097                         colors2 = geometry.colors;
28098
28099                 if ( matrix !== undefined ) {
28100
28101                         normalMatrix = new Matrix3().getNormalMatrix( matrix );
28102
28103                 }
28104
28105                 // vertices
28106
28107                 for ( let i = 0, il = vertices2.length; i < il; i ++ ) {
28108
28109                         const vertex = vertices2[ i ];
28110
28111                         const vertexCopy = vertex.clone();
28112
28113                         if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
28114
28115                         vertices1.push( vertexCopy );
28116
28117                 }
28118
28119                 // colors
28120
28121                 for ( let i = 0, il = colors2.length; i < il; i ++ ) {
28122
28123                         colors1.push( colors2[ i ].clone() );
28124
28125                 }
28126
28127                 // faces
28128
28129                 for ( let i = 0, il = faces2.length; i < il; i ++ ) {
28130
28131                         const face = faces2[ i ];
28132                         let normal, color;
28133                         const faceVertexNormals = face.vertexNormals,
28134                                 faceVertexColors = face.vertexColors;
28135
28136                         const faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
28137                         faceCopy.normal.copy( face.normal );
28138
28139                         if ( normalMatrix !== undefined ) {
28140
28141                                 faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
28142
28143                         }
28144
28145                         for ( let j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
28146
28147                                 normal = faceVertexNormals[ j ].clone();
28148
28149                                 if ( normalMatrix !== undefined ) {
28150
28151                                         normal.applyMatrix3( normalMatrix ).normalize();
28152
28153                                 }
28154
28155                                 faceCopy.vertexNormals.push( normal );
28156
28157                         }
28158
28159                         faceCopy.color.copy( face.color );
28160
28161                         for ( let j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
28162
28163                                 color = faceVertexColors[ j ];
28164                                 faceCopy.vertexColors.push( color.clone() );
28165
28166                         }
28167
28168                         faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
28169
28170                         faces1.push( faceCopy );
28171
28172                 }
28173
28174                 // uvs
28175
28176                 for ( let i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
28177
28178                         const faceVertexUvs2 = geometry.faceVertexUvs[ i ];
28179
28180                         if ( this.faceVertexUvs[ i ] === undefined ) this.faceVertexUvs[ i ] = [];
28181
28182                         for ( let j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) {
28183
28184                                 const uvs2 = faceVertexUvs2[ j ], uvsCopy = [];
28185
28186                                 for ( let k = 0, kl = uvs2.length; k < kl; k ++ ) {
28187
28188                                         uvsCopy.push( uvs2[ k ].clone() );
28189
28190                                 }
28191
28192                                 this.faceVertexUvs[ i ].push( uvsCopy );
28193
28194                         }
28195
28196                 }
28197
28198         },
28199
28200         mergeMesh: function ( mesh ) {
28201
28202                 if ( ! ( mesh && mesh.isMesh ) ) {
28203
28204                         console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
28205                         return;
28206
28207                 }
28208
28209                 if ( mesh.matrixAutoUpdate ) mesh.updateMatrix();
28210
28211                 this.merge( mesh.geometry, mesh.matrix );
28212
28213         },
28214
28215         /*
28216          * Checks for duplicate vertices with hashmap.
28217          * Duplicated vertices are removed
28218          * and faces' vertices are updated.
28219          */
28220
28221         mergeVertices: function ( precisionPoints = 4 ) {
28222
28223                 const verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
28224                 const unique = [], changes = [];
28225
28226                 const precision = Math.pow( 10, precisionPoints );
28227
28228                 for ( let i = 0, il = this.vertices.length; i < il; i ++ ) {
28229
28230                         const v = this.vertices[ i ];
28231                         const key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
28232
28233                         if ( verticesMap[ key ] === undefined ) {
28234
28235                                 verticesMap[ key ] = i;
28236                                 unique.push( this.vertices[ i ] );
28237                                 changes[ i ] = unique.length - 1;
28238
28239                         } else {
28240
28241                                 //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
28242                                 changes[ i ] = changes[ verticesMap[ key ] ];
28243
28244                         }
28245
28246                 }
28247
28248
28249                 // if faces are completely degenerate after merging vertices, we
28250                 // have to remove them from the geometry.
28251                 const faceIndicesToRemove = [];
28252
28253                 for ( let i = 0, il = this.faces.length; i < il; i ++ ) {
28254
28255                         const face = this.faces[ i ];
28256
28257                         face.a = changes[ face.a ];
28258                         face.b = changes[ face.b ];
28259                         face.c = changes[ face.c ];
28260
28261                         const indices = [ face.a, face.b, face.c ];
28262
28263                         // if any duplicate vertices are found in a Face3
28264                         // we have to remove the face as nothing can be saved
28265                         for ( let n = 0; n < 3; n ++ ) {
28266
28267                                 if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
28268
28269                                         faceIndicesToRemove.push( i );
28270                                         break;
28271
28272                                 }
28273
28274                         }
28275
28276                 }
28277
28278                 for ( let i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
28279
28280                         const idx = faceIndicesToRemove[ i ];
28281
28282                         this.faces.splice( idx, 1 );
28283
28284                         for ( let j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
28285
28286                                 this.faceVertexUvs[ j ].splice( idx, 1 );
28287
28288                         }
28289
28290                 }
28291
28292                 // Use unique set of vertices
28293
28294                 const diff = this.vertices.length - unique.length;
28295                 this.vertices = unique;
28296                 return diff;
28297
28298         },
28299
28300         setFromPoints: function ( points ) {
28301
28302                 this.vertices = [];
28303
28304                 for ( let i = 0, l = points.length; i < l; i ++ ) {
28305
28306                         const point = points[ i ];
28307                         this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
28308
28309                 }
28310
28311                 return this;
28312
28313         },
28314
28315         sortFacesByMaterialIndex: function () {
28316
28317                 const faces = this.faces;
28318                 const length = faces.length;
28319
28320                 // tag faces
28321
28322                 for ( let i = 0; i < length; i ++ ) {
28323
28324                         faces[ i ]._id = i;
28325
28326                 }
28327
28328                 // sort faces
28329
28330                 function materialIndexSort( a, b ) {
28331
28332                         return a.materialIndex - b.materialIndex;
28333
28334                 }
28335
28336                 faces.sort( materialIndexSort );
28337
28338                 // sort uvs
28339
28340                 const uvs1 = this.faceVertexUvs[ 0 ];
28341                 const uvs2 = this.faceVertexUvs[ 1 ];
28342
28343                 let newUvs1, newUvs2;
28344
28345                 if ( uvs1 && uvs1.length === length ) newUvs1 = [];
28346                 if ( uvs2 && uvs2.length === length ) newUvs2 = [];
28347
28348                 for ( let i = 0; i < length; i ++ ) {
28349
28350                         const id = faces[ i ]._id;
28351
28352                         if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
28353                         if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
28354
28355                 }
28356
28357                 if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
28358                 if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
28359
28360         },
28361
28362         toJSON: function () {
28363
28364                 const data = {
28365                         metadata: {
28366                                 version: 4.5,
28367                                 type: 'Geometry',
28368                                 generator: 'Geometry.toJSON'
28369                         }
28370                 };
28371
28372                 // standard Geometry serialization
28373
28374                 data.uuid = this.uuid;
28375                 data.type = this.type;
28376                 if ( this.name !== '' ) data.name = this.name;
28377
28378                 if ( this.parameters !== undefined ) {
28379
28380                         const parameters = this.parameters;
28381
28382                         for ( const key in parameters ) {
28383
28384                                 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
28385
28386                         }
28387
28388                         return data;
28389
28390                 }
28391
28392                 const vertices = [];
28393
28394                 for ( let i = 0; i < this.vertices.length; i ++ ) {
28395
28396                         const vertex = this.vertices[ i ];
28397                         vertices.push( vertex.x, vertex.y, vertex.z );
28398
28399                 }
28400
28401                 const faces = [];
28402                 const normals = [];
28403                 const normalsHash = {};
28404                 const colors = [];
28405                 const colorsHash = {};
28406                 const uvs = [];
28407                 const uvsHash = {};
28408
28409                 for ( let i = 0; i < this.faces.length; i ++ ) {
28410
28411                         const face = this.faces[ i ];
28412
28413                         const hasMaterial = true;
28414                         const hasFaceUv = false; // deprecated
28415                         const hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
28416                         const hasFaceNormal = face.normal.length() > 0;
28417                         const hasFaceVertexNormal = face.vertexNormals.length > 0;
28418                         const hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
28419                         const hasFaceVertexColor = face.vertexColors.length > 0;
28420
28421                         let faceType = 0;
28422
28423                         faceType = setBit( faceType, 0, 0 ); // isQuad
28424                         faceType = setBit( faceType, 1, hasMaterial );
28425                         faceType = setBit( faceType, 2, hasFaceUv );
28426                         faceType = setBit( faceType, 3, hasFaceVertexUv );
28427                         faceType = setBit( faceType, 4, hasFaceNormal );
28428                         faceType = setBit( faceType, 5, hasFaceVertexNormal );
28429                         faceType = setBit( faceType, 6, hasFaceColor );
28430                         faceType = setBit( faceType, 7, hasFaceVertexColor );
28431
28432                         faces.push( faceType );
28433                         faces.push( face.a, face.b, face.c );
28434                         faces.push( face.materialIndex );
28435
28436                         if ( hasFaceVertexUv ) {
28437
28438                                 const faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
28439
28440                                 faces.push(
28441                                         getUvIndex( faceVertexUvs[ 0 ] ),
28442                                         getUvIndex( faceVertexUvs[ 1 ] ),
28443                                         getUvIndex( faceVertexUvs[ 2 ] )
28444                                 );
28445
28446                         }
28447
28448                         if ( hasFaceNormal ) {
28449
28450                                 faces.push( getNormalIndex( face.normal ) );
28451
28452                         }
28453
28454                         if ( hasFaceVertexNormal ) {
28455
28456                                 const vertexNormals = face.vertexNormals;
28457
28458                                 faces.push(
28459                                         getNormalIndex( vertexNormals[ 0 ] ),
28460                                         getNormalIndex( vertexNormals[ 1 ] ),
28461                                         getNormalIndex( vertexNormals[ 2 ] )
28462                                 );
28463
28464                         }
28465
28466                         if ( hasFaceColor ) {
28467
28468                                 faces.push( getColorIndex( face.color ) );
28469
28470                         }
28471
28472                         if ( hasFaceVertexColor ) {
28473
28474                                 const vertexColors = face.vertexColors;
28475
28476                                 faces.push(
28477                                         getColorIndex( vertexColors[ 0 ] ),
28478                                         getColorIndex( vertexColors[ 1 ] ),
28479                                         getColorIndex( vertexColors[ 2 ] )
28480                                 );
28481
28482                         }
28483
28484                 }
28485
28486                 function setBit( value, position, enabled ) {
28487
28488                         return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
28489
28490                 }
28491
28492                 function getNormalIndex( normal ) {
28493
28494                         const hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
28495
28496                         if ( normalsHash[ hash ] !== undefined ) {
28497
28498                                 return normalsHash[ hash ];
28499
28500                         }
28501
28502                         normalsHash[ hash ] = normals.length / 3;
28503                         normals.push( normal.x, normal.y, normal.z );
28504
28505                         return normalsHash[ hash ];
28506
28507                 }
28508
28509                 function getColorIndex( color ) {
28510
28511                         const hash = color.r.toString() + color.g.toString() + color.b.toString();
28512
28513                         if ( colorsHash[ hash ] !== undefined ) {
28514
28515                                 return colorsHash[ hash ];
28516
28517                         }
28518
28519                         colorsHash[ hash ] = colors.length;
28520                         colors.push( color.getHex() );
28521
28522                         return colorsHash[ hash ];
28523
28524                 }
28525
28526                 function getUvIndex( uv ) {
28527
28528                         const hash = uv.x.toString() + uv.y.toString();
28529
28530                         if ( uvsHash[ hash ] !== undefined ) {
28531
28532                                 return uvsHash[ hash ];
28533
28534                         }
28535
28536                         uvsHash[ hash ] = uvs.length / 2;
28537                         uvs.push( uv.x, uv.y );
28538
28539                         return uvsHash[ hash ];
28540
28541                 }
28542
28543                 data.data = {};
28544
28545                 data.data.vertices = vertices;
28546                 data.data.normals = normals;
28547                 if ( colors.length > 0 ) data.data.colors = colors;
28548                 if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
28549                 data.data.faces = faces;
28550
28551                 return data;
28552
28553         },
28554
28555         clone: function () {
28556
28557                 /*
28558                  // Handle primitives
28559
28560                  const parameters = this.parameters;
28561
28562                  if ( parameters !== undefined ) {
28563
28564                  const values = [];
28565
28566                  for ( const key in parameters ) {
28567
28568                  values.push( parameters[ key ] );
28569
28570                  }
28571
28572                  const geometry = Object.create( this.constructor.prototype );
28573                  this.constructor.apply( geometry, values );
28574                  return geometry;
28575
28576                  }
28577
28578                  return new this.constructor().copy( this );
28579                  */
28580
28581                 return new Geometry().copy( this );
28582
28583         },
28584
28585         copy: function ( source ) {
28586
28587                 // reset
28588
28589                 this.vertices = [];
28590                 this.colors = [];
28591                 this.faces = [];
28592                 this.faceVertexUvs = [[]];
28593                 this.morphTargets = [];
28594                 this.morphNormals = [];
28595                 this.skinWeights = [];
28596                 this.skinIndices = [];
28597                 this.lineDistances = [];
28598                 this.boundingBox = null;
28599                 this.boundingSphere = null;
28600
28601                 // name
28602
28603                 this.name = source.name;
28604
28605                 // vertices
28606
28607                 const vertices = source.vertices;
28608
28609                 for ( let i = 0, il = vertices.length; i < il; i ++ ) {
28610
28611                         this.vertices.push( vertices[ i ].clone() );
28612
28613                 }
28614
28615                 // colors
28616
28617                 const colors = source.colors;
28618
28619                 for ( let i = 0, il = colors.length; i < il; i ++ ) {
28620
28621                         this.colors.push( colors[ i ].clone() );
28622
28623                 }
28624
28625                 // faces
28626
28627                 const faces = source.faces;
28628
28629                 for ( let i = 0, il = faces.length; i < il; i ++ ) {
28630
28631                         this.faces.push( faces[ i ].clone() );
28632
28633                 }
28634
28635                 // face vertex uvs
28636
28637                 for ( let i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
28638
28639                         const faceVertexUvs = source.faceVertexUvs[ i ];
28640
28641                         if ( this.faceVertexUvs[ i ] === undefined ) {
28642
28643                                 this.faceVertexUvs[ i ] = [];
28644
28645                         }
28646
28647                         for ( let j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
28648
28649                                 const uvs = faceVertexUvs[ j ], uvsCopy = [];
28650
28651                                 for ( let k = 0, kl = uvs.length; k < kl; k ++ ) {
28652
28653                                         const uv = uvs[ k ];
28654
28655                                         uvsCopy.push( uv.clone() );
28656
28657                                 }
28658
28659                                 this.faceVertexUvs[ i ].push( uvsCopy );
28660
28661                         }
28662
28663                 }
28664
28665                 // morph targets
28666
28667                 const morphTargets = source.morphTargets;
28668
28669                 for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
28670
28671                         const morphTarget = {};
28672                         morphTarget.name = morphTargets[ i ].name;
28673
28674                         // vertices
28675
28676                         if ( morphTargets[ i ].vertices !== undefined ) {
28677
28678                                 morphTarget.vertices = [];
28679
28680                                 for ( let j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
28681
28682                                         morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
28683
28684                                 }
28685
28686                         }
28687
28688                         // normals
28689
28690                         if ( morphTargets[ i ].normals !== undefined ) {
28691
28692                                 morphTarget.normals = [];
28693
28694                                 for ( let j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
28695
28696                                         morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
28697
28698                                 }
28699
28700                         }
28701
28702                         this.morphTargets.push( morphTarget );
28703
28704                 }
28705
28706                 // morph normals
28707
28708                 const morphNormals = source.morphNormals;
28709
28710                 for ( let i = 0, il = morphNormals.length; i < il; i ++ ) {
28711
28712                         const morphNormal = {};
28713
28714                         // vertex normals
28715
28716                         if ( morphNormals[ i ].vertexNormals !== undefined ) {
28717
28718                                 morphNormal.vertexNormals = [];
28719
28720                                 for ( let j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
28721
28722                                         const srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
28723                                         const destVertexNormal = {};
28724
28725                                         destVertexNormal.a = srcVertexNormal.a.clone();
28726                                         destVertexNormal.b = srcVertexNormal.b.clone();
28727                                         destVertexNormal.c = srcVertexNormal.c.clone();
28728
28729                                         morphNormal.vertexNormals.push( destVertexNormal );
28730
28731                                 }
28732
28733                         }
28734
28735                         // face normals
28736
28737                         if ( morphNormals[ i ].faceNormals !== undefined ) {
28738
28739                                 morphNormal.faceNormals = [];
28740
28741                                 for ( let j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
28742
28743                                         morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
28744
28745                                 }
28746
28747                         }
28748
28749                         this.morphNormals.push( morphNormal );
28750
28751                 }
28752
28753                 // skin weights
28754
28755                 const skinWeights = source.skinWeights;
28756
28757                 for ( let i = 0, il = skinWeights.length; i < il; i ++ ) {
28758
28759                         this.skinWeights.push( skinWeights[ i ].clone() );
28760
28761                 }
28762
28763                 // skin indices
28764
28765                 const skinIndices = source.skinIndices;
28766
28767                 for ( let i = 0, il = skinIndices.length; i < il; i ++ ) {
28768
28769                         this.skinIndices.push( skinIndices[ i ].clone() );
28770
28771                 }
28772
28773                 // line distances
28774
28775                 const lineDistances = source.lineDistances;
28776
28777                 for ( let i = 0, il = lineDistances.length; i < il; i ++ ) {
28778
28779                         this.lineDistances.push( lineDistances[ i ] );
28780
28781                 }
28782
28783                 // bounding box
28784
28785                 const boundingBox = source.boundingBox;
28786
28787                 if ( boundingBox !== null ) {
28788
28789                         this.boundingBox = boundingBox.clone();
28790
28791                 }
28792
28793                 // bounding sphere
28794
28795                 const boundingSphere = source.boundingSphere;
28796
28797                 if ( boundingSphere !== null ) {
28798
28799                         this.boundingSphere = boundingSphere.clone();
28800
28801                 }
28802
28803                 // update flags
28804
28805                 this.elementsNeedUpdate = source.elementsNeedUpdate;
28806                 this.verticesNeedUpdate = source.verticesNeedUpdate;
28807                 this.uvsNeedUpdate = source.uvsNeedUpdate;
28808                 this.normalsNeedUpdate = source.normalsNeedUpdate;
28809                 this.colorsNeedUpdate = source.colorsNeedUpdate;
28810                 this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
28811                 this.groupsNeedUpdate = source.groupsNeedUpdate;
28812
28813                 return this;
28814
28815         },
28816
28817         dispose: function () {
28818
28819                 this.dispatchEvent( { type: 'dispose' } );
28820
28821         }
28822
28823 } );
28824
28825 class BoxGeometry extends Geometry {
28826
28827         constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {
28828
28829                 super();
28830
28831                 this.type = 'BoxGeometry';
28832
28833                 this.parameters = {
28834                         width: width,
28835                         height: height,
28836                         depth: depth,
28837                         widthSegments: widthSegments,
28838                         heightSegments: heightSegments,
28839                         depthSegments: depthSegments
28840                 };
28841
28842                 this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
28843                 this.mergeVertices();
28844
28845         }
28846
28847 }
28848
28849 class CircleBufferGeometry extends BufferGeometry {
28850
28851         constructor( radius = 1, segments = 8, thetaStart = 0, thetaLength = Math.PI * 2 ) {
28852
28853                 super();
28854
28855                 this.type = 'CircleBufferGeometry';
28856
28857                 this.parameters = {
28858                         radius: radius,
28859                         segments: segments,
28860                         thetaStart: thetaStart,
28861                         thetaLength: thetaLength
28862                 };
28863
28864                 segments = Math.max( 3, segments );
28865
28866                 // buffers
28867
28868                 const indices = [];
28869                 const vertices = [];
28870                 const normals = [];
28871                 const uvs = [];
28872
28873                 // helper variables
28874
28875                 const vertex = new Vector3();
28876                 const uv = new Vector2();
28877
28878                 // center point
28879
28880                 vertices.push( 0, 0, 0 );
28881                 normals.push( 0, 0, 1 );
28882                 uvs.push( 0.5, 0.5 );
28883
28884                 for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
28885
28886                         const segment = thetaStart + s / segments * thetaLength;
28887
28888                         // vertex
28889
28890                         vertex.x = radius * Math.cos( segment );
28891                         vertex.y = radius * Math.sin( segment );
28892
28893                         vertices.push( vertex.x, vertex.y, vertex.z );
28894
28895                         // normal
28896
28897                         normals.push( 0, 0, 1 );
28898
28899                         // uvs
28900
28901                         uv.x = ( vertices[ i ] / radius + 1 ) / 2;
28902                         uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
28903
28904                         uvs.push( uv.x, uv.y );
28905
28906                 }
28907
28908                 // indices
28909
28910                 for ( let i = 1; i <= segments; i ++ ) {
28911
28912                         indices.push( i, i + 1, 0 );
28913
28914                 }
28915
28916                 // build geometry
28917
28918                 this.setIndex( indices );
28919                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28920                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28921                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28922
28923         }
28924
28925 }
28926
28927 class CircleGeometry extends Geometry {
28928
28929         constructor( radius, segments, thetaStart, thetaLength ) {
28930
28931                 super();
28932                 this.type = 'CircleGeometry';
28933
28934                 this.parameters = {
28935                         radius: radius,
28936                         segments: segments,
28937                         thetaStart: thetaStart,
28938                         thetaLength: thetaLength
28939                 };
28940
28941                 this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
28942                 this.mergeVertices();
28943
28944         }
28945
28946 }
28947
28948 class CylinderBufferGeometry extends BufferGeometry {
28949
28950         constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
28951
28952                 super();
28953                 this.type = 'CylinderBufferGeometry';
28954
28955                 this.parameters = {
28956                         radiusTop: radiusTop,
28957                         radiusBottom: radiusBottom,
28958                         height: height,
28959                         radialSegments: radialSegments,
28960                         heightSegments: heightSegments,
28961                         openEnded: openEnded,
28962                         thetaStart: thetaStart,
28963                         thetaLength: thetaLength
28964                 };
28965
28966                 const scope = this;
28967
28968                 radialSegments = Math.floor( radialSegments );
28969                 heightSegments = Math.floor( heightSegments );
28970
28971                 // buffers
28972
28973                 const indices = [];
28974                 const vertices = [];
28975                 const normals = [];
28976                 const uvs = [];
28977
28978                 // helper variables
28979
28980                 let index = 0;
28981                 const indexArray = [];
28982                 const halfHeight = height / 2;
28983                 let groupStart = 0;
28984
28985                 // generate geometry
28986
28987                 generateTorso();
28988
28989                 if ( openEnded === false ) {
28990
28991                         if ( radiusTop > 0 ) generateCap( true );
28992                         if ( radiusBottom > 0 ) generateCap( false );
28993
28994                 }
28995
28996                 // build geometry
28997
28998                 this.setIndex( indices );
28999                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29000                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29001                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29002
29003                 function generateTorso() {
29004
29005                         const normal = new Vector3();
29006                         const vertex = new Vector3();
29007
29008                         let groupCount = 0;
29009
29010                         // this will be used to calculate the normal
29011                         const slope = ( radiusBottom - radiusTop ) / height;
29012
29013                         // generate vertices, normals and uvs
29014
29015                         for ( let y = 0; y <= heightSegments; y ++ ) {
29016
29017                                 const indexRow = [];
29018
29019                                 const v = y / heightSegments;
29020
29021                                 // calculate the radius of the current row
29022
29023                                 const radius = v * ( radiusBottom - radiusTop ) + radiusTop;
29024
29025                                 for ( let x = 0; x <= radialSegments; x ++ ) {
29026
29027                                         const u = x / radialSegments;
29028
29029                                         const theta = u * thetaLength + thetaStart;
29030
29031                                         const sinTheta = Math.sin( theta );
29032                                         const cosTheta = Math.cos( theta );
29033
29034                                         // vertex
29035
29036                                         vertex.x = radius * sinTheta;
29037                                         vertex.y = - v * height + halfHeight;
29038                                         vertex.z = radius * cosTheta;
29039                                         vertices.push( vertex.x, vertex.y, vertex.z );
29040
29041                                         // normal
29042
29043                                         normal.set( sinTheta, slope, cosTheta ).normalize();
29044                                         normals.push( normal.x, normal.y, normal.z );
29045
29046                                         // uv
29047
29048                                         uvs.push( u, 1 - v );
29049
29050                                         // save index of vertex in respective row
29051
29052                                         indexRow.push( index ++ );
29053
29054                                 }
29055
29056                                 // now save vertices of the row in our index array
29057
29058                                 indexArray.push( indexRow );
29059
29060                         }
29061
29062                         // generate indices
29063
29064                         for ( let x = 0; x < radialSegments; x ++ ) {
29065
29066                                 for ( let y = 0; y < heightSegments; y ++ ) {
29067
29068                                         // we use the index array to access the correct indices
29069
29070                                         const a = indexArray[ y ][ x ];
29071                                         const b = indexArray[ y + 1 ][ x ];
29072                                         const c = indexArray[ y + 1 ][ x + 1 ];
29073                                         const d = indexArray[ y ][ x + 1 ];
29074
29075                                         // faces
29076
29077                                         indices.push( a, b, d );
29078                                         indices.push( b, c, d );
29079
29080                                         // update group counter
29081
29082                                         groupCount += 6;
29083
29084                                 }
29085
29086                         }
29087
29088                         // add a group to the geometry. this will ensure multi material support
29089
29090                         scope.addGroup( groupStart, groupCount, 0 );
29091
29092                         // calculate new start value for groups
29093
29094                         groupStart += groupCount;
29095
29096                 }
29097
29098                 function generateCap( top ) {
29099
29100                         // save the index of the first center vertex
29101                         const centerIndexStart = index;
29102
29103                         const uv = new Vector2();
29104                         const vertex = new Vector3();
29105
29106                         let groupCount = 0;
29107
29108                         const radius = ( top === true ) ? radiusTop : radiusBottom;
29109                         const sign = ( top === true ) ? 1 : - 1;
29110
29111                         // first we generate the center vertex data of the cap.
29112                         // because the geometry needs one set of uvs per face,
29113                         // we must generate a center vertex per face/segment
29114
29115                         for ( let x = 1; x <= radialSegments; x ++ ) {
29116
29117                                 // vertex
29118
29119                                 vertices.push( 0, halfHeight * sign, 0 );
29120
29121                                 // normal
29122
29123                                 normals.push( 0, sign, 0 );
29124
29125                                 // uv
29126
29127                                 uvs.push( 0.5, 0.5 );
29128
29129                                 // increase index
29130
29131                                 index ++;
29132
29133                         }
29134
29135                         // save the index of the last center vertex
29136                         const centerIndexEnd = index;
29137
29138                         // now we generate the surrounding vertices, normals and uvs
29139
29140                         for ( let x = 0; x <= radialSegments; x ++ ) {
29141
29142                                 const u = x / radialSegments;
29143                                 const theta = u * thetaLength + thetaStart;
29144
29145                                 const cosTheta = Math.cos( theta );
29146                                 const sinTheta = Math.sin( theta );
29147
29148                                 // vertex
29149
29150                                 vertex.x = radius * sinTheta;
29151                                 vertex.y = halfHeight * sign;
29152                                 vertex.z = radius * cosTheta;
29153                                 vertices.push( vertex.x, vertex.y, vertex.z );
29154
29155                                 // normal
29156
29157                                 normals.push( 0, sign, 0 );
29158
29159                                 // uv
29160
29161                                 uv.x = ( cosTheta * 0.5 ) + 0.5;
29162                                 uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
29163                                 uvs.push( uv.x, uv.y );
29164
29165                                 // increase index
29166
29167                                 index ++;
29168
29169                         }
29170
29171                         // generate indices
29172
29173                         for ( let x = 0; x < radialSegments; x ++ ) {
29174
29175                                 const c = centerIndexStart + x;
29176                                 const i = centerIndexEnd + x;
29177
29178                                 if ( top === true ) {
29179
29180                                         // face top
29181
29182                                         indices.push( i, i + 1, c );
29183
29184                                 } else {
29185
29186                                         // face bottom
29187
29188                                         indices.push( i + 1, i, c );
29189
29190                                 }
29191
29192                                 groupCount += 3;
29193
29194                         }
29195
29196                         // add a group to the geometry. this will ensure multi material support
29197
29198                         scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
29199
29200                         // calculate new start value for groups
29201
29202                         groupStart += groupCount;
29203
29204                 }
29205
29206         }
29207
29208 }
29209
29210 class CylinderGeometry extends Geometry {
29211
29212         constructor( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29213
29214                 super();
29215                 this.type = 'CylinderGeometry';
29216
29217                 this.parameters = {
29218                         radiusTop: radiusTop,
29219                         radiusBottom: radiusBottom,
29220                         height: height,
29221                         radialSegments: radialSegments,
29222                         heightSegments: heightSegments,
29223                         openEnded: openEnded,
29224                         thetaStart: thetaStart,
29225                         thetaLength: thetaLength
29226                 };
29227
29228                 this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
29229                 this.mergeVertices();
29230
29231         }
29232
29233 }
29234
29235 class ConeGeometry extends CylinderGeometry {
29236
29237         constructor( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29238
29239                 super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
29240                 this.type = 'ConeGeometry';
29241
29242                 this.parameters = {
29243                         radius: radius,
29244                         height: height,
29245                         radialSegments: radialSegments,
29246                         heightSegments: heightSegments,
29247                         openEnded: openEnded,
29248                         thetaStart: thetaStart,
29249                         thetaLength: thetaLength
29250                 };
29251
29252         }
29253
29254 }
29255
29256 class ConeBufferGeometry extends CylinderBufferGeometry {
29257
29258         constructor( radius = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
29259
29260                 super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
29261
29262                 this.type = 'ConeBufferGeometry';
29263
29264                 this.parameters = {
29265                         radius: radius,
29266                         height: height,
29267                         radialSegments: radialSegments,
29268                         heightSegments: heightSegments,
29269                         openEnded: openEnded,
29270                         thetaStart: thetaStart,
29271                         thetaLength: thetaLength
29272                 };
29273
29274         }
29275
29276 }
29277
29278 class PolyhedronBufferGeometry extends BufferGeometry {
29279
29280         constructor( vertices, indices, radius = 1, detail = 0 ) {
29281
29282                 super();
29283
29284                 this.type = 'PolyhedronBufferGeometry';
29285
29286                 this.parameters = {
29287                         vertices: vertices,
29288                         indices: indices,
29289                         radius: radius,
29290                         detail: detail
29291                 };
29292
29293                 // default buffer data
29294
29295                 const vertexBuffer = [];
29296                 const uvBuffer = [];
29297
29298                 // the subdivision creates the vertex buffer data
29299
29300                 subdivide( detail );
29301
29302                 // all vertices should lie on a conceptual sphere with a given radius
29303
29304                 applyRadius( radius );
29305
29306                 // finally, create the uv data
29307
29308                 generateUVs();
29309
29310                 // build non-indexed geometry
29311
29312                 this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
29313                 this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
29314                 this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
29315
29316                 if ( detail === 0 ) {
29317
29318                         this.computeVertexNormals(); // flat normals
29319
29320                 } else {
29321
29322                         this.normalizeNormals(); // smooth normals
29323
29324                 }
29325
29326                 // helper functions
29327
29328                 function subdivide( detail ) {
29329
29330                         const a = new Vector3();
29331                         const b = new Vector3();
29332                         const c = new Vector3();
29333
29334                         // iterate over all faces and apply a subdivison with the given detail value
29335
29336                         for ( let i = 0; i < indices.length; i += 3 ) {
29337
29338                                 // get the vertices of the face
29339
29340                                 getVertexByIndex( indices[ i + 0 ], a );
29341                                 getVertexByIndex( indices[ i + 1 ], b );
29342                                 getVertexByIndex( indices[ i + 2 ], c );
29343
29344                                 // perform subdivision
29345
29346                                 subdivideFace( a, b, c, detail );
29347
29348                         }
29349
29350                 }
29351
29352                 function subdivideFace( a, b, c, detail ) {
29353
29354                         const cols = detail + 1;
29355
29356                         // we use this multidimensional array as a data structure for creating the subdivision
29357
29358                         const v = [];
29359
29360                         // construct all of the vertices for this subdivision
29361
29362                         for ( let i = 0; i <= cols; i ++ ) {
29363
29364                                 v[ i ] = [];
29365
29366                                 const aj = a.clone().lerp( c, i / cols );
29367                                 const bj = b.clone().lerp( c, i / cols );
29368
29369                                 const rows = cols - i;
29370
29371                                 for ( let j = 0; j <= rows; j ++ ) {
29372
29373                                         if ( j === 0 && i === cols ) {
29374
29375                                                 v[ i ][ j ] = aj;
29376
29377                                         } else {
29378
29379                                                 v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
29380
29381                                         }
29382
29383                                 }
29384
29385                         }
29386
29387                         // construct all of the faces
29388
29389                         for ( let i = 0; i < cols; i ++ ) {
29390
29391                                 for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
29392
29393                                         const k = Math.floor( j / 2 );
29394
29395                                         if ( j % 2 === 0 ) {
29396
29397                                                 pushVertex( v[ i ][ k + 1 ] );
29398                                                 pushVertex( v[ i + 1 ][ k ] );
29399                                                 pushVertex( v[ i ][ k ] );
29400
29401                                         } else {
29402
29403                                                 pushVertex( v[ i ][ k + 1 ] );
29404                                                 pushVertex( v[ i + 1 ][ k + 1 ] );
29405                                                 pushVertex( v[ i + 1 ][ k ] );
29406
29407                                         }
29408
29409                                 }
29410
29411                         }
29412
29413                 }
29414
29415                 function applyRadius( radius ) {
29416
29417                         const vertex = new Vector3();
29418
29419                         // iterate over the entire buffer and apply the radius to each vertex
29420
29421                         for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
29422
29423                                 vertex.x = vertexBuffer[ i + 0 ];
29424                                 vertex.y = vertexBuffer[ i + 1 ];
29425                                 vertex.z = vertexBuffer[ i + 2 ];
29426
29427                                 vertex.normalize().multiplyScalar( radius );
29428
29429                                 vertexBuffer[ i + 0 ] = vertex.x;
29430                                 vertexBuffer[ i + 1 ] = vertex.y;
29431                                 vertexBuffer[ i + 2 ] = vertex.z;
29432
29433                         }
29434
29435                 }
29436
29437                 function generateUVs() {
29438
29439                         const vertex = new Vector3();
29440
29441                         for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
29442
29443                                 vertex.x = vertexBuffer[ i + 0 ];
29444                                 vertex.y = vertexBuffer[ i + 1 ];
29445                                 vertex.z = vertexBuffer[ i + 2 ];
29446
29447                                 const u = azimuth( vertex ) / 2 / Math.PI + 0.5;
29448                                 const v = inclination( vertex ) / Math.PI + 0.5;
29449                                 uvBuffer.push( u, 1 - v );
29450
29451                         }
29452
29453                         correctUVs();
29454
29455                         correctSeam();
29456
29457                 }
29458
29459                 function correctSeam() {
29460
29461                         // handle case when face straddles the seam, see #3269
29462
29463                         for ( let i = 0; i < uvBuffer.length; i += 6 ) {
29464
29465                                 // uv data of a single face
29466
29467                                 const x0 = uvBuffer[ i + 0 ];
29468                                 const x1 = uvBuffer[ i + 2 ];
29469                                 const x2 = uvBuffer[ i + 4 ];
29470
29471                                 const max = Math.max( x0, x1, x2 );
29472                                 const min = Math.min( x0, x1, x2 );
29473
29474                                 // 0.9 is somewhat arbitrary
29475
29476                                 if ( max > 0.9 && min < 0.1 ) {
29477
29478                                         if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
29479                                         if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
29480                                         if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
29481
29482                                 }
29483
29484                         }
29485
29486                 }
29487
29488                 function pushVertex( vertex ) {
29489
29490                         vertexBuffer.push( vertex.x, vertex.y, vertex.z );
29491
29492                 }
29493
29494                 function getVertexByIndex( index, vertex ) {
29495
29496                         const stride = index * 3;
29497
29498                         vertex.x = vertices[ stride + 0 ];
29499                         vertex.y = vertices[ stride + 1 ];
29500                         vertex.z = vertices[ stride + 2 ];
29501
29502                 }
29503
29504                 function correctUVs() {
29505
29506                         const a = new Vector3();
29507                         const b = new Vector3();
29508                         const c = new Vector3();
29509
29510                         const centroid = new Vector3();
29511
29512                         const uvA = new Vector2();
29513                         const uvB = new Vector2();
29514                         const uvC = new Vector2();
29515
29516                         for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
29517
29518                                 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
29519                                 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
29520                                 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
29521
29522                                 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
29523                                 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
29524                                 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
29525
29526                                 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
29527
29528                                 const azi = azimuth( centroid );
29529
29530                                 correctUV( uvA, j + 0, a, azi );
29531                                 correctUV( uvB, j + 2, b, azi );
29532                                 correctUV( uvC, j + 4, c, azi );
29533
29534                         }
29535
29536                 }
29537
29538                 function correctUV( uv, stride, vector, azimuth ) {
29539
29540                         if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
29541
29542                                 uvBuffer[ stride ] = uv.x - 1;
29543
29544                         }
29545
29546                         if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
29547
29548                                 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
29549
29550                         }
29551
29552                 }
29553
29554                 // Angle around the Y axis, counter-clockwise when looking from above.
29555
29556                 function azimuth( vector ) {
29557
29558                         return Math.atan2( vector.z, - vector.x );
29559
29560                 }
29561
29562
29563                 // Angle above the XZ plane.
29564
29565                 function inclination( vector ) {
29566
29567                         return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
29568
29569                 }
29570
29571         }
29572
29573 }
29574
29575 class DodecahedronBufferGeometry extends PolyhedronBufferGeometry {
29576
29577         constructor( radius = 1, detail = 0 ) {
29578
29579                 const t = ( 1 + Math.sqrt( 5 ) ) / 2;
29580                 const r = 1 / t;
29581
29582                 const vertices = [
29583
29584                         // (±1, Â±1, Â±1)
29585                         - 1, - 1, - 1,  - 1, - 1, 1,
29586                         - 1, 1, - 1, - 1, 1, 1,
29587                         1, - 1, - 1, 1, - 1, 1,
29588                         1, 1, - 1, 1, 1, 1,
29589
29590                         // (0, Â±1/φ, Â±Ï†)
29591                         0, - r, - t, 0, - r, t,
29592                         0, r, - t, 0, r, t,
29593
29594                         // (±1/φ, Â±Ï†, 0)
29595                         - r, - t, 0, - r, t, 0,
29596                         r, - t, 0, r, t, 0,
29597
29598                         // (±φ, 0, Â±1/φ)
29599                         - t, 0, - r, t, 0, - r,
29600                         - t, 0, r, t, 0, r
29601                 ];
29602
29603                 const indices = [
29604                         3, 11, 7,       3, 7, 15,       3, 15, 13,
29605                         7, 19, 17,      7, 17, 6,       7, 6, 15,
29606                         17, 4, 8,       17, 8, 10,      17, 10, 6,
29607                         8, 0, 16,       8, 16, 2,       8, 2, 10,
29608                         0, 12, 1,       0, 1, 18,       0, 18, 16,
29609                         6, 10, 2,       6, 2, 13,       6, 13, 15,
29610                         2, 16, 18,      2, 18, 3,       2, 3, 13,
29611                         18, 1, 9,       18, 9, 11,      18, 11, 3,
29612                         4, 14, 12,      4, 12, 0,       4, 0, 8,
29613                         11, 9, 5,       11, 5, 19,      11, 19, 7,
29614                         19, 5, 14,      19, 14, 4,      19, 4, 17,
29615                         1, 12, 14,      1, 14, 5,       1, 5, 9
29616                 ];
29617
29618                 super( vertices, indices, radius, detail );
29619
29620                 this.type = 'DodecahedronBufferGeometry';
29621
29622                 this.parameters = {
29623                         radius: radius,
29624                         detail: detail
29625                 };
29626
29627         }
29628
29629 }
29630
29631 class DodecahedronGeometry extends Geometry {
29632
29633         constructor( radius, detail ) {
29634
29635                 super();
29636                 this.type = 'DodecahedronGeometry';
29637
29638                 this.parameters = {
29639                         radius: radius,
29640                         detail: detail
29641                 };
29642
29643                 this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
29644                 this.mergeVertices();
29645
29646         }
29647
29648 }
29649
29650 const _v0$2 = new Vector3();
29651 const _v1$5 = new Vector3();
29652 const _normal$1 = new Vector3();
29653 const _triangle = new Triangle();
29654
29655 class EdgesGeometry extends BufferGeometry {
29656
29657         constructor( geometry, thresholdAngle ) {
29658
29659                 super();
29660
29661                 this.type = 'EdgesGeometry';
29662
29663                 this.parameters = {
29664                         thresholdAngle: thresholdAngle
29665                 };
29666
29667                 thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
29668
29669                 if ( geometry.isGeometry ) {
29670
29671                         geometry = new BufferGeometry().fromGeometry( geometry );
29672
29673                 }
29674
29675                 const precisionPoints = 4;
29676                 const precision = Math.pow( 10, precisionPoints );
29677                 const thresholdDot = Math.cos( MathUtils.DEG2RAD * thresholdAngle );
29678
29679                 const indexAttr = geometry.getIndex();
29680                 const positionAttr = geometry.getAttribute( 'position' );
29681                 const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
29682
29683                 const indexArr = [ 0, 0, 0 ];
29684                 const vertKeys = [ 'a', 'b', 'c' ];
29685                 const hashes = new Array( 3 );
29686
29687                 const edgeData = {};
29688                 const vertices = [];
29689                 for ( let i = 0; i < indexCount; i += 3 ) {
29690
29691                         if ( indexAttr ) {
29692
29693                                 indexArr[ 0 ] = indexAttr.getX( i );
29694                                 indexArr[ 1 ] = indexAttr.getX( i + 1 );
29695                                 indexArr[ 2 ] = indexAttr.getX( i + 2 );
29696
29697                         } else {
29698
29699                                 indexArr[ 0 ] = i;
29700                                 indexArr[ 1 ] = i + 1;
29701                                 indexArr[ 2 ] = i + 2;
29702
29703                         }
29704
29705                         const { a, b, c } = _triangle;
29706                         a.fromBufferAttribute( positionAttr, indexArr[ 0 ] );
29707                         b.fromBufferAttribute( positionAttr, indexArr[ 1 ] );
29708                         c.fromBufferAttribute( positionAttr, indexArr[ 2 ] );
29709                         _triangle.getNormal( _normal$1 );
29710
29711                         // create hashes for the edge from the vertices
29712                         hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`;
29713                         hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`;
29714                         hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`;
29715
29716                         // skip degenerate triangles
29717                         if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) {
29718
29719                                 continue;
29720
29721                         }
29722
29723                         // iterate over every edge
29724                         for ( let j = 0; j < 3; j ++ ) {
29725
29726                                 // get the first and next vertex making up the edge
29727                                 const jNext = ( j + 1 ) % 3;
29728                                 const vecHash0 = hashes[ j ];
29729                                 const vecHash1 = hashes[ jNext ];
29730                                 const v0 = _triangle[ vertKeys[ j ] ];
29731                                 const v1 = _triangle[ vertKeys[ jNext ] ];
29732
29733                                 const hash = `${ vecHash0 }_${ vecHash1 }`;
29734                                 const reverseHash = `${ vecHash1 }_${ vecHash0 }`;
29735
29736                                 if ( reverseHash in edgeData && edgeData[ reverseHash ] ) {
29737
29738                                         // if we found a sibling edge add it into the vertex array if
29739                                         // it meets the angle threshold and delete the edge from the map.
29740                                         if ( _normal$1.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) {
29741
29742                                                 vertices.push( v0.x, v0.y, v0.z );
29743                                                 vertices.push( v1.x, v1.y, v1.z );
29744
29745                                         }
29746
29747                                         edgeData[ reverseHash ] = null;
29748
29749                                 } else if ( ! ( hash in edgeData ) ) {
29750
29751                                         // if we've already got an edge here then skip adding a new one
29752                                         edgeData[ hash ] = {
29753
29754                                                 index0: indexArr[ j ],
29755                                                 index1: indexArr[ jNext ],
29756                                                 normal: _normal$1.clone(),
29757
29758                                         };
29759
29760                                 }
29761
29762                         }
29763
29764                 }
29765
29766                 // iterate over all remaining, unmatched edges and add them to the vertex array
29767                 for ( const key in edgeData ) {
29768
29769                         if ( edgeData[ key ] ) {
29770
29771                                 const { index0, index1 } = edgeData[ key ];
29772                                 _v0$2.fromBufferAttribute( positionAttr, index0 );
29773                                 _v1$5.fromBufferAttribute( positionAttr, index1 );
29774
29775                                 vertices.push( _v0$2.x, _v0$2.y, _v0$2.z );
29776                                 vertices.push( _v1$5.x, _v1$5.y, _v1$5.z );
29777
29778                         }
29779
29780                 }
29781
29782                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29783
29784         }
29785
29786 }
29787
29788 /**
29789  * Port from https://github.com/mapbox/earcut (v2.2.2)
29790  */
29791
29792 const Earcut = {
29793
29794         triangulate: function ( data, holeIndices, dim ) {
29795
29796                 dim = dim || 2;
29797
29798                 const hasHoles = holeIndices && holeIndices.length;
29799                 const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
29800                 let outerNode = linkedList( data, 0, outerLen, dim, true );
29801                 const triangles = [];
29802
29803                 if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
29804
29805                 let minX, minY, maxX, maxY, x, y, invSize;
29806
29807                 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
29808
29809                 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
29810                 if ( data.length > 80 * dim ) {
29811
29812                         minX = maxX = data[ 0 ];
29813                         minY = maxY = data[ 1 ];
29814
29815                         for ( let i = dim; i < outerLen; i += dim ) {
29816
29817                                 x = data[ i ];
29818                                 y = data[ i + 1 ];
29819                                 if ( x < minX ) minX = x;
29820                                 if ( y < minY ) minY = y;
29821                                 if ( x > maxX ) maxX = x;
29822                                 if ( y > maxY ) maxY = y;
29823
29824                         }
29825
29826                         // minX, minY and invSize are later used to transform coords into integers for z-order calculation
29827                         invSize = Math.max( maxX - minX, maxY - minY );
29828                         invSize = invSize !== 0 ? 1 / invSize : 0;
29829
29830                 }
29831
29832                 earcutLinked( outerNode, triangles, dim, minX, minY, invSize );
29833
29834                 return triangles;
29835
29836         }
29837
29838 };
29839
29840 // create a circular doubly linked list from polygon points in the specified winding order
29841 function linkedList( data, start, end, dim, clockwise ) {
29842
29843         let i, last;
29844
29845         if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
29846
29847                 for ( i = start; i < end; i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
29848
29849         } else {
29850
29851                 for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
29852
29853         }
29854
29855         if ( last && equals( last, last.next ) ) {
29856
29857                 removeNode( last );
29858                 last = last.next;
29859
29860         }
29861
29862         return last;
29863
29864 }
29865
29866 // eliminate colinear or duplicate points
29867 function filterPoints( start, end ) {
29868
29869         if ( ! start ) return start;
29870         if ( ! end ) end = start;
29871
29872         let p = start,
29873                 again;
29874         do {
29875
29876                 again = false;
29877
29878                 if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
29879
29880                         removeNode( p );
29881                         p = end = p.prev;
29882                         if ( p === p.next ) break;
29883                         again = true;
29884
29885                 } else {
29886
29887                         p = p.next;
29888
29889                 }
29890
29891         } while ( again || p !== end );
29892
29893         return end;
29894
29895 }
29896
29897 // main ear slicing loop which triangulates a polygon (given as a linked list)
29898 function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
29899
29900         if ( ! ear ) return;
29901
29902         // interlink polygon nodes in z-order
29903         if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
29904
29905         let stop = ear,
29906                 prev, next;
29907
29908         // iterate through ears, slicing them one by one
29909         while ( ear.prev !== ear.next ) {
29910
29911                 prev = ear.prev;
29912                 next = ear.next;
29913
29914                 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
29915
29916                         // cut off the triangle
29917                         triangles.push( prev.i / dim );
29918                         triangles.push( ear.i / dim );
29919                         triangles.push( next.i / dim );
29920
29921                         removeNode( ear );
29922
29923                         // skipping the next vertex leads to less sliver triangles
29924                         ear = next.next;
29925                         stop = next.next;
29926
29927                         continue;
29928
29929                 }
29930
29931                 ear = next;
29932
29933                 // if we looped through the whole remaining polygon and can't find any more ears
29934                 if ( ear === stop ) {
29935
29936                         // try filtering points and slicing again
29937                         if ( ! pass ) {
29938
29939                                 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
29940
29941                                 // if this didn't work, try curing all small self-intersections locally
29942
29943                         } else if ( pass === 1 ) {
29944
29945                                 ear = cureLocalIntersections( filterPoints( ear ), triangles, dim );
29946                                 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
29947
29948                                 // as a last resort, try splitting the remaining polygon into two
29949
29950                         } else if ( pass === 2 ) {
29951
29952                                 splitEarcut( ear, triangles, dim, minX, minY, invSize );
29953
29954                         }
29955
29956                         break;
29957
29958                 }
29959
29960         }
29961
29962 }
29963
29964 // check whether a polygon node forms a valid ear with adjacent nodes
29965 function isEar( ear ) {
29966
29967         const a = ear.prev,
29968                 b = ear,
29969                 c = ear.next;
29970
29971         if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
29972
29973         // now make sure we don't have other points inside the potential ear
29974         let p = ear.next.next;
29975
29976         while ( p !== ear.prev ) {
29977
29978                 if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
29979                         area( p.prev, p, p.next ) >= 0 ) return false;
29980                 p = p.next;
29981
29982         }
29983
29984         return true;
29985
29986 }
29987
29988 function isEarHashed( ear, minX, minY, invSize ) {
29989
29990         const a = ear.prev,
29991                 b = ear,
29992                 c = ear.next;
29993
29994         if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
29995
29996         // triangle bbox; min & max are calculated like this for speed
29997         const minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
29998                 minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
29999                 maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
30000                 maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
30001
30002         // z-order range for the current triangle bbox;
30003         const minZ = zOrder( minTX, minTY, minX, minY, invSize ),
30004                 maxZ = zOrder( maxTX, maxTY, minX, minY, invSize );
30005
30006         let p = ear.prevZ,
30007                 n = ear.nextZ;
30008
30009         // look for points inside the triangle in both directions
30010         while ( p && p.z >= minZ && n && n.z <= maxZ ) {
30011
30012                 if ( p !== ear.prev && p !== ear.next &&
30013                         pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
30014                         area( p.prev, p, p.next ) >= 0 ) return false;
30015                 p = p.prevZ;
30016
30017                 if ( n !== ear.prev && n !== ear.next &&
30018                         pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
30019                         area( n.prev, n, n.next ) >= 0 ) return false;
30020                 n = n.nextZ;
30021
30022         }
30023
30024         // look for remaining points in decreasing z-order
30025         while ( p && p.z >= minZ ) {
30026
30027                 if ( p !== ear.prev && p !== ear.next &&
30028                         pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
30029                         area( p.prev, p, p.next ) >= 0 ) return false;
30030                 p = p.prevZ;
30031
30032         }
30033
30034         // look for remaining points in increasing z-order
30035         while ( n && n.z <= maxZ ) {
30036
30037                 if ( n !== ear.prev && n !== ear.next &&
30038                         pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
30039                         area( n.prev, n, n.next ) >= 0 ) return false;
30040                 n = n.nextZ;
30041
30042         }
30043
30044         return true;
30045
30046 }
30047
30048 // go through all polygon nodes and cure small local self-intersections
30049 function cureLocalIntersections( start, triangles, dim ) {
30050
30051         let p = start;
30052         do {
30053
30054                 const a = p.prev,
30055                         b = p.next.next;
30056
30057                 if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
30058
30059                         triangles.push( a.i / dim );
30060                         triangles.push( p.i / dim );
30061                         triangles.push( b.i / dim );
30062
30063                         // remove two nodes involved
30064                         removeNode( p );
30065                         removeNode( p.next );
30066
30067                         p = start = b;
30068
30069                 }
30070
30071                 p = p.next;
30072
30073         } while ( p !== start );
30074
30075         return filterPoints( p );
30076
30077 }
30078
30079 // try splitting polygon into two and triangulate them independently
30080 function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
30081
30082         // look for a valid diagonal that divides the polygon into two
30083         let a = start;
30084         do {
30085
30086                 let b = a.next.next;
30087                 while ( b !== a.prev ) {
30088
30089                         if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
30090
30091                                 // split the polygon in two by the diagonal
30092                                 let c = splitPolygon( a, b );
30093
30094                                 // filter colinear points around the cuts
30095                                 a = filterPoints( a, a.next );
30096                                 c = filterPoints( c, c.next );
30097
30098                                 // run earcut on each half
30099                                 earcutLinked( a, triangles, dim, minX, minY, invSize );
30100                                 earcutLinked( c, triangles, dim, minX, minY, invSize );
30101                                 return;
30102
30103                         }
30104
30105                         b = b.next;
30106
30107                 }
30108
30109                 a = a.next;
30110
30111         } while ( a !== start );
30112
30113 }
30114
30115 // link every hole into the outer loop, producing a single-ring polygon without holes
30116 function eliminateHoles( data, holeIndices, outerNode, dim ) {
30117
30118         const queue = [];
30119         let i, len, start, end, list;
30120
30121         for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
30122
30123                 start = holeIndices[ i ] * dim;
30124                 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
30125                 list = linkedList( data, start, end, dim, false );
30126                 if ( list === list.next ) list.steiner = true;
30127                 queue.push( getLeftmost( list ) );
30128
30129         }
30130
30131         queue.sort( compareX );
30132
30133         // process holes from left to right
30134         for ( i = 0; i < queue.length; i ++ ) {
30135
30136                 eliminateHole( queue[ i ], outerNode );
30137                 outerNode = filterPoints( outerNode, outerNode.next );
30138
30139         }
30140
30141         return outerNode;
30142
30143 }
30144
30145 function compareX( a, b ) {
30146
30147         return a.x - b.x;
30148
30149 }
30150
30151 // find a bridge between vertices that connects hole with an outer ring and and link it
30152 function eliminateHole( hole, outerNode ) {
30153
30154         outerNode = findHoleBridge( hole, outerNode );
30155         if ( outerNode ) {
30156
30157                 const b = splitPolygon( outerNode, hole );
30158
30159                 // filter collinear points around the cuts
30160                 filterPoints( outerNode, outerNode.next );
30161                 filterPoints( b, b.next );
30162
30163         }
30164
30165 }
30166
30167 // David Eberly's algorithm for finding a bridge between hole and outer polygon
30168 function findHoleBridge( hole, outerNode ) {
30169
30170         let p = outerNode;
30171         const hx = hole.x;
30172         const hy = hole.y;
30173         let qx = - Infinity, m;
30174
30175         // find a segment intersected by a ray from the hole's leftmost point to the left;
30176         // segment's endpoint with lesser x will be potential connection point
30177         do {
30178
30179                 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
30180
30181                         const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
30182                         if ( x <= hx && x > qx ) {
30183
30184                                 qx = x;
30185                                 if ( x === hx ) {
30186
30187                                         if ( hy === p.y ) return p;
30188                                         if ( hy === p.next.y ) return p.next;
30189
30190                                 }
30191
30192                                 m = p.x < p.next.x ? p : p.next;
30193
30194                         }
30195
30196                 }
30197
30198                 p = p.next;
30199
30200         } while ( p !== outerNode );
30201
30202         if ( ! m ) return null;
30203
30204         if ( hx === qx ) return m; // hole touches outer segment; pick leftmost endpoint
30205
30206         // look for points inside the triangle of hole point, segment intersection and endpoint;
30207         // if there are no points found, we have a valid connection;
30208         // otherwise choose the point of the minimum angle with the ray as connection point
30209
30210         const stop = m,
30211                 mx = m.x,
30212                 my = m.y;
30213         let tanMin = Infinity, tan;
30214
30215         p = m;
30216
30217         do {
30218
30219                 if ( hx >= p.x && p.x >= mx && hx !== p.x &&
30220                                 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
30221
30222                         tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
30223
30224                         if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) {
30225
30226                                 m = p;
30227                                 tanMin = tan;
30228
30229                         }
30230
30231                 }
30232
30233                 p = p.next;
30234
30235         } while ( p !== stop );
30236
30237         return m;
30238
30239 }
30240
30241 // whether sector in vertex m contains sector in vertex p in the same coordinates
30242 function sectorContainsSector( m, p ) {
30243
30244         return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0;
30245
30246 }
30247
30248 // interlink polygon nodes in z-order
30249 function indexCurve( start, minX, minY, invSize ) {
30250
30251         let p = start;
30252         do {
30253
30254                 if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
30255                 p.prevZ = p.prev;
30256                 p.nextZ = p.next;
30257                 p = p.next;
30258
30259         } while ( p !== start );
30260
30261         p.prevZ.nextZ = null;
30262         p.prevZ = null;
30263
30264         sortLinked( p );
30265
30266 }
30267
30268 // Simon Tatham's linked list merge sort algorithm
30269 // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
30270 function sortLinked( list ) {
30271
30272         let i, p, q, e, tail, numMerges, pSize, qSize,
30273                 inSize = 1;
30274
30275         do {
30276
30277                 p = list;
30278                 list = null;
30279                 tail = null;
30280                 numMerges = 0;
30281
30282                 while ( p ) {
30283
30284                         numMerges ++;
30285                         q = p;
30286                         pSize = 0;
30287                         for ( i = 0; i < inSize; i ++ ) {
30288
30289                                 pSize ++;
30290                                 q = q.nextZ;
30291                                 if ( ! q ) break;
30292
30293                         }
30294
30295                         qSize = inSize;
30296
30297                         while ( pSize > 0 || ( qSize > 0 && q ) ) {
30298
30299                                 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
30300
30301                                         e = p;
30302                                         p = p.nextZ;
30303                                         pSize --;
30304
30305                                 } else {
30306
30307                                         e = q;
30308                                         q = q.nextZ;
30309                                         qSize --;
30310
30311                                 }
30312
30313                                 if ( tail ) tail.nextZ = e;
30314                                 else list = e;
30315
30316                                 e.prevZ = tail;
30317                                 tail = e;
30318
30319                         }
30320
30321                         p = q;
30322
30323                 }
30324
30325                 tail.nextZ = null;
30326                 inSize *= 2;
30327
30328         } while ( numMerges > 1 );
30329
30330         return list;
30331
30332 }
30333
30334 // z-order of a point given coords and inverse of the longer side of data bbox
30335 function zOrder( x, y, minX, minY, invSize ) {
30336
30337         // coords are transformed into non-negative 15-bit integer range
30338         x = 32767 * ( x - minX ) * invSize;
30339         y = 32767 * ( y - minY ) * invSize;
30340
30341         x = ( x | ( x << 8 ) ) & 0x00FF00FF;
30342         x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
30343         x = ( x | ( x << 2 ) ) & 0x33333333;
30344         x = ( x | ( x << 1 ) ) & 0x55555555;
30345
30346         y = ( y | ( y << 8 ) ) & 0x00FF00FF;
30347         y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
30348         y = ( y | ( y << 2 ) ) & 0x33333333;
30349         y = ( y | ( y << 1 ) ) & 0x55555555;
30350
30351         return x | ( y << 1 );
30352
30353 }
30354
30355 // find the leftmost node of a polygon ring
30356 function getLeftmost( start ) {
30357
30358         let p = start,
30359                 leftmost = start;
30360         do {
30361
30362                 if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
30363                 p = p.next;
30364
30365         } while ( p !== start );
30366
30367         return leftmost;
30368
30369 }
30370
30371 // check if a point lies within a convex triangle
30372 function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
30373
30374         return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
30375                         ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
30376                         ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
30377
30378 }
30379
30380 // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
30381 function isValidDiagonal( a, b ) {
30382
30383         return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges
30384                 ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible
30385                 ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors
30386                 equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case
30387
30388 }
30389
30390 // signed area of a triangle
30391 function area( p, q, r ) {
30392
30393         return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
30394
30395 }
30396
30397 // check if two points are equal
30398 function equals( p1, p2 ) {
30399
30400         return p1.x === p2.x && p1.y === p2.y;
30401
30402 }
30403
30404 // check if two segments intersect
30405 function intersects( p1, q1, p2, q2 ) {
30406
30407         const o1 = sign( area( p1, q1, p2 ) );
30408         const o2 = sign( area( p1, q1, q2 ) );
30409         const o3 = sign( area( p2, q2, p1 ) );
30410         const o4 = sign( area( p2, q2, q1 ) );
30411
30412         if ( o1 !== o2 && o3 !== o4 ) return true; // general case
30413
30414         if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
30415         if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
30416         if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
30417         if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
30418
30419         return false;
30420
30421 }
30422
30423 // for collinear points p, q, r, check if point q lies on segment pr
30424 function onSegment( p, q, r ) {
30425
30426         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 );
30427
30428 }
30429
30430 function sign( num ) {
30431
30432         return num > 0 ? 1 : num < 0 ? - 1 : 0;
30433
30434 }
30435
30436 // check if a polygon diagonal intersects any polygon segments
30437 function intersectsPolygon( a, b ) {
30438
30439         let p = a;
30440         do {
30441
30442                 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
30443                                 intersects( p, p.next, a, b ) ) return true;
30444                 p = p.next;
30445
30446         } while ( p !== a );
30447
30448         return false;
30449
30450 }
30451
30452 // check if a polygon diagonal is locally inside the polygon
30453 function locallyInside( a, b ) {
30454
30455         return area( a.prev, a, a.next ) < 0 ?
30456                 area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
30457                 area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
30458
30459 }
30460
30461 // check if the middle point of a polygon diagonal is inside the polygon
30462 function middleInside( a, b ) {
30463
30464         let p = a,
30465                 inside = false;
30466         const px = ( a.x + b.x ) / 2,
30467                 py = ( a.y + b.y ) / 2;
30468         do {
30469
30470                 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
30471                                 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
30472                         inside = ! inside;
30473                 p = p.next;
30474
30475         } while ( p !== a );
30476
30477         return inside;
30478
30479 }
30480
30481 // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
30482 // if one belongs to the outer ring and another to a hole, it merges it into a single ring
30483 function splitPolygon( a, b ) {
30484
30485         const a2 = new Node( a.i, a.x, a.y ),
30486                 b2 = new Node( b.i, b.x, b.y ),
30487                 an = a.next,
30488                 bp = b.prev;
30489
30490         a.next = b;
30491         b.prev = a;
30492
30493         a2.next = an;
30494         an.prev = a2;
30495
30496         b2.next = a2;
30497         a2.prev = b2;
30498
30499         bp.next = b2;
30500         b2.prev = bp;
30501
30502         return b2;
30503
30504 }
30505
30506 // create a node and optionally link it with previous one (in a circular doubly linked list)
30507 function insertNode( i, x, y, last ) {
30508
30509         const p = new Node( i, x, y );
30510
30511         if ( ! last ) {
30512
30513                 p.prev = p;
30514                 p.next = p;
30515
30516         } else {
30517
30518                 p.next = last.next;
30519                 p.prev = last;
30520                 last.next.prev = p;
30521                 last.next = p;
30522
30523         }
30524
30525         return p;
30526
30527 }
30528
30529 function removeNode( p ) {
30530
30531         p.next.prev = p.prev;
30532         p.prev.next = p.next;
30533
30534         if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
30535         if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
30536
30537 }
30538
30539 function Node( i, x, y ) {
30540
30541         // vertex index in coordinates array
30542         this.i = i;
30543
30544         // vertex coordinates
30545         this.x = x;
30546         this.y = y;
30547
30548         // previous and next vertex nodes in a polygon ring
30549         this.prev = null;
30550         this.next = null;
30551
30552         // z-order curve value
30553         this.z = null;
30554
30555         // previous and next nodes in z-order
30556         this.prevZ = null;
30557         this.nextZ = null;
30558
30559         // indicates whether this is a steiner point
30560         this.steiner = false;
30561
30562 }
30563
30564 function signedArea( data, start, end, dim ) {
30565
30566         let sum = 0;
30567         for ( let i = start, j = end - dim; i < end; i += dim ) {
30568
30569                 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
30570                 j = i;
30571
30572         }
30573
30574         return sum;
30575
30576 }
30577
30578 const ShapeUtils = {
30579
30580         // calculate area of the contour polygon
30581
30582         area: function ( contour ) {
30583
30584                 const n = contour.length;
30585                 let a = 0.0;
30586
30587                 for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
30588
30589                         a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
30590
30591                 }
30592
30593                 return a * 0.5;
30594
30595         },
30596
30597         isClockWise: function ( pts ) {
30598
30599                 return ShapeUtils.area( pts ) < 0;
30600
30601         },
30602
30603         triangulateShape: function ( contour, holes ) {
30604
30605                 const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
30606                 const holeIndices = []; // array of hole indices
30607                 const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
30608
30609                 removeDupEndPts( contour );
30610                 addContour( vertices, contour );
30611
30612                 //
30613
30614                 let holeIndex = contour.length;
30615
30616                 holes.forEach( removeDupEndPts );
30617
30618                 for ( let i = 0; i < holes.length; i ++ ) {
30619
30620                         holeIndices.push( holeIndex );
30621                         holeIndex += holes[ i ].length;
30622                         addContour( vertices, holes[ i ] );
30623
30624                 }
30625
30626                 //
30627
30628                 const triangles = Earcut.triangulate( vertices, holeIndices );
30629
30630                 //
30631
30632                 for ( let i = 0; i < triangles.length; i += 3 ) {
30633
30634                         faces.push( triangles.slice( i, i + 3 ) );
30635
30636                 }
30637
30638                 return faces;
30639
30640         }
30641
30642 };
30643
30644 function removeDupEndPts( points ) {
30645
30646         const l = points.length;
30647
30648         if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
30649
30650                 points.pop();
30651
30652         }
30653
30654 }
30655
30656 function addContour( vertices, contour ) {
30657
30658         for ( let i = 0; i < contour.length; i ++ ) {
30659
30660                 vertices.push( contour[ i ].x );
30661                 vertices.push( contour[ i ].y );
30662
30663         }
30664
30665 }
30666
30667 /**
30668  * Creates extruded geometry from a path shape.
30669  *
30670  * parameters = {
30671  *
30672  *  curveSegments: <int>, // number of points on the curves
30673  *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
30674  *  depth: <float>, // Depth to extrude the shape
30675  *
30676  *  bevelEnabled: <bool>, // turn on bevel
30677  *  bevelThickness: <float>, // how deep into the original shape bevel goes
30678  *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
30679  *  bevelOffset: <float>, // how far from shape outline does bevel start
30680  *  bevelSegments: <int>, // number of bevel layers
30681  *
30682  *  extrudePath: <THREE.Curve> // curve to extrude shape along
30683  *
30684  *  UVGenerator: <Object> // object that provides UV generator functions
30685  *
30686  * }
30687  */
30688
30689 class ExtrudeBufferGeometry extends BufferGeometry {
30690
30691         constructor( shapes, options ) {
30692
30693                 super();
30694
30695                 this.type = 'ExtrudeBufferGeometry';
30696
30697                 this.parameters = {
30698                         shapes: shapes,
30699                         options: options
30700                 };
30701
30702                 shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
30703
30704                 const scope = this;
30705
30706                 const verticesArray = [];
30707                 const uvArray = [];
30708
30709                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
30710
30711                         const shape = shapes[ i ];
30712                         addShape( shape );
30713
30714                 }
30715
30716                 // build geometry
30717
30718                 this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
30719                 this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
30720
30721                 this.computeVertexNormals();
30722
30723                 // functions
30724
30725                 function addShape( shape ) {
30726
30727                         const placeholder = [];
30728
30729                         // options
30730
30731                         const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
30732                         const steps = options.steps !== undefined ? options.steps : 1;
30733                         let depth = options.depth !== undefined ? options.depth : 100;
30734
30735                         let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
30736                         let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
30737                         let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
30738                         let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
30739                         let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
30740
30741                         const extrudePath = options.extrudePath;
30742
30743                         const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
30744
30745                         // deprecated options
30746
30747                         if ( options.amount !== undefined ) {
30748
30749                                 console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );
30750                                 depth = options.amount;
30751
30752                         }
30753
30754                         //
30755
30756                         let extrudePts, extrudeByPath = false;
30757                         let splineTube, binormal, normal, position2;
30758
30759                         if ( extrudePath ) {
30760
30761                                 extrudePts = extrudePath.getSpacedPoints( steps );
30762
30763                                 extrudeByPath = true;
30764                                 bevelEnabled = false; // bevels not supported for path extrusion
30765
30766                                 // SETUP TNB variables
30767
30768                                 // TODO1 - have a .isClosed in spline?
30769
30770                                 splineTube = extrudePath.computeFrenetFrames( steps, false );
30771
30772                                 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
30773
30774                                 binormal = new Vector3();
30775                                 normal = new Vector3();
30776                                 position2 = new Vector3();
30777
30778                         }
30779
30780                         // Safeguards if bevels are not enabled
30781
30782                         if ( ! bevelEnabled ) {
30783
30784                                 bevelSegments = 0;
30785                                 bevelThickness = 0;
30786                                 bevelSize = 0;
30787                                 bevelOffset = 0;
30788
30789                         }
30790
30791                         // Variables initialization
30792
30793                         const shapePoints = shape.extractPoints( curveSegments );
30794
30795                         let vertices = shapePoints.shape;
30796                         const holes = shapePoints.holes;
30797
30798                         const reverse = ! ShapeUtils.isClockWise( vertices );
30799
30800                         if ( reverse ) {
30801
30802                                 vertices = vertices.reverse();
30803
30804                                 // Maybe we should also check if holes are in the opposite direction, just to be safe ...
30805
30806                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
30807
30808                                         const ahole = holes[ h ];
30809
30810                                         if ( ShapeUtils.isClockWise( ahole ) ) {
30811
30812                                                 holes[ h ] = ahole.reverse();
30813
30814                                         }
30815
30816                                 }
30817
30818                         }
30819
30820
30821                         const faces = ShapeUtils.triangulateShape( vertices, holes );
30822
30823                         /* Vertices */
30824
30825                         const contour = vertices; // vertices has all points but contour has only points of circumference
30826
30827                         for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
30828
30829                                 const ahole = holes[ h ];
30830
30831                                 vertices = vertices.concat( ahole );
30832
30833                         }
30834
30835
30836                         function scalePt2( pt, vec, size ) {
30837
30838                                 if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
30839
30840                                 return vec.clone().multiplyScalar( size ).add( pt );
30841
30842                         }
30843
30844                         const vlen = vertices.length, flen = faces.length;
30845
30846
30847                         // Find directions for point movement
30848
30849
30850                         function getBevelVec( inPt, inPrev, inNext ) {
30851
30852                                 // computes for inPt the corresponding point inPt' on a new contour
30853                                 //   shifted by 1 unit (length of normalized vector) to the left
30854                                 // if we walk along contour clockwise, this new contour is outside the old one
30855                                 //
30856                                 // inPt' is the intersection of the two lines parallel to the two
30857                                 //  adjacent edges of inPt at a distance of 1 unit on the left side.
30858
30859                                 let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
30860
30861                                 // good reading for geometry algorithms (here: line-line intersection)
30862                                 // http://geomalgorithms.com/a05-_intersect-1.html
30863
30864                                 const v_prev_x = inPt.x - inPrev.x,
30865                                         v_prev_y = inPt.y - inPrev.y;
30866                                 const v_next_x = inNext.x - inPt.x,
30867                                         v_next_y = inNext.y - inPt.y;
30868
30869                                 const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
30870
30871                                 // check for collinear edges
30872                                 const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
30873
30874                                 if ( Math.abs( collinear0 ) > Number.EPSILON ) {
30875
30876                                         // not collinear
30877
30878                                         // length of vectors for normalizing
30879
30880                                         const v_prev_len = Math.sqrt( v_prev_lensq );
30881                                         const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
30882
30883                                         // shift adjacent points by unit vectors to the left
30884
30885                                         const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
30886                                         const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
30887
30888                                         const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
30889                                         const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
30890
30891                                         // scaling factor for v_prev to intersection point
30892
30893                                         const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
30894                                                         ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
30895                                                 ( v_prev_x * v_next_y - v_prev_y * v_next_x );
30896
30897                                         // vector from inPt to intersection point
30898
30899                                         v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
30900                                         v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
30901
30902                                         // Don't normalize!, otherwise sharp corners become ugly
30903                                         //  but prevent crazy spikes
30904                                         const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
30905                                         if ( v_trans_lensq <= 2 ) {
30906
30907                                                 return new Vector2( v_trans_x, v_trans_y );
30908
30909                                         } else {
30910
30911                                                 shrink_by = Math.sqrt( v_trans_lensq / 2 );
30912
30913                                         }
30914
30915                                 } else {
30916
30917                                         // handle special case of collinear edges
30918
30919                                         let direction_eq = false; // assumes: opposite
30920
30921                                         if ( v_prev_x > Number.EPSILON ) {
30922
30923                                                 if ( v_next_x > Number.EPSILON ) {
30924
30925                                                         direction_eq = true;
30926
30927                                                 }
30928
30929                                         } else {
30930
30931                                                 if ( v_prev_x < - Number.EPSILON ) {
30932
30933                                                         if ( v_next_x < - Number.EPSILON ) {
30934
30935                                                                 direction_eq = true;
30936
30937                                                         }
30938
30939                                                 } else {
30940
30941                                                         if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
30942
30943                                                                 direction_eq = true;
30944
30945                                                         }
30946
30947                                                 }
30948
30949                                         }
30950
30951                                         if ( direction_eq ) {
30952
30953                                                 // console.log("Warning: lines are a straight sequence");
30954                                                 v_trans_x = - v_prev_y;
30955                                                 v_trans_y = v_prev_x;
30956                                                 shrink_by = Math.sqrt( v_prev_lensq );
30957
30958                                         } else {
30959
30960                                                 // console.log("Warning: lines are a straight spike");
30961                                                 v_trans_x = v_prev_x;
30962                                                 v_trans_y = v_prev_y;
30963                                                 shrink_by = Math.sqrt( v_prev_lensq / 2 );
30964
30965                                         }
30966
30967                                 }
30968
30969                                 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
30970
30971                         }
30972
30973
30974                         const contourMovements = [];
30975
30976                         for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
30977
30978                                 if ( j === il ) j = 0;
30979                                 if ( k === il ) k = 0;
30980
30981                                 //  (j)---(i)---(k)
30982                                 // console.log('i,j,k', i, j , k)
30983
30984                                 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
30985
30986                         }
30987
30988                         const holesMovements = [];
30989                         let oneHoleMovements, verticesMovements = contourMovements.concat();
30990
30991                         for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
30992
30993                                 const ahole = holes[ h ];
30994
30995                                 oneHoleMovements = [];
30996
30997                                 for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
30998
30999                                         if ( j === il ) j = 0;
31000                                         if ( k === il ) k = 0;
31001
31002                                         //  (j)---(i)---(k)
31003                                         oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
31004
31005                                 }
31006
31007                                 holesMovements.push( oneHoleMovements );
31008                                 verticesMovements = verticesMovements.concat( oneHoleMovements );
31009
31010                         }
31011
31012
31013                         // Loop bevelSegments, 1 for the front, 1 for the back
31014
31015                         for ( let b = 0; b < bevelSegments; b ++ ) {
31016
31017                                 //for ( b = bevelSegments; b > 0; b -- ) {
31018
31019                                 const t = b / bevelSegments;
31020                                 const z = bevelThickness * Math.cos( t * Math.PI / 2 );
31021                                 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
31022
31023                                 // contract shape
31024
31025                                 for ( let i = 0, il = contour.length; i < il; i ++ ) {
31026
31027                                         const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
31028
31029                                         v( vert.x, vert.y, - z );
31030
31031                                 }
31032
31033                                 // expand holes
31034
31035                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
31036
31037                                         const ahole = holes[ h ];
31038                                         oneHoleMovements = holesMovements[ h ];
31039
31040                                         for ( let i = 0, il = ahole.length; i < il; i ++ ) {
31041
31042                                                 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
31043
31044                                                 v( vert.x, vert.y, - z );
31045
31046                                         }
31047
31048                                 }
31049
31050                         }
31051
31052                         const bs = bevelSize + bevelOffset;
31053
31054                         // Back facing vertices
31055
31056                         for ( let i = 0; i < vlen; i ++ ) {
31057
31058                                 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
31059
31060                                 if ( ! extrudeByPath ) {
31061
31062                                         v( vert.x, vert.y, 0 );
31063
31064                                 } else {
31065
31066                                         // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
31067
31068                                         normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
31069                                         binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
31070
31071                                         position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
31072
31073                                         v( position2.x, position2.y, position2.z );
31074
31075                                 }
31076
31077                         }
31078
31079                         // Add stepped vertices...
31080                         // Including front facing vertices
31081
31082                         for ( let s = 1; s <= steps; s ++ ) {
31083
31084                                 for ( let i = 0; i < vlen; i ++ ) {
31085
31086                                         const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
31087
31088                                         if ( ! extrudeByPath ) {
31089
31090                                                 v( vert.x, vert.y, depth / steps * s );
31091
31092                                         } else {
31093
31094                                                 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
31095
31096                                                 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
31097                                                 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
31098
31099                                                 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
31100
31101                                                 v( position2.x, position2.y, position2.z );
31102
31103                                         }
31104
31105                                 }
31106
31107                         }
31108
31109
31110                         // Add bevel segments planes
31111
31112                         //for ( b = 1; b <= bevelSegments; b ++ ) {
31113                         for ( let b = bevelSegments - 1; b >= 0; b -- ) {
31114
31115                                 const t = b / bevelSegments;
31116                                 const z = bevelThickness * Math.cos( t * Math.PI / 2 );
31117                                 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
31118
31119                                 // contract shape
31120
31121                                 for ( let i = 0, il = contour.length; i < il; i ++ ) {
31122
31123                                         const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
31124                                         v( vert.x, vert.y, depth + z );
31125
31126                                 }
31127
31128                                 // expand holes
31129
31130                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
31131
31132                                         const ahole = holes[ h ];
31133                                         oneHoleMovements = holesMovements[ h ];
31134
31135                                         for ( let i = 0, il = ahole.length; i < il; i ++ ) {
31136
31137                                                 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
31138
31139                                                 if ( ! extrudeByPath ) {
31140
31141                                                         v( vert.x, vert.y, depth + z );
31142
31143                                                 } else {
31144
31145                                                         v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
31146
31147                                                 }
31148
31149                                         }
31150
31151                                 }
31152
31153                         }
31154
31155                         /* Faces */
31156
31157                         // Top and bottom faces
31158
31159                         buildLidFaces();
31160
31161                         // Sides faces
31162
31163                         buildSideFaces();
31164
31165
31166                         /////  Internal functions
31167
31168                         function buildLidFaces() {
31169
31170                                 const start = verticesArray.length / 3;
31171
31172                                 if ( bevelEnabled ) {
31173
31174                                         let layer = 0; // steps + 1
31175                                         let offset = vlen * layer;
31176
31177                                         // Bottom faces
31178
31179                                         for ( let i = 0; i < flen; i ++ ) {
31180
31181                                                 const face = faces[ i ];
31182                                                 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
31183
31184                                         }
31185
31186                                         layer = steps + bevelSegments * 2;
31187                                         offset = vlen * layer;
31188
31189                                         // Top faces
31190
31191                                         for ( let i = 0; i < flen; i ++ ) {
31192
31193                                                 const face = faces[ i ];
31194                                                 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
31195
31196                                         }
31197
31198                                 } else {
31199
31200                                         // Bottom faces
31201
31202                                         for ( let i = 0; i < flen; i ++ ) {
31203
31204                                                 const face = faces[ i ];
31205                                                 f3( face[ 2 ], face[ 1 ], face[ 0 ] );
31206
31207                                         }
31208
31209                                         // Top faces
31210
31211                                         for ( let i = 0; i < flen; i ++ ) {
31212
31213                                                 const face = faces[ i ];
31214                                                 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
31215
31216                                         }
31217
31218                                 }
31219
31220                                 scope.addGroup( start, verticesArray.length / 3 - start, 0 );
31221
31222                         }
31223
31224                         // Create faces for the z-sides of the shape
31225
31226                         function buildSideFaces() {
31227
31228                                 const start = verticesArray.length / 3;
31229                                 let layeroffset = 0;
31230                                 sidewalls( contour, layeroffset );
31231                                 layeroffset += contour.length;
31232
31233                                 for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
31234
31235                                         const ahole = holes[ h ];
31236                                         sidewalls( ahole, layeroffset );
31237
31238                                         //, true
31239                                         layeroffset += ahole.length;
31240
31241                                 }
31242
31243
31244                                 scope.addGroup( start, verticesArray.length / 3 - start, 1 );
31245
31246
31247                         }
31248
31249                         function sidewalls( contour, layeroffset ) {
31250
31251                                 let i = contour.length;
31252
31253                                 while ( -- i >= 0 ) {
31254
31255                                         const j = i;
31256                                         let k = i - 1;
31257                                         if ( k < 0 ) k = contour.length - 1;
31258
31259                                         //console.log('b', i,j, i-1, k,vertices.length);
31260
31261                                         for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
31262
31263                                                 const slen1 = vlen * s;
31264                                                 const slen2 = vlen * ( s + 1 );
31265
31266                                                 const a = layeroffset + j + slen1,
31267                                                         b = layeroffset + k + slen1,
31268                                                         c = layeroffset + k + slen2,
31269                                                         d = layeroffset + j + slen2;
31270
31271                                                 f4( a, b, c, d );
31272
31273                                         }
31274
31275                                 }
31276
31277                         }
31278
31279                         function v( x, y, z ) {
31280
31281                                 placeholder.push( x );
31282                                 placeholder.push( y );
31283                                 placeholder.push( z );
31284
31285                         }
31286
31287
31288                         function f3( a, b, c ) {
31289
31290                                 addVertex( a );
31291                                 addVertex( b );
31292                                 addVertex( c );
31293
31294                                 const nextIndex = verticesArray.length / 3;
31295                                 const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
31296
31297                                 addUV( uvs[ 0 ] );
31298                                 addUV( uvs[ 1 ] );
31299                                 addUV( uvs[ 2 ] );
31300
31301                         }
31302
31303                         function f4( a, b, c, d ) {
31304
31305                                 addVertex( a );
31306                                 addVertex( b );
31307                                 addVertex( d );
31308
31309                                 addVertex( b );
31310                                 addVertex( c );
31311                                 addVertex( d );
31312
31313
31314                                 const nextIndex = verticesArray.length / 3;
31315                                 const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
31316
31317                                 addUV( uvs[ 0 ] );
31318                                 addUV( uvs[ 1 ] );
31319                                 addUV( uvs[ 3 ] );
31320
31321                                 addUV( uvs[ 1 ] );
31322                                 addUV( uvs[ 2 ] );
31323                                 addUV( uvs[ 3 ] );
31324
31325                         }
31326
31327                         function addVertex( index ) {
31328
31329                                 verticesArray.push( placeholder[ index * 3 + 0 ] );
31330                                 verticesArray.push( placeholder[ index * 3 + 1 ] );
31331                                 verticesArray.push( placeholder[ index * 3 + 2 ] );
31332
31333                         }
31334
31335
31336                         function addUV( vector2 ) {
31337
31338                                 uvArray.push( vector2.x );
31339                                 uvArray.push( vector2.y );
31340
31341                         }
31342
31343                 }
31344
31345         }
31346
31347         toJSON() {
31348
31349                 const data = BufferGeometry.prototype.toJSON.call( this );
31350
31351                 const shapes = this.parameters.shapes;
31352                 const options = this.parameters.options;
31353
31354                 return toJSON( shapes, options, data );
31355
31356         }
31357
31358 }
31359
31360 const WorldUVGenerator = {
31361
31362         generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
31363
31364                 const a_x = vertices[ indexA * 3 ];
31365                 const a_y = vertices[ indexA * 3 + 1 ];
31366                 const b_x = vertices[ indexB * 3 ];
31367                 const b_y = vertices[ indexB * 3 + 1 ];
31368                 const c_x = vertices[ indexC * 3 ];
31369                 const c_y = vertices[ indexC * 3 + 1 ];
31370
31371                 return [
31372                         new Vector2( a_x, a_y ),
31373                         new Vector2( b_x, b_y ),
31374                         new Vector2( c_x, c_y )
31375                 ];
31376
31377         },
31378
31379         generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
31380
31381                 const a_x = vertices[ indexA * 3 ];
31382                 const a_y = vertices[ indexA * 3 + 1 ];
31383                 const a_z = vertices[ indexA * 3 + 2 ];
31384                 const b_x = vertices[ indexB * 3 ];
31385                 const b_y = vertices[ indexB * 3 + 1 ];
31386                 const b_z = vertices[ indexB * 3 + 2 ];
31387                 const c_x = vertices[ indexC * 3 ];
31388                 const c_y = vertices[ indexC * 3 + 1 ];
31389                 const c_z = vertices[ indexC * 3 + 2 ];
31390                 const d_x = vertices[ indexD * 3 ];
31391                 const d_y = vertices[ indexD * 3 + 1 ];
31392                 const d_z = vertices[ indexD * 3 + 2 ];
31393
31394                 if ( Math.abs( a_y - b_y ) < 0.01 ) {
31395
31396                         return [
31397                                 new Vector2( a_x, 1 - a_z ),
31398                                 new Vector2( b_x, 1 - b_z ),
31399                                 new Vector2( c_x, 1 - c_z ),
31400                                 new Vector2( d_x, 1 - d_z )
31401                         ];
31402
31403                 } else {
31404
31405                         return [
31406                                 new Vector2( a_y, 1 - a_z ),
31407                                 new Vector2( b_y, 1 - b_z ),
31408                                 new Vector2( c_y, 1 - c_z ),
31409                                 new Vector2( d_y, 1 - d_z )
31410                         ];
31411
31412                 }
31413
31414         }
31415
31416 };
31417
31418 function toJSON( shapes, options, data ) {
31419
31420         data.shapes = [];
31421
31422         if ( Array.isArray( shapes ) ) {
31423
31424                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
31425
31426                         const shape = shapes[ i ];
31427
31428                         data.shapes.push( shape.uuid );
31429
31430                 }
31431
31432         } else {
31433
31434                 data.shapes.push( shapes.uuid );
31435
31436         }
31437
31438         if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
31439
31440         return data;
31441
31442 }
31443
31444 /**
31445  * Creates extruded geometry from a path shape.
31446  *
31447  * parameters = {
31448  *
31449  *  curveSegments: <int>, // number of points on the curves
31450  *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
31451  *  depth: <float>, // Depth to extrude the shape
31452  *
31453  *  bevelEnabled: <bool>, // turn on bevel
31454  *  bevelThickness: <float>, // how deep into the original shape bevel goes
31455  *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
31456  *  bevelOffset: <float>, // how far from shape outline does bevel start
31457  *  bevelSegments: <int>, // number of bevel layers
31458  *
31459  *  extrudePath: <THREE.Curve> // curve to extrude shape along
31460  *
31461  *  UVGenerator: <Object> // object that provides UV generator functions
31462  *
31463  * }
31464  */
31465
31466 class ExtrudeGeometry extends Geometry {
31467
31468         constructor( shapes, options ) {
31469
31470                 super();
31471
31472                 this.type = 'ExtrudeGeometry';
31473
31474                 this.parameters = {
31475                         shapes: shapes,
31476                         options: options
31477                 };
31478
31479                 this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
31480                 this.mergeVertices();
31481
31482         }
31483
31484         toJSON() {
31485
31486                 const data = super.toJSON();
31487
31488                 const shapes = this.parameters.shapes;
31489                 const options = this.parameters.options;
31490
31491                 return toJSON$1( shapes, options, data );
31492
31493         }
31494
31495 }
31496
31497 function toJSON$1( shapes, options, data ) {
31498
31499         data.shapes = [];
31500
31501         if ( Array.isArray( shapes ) ) {
31502
31503                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
31504
31505                         const shape = shapes[ i ];
31506
31507                         data.shapes.push( shape.uuid );
31508
31509                 }
31510
31511         } else {
31512
31513                 data.shapes.push( shapes.uuid );
31514
31515         }
31516
31517         if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
31518
31519         return data;
31520
31521 }
31522
31523 class IcosahedronBufferGeometry extends PolyhedronBufferGeometry {
31524
31525         constructor( radius = 1, detail = 0 ) {
31526
31527                 const t = ( 1 + Math.sqrt( 5 ) ) / 2;
31528
31529                 const vertices = [
31530                         - 1, t, 0,      1, t, 0,        - 1, - t, 0,    1, - t, 0,
31531                         0, - 1, t,      0, 1, t,        0, - 1, - t,    0, 1, - t,
31532                         t, 0, - 1,      t, 0, 1,        - t, 0, - 1,    - t, 0, 1
31533                 ];
31534
31535                 const indices = [
31536                         0, 11, 5,       0, 5, 1,        0, 1, 7,        0, 7, 10,       0, 10, 11,
31537                         1, 5, 9,        5, 11, 4,       11, 10, 2,      10, 7, 6,       7, 1, 8,
31538                         3, 9, 4,        3, 4, 2,        3, 2, 6,        3, 6, 8,        3, 8, 9,
31539                         4, 9, 5,        2, 4, 11,       6, 2, 10,       8, 6, 7,        9, 8, 1
31540                 ];
31541
31542                 super( vertices, indices, radius, detail );
31543
31544                 this.type = 'IcosahedronBufferGeometry';
31545
31546                 this.parameters = {
31547                         radius: radius,
31548                         detail: detail
31549                 };
31550
31551         }
31552
31553 }
31554
31555 class IcosahedronGeometry extends Geometry {
31556
31557         constructor( radius, detail ) {
31558
31559                 super();
31560
31561                 this.type = 'IcosahedronGeometry';
31562
31563                 this.parameters = {
31564                         radius: radius,
31565                         detail: detail
31566                 };
31567
31568                 this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
31569                 this.mergeVertices();
31570
31571         }
31572
31573 }
31574
31575 class LatheBufferGeometry extends BufferGeometry {
31576
31577         constructor( points, segments = 12, phiStart = 0, phiLength = Math.PI * 2 ) {
31578
31579                 super();
31580
31581                 this.type = 'LatheBufferGeometry';
31582
31583                 this.parameters = {
31584                         points: points,
31585                         segments: segments,
31586                         phiStart: phiStart,
31587                         phiLength: phiLength
31588                 };
31589
31590                 segments = Math.floor( segments );
31591
31592                 // clamp phiLength so it's in range of [ 0, 2PI ]
31593
31594                 phiLength = MathUtils.clamp( phiLength, 0, Math.PI * 2 );
31595
31596                 // buffers
31597
31598                 const indices = [];
31599                 const vertices = [];
31600                 const uvs = [];
31601
31602                 // helper variables
31603
31604                 const inverseSegments = 1.0 / segments;
31605                 const vertex = new Vector3();
31606                 const uv = new Vector2();
31607
31608                 // generate vertices and uvs
31609
31610                 for ( let i = 0; i <= segments; i ++ ) {
31611
31612                         const phi = phiStart + i * inverseSegments * phiLength;
31613
31614                         const sin = Math.sin( phi );
31615                         const cos = Math.cos( phi );
31616
31617                         for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
31618
31619                                 // vertex
31620
31621                                 vertex.x = points[ j ].x * sin;
31622                                 vertex.y = points[ j ].y;
31623                                 vertex.z = points[ j ].x * cos;
31624
31625                                 vertices.push( vertex.x, vertex.y, vertex.z );
31626
31627                                 // uv
31628
31629                                 uv.x = i / segments;
31630                                 uv.y = j / ( points.length - 1 );
31631
31632                                 uvs.push( uv.x, uv.y );
31633
31634
31635                         }
31636
31637                 }
31638
31639                 // indices
31640
31641                 for ( let i = 0; i < segments; i ++ ) {
31642
31643                         for ( let j = 0; j < ( points.length - 1 ); j ++ ) {
31644
31645                                 const base = j + i * points.length;
31646
31647                                 const a = base;
31648                                 const b = base + points.length;
31649                                 const c = base + points.length + 1;
31650                                 const d = base + 1;
31651
31652                                 // faces
31653
31654                                 indices.push( a, b, d );
31655                                 indices.push( b, c, d );
31656
31657                         }
31658
31659                 }
31660
31661                 // build geometry
31662
31663                 this.setIndex( indices );
31664                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31665                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
31666
31667                 // generate normals
31668
31669                 this.computeVertexNormals();
31670
31671                 // if the geometry is closed, we need to average the normals along the seam.
31672                 // because the corresponding vertices are identical (but still have different UVs).
31673
31674                 if ( phiLength === Math.PI * 2 ) {
31675
31676                         const normals = this.attributes.normal.array;
31677                         const n1 = new Vector3();
31678                         const n2 = new Vector3();
31679                         const n = new Vector3();
31680
31681                         // this is the buffer offset for the last line of vertices
31682
31683                         const base = segments * points.length * 3;
31684
31685                         for ( let i = 0, j = 0; i < points.length; i ++, j += 3 ) {
31686
31687                                 // select the normal of the vertex in the first line
31688
31689                                 n1.x = normals[ j + 0 ];
31690                                 n1.y = normals[ j + 1 ];
31691                                 n1.z = normals[ j + 2 ];
31692
31693                                 // select the normal of the vertex in the last line
31694
31695                                 n2.x = normals[ base + j + 0 ];
31696                                 n2.y = normals[ base + j + 1 ];
31697                                 n2.z = normals[ base + j + 2 ];
31698
31699                                 // average normals
31700
31701                                 n.addVectors( n1, n2 ).normalize();
31702
31703                                 // assign the new values to both normals
31704
31705                                 normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
31706                                 normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
31707                                 normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
31708
31709                         }
31710
31711                 }
31712
31713         }
31714
31715 }
31716
31717 class LatheGeometry extends Geometry {
31718
31719         constructor( points, segments, phiStart, phiLength ) {
31720
31721                 super();
31722
31723                 this.type = 'LatheGeometry';
31724
31725                 this.parameters = {
31726                         points: points,
31727                         segments: segments,
31728                         phiStart: phiStart,
31729                         phiLength: phiLength
31730                 };
31731
31732                 this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
31733                 this.mergeVertices();
31734
31735         }
31736
31737 }
31738
31739 class OctahedronBufferGeometry extends PolyhedronBufferGeometry {
31740
31741         constructor( radius = 1, detail = 0 ) {
31742
31743                 const vertices = [
31744                         1, 0, 0,        - 1, 0, 0,      0, 1, 0,
31745                         0, - 1, 0,      0, 0, 1,        0, 0, - 1
31746                 ];
31747
31748                 const indices = [
31749                         0, 2, 4,        0, 4, 3,        0, 3, 5,
31750                         0, 5, 2,        1, 2, 5,        1, 5, 3,
31751                         1, 3, 4,        1, 4, 2
31752                 ];
31753
31754                 super( vertices, indices, radius, detail );
31755
31756                 this.type = 'OctahedronBufferGeometry';
31757
31758                 this.parameters = {
31759                         radius: radius,
31760                         detail: detail
31761                 };
31762
31763         }
31764
31765 }
31766
31767 class OctahedronGeometry extends Geometry {
31768
31769         constructor( radius, detail ) {
31770
31771                 super();
31772
31773                 this.type = 'OctahedronGeometry';
31774
31775                 this.parameters = {
31776                         radius: radius,
31777                         detail: detail
31778                 };
31779
31780                 this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
31781                 this.mergeVertices();
31782
31783         }
31784
31785 }
31786
31787 /**
31788  * Parametric Surfaces Geometry
31789  * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
31790  */
31791
31792 function ParametricBufferGeometry( func, slices, stacks ) {
31793
31794         BufferGeometry.call( this );
31795
31796         this.type = 'ParametricBufferGeometry';
31797
31798         this.parameters = {
31799                 func: func,
31800                 slices: slices,
31801                 stacks: stacks
31802         };
31803
31804         // buffers
31805
31806         const indices = [];
31807         const vertices = [];
31808         const normals = [];
31809         const uvs = [];
31810
31811         const EPS = 0.00001;
31812
31813         const normal = new Vector3();
31814
31815         const p0 = new Vector3(), p1 = new Vector3();
31816         const pu = new Vector3(), pv = new Vector3();
31817
31818         if ( func.length < 3 ) {
31819
31820                 console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );
31821
31822         }
31823
31824         // generate vertices, normals and uvs
31825
31826         const sliceCount = slices + 1;
31827
31828         for ( let i = 0; i <= stacks; i ++ ) {
31829
31830                 const v = i / stacks;
31831
31832                 for ( let j = 0; j <= slices; j ++ ) {
31833
31834                         const u = j / slices;
31835
31836                         // vertex
31837
31838                         func( u, v, p0 );
31839                         vertices.push( p0.x, p0.y, p0.z );
31840
31841                         // normal
31842
31843                         // approximate tangent vectors via finite differences
31844
31845                         if ( u - EPS >= 0 ) {
31846
31847                                 func( u - EPS, v, p1 );
31848                                 pu.subVectors( p0, p1 );
31849
31850                         } else {
31851
31852                                 func( u + EPS, v, p1 );
31853                                 pu.subVectors( p1, p0 );
31854
31855                         }
31856
31857                         if ( v - EPS >= 0 ) {
31858
31859                                 func( u, v - EPS, p1 );
31860                                 pv.subVectors( p0, p1 );
31861
31862                         } else {
31863
31864                                 func( u, v + EPS, p1 );
31865                                 pv.subVectors( p1, p0 );
31866
31867                         }
31868
31869                         // cross product of tangent vectors returns surface normal
31870
31871                         normal.crossVectors( pu, pv ).normalize();
31872                         normals.push( normal.x, normal.y, normal.z );
31873
31874                         // uv
31875
31876                         uvs.push( u, v );
31877
31878                 }
31879
31880         }
31881
31882         // generate indices
31883
31884         for ( let i = 0; i < stacks; i ++ ) {
31885
31886                 for ( let j = 0; j < slices; j ++ ) {
31887
31888                         const a = i * sliceCount + j;
31889                         const b = i * sliceCount + j + 1;
31890                         const c = ( i + 1 ) * sliceCount + j + 1;
31891                         const d = ( i + 1 ) * sliceCount + j;
31892
31893                         // faces one and two
31894
31895                         indices.push( a, b, d );
31896                         indices.push( b, c, d );
31897
31898                 }
31899
31900         }
31901
31902         // build geometry
31903
31904         this.setIndex( indices );
31905         this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31906         this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
31907         this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
31908
31909 }
31910
31911 ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
31912 ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
31913
31914 /**
31915  * Parametric Surfaces Geometry
31916  * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
31917  */
31918
31919 function ParametricGeometry( func, slices, stacks ) {
31920
31921         Geometry.call( this );
31922
31923         this.type = 'ParametricGeometry';
31924
31925         this.parameters = {
31926                 func: func,
31927                 slices: slices,
31928                 stacks: stacks
31929         };
31930
31931         this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
31932         this.mergeVertices();
31933
31934 }
31935
31936 ParametricGeometry.prototype = Object.create( Geometry.prototype );
31937 ParametricGeometry.prototype.constructor = ParametricGeometry;
31938
31939 class PlaneGeometry extends Geometry {
31940
31941         constructor( width, height, widthSegments, heightSegments ) {
31942
31943                 super();
31944
31945                 this.type = 'PlaneGeometry';
31946
31947                 this.parameters = {
31948                         width: width,
31949                         height: height,
31950                         widthSegments: widthSegments,
31951                         heightSegments: heightSegments
31952                 };
31953
31954                 this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
31955                 this.mergeVertices();
31956
31957         }
31958
31959 }
31960
31961 class PolyhedronGeometry extends Geometry {
31962
31963         constructor( vertices, indices, radius, detail ) {
31964
31965                 super();
31966
31967                 this.type = 'PolyhedronGeometry';
31968
31969                 this.parameters = {
31970                         vertices: vertices,
31971                         indices: indices,
31972                         radius: radius,
31973                         detail: detail
31974                 };
31975
31976                 this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
31977                 this.mergeVertices();
31978
31979         }
31980
31981 }
31982
31983 class RingBufferGeometry extends BufferGeometry {
31984
31985         constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 8, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) {
31986
31987                 super();
31988
31989                 this.type = 'RingBufferGeometry';
31990
31991                 this.parameters = {
31992                         innerRadius: innerRadius,
31993                         outerRadius: outerRadius,
31994                         thetaSegments: thetaSegments,
31995                         phiSegments: phiSegments,
31996                         thetaStart: thetaStart,
31997                         thetaLength: thetaLength
31998                 };
31999
32000                 thetaSegments = Math.max( 3, thetaSegments );
32001                 phiSegments = Math.max( 1, phiSegments );
32002
32003                 // buffers
32004
32005                 const indices = [];
32006                 const vertices = [];
32007                 const normals = [];
32008                 const uvs = [];
32009
32010                 // some helper variables
32011
32012                 let radius = innerRadius;
32013                 const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
32014                 const vertex = new Vector3();
32015                 const uv = new Vector2();
32016
32017                 // generate vertices, normals and uvs
32018
32019                 for ( let j = 0; j <= phiSegments; j ++ ) {
32020
32021                         for ( let i = 0; i <= thetaSegments; i ++ ) {
32022
32023                                 // values are generate from the inside of the ring to the outside
32024
32025                                 const segment = thetaStart + i / thetaSegments * thetaLength;
32026
32027                                 // vertex
32028
32029                                 vertex.x = radius * Math.cos( segment );
32030                                 vertex.y = radius * Math.sin( segment );
32031
32032                                 vertices.push( vertex.x, vertex.y, vertex.z );
32033
32034                                 // normal
32035
32036                                 normals.push( 0, 0, 1 );
32037
32038                                 // uv
32039
32040                                 uv.x = ( vertex.x / outerRadius + 1 ) / 2;
32041                                 uv.y = ( vertex.y / outerRadius + 1 ) / 2;
32042
32043                                 uvs.push( uv.x, uv.y );
32044
32045                         }
32046
32047                         // increase the radius for next row of vertices
32048
32049                         radius += radiusStep;
32050
32051                 }
32052
32053                 // indices
32054
32055                 for ( let j = 0; j < phiSegments; j ++ ) {
32056
32057                         const thetaSegmentLevel = j * ( thetaSegments + 1 );
32058
32059                         for ( let i = 0; i < thetaSegments; i ++ ) {
32060
32061                                 const segment = i + thetaSegmentLevel;
32062
32063                                 const a = segment;
32064                                 const b = segment + thetaSegments + 1;
32065                                 const c = segment + thetaSegments + 2;
32066                                 const d = segment + 1;
32067
32068                                 // faces
32069
32070                                 indices.push( a, b, d );
32071                                 indices.push( b, c, d );
32072
32073                         }
32074
32075                 }
32076
32077                 // build geometry
32078
32079                 this.setIndex( indices );
32080                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32081                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32082                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32083
32084         }
32085
32086 }
32087
32088 class RingGeometry extends Geometry {
32089
32090         constructor( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
32091
32092                 super();
32093
32094                 this.type = 'RingGeometry';
32095
32096                 this.parameters = {
32097                         innerRadius: innerRadius,
32098                         outerRadius: outerRadius,
32099                         thetaSegments: thetaSegments,
32100                         phiSegments: phiSegments,
32101                         thetaStart: thetaStart,
32102                         thetaLength: thetaLength
32103                 };
32104
32105                 this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
32106                 this.mergeVertices();
32107
32108         }
32109
32110 }
32111
32112 class ShapeBufferGeometry extends BufferGeometry {
32113
32114         constructor( shapes, curveSegments = 12 ) {
32115
32116                 super();
32117                 this.type = 'ShapeBufferGeometry';
32118
32119                 this.parameters = {
32120                         shapes: shapes,
32121                         curveSegments: curveSegments
32122                 };
32123
32124                 // buffers
32125
32126                 const indices = [];
32127                 const vertices = [];
32128                 const normals = [];
32129                 const uvs = [];
32130
32131                 // helper variables
32132
32133                 let groupStart = 0;
32134                 let groupCount = 0;
32135
32136                 // allow single and array values for "shapes" parameter
32137
32138                 if ( Array.isArray( shapes ) === false ) {
32139
32140                         addShape( shapes );
32141
32142                 } else {
32143
32144                         for ( let i = 0; i < shapes.length; i ++ ) {
32145
32146                                 addShape( shapes[ i ] );
32147
32148                                 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
32149
32150                                 groupStart += groupCount;
32151                                 groupCount = 0;
32152
32153                         }
32154
32155                 }
32156
32157                 // build geometry
32158
32159                 this.setIndex( indices );
32160                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32161                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32162                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32163
32164
32165                 // helper functions
32166
32167                 function addShape( shape ) {
32168
32169                         const indexOffset = vertices.length / 3;
32170                         const points = shape.extractPoints( curveSegments );
32171
32172                         let shapeVertices = points.shape;
32173                         const shapeHoles = points.holes;
32174
32175                         // check direction of vertices
32176
32177                         if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
32178
32179                                 shapeVertices = shapeVertices.reverse();
32180
32181                         }
32182
32183                         for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
32184
32185                                 const shapeHole = shapeHoles[ i ];
32186
32187                                 if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
32188
32189                                         shapeHoles[ i ] = shapeHole.reverse();
32190
32191                                 }
32192
32193                         }
32194
32195                         const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
32196
32197                         // join vertices of inner and outer paths to a single array
32198
32199                         for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
32200
32201                                 const shapeHole = shapeHoles[ i ];
32202                                 shapeVertices = shapeVertices.concat( shapeHole );
32203
32204                         }
32205
32206                         // vertices, normals, uvs
32207
32208                         for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
32209
32210                                 const vertex = shapeVertices[ i ];
32211
32212                                 vertices.push( vertex.x, vertex.y, 0 );
32213                                 normals.push( 0, 0, 1 );
32214                                 uvs.push( vertex.x, vertex.y ); // world uvs
32215
32216                         }
32217
32218                         // incides
32219
32220                         for ( let i = 0, l = faces.length; i < l; i ++ ) {
32221
32222                                 const face = faces[ i ];
32223
32224                                 const a = face[ 0 ] + indexOffset;
32225                                 const b = face[ 1 ] + indexOffset;
32226                                 const c = face[ 2 ] + indexOffset;
32227
32228                                 indices.push( a, b, c );
32229                                 groupCount += 3;
32230
32231                         }
32232
32233                 }
32234
32235         }
32236
32237         toJSON() {
32238
32239                 const data = BufferGeometry.prototype.toJSON.call( this );
32240
32241                 const shapes = this.parameters.shapes;
32242
32243                 return toJSON$2( shapes, data );
32244
32245         }
32246
32247 }
32248
32249 function toJSON$2( shapes, data ) {
32250
32251         data.shapes = [];
32252
32253         if ( Array.isArray( shapes ) ) {
32254
32255                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
32256
32257                         const shape = shapes[ i ];
32258
32259                         data.shapes.push( shape.uuid );
32260
32261                 }
32262
32263         } else {
32264
32265                 data.shapes.push( shapes.uuid );
32266
32267         }
32268
32269         return data;
32270
32271 }
32272
32273 class ShapeGeometry extends Geometry {
32274
32275         constructor( shapes, curveSegments ) {
32276
32277                 super();
32278                 this.type = 'ShapeGeometry';
32279
32280                 if ( typeof curveSegments === 'object' ) {
32281
32282                         console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
32283
32284                         curveSegments = curveSegments.curveSegments;
32285
32286                 }
32287
32288                 this.parameters = {
32289                         shapes: shapes,
32290                         curveSegments: curveSegments
32291                 };
32292
32293                 this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
32294                 this.mergeVertices();
32295
32296         }
32297
32298         toJSON() {
32299
32300                 const data = Geometry.prototype.toJSON.call( this );
32301
32302                 const shapes = this.parameters.shapes;
32303
32304                 return toJSON$3( shapes, data );
32305
32306         }
32307
32308 }
32309
32310 function toJSON$3( shapes, data ) {
32311
32312         data.shapes = [];
32313
32314         if ( Array.isArray( shapes ) ) {
32315
32316                 for ( let i = 0, l = shapes.length; i < l; i ++ ) {
32317
32318                         const shape = shapes[ i ];
32319
32320                         data.shapes.push( shape.uuid );
32321
32322                 }
32323
32324         } else {
32325
32326                 data.shapes.push( shapes.uuid );
32327
32328         }
32329
32330         return data;
32331
32332 }
32333
32334 class SphereBufferGeometry extends BufferGeometry {
32335
32336         constructor( radius = 1, widthSegments = 8, heightSegments = 6, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
32337
32338                 super();
32339                 this.type = 'SphereBufferGeometry';
32340
32341                 this.parameters = {
32342                         radius: radius,
32343                         widthSegments: widthSegments,
32344                         heightSegments: heightSegments,
32345                         phiStart: phiStart,
32346                         phiLength: phiLength,
32347                         thetaStart: thetaStart,
32348                         thetaLength: thetaLength
32349                 };
32350
32351                 widthSegments = Math.max( 3, Math.floor( widthSegments ) );
32352                 heightSegments = Math.max( 2, Math.floor( heightSegments ) );
32353
32354                 const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
32355
32356                 let index = 0;
32357                 const grid = [];
32358
32359                 const vertex = new Vector3();
32360                 const normal = new Vector3();
32361
32362                 // buffers
32363
32364                 const indices = [];
32365                 const vertices = [];
32366                 const normals = [];
32367                 const uvs = [];
32368
32369                 // generate vertices, normals and uvs
32370
32371                 for ( let iy = 0; iy <= heightSegments; iy ++ ) {
32372
32373                         const verticesRow = [];
32374
32375                         const v = iy / heightSegments;
32376
32377                         // special case for the poles
32378
32379                         let uOffset = 0;
32380
32381                         if ( iy == 0 && thetaStart == 0 ) {
32382
32383                                 uOffset = 0.5 / widthSegments;
32384
32385                         } else if ( iy == heightSegments && thetaEnd == Math.PI ) {
32386
32387                                 uOffset = - 0.5 / widthSegments;
32388
32389                         }
32390
32391                         for ( let ix = 0; ix <= widthSegments; ix ++ ) {
32392
32393                                 const u = ix / widthSegments;
32394
32395                                 // vertex
32396
32397                                 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
32398                                 vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
32399                                 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
32400
32401                                 vertices.push( vertex.x, vertex.y, vertex.z );
32402
32403                                 // normal
32404
32405                                 normal.copy( vertex ).normalize();
32406                                 normals.push( normal.x, normal.y, normal.z );
32407
32408                                 // uv
32409
32410                                 uvs.push( u + uOffset, 1 - v );
32411
32412                                 verticesRow.push( index ++ );
32413
32414                         }
32415
32416                         grid.push( verticesRow );
32417
32418                 }
32419
32420                 // indices
32421
32422                 for ( let iy = 0; iy < heightSegments; iy ++ ) {
32423
32424                         for ( let ix = 0; ix < widthSegments; ix ++ ) {
32425
32426                                 const a = grid[ iy ][ ix + 1 ];
32427                                 const b = grid[ iy ][ ix ];
32428                                 const c = grid[ iy + 1 ][ ix ];
32429                                 const d = grid[ iy + 1 ][ ix + 1 ];
32430
32431                                 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
32432                                 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
32433
32434                         }
32435
32436                 }
32437
32438                 // build geometry
32439
32440                 this.setIndex( indices );
32441                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32442                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32443                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32444
32445         }
32446
32447 }
32448
32449 class SphereGeometry extends Geometry {
32450
32451         constructor( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
32452
32453                 super();
32454                 this.type = 'SphereGeometry';
32455
32456                 this.parameters = {
32457                         radius: radius,
32458                         widthSegments: widthSegments,
32459                         heightSegments: heightSegments,
32460                         phiStart: phiStart,
32461                         phiLength: phiLength,
32462                         thetaStart: thetaStart,
32463                         thetaLength: thetaLength
32464                 };
32465
32466                 this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
32467                 this.mergeVertices();
32468
32469         }
32470
32471 }
32472
32473 class TetrahedronBufferGeometry extends PolyhedronBufferGeometry {
32474
32475         constructor( radius = 1, detail = 0 ) {
32476
32477                 const vertices = [
32478                         1, 1, 1,        - 1, - 1, 1,    - 1, 1, - 1,    1, - 1, - 1
32479                 ];
32480
32481                 const indices = [
32482                         2, 1, 0,        0, 3, 2,        1, 3, 0,        2, 3, 1
32483                 ];
32484
32485                 super( vertices, indices, radius, detail );
32486
32487                 this.type = 'TetrahedronBufferGeometry';
32488
32489                 this.parameters = {
32490                         radius: radius,
32491                         detail: detail
32492                 };
32493
32494         }
32495
32496 }
32497
32498 class TetrahedronGeometry extends Geometry {
32499
32500         constructor( radius, detail ) {
32501
32502                 super();
32503                 this.type = 'TetrahedronGeometry';
32504
32505                 this.parameters = {
32506                         radius: radius,
32507                         detail: detail
32508                 };
32509
32510                 this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
32511                 this.mergeVertices();
32512
32513         }
32514
32515 }
32516
32517 /**
32518  * Text = 3D Text
32519  *
32520  * parameters = {
32521  *  font: <THREE.Font>, // font
32522  *
32523  *  size: <float>, // size of the text
32524  *  height: <float>, // thickness to extrude text
32525  *  curveSegments: <int>, // number of points on the curves
32526  *
32527  *  bevelEnabled: <bool>, // turn on bevel
32528  *  bevelThickness: <float>, // how deep into text bevel goes
32529  *  bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
32530  *  bevelOffset: <float> // how far from text outline does bevel start
32531  * }
32532  */
32533
32534 class TextBufferGeometry extends ExtrudeBufferGeometry {
32535
32536         constructor( text, parameters = {} ) {
32537
32538                 const font = parameters.font;
32539
32540                 if ( ! ( font && font.isFont ) ) {
32541
32542                         console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
32543                         return new BufferGeometry();
32544
32545                 }
32546
32547                 const shapes = font.generateShapes( text, parameters.size );
32548
32549                 // translate parameters to ExtrudeGeometry API
32550
32551                 parameters.depth = parameters.height !== undefined ? parameters.height : 50;
32552
32553                 // defaults
32554
32555                 if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
32556                 if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
32557                 if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
32558
32559                 super( shapes, parameters );
32560
32561                 this.type = 'TextBufferGeometry';
32562
32563         }
32564
32565 }
32566
32567 /**
32568  * Text = 3D Text
32569  *
32570  * parameters = {
32571  *  font: <THREE.Font>, // font
32572  *
32573  *  size: <float>, // size of the text
32574  *  height: <float>, // thickness to extrude text
32575  *  curveSegments: <int>, // number of points on the curves
32576  *
32577  *  bevelEnabled: <bool>, // turn on bevel
32578  *  bevelThickness: <float>, // how deep into text bevel goes
32579  *  bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
32580  *  bevelOffset: <float> // how far from text outline does bevel start
32581  * }
32582  */
32583
32584 class TextGeometry extends Geometry {
32585
32586         constructor( text, parameters ) {
32587
32588                 super();
32589                 this.type = 'TextGeometry';
32590
32591                 this.parameters = {
32592                         text: text,
32593                         parameters: parameters
32594                 };
32595
32596                 this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
32597                 this.mergeVertices();
32598
32599         }
32600
32601 }
32602
32603 class TorusBufferGeometry extends BufferGeometry {
32604
32605         constructor( radius = 1, tube = 0.4, radialSegments = 8, tubularSegments = 6, arc = Math.PI * 2 ) {
32606
32607                 super();
32608                 this.type = 'TorusBufferGeometry';
32609
32610                 this.parameters = {
32611                         radius: radius,
32612                         tube: tube,
32613                         radialSegments: radialSegments,
32614                         tubularSegments: tubularSegments,
32615                         arc: arc
32616                 };
32617
32618                 radialSegments = Math.floor( radialSegments );
32619                 tubularSegments = Math.floor( tubularSegments );
32620
32621                 // buffers
32622
32623                 const indices = [];
32624                 const vertices = [];
32625                 const normals = [];
32626                 const uvs = [];
32627
32628                 // helper variables
32629
32630                 const center = new Vector3();
32631                 const vertex = new Vector3();
32632                 const normal = new Vector3();
32633
32634                 // generate vertices, normals and uvs
32635
32636                 for ( let j = 0; j <= radialSegments; j ++ ) {
32637
32638                         for ( let i = 0; i <= tubularSegments; i ++ ) {
32639
32640                                 const u = i / tubularSegments * arc;
32641                                 const v = j / radialSegments * Math.PI * 2;
32642
32643                                 // vertex
32644
32645                                 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
32646                                 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
32647                                 vertex.z = tube * Math.sin( v );
32648
32649                                 vertices.push( vertex.x, vertex.y, vertex.z );
32650
32651                                 // normal
32652
32653                                 center.x = radius * Math.cos( u );
32654                                 center.y = radius * Math.sin( u );
32655                                 normal.subVectors( vertex, center ).normalize();
32656
32657                                 normals.push( normal.x, normal.y, normal.z );
32658
32659                                 // uv
32660
32661                                 uvs.push( i / tubularSegments );
32662                                 uvs.push( j / radialSegments );
32663
32664                         }
32665
32666                 }
32667
32668                 // generate indices
32669
32670                 for ( let j = 1; j <= radialSegments; j ++ ) {
32671
32672                         for ( let i = 1; i <= tubularSegments; i ++ ) {
32673
32674                                 // indices
32675
32676                                 const a = ( tubularSegments + 1 ) * j + i - 1;
32677                                 const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
32678                                 const c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
32679                                 const d = ( tubularSegments + 1 ) * j + i;
32680
32681                                 // faces
32682
32683                                 indices.push( a, b, d );
32684                                 indices.push( b, c, d );
32685
32686                         }
32687
32688                 }
32689
32690                 // build geometry
32691
32692                 this.setIndex( indices );
32693                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32694                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32695                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32696
32697         }
32698
32699 }
32700
32701 class TorusGeometry extends Geometry {
32702
32703         constructor( radius, tube, radialSegments, tubularSegments, arc ) {
32704
32705                 super();
32706                 this.type = 'TorusGeometry';
32707
32708                 this.parameters = {
32709                         radius: radius,
32710                         tube: tube,
32711                         radialSegments: radialSegments,
32712                         tubularSegments: tubularSegments,
32713                         arc: arc
32714                 };
32715
32716                 this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
32717                 this.mergeVertices();
32718
32719         }
32720
32721 }
32722
32723 class TorusKnotBufferGeometry extends BufferGeometry {
32724
32725         constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) {
32726
32727                 super();
32728                 this.type = 'TorusKnotBufferGeometry';
32729
32730                 this.parameters = {
32731                         radius: radius,
32732                         tube: tube,
32733                         tubularSegments: tubularSegments,
32734                         radialSegments: radialSegments,
32735                         p: p,
32736                         q: q
32737                 };
32738
32739                 tubularSegments = Math.floor( tubularSegments );
32740                 radialSegments = Math.floor( radialSegments );
32741
32742                 // buffers
32743
32744                 const indices = [];
32745                 const vertices = [];
32746                 const normals = [];
32747                 const uvs = [];
32748
32749                 // helper variables
32750
32751                 const vertex = new Vector3();
32752                 const normal = new Vector3();
32753
32754                 const P1 = new Vector3();
32755                 const P2 = new Vector3();
32756
32757                 const B = new Vector3();
32758                 const T = new Vector3();
32759                 const N = new Vector3();
32760
32761                 // generate vertices, normals and uvs
32762
32763                 for ( let i = 0; i <= tubularSegments; ++ i ) {
32764
32765                         // the radian "u" is used to calculate the position on the torus curve of the current tubular segement
32766
32767                         const u = i / tubularSegments * p * Math.PI * 2;
32768
32769                         // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
32770                         // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
32771
32772                         calculatePositionOnCurve( u, p, q, radius, P1 );
32773                         calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
32774
32775                         // calculate orthonormal basis
32776
32777                         T.subVectors( P2, P1 );
32778                         N.addVectors( P2, P1 );
32779                         B.crossVectors( T, N );
32780                         N.crossVectors( B, T );
32781
32782                         // normalize B, N. T can be ignored, we don't use it
32783
32784                         B.normalize();
32785                         N.normalize();
32786
32787                         for ( let j = 0; j <= radialSegments; ++ j ) {
32788
32789                                 // now calculate the vertices. they are nothing more than an extrusion of the torus curve.
32790                                 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
32791
32792                                 const v = j / radialSegments * Math.PI * 2;
32793                                 const cx = - tube * Math.cos( v );
32794                                 const cy = tube * Math.sin( v );
32795
32796                                 // now calculate the final vertex position.
32797                                 // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
32798
32799                                 vertex.x = P1.x + ( cx * N.x + cy * B.x );
32800                                 vertex.y = P1.y + ( cx * N.y + cy * B.y );
32801                                 vertex.z = P1.z + ( cx * N.z + cy * B.z );
32802
32803                                 vertices.push( vertex.x, vertex.y, vertex.z );
32804
32805                                 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
32806
32807                                 normal.subVectors( vertex, P1 ).normalize();
32808
32809                                 normals.push( normal.x, normal.y, normal.z );
32810
32811                                 // uv
32812
32813                                 uvs.push( i / tubularSegments );
32814                                 uvs.push( j / radialSegments );
32815
32816                         }
32817
32818                 }
32819
32820                 // generate indices
32821
32822                 for ( let j = 1; j <= tubularSegments; j ++ ) {
32823
32824                         for ( let i = 1; i <= radialSegments; i ++ ) {
32825
32826                                 // indices
32827
32828                                 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
32829                                 const b = ( radialSegments + 1 ) * j + ( i - 1 );
32830                                 const c = ( radialSegments + 1 ) * j + i;
32831                                 const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
32832
32833                                 // faces
32834
32835                                 indices.push( a, b, d );
32836                                 indices.push( b, c, d );
32837
32838                         }
32839
32840                 }
32841
32842                 // build geometry
32843
32844                 this.setIndex( indices );
32845                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32846                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32847                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32848
32849                 // this function calculates the current position on the torus curve
32850
32851                 function calculatePositionOnCurve( u, p, q, radius, position ) {
32852
32853                         const cu = Math.cos( u );
32854                         const su = Math.sin( u );
32855                         const quOverP = q / p * u;
32856                         const cs = Math.cos( quOverP );
32857
32858                         position.x = radius * ( 2 + cs ) * 0.5 * cu;
32859                         position.y = radius * ( 2 + cs ) * su * 0.5;
32860                         position.z = radius * Math.sin( quOverP ) * 0.5;
32861
32862                 }
32863
32864         }
32865
32866 }
32867
32868 class TorusKnotGeometry extends Geometry {
32869
32870         constructor( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
32871
32872                 super();
32873                 this.type = 'TorusKnotGeometry';
32874
32875                 this.parameters = {
32876                         radius: radius,
32877                         tube: tube,
32878                         tubularSegments: tubularSegments,
32879                         radialSegments: radialSegments,
32880                         p: p,
32881                         q: q
32882                 };
32883
32884                 if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
32885
32886                 this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
32887                 this.mergeVertices();
32888
32889         }
32890
32891 }
32892
32893 class TubeBufferGeometry extends BufferGeometry {
32894
32895         constructor( path, tubularSegments = 64, radius = 1, radialSegments = 8, closed = false ) {
32896
32897                 super();
32898                 this.type = 'TubeBufferGeometry';
32899
32900                 this.parameters = {
32901                         path: path,
32902                         tubularSegments: tubularSegments,
32903                         radius: radius,
32904                         radialSegments: radialSegments,
32905                         closed: closed
32906                 };
32907
32908                 const frames = path.computeFrenetFrames( tubularSegments, closed );
32909
32910                 // expose internals
32911
32912                 this.tangents = frames.tangents;
32913                 this.normals = frames.normals;
32914                 this.binormals = frames.binormals;
32915
32916                 // helper variables
32917
32918                 const vertex = new Vector3();
32919                 const normal = new Vector3();
32920                 const uv = new Vector2();
32921                 let P = new Vector3();
32922
32923                 // buffer
32924
32925                 const vertices = [];
32926                 const normals = [];
32927                 const uvs = [];
32928                 const indices = [];
32929
32930                 // create buffer data
32931
32932                 generateBufferData();
32933
32934                 // build geometry
32935
32936                 this.setIndex( indices );
32937                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32938                 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32939                 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32940
32941                 // functions
32942
32943                 function generateBufferData() {
32944
32945                         for ( let i = 0; i < tubularSegments; i ++ ) {
32946
32947                                 generateSegment( i );
32948
32949                         }
32950
32951                         // if the geometry is not closed, generate the last row of vertices and normals
32952                         // at the regular position on the given path
32953                         //
32954                         // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
32955
32956                         generateSegment( ( closed === false ) ? tubularSegments : 0 );
32957
32958                         // uvs are generated in a separate function.
32959                         // this makes it easy compute correct values for closed geometries
32960
32961                         generateUVs();
32962
32963                         // finally create faces
32964
32965                         generateIndices();
32966
32967                 }
32968
32969                 function generateSegment( i ) {
32970
32971                         // we use getPointAt to sample evenly distributed points from the given path
32972
32973                         P = path.getPointAt( i / tubularSegments, P );
32974
32975                         // retrieve corresponding normal and binormal
32976
32977                         const N = frames.normals[ i ];
32978                         const B = frames.binormals[ i ];
32979
32980                         // generate normals and vertices for the current segment
32981
32982                         for ( let j = 0; j <= radialSegments; j ++ ) {
32983
32984                                 const v = j / radialSegments * Math.PI * 2;
32985
32986                                 const sin = Math.sin( v );
32987                                 const cos = - Math.cos( v );
32988
32989                                 // normal
32990
32991                                 normal.x = ( cos * N.x + sin * B.x );
32992                                 normal.y = ( cos * N.y + sin * B.y );
32993                                 normal.z = ( cos * N.z + sin * B.z );
32994                                 normal.normalize();
32995
32996                                 normals.push( normal.x, normal.y, normal.z );
32997
32998                                 // vertex
32999
33000                                 vertex.x = P.x + radius * normal.x;
33001                                 vertex.y = P.y + radius * normal.y;
33002                                 vertex.z = P.z + radius * normal.z;
33003
33004                                 vertices.push( vertex.x, vertex.y, vertex.z );
33005
33006                         }
33007
33008                 }
33009
33010                 function generateIndices() {
33011
33012                         for ( let j = 1; j <= tubularSegments; j ++ ) {
33013
33014                                 for ( let i = 1; i <= radialSegments; i ++ ) {
33015
33016                                         const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
33017                                         const b = ( radialSegments + 1 ) * j + ( i - 1 );
33018                                         const c = ( radialSegments + 1 ) * j + i;
33019                                         const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
33020
33021                                         // faces
33022
33023                                         indices.push( a, b, d );
33024                                         indices.push( b, c, d );
33025
33026                                 }
33027
33028                         }
33029
33030                 }
33031
33032                 function generateUVs() {
33033
33034                         for ( let i = 0; i <= tubularSegments; i ++ ) {
33035
33036                                 for ( let j = 0; j <= radialSegments; j ++ ) {
33037
33038                                         uv.x = i / tubularSegments;
33039                                         uv.y = j / radialSegments;
33040
33041                                         uvs.push( uv.x, uv.y );
33042
33043                                 }
33044
33045                         }
33046
33047                 }
33048
33049         }
33050         toJSON() {
33051
33052                 const data = BufferGeometry.prototype.toJSON.call( this );
33053
33054                 data.path = this.parameters.path.toJSON();
33055
33056                 return data;
33057
33058         }
33059
33060 }
33061
33062 class TubeGeometry extends Geometry {
33063
33064         constructor( path, tubularSegments, radius, radialSegments, closed, taper ) {
33065
33066                 super();
33067                 this.type = 'TubeGeometry';
33068
33069                 this.parameters = {
33070                         path: path,
33071                         tubularSegments: tubularSegments,
33072                         radius: radius,
33073                         radialSegments: radialSegments,
33074                         closed: closed
33075                 };
33076
33077                 if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
33078
33079                 const bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
33080
33081                 // expose internals
33082
33083                 this.tangents = bufferGeometry.tangents;
33084                 this.normals = bufferGeometry.normals;
33085                 this.binormals = bufferGeometry.binormals;
33086
33087                 // create geometry
33088
33089                 this.fromBufferGeometry( bufferGeometry );
33090                 this.mergeVertices();
33091
33092         }
33093
33094 }
33095
33096 class WireframeGeometry extends BufferGeometry {
33097
33098         constructor( geometry ) {
33099
33100                 super();
33101                 this.type = 'WireframeGeometry';
33102
33103                 // buffer
33104
33105                 const vertices = [];
33106
33107                 // helper variables
33108
33109                 const edge = [ 0, 0 ], edges = {};
33110                 const keys = [ 'a', 'b', 'c' ];
33111
33112                 // different logic for Geometry and BufferGeometry
33113
33114                 if ( geometry && geometry.isGeometry ) {
33115
33116                         // create a data structure that contains all edges without duplicates
33117
33118                         const faces = geometry.faces;
33119
33120                         for ( let i = 0, l = faces.length; i < l; i ++ ) {
33121
33122                                 const face = faces[ i ];
33123
33124                                 for ( let j = 0; j < 3; j ++ ) {
33125
33126                                         const edge1 = face[ keys[ j ] ];
33127                                         const edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
33128                                         edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
33129                                         edge[ 1 ] = Math.max( edge1, edge2 );
33130
33131                                         const key = edge[ 0 ] + ',' + edge[ 1 ];
33132
33133                                         if ( edges[ key ] === undefined ) {
33134
33135                                                 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
33136
33137                                         }
33138
33139                                 }
33140
33141                         }
33142
33143                         // generate vertices
33144
33145                         for ( const key in edges ) {
33146
33147                                 const e = edges[ key ];
33148
33149                                 let vertex = geometry.vertices[ e.index1 ];
33150                                 vertices.push( vertex.x, vertex.y, vertex.z );
33151
33152                                 vertex = geometry.vertices[ e.index2 ];
33153                                 vertices.push( vertex.x, vertex.y, vertex.z );
33154
33155                         }
33156
33157                 } else if ( geometry && geometry.isBufferGeometry ) {
33158
33159                         const vertex = new Vector3();
33160
33161                         if ( geometry.index !== null ) {
33162
33163                                 // indexed BufferGeometry
33164
33165                                 const position = geometry.attributes.position;
33166                                 const indices = geometry.index;
33167                                 let groups = geometry.groups;
33168
33169                                 if ( groups.length === 0 ) {
33170
33171                                         groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
33172
33173                                 }
33174
33175                                 // create a data structure that contains all eges without duplicates
33176
33177                                 for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
33178
33179                                         const group = groups[ o ];
33180
33181                                         const start = group.start;
33182                                         const count = group.count;
33183
33184                                         for ( let i = start, l = ( start + count ); i < l; i += 3 ) {
33185
33186                                                 for ( let j = 0; j < 3; j ++ ) {
33187
33188                                                         const edge1 = indices.getX( i + j );
33189                                                         const edge2 = indices.getX( i + ( j + 1 ) % 3 );
33190                                                         edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
33191                                                         edge[ 1 ] = Math.max( edge1, edge2 );
33192
33193                                                         const key = edge[ 0 ] + ',' + edge[ 1 ];
33194
33195                                                         if ( edges[ key ] === undefined ) {
33196
33197                                                                 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
33198
33199                                                         }
33200
33201                                                 }
33202
33203                                         }
33204
33205                                 }
33206
33207                                 // generate vertices
33208
33209                                 for ( const key in edges ) {
33210
33211                                         const e = edges[ key ];
33212
33213                                         vertex.fromBufferAttribute( position, e.index1 );
33214                                         vertices.push( vertex.x, vertex.y, vertex.z );
33215
33216                                         vertex.fromBufferAttribute( position, e.index2 );
33217                                         vertices.push( vertex.x, vertex.y, vertex.z );
33218
33219                                 }
33220
33221                         } else {
33222
33223                                 // non-indexed BufferGeometry
33224
33225                                 const position = geometry.attributes.position;
33226
33227                                 for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
33228
33229                                         for ( let j = 0; j < 3; j ++ ) {
33230
33231                                                 // three edges per triangle, an edge is represented as (index1, index2)
33232                                                 // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
33233
33234                                                 const index1 = 3 * i + j;
33235                                                 vertex.fromBufferAttribute( position, index1 );
33236                                                 vertices.push( vertex.x, vertex.y, vertex.z );
33237
33238                                                 const index2 = 3 * i + ( ( j + 1 ) % 3 );
33239                                                 vertex.fromBufferAttribute( position, index2 );
33240                                                 vertices.push( vertex.x, vertex.y, vertex.z );
33241
33242                                         }
33243
33244                                 }
33245
33246                         }
33247
33248                 }
33249
33250                 // build geometry
33251
33252                 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
33253
33254         }
33255
33256 }
33257
33258 var Geometries = /*#__PURE__*/Object.freeze({
33259         __proto__: null,
33260         BoxGeometry: BoxGeometry,
33261         BoxBufferGeometry: BoxBufferGeometry,
33262         CircleGeometry: CircleGeometry,
33263         CircleBufferGeometry: CircleBufferGeometry,
33264         ConeGeometry: ConeGeometry,
33265         ConeBufferGeometry: ConeBufferGeometry,
33266         CylinderGeometry: CylinderGeometry,
33267         CylinderBufferGeometry: CylinderBufferGeometry,
33268         DodecahedronGeometry: DodecahedronGeometry,
33269         DodecahedronBufferGeometry: DodecahedronBufferGeometry,
33270         EdgesGeometry: EdgesGeometry,
33271         ExtrudeGeometry: ExtrudeGeometry,
33272         ExtrudeBufferGeometry: ExtrudeBufferGeometry,
33273         IcosahedronGeometry: IcosahedronGeometry,
33274         IcosahedronBufferGeometry: IcosahedronBufferGeometry,
33275         LatheGeometry: LatheGeometry,
33276         LatheBufferGeometry: LatheBufferGeometry,
33277         OctahedronGeometry: OctahedronGeometry,
33278         OctahedronBufferGeometry: OctahedronBufferGeometry,
33279         ParametricGeometry: ParametricGeometry,
33280         ParametricBufferGeometry: ParametricBufferGeometry,
33281         PlaneGeometry: PlaneGeometry,
33282         PlaneBufferGeometry: PlaneBufferGeometry,
33283         PolyhedronGeometry: PolyhedronGeometry,
33284         PolyhedronBufferGeometry: PolyhedronBufferGeometry,
33285         RingGeometry: RingGeometry,
33286         RingBufferGeometry: RingBufferGeometry,
33287         ShapeGeometry: ShapeGeometry,
33288         ShapeBufferGeometry: ShapeBufferGeometry,
33289         SphereGeometry: SphereGeometry,
33290         SphereBufferGeometry: SphereBufferGeometry,
33291         TetrahedronGeometry: TetrahedronGeometry,
33292         TetrahedronBufferGeometry: TetrahedronBufferGeometry,
33293         TextGeometry: TextGeometry,
33294         TextBufferGeometry: TextBufferGeometry,
33295         TorusGeometry: TorusGeometry,
33296         TorusBufferGeometry: TorusBufferGeometry,
33297         TorusKnotGeometry: TorusKnotGeometry,
33298         TorusKnotBufferGeometry: TorusKnotBufferGeometry,
33299         TubeGeometry: TubeGeometry,
33300         TubeBufferGeometry: TubeBufferGeometry,
33301         WireframeGeometry: WireframeGeometry
33302 });
33303
33304 /**
33305  * parameters = {
33306  *  color: <THREE.Color>
33307  * }
33308  */
33309
33310 function ShadowMaterial( parameters ) {
33311
33312         Material.call( this );
33313
33314         this.type = 'ShadowMaterial';
33315
33316         this.color = new Color( 0x000000 );
33317         this.transparent = true;
33318
33319         this.setValues( parameters );
33320
33321 }
33322
33323 ShadowMaterial.prototype = Object.create( Material.prototype );
33324 ShadowMaterial.prototype.constructor = ShadowMaterial;
33325
33326 ShadowMaterial.prototype.isShadowMaterial = true;
33327
33328 ShadowMaterial.prototype.copy = function ( source ) {
33329
33330         Material.prototype.copy.call( this, source );
33331
33332         this.color.copy( source.color );
33333
33334         return this;
33335
33336 };
33337
33338 function RawShaderMaterial( parameters ) {
33339
33340         ShaderMaterial.call( this, parameters );
33341
33342         this.type = 'RawShaderMaterial';
33343
33344 }
33345
33346 RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
33347 RawShaderMaterial.prototype.constructor = RawShaderMaterial;
33348
33349 RawShaderMaterial.prototype.isRawShaderMaterial = true;
33350
33351 /**
33352  * parameters = {
33353  *  color: <hex>,
33354  *  roughness: <float>,
33355  *  metalness: <float>,
33356  *  opacity: <float>,
33357  *
33358  *  map: new THREE.Texture( <Image> ),
33359  *
33360  *  lightMap: new THREE.Texture( <Image> ),
33361  *  lightMapIntensity: <float>
33362  *
33363  *  aoMap: new THREE.Texture( <Image> ),
33364  *  aoMapIntensity: <float>
33365  *
33366  *  emissive: <hex>,
33367  *  emissiveIntensity: <float>
33368  *  emissiveMap: new THREE.Texture( <Image> ),
33369  *
33370  *  bumpMap: new THREE.Texture( <Image> ),
33371  *  bumpScale: <float>,
33372  *
33373  *  normalMap: new THREE.Texture( <Image> ),
33374  *  normalMapType: THREE.TangentSpaceNormalMap,
33375  *  normalScale: <Vector2>,
33376  *
33377  *  displacementMap: new THREE.Texture( <Image> ),
33378  *  displacementScale: <float>,
33379  *  displacementBias: <float>,
33380  *
33381  *  roughnessMap: new THREE.Texture( <Image> ),
33382  *
33383  *  metalnessMap: new THREE.Texture( <Image> ),
33384  *
33385  *  alphaMap: new THREE.Texture( <Image> ),
33386  *
33387  *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
33388  *  envMapIntensity: <float>
33389  *
33390  *  refractionRatio: <float>,
33391  *
33392  *  wireframe: <boolean>,
33393  *  wireframeLinewidth: <float>,
33394  *
33395  *  skinning: <bool>,
33396  *  morphTargets: <bool>,
33397  *  morphNormals: <bool>
33398  * }
33399  */
33400
33401 function MeshStandardMaterial( parameters ) {
33402
33403         Material.call( this );
33404
33405         this.defines = { 'STANDARD': '' };
33406
33407         this.type = 'MeshStandardMaterial';
33408
33409         this.color = new Color( 0xffffff ); // diffuse
33410         this.roughness = 1.0;
33411         this.metalness = 0.0;
33412
33413         this.map = null;
33414
33415         this.lightMap = null;
33416         this.lightMapIntensity = 1.0;
33417
33418         this.aoMap = null;
33419         this.aoMapIntensity = 1.0;
33420
33421         this.emissive = new Color( 0x000000 );
33422         this.emissiveIntensity = 1.0;
33423         this.emissiveMap = null;
33424
33425         this.bumpMap = null;
33426         this.bumpScale = 1;
33427
33428         this.normalMap = null;
33429         this.normalMapType = TangentSpaceNormalMap;
33430         this.normalScale = new Vector2( 1, 1 );
33431
33432         this.displacementMap = null;
33433         this.displacementScale = 1;
33434         this.displacementBias = 0;
33435
33436         this.roughnessMap = null;
33437
33438         this.metalnessMap = null;
33439
33440         this.alphaMap = null;
33441
33442         this.envMap = null;
33443         this.envMapIntensity = 1.0;
33444
33445         this.refractionRatio = 0.98;
33446
33447         this.wireframe = false;
33448         this.wireframeLinewidth = 1;
33449         this.wireframeLinecap = 'round';
33450         this.wireframeLinejoin = 'round';
33451
33452         this.skinning = false;
33453         this.morphTargets = false;
33454         this.morphNormals = false;
33455
33456         this.vertexTangents = false;
33457
33458         this.setValues( parameters );
33459
33460 }
33461
33462 MeshStandardMaterial.prototype = Object.create( Material.prototype );
33463 MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
33464
33465 MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
33466
33467 MeshStandardMaterial.prototype.copy = function ( source ) {
33468
33469         Material.prototype.copy.call( this, source );
33470
33471         this.defines = { 'STANDARD': '' };
33472
33473         this.color.copy( source.color );
33474         this.roughness = source.roughness;
33475         this.metalness = source.metalness;
33476
33477         this.map = source.map;
33478
33479         this.lightMap = source.lightMap;
33480         this.lightMapIntensity = source.lightMapIntensity;
33481
33482         this.aoMap = source.aoMap;
33483         this.aoMapIntensity = source.aoMapIntensity;
33484
33485         this.emissive.copy( source.emissive );
33486         this.emissiveMap = source.emissiveMap;
33487         this.emissiveIntensity = source.emissiveIntensity;
33488
33489         this.bumpMap = source.bumpMap;
33490         this.bumpScale = source.bumpScale;
33491
33492         this.normalMap = source.normalMap;
33493         this.normalMapType = source.normalMapType;
33494         this.normalScale.copy( source.normalScale );
33495
33496         this.displacementMap = source.displacementMap;
33497         this.displacementScale = source.displacementScale;
33498         this.displacementBias = source.displacementBias;
33499
33500         this.roughnessMap = source.roughnessMap;
33501
33502         this.metalnessMap = source.metalnessMap;
33503
33504         this.alphaMap = source.alphaMap;
33505
33506         this.envMap = source.envMap;
33507         this.envMapIntensity = source.envMapIntensity;
33508
33509         this.refractionRatio = source.refractionRatio;
33510
33511         this.wireframe = source.wireframe;
33512         this.wireframeLinewidth = source.wireframeLinewidth;
33513         this.wireframeLinecap = source.wireframeLinecap;
33514         this.wireframeLinejoin = source.wireframeLinejoin;
33515
33516         this.skinning = source.skinning;
33517         this.morphTargets = source.morphTargets;
33518         this.morphNormals = source.morphNormals;
33519
33520         this.vertexTangents = source.vertexTangents;
33521
33522         return this;
33523
33524 };
33525
33526 /**
33527  * parameters = {
33528  *  clearcoat: <float>,
33529  *  clearcoatMap: new THREE.Texture( <Image> ),
33530  *  clearcoatRoughness: <float>,
33531  *  clearcoatRoughnessMap: new THREE.Texture( <Image> ),
33532  *  clearcoatNormalScale: <Vector2>,
33533  *  clearcoatNormalMap: new THREE.Texture( <Image> ),
33534  *
33535  *  reflectivity: <float>,
33536  *  ior: <float>,
33537  *
33538  *  sheen: <Color>,
33539  *
33540  *  transmission: <float>,
33541  *  transmissionMap: new THREE.Texture( <Image> )
33542  * }
33543  */
33544
33545 function MeshPhysicalMaterial( parameters ) {
33546
33547         MeshStandardMaterial.call( this );
33548
33549         this.defines = {
33550
33551                 'STANDARD': '',
33552                 'PHYSICAL': ''
33553
33554         };
33555
33556         this.type = 'MeshPhysicalMaterial';
33557
33558         this.clearcoat = 0.0;
33559         this.clearcoatMap = null;
33560         this.clearcoatRoughness = 0.0;
33561         this.clearcoatRoughnessMap = null;
33562         this.clearcoatNormalScale = new Vector2( 1, 1 );
33563         this.clearcoatNormalMap = null;
33564
33565         this.reflectivity = 0.5; // maps to F0 = 0.04
33566
33567         Object.defineProperty( this, 'ior', {
33568                 get: function () {
33569
33570                         return ( 1 + 0.4 * this.reflectivity ) / ( 1 - 0.4 * this.reflectivity );
33571
33572                 },
33573                 set: function ( ior ) {
33574
33575                         this.reflectivity = MathUtils.clamp( 2.5 * ( ior - 1 ) / ( ior + 1 ), 0, 1 );
33576
33577                 }
33578         } );
33579
33580         this.sheen = null; // null will disable sheen bsdf
33581
33582         this.transmission = 0.0;
33583         this.transmissionMap = null;
33584
33585         this.setValues( parameters );
33586
33587 }
33588
33589 MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
33590 MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
33591
33592 MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
33593
33594 MeshPhysicalMaterial.prototype.copy = function ( source ) {
33595
33596         MeshStandardMaterial.prototype.copy.call( this, source );
33597
33598         this.defines = {
33599
33600                 'STANDARD': '',
33601                 'PHYSICAL': ''
33602
33603         };
33604
33605         this.clearcoat = source.clearcoat;
33606         this.clearcoatMap = source.clearcoatMap;
33607         this.clearcoatRoughness = source.clearcoatRoughness;
33608         this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
33609         this.clearcoatNormalMap = source.clearcoatNormalMap;
33610         this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
33611
33612         this.reflectivity = source.reflectivity;
33613
33614         if ( source.sheen ) {
33615
33616                 this.sheen = ( this.sheen || new Color() ).copy( source.sheen );
33617
33618         } else {
33619
33620                 this.sheen = null;
33621
33622         }
33623
33624         this.transmission = source.transmission;
33625         this.transmissionMap = source.transmissionMap;
33626
33627         return this;
33628
33629 };
33630
33631 /**
33632  * parameters = {
33633  *  color: <hex>,
33634  *  specular: <hex>,
33635  *  shininess: <float>,
33636  *  opacity: <float>,
33637  *
33638  *  map: new THREE.Texture( <Image> ),
33639  *
33640  *  lightMap: new THREE.Texture( <Image> ),
33641  *  lightMapIntensity: <float>
33642  *
33643  *  aoMap: new THREE.Texture( <Image> ),
33644  *  aoMapIntensity: <float>
33645  *
33646  *  emissive: <hex>,
33647  *  emissiveIntensity: <float>
33648  *  emissiveMap: new THREE.Texture( <Image> ),
33649  *
33650  *  bumpMap: new THREE.Texture( <Image> ),
33651  *  bumpScale: <float>,
33652  *
33653  *  normalMap: new THREE.Texture( <Image> ),
33654  *  normalMapType: THREE.TangentSpaceNormalMap,
33655  *  normalScale: <Vector2>,
33656  *
33657  *  displacementMap: new THREE.Texture( <Image> ),
33658  *  displacementScale: <float>,
33659  *  displacementBias: <float>,
33660  *
33661  *  specularMap: new THREE.Texture( <Image> ),
33662  *
33663  *  alphaMap: new THREE.Texture( <Image> ),
33664  *
33665  *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
33666  *  combine: THREE.MultiplyOperation,
33667  *  reflectivity: <float>,
33668  *  refractionRatio: <float>,
33669  *
33670  *  wireframe: <boolean>,
33671  *  wireframeLinewidth: <float>,
33672  *
33673  *  skinning: <bool>,
33674  *  morphTargets: <bool>,
33675  *  morphNormals: <bool>
33676  * }
33677  */
33678
33679 function MeshPhongMaterial( parameters ) {
33680
33681         Material.call( this );
33682
33683         this.type = 'MeshPhongMaterial';
33684
33685         this.color = new Color( 0xffffff ); // diffuse
33686         this.specular = new Color( 0x111111 );
33687         this.shininess = 30;
33688
33689         this.map = null;
33690
33691         this.lightMap = null;
33692         this.lightMapIntensity = 1.0;
33693
33694         this.aoMap = null;
33695         this.aoMapIntensity = 1.0;
33696
33697         this.emissive = new Color( 0x000000 );
33698         this.emissiveIntensity = 1.0;
33699         this.emissiveMap = null;
33700
33701         this.bumpMap = null;
33702         this.bumpScale = 1;
33703
33704         this.normalMap = null;
33705         this.normalMapType = TangentSpaceNormalMap;
33706         this.normalScale = new Vector2( 1, 1 );
33707
33708         this.displacementMap = null;
33709         this.displacementScale = 1;
33710         this.displacementBias = 0;
33711
33712         this.specularMap = null;
33713
33714         this.alphaMap = null;
33715
33716         this.envMap = null;
33717         this.combine = MultiplyOperation;
33718         this.reflectivity = 1;
33719         this.refractionRatio = 0.98;
33720
33721         this.wireframe = false;
33722         this.wireframeLinewidth = 1;
33723         this.wireframeLinecap = 'round';
33724         this.wireframeLinejoin = 'round';
33725
33726         this.skinning = false;
33727         this.morphTargets = false;
33728         this.morphNormals = false;
33729
33730         this.setValues( parameters );
33731
33732 }
33733
33734 MeshPhongMaterial.prototype = Object.create( Material.prototype );
33735 MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
33736
33737 MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
33738
33739 MeshPhongMaterial.prototype.copy = function ( source ) {
33740
33741         Material.prototype.copy.call( this, source );
33742
33743         this.color.copy( source.color );
33744         this.specular.copy( source.specular );
33745         this.shininess = source.shininess;
33746
33747         this.map = source.map;
33748
33749         this.lightMap = source.lightMap;
33750         this.lightMapIntensity = source.lightMapIntensity;
33751
33752         this.aoMap = source.aoMap;
33753         this.aoMapIntensity = source.aoMapIntensity;
33754
33755         this.emissive.copy( source.emissive );
33756         this.emissiveMap = source.emissiveMap;
33757         this.emissiveIntensity = source.emissiveIntensity;
33758
33759         this.bumpMap = source.bumpMap;
33760         this.bumpScale = source.bumpScale;
33761
33762         this.normalMap = source.normalMap;
33763         this.normalMapType = source.normalMapType;
33764         this.normalScale.copy( source.normalScale );
33765
33766         this.displacementMap = source.displacementMap;
33767         this.displacementScale = source.displacementScale;
33768         this.displacementBias = source.displacementBias;
33769
33770         this.specularMap = source.specularMap;
33771
33772         this.alphaMap = source.alphaMap;
33773
33774         this.envMap = source.envMap;
33775         this.combine = source.combine;
33776         this.reflectivity = source.reflectivity;
33777         this.refractionRatio = source.refractionRatio;
33778
33779         this.wireframe = source.wireframe;
33780         this.wireframeLinewidth = source.wireframeLinewidth;
33781         this.wireframeLinecap = source.wireframeLinecap;
33782         this.wireframeLinejoin = source.wireframeLinejoin;
33783
33784         this.skinning = source.skinning;
33785         this.morphTargets = source.morphTargets;
33786         this.morphNormals = source.morphNormals;
33787
33788         return this;
33789
33790 };
33791
33792 /**
33793  * parameters = {
33794  *  color: <hex>,
33795  *
33796  *  map: new THREE.Texture( <Image> ),
33797  *  gradientMap: new THREE.Texture( <Image> ),
33798  *
33799  *  lightMap: new THREE.Texture( <Image> ),
33800  *  lightMapIntensity: <float>
33801  *
33802  *  aoMap: new THREE.Texture( <Image> ),
33803  *  aoMapIntensity: <float>
33804  *
33805  *  emissive: <hex>,
33806  *  emissiveIntensity: <float>
33807  *  emissiveMap: new THREE.Texture( <Image> ),
33808  *
33809  *  bumpMap: new THREE.Texture( <Image> ),
33810  *  bumpScale: <float>,
33811  *
33812  *  normalMap: new THREE.Texture( <Image> ),
33813  *  normalMapType: THREE.TangentSpaceNormalMap,
33814  *  normalScale: <Vector2>,
33815  *
33816  *  displacementMap: new THREE.Texture( <Image> ),
33817  *  displacementScale: <float>,
33818  *  displacementBias: <float>,
33819  *
33820  *  alphaMap: new THREE.Texture( <Image> ),
33821  *
33822  *  wireframe: <boolean>,
33823  *  wireframeLinewidth: <float>,
33824  *
33825  *  skinning: <bool>,
33826  *  morphTargets: <bool>,
33827  *  morphNormals: <bool>
33828  * }
33829  */
33830
33831 function MeshToonMaterial( parameters ) {
33832
33833         Material.call( this );
33834
33835         this.defines = { 'TOON': '' };
33836
33837         this.type = 'MeshToonMaterial';
33838
33839         this.color = new Color( 0xffffff );
33840
33841         this.map = null;
33842         this.gradientMap = null;
33843
33844         this.lightMap = null;
33845         this.lightMapIntensity = 1.0;
33846
33847         this.aoMap = null;
33848         this.aoMapIntensity = 1.0;
33849
33850         this.emissive = new Color( 0x000000 );
33851         this.emissiveIntensity = 1.0;
33852         this.emissiveMap = null;
33853
33854         this.bumpMap = null;
33855         this.bumpScale = 1;
33856
33857         this.normalMap = null;
33858         this.normalMapType = TangentSpaceNormalMap;
33859         this.normalScale = new Vector2( 1, 1 );
33860
33861         this.displacementMap = null;
33862         this.displacementScale = 1;
33863         this.displacementBias = 0;
33864
33865         this.alphaMap = null;
33866
33867         this.wireframe = false;
33868         this.wireframeLinewidth = 1;
33869         this.wireframeLinecap = 'round';
33870         this.wireframeLinejoin = 'round';
33871
33872         this.skinning = false;
33873         this.morphTargets = false;
33874         this.morphNormals = false;
33875
33876         this.setValues( parameters );
33877
33878 }
33879
33880 MeshToonMaterial.prototype = Object.create( Material.prototype );
33881 MeshToonMaterial.prototype.constructor = MeshToonMaterial;
33882
33883 MeshToonMaterial.prototype.isMeshToonMaterial = true;
33884
33885 MeshToonMaterial.prototype.copy = function ( source ) {
33886
33887         Material.prototype.copy.call( this, source );
33888
33889         this.color.copy( source.color );
33890
33891         this.map = source.map;
33892         this.gradientMap = source.gradientMap;
33893
33894         this.lightMap = source.lightMap;
33895         this.lightMapIntensity = source.lightMapIntensity;
33896
33897         this.aoMap = source.aoMap;
33898         this.aoMapIntensity = source.aoMapIntensity;
33899
33900         this.emissive.copy( source.emissive );
33901         this.emissiveMap = source.emissiveMap;
33902         this.emissiveIntensity = source.emissiveIntensity;
33903
33904         this.bumpMap = source.bumpMap;
33905         this.bumpScale = source.bumpScale;
33906
33907         this.normalMap = source.normalMap;
33908         this.normalMapType = source.normalMapType;
33909         this.normalScale.copy( source.normalScale );
33910
33911         this.displacementMap = source.displacementMap;
33912         this.displacementScale = source.displacementScale;
33913         this.displacementBias = source.displacementBias;
33914
33915         this.alphaMap = source.alphaMap;
33916
33917         this.wireframe = source.wireframe;
33918         this.wireframeLinewidth = source.wireframeLinewidth;
33919         this.wireframeLinecap = source.wireframeLinecap;
33920         this.wireframeLinejoin = source.wireframeLinejoin;
33921
33922         this.skinning = source.skinning;
33923         this.morphTargets = source.morphTargets;
33924         this.morphNormals = source.morphNormals;
33925
33926         return this;
33927
33928 };
33929
33930 /**
33931  * parameters = {
33932  *  opacity: <float>,
33933  *
33934  *  bumpMap: new THREE.Texture( <Image> ),
33935  *  bumpScale: <float>,
33936  *
33937  *  normalMap: new THREE.Texture( <Image> ),
33938  *  normalMapType: THREE.TangentSpaceNormalMap,
33939  *  normalScale: <Vector2>,
33940  *
33941  *  displacementMap: new THREE.Texture( <Image> ),
33942  *  displacementScale: <float>,
33943  *  displacementBias: <float>,
33944  *
33945  *  wireframe: <boolean>,
33946  *  wireframeLinewidth: <float>
33947  *
33948  *  skinning: <bool>,
33949  *  morphTargets: <bool>,
33950  *  morphNormals: <bool>
33951  * }
33952  */
33953
33954 function MeshNormalMaterial( parameters ) {
33955
33956         Material.call( this );
33957
33958         this.type = 'MeshNormalMaterial';
33959
33960         this.bumpMap = null;
33961         this.bumpScale = 1;
33962
33963         this.normalMap = null;
33964         this.normalMapType = TangentSpaceNormalMap;
33965         this.normalScale = new Vector2( 1, 1 );
33966
33967         this.displacementMap = null;
33968         this.displacementScale = 1;
33969         this.displacementBias = 0;
33970
33971         this.wireframe = false;
33972         this.wireframeLinewidth = 1;
33973
33974         this.fog = false;
33975
33976         this.skinning = false;
33977         this.morphTargets = false;
33978         this.morphNormals = false;
33979
33980         this.setValues( parameters );
33981
33982 }
33983
33984 MeshNormalMaterial.prototype = Object.create( Material.prototype );
33985 MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
33986
33987 MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
33988
33989 MeshNormalMaterial.prototype.copy = function ( source ) {
33990
33991         Material.prototype.copy.call( this, source );
33992
33993         this.bumpMap = source.bumpMap;
33994         this.bumpScale = source.bumpScale;
33995
33996         this.normalMap = source.normalMap;
33997         this.normalMapType = source.normalMapType;
33998         this.normalScale.copy( source.normalScale );
33999
34000         this.displacementMap = source.displacementMap;
34001         this.displacementScale = source.displacementScale;
34002         this.displacementBias = source.displacementBias;
34003
34004         this.wireframe = source.wireframe;
34005         this.wireframeLinewidth = source.wireframeLinewidth;
34006
34007         this.skinning = source.skinning;
34008         this.morphTargets = source.morphTargets;
34009         this.morphNormals = source.morphNormals;
34010
34011         return this;
34012
34013 };
34014
34015 /**
34016  * parameters = {
34017  *  color: <hex>,
34018  *  opacity: <float>,
34019  *
34020  *  map: new THREE.Texture( <Image> ),
34021  *
34022  *  lightMap: new THREE.Texture( <Image> ),
34023  *  lightMapIntensity: <float>
34024  *
34025  *  aoMap: new THREE.Texture( <Image> ),
34026  *  aoMapIntensity: <float>
34027  *
34028  *  emissive: <hex>,
34029  *  emissiveIntensity: <float>
34030  *  emissiveMap: new THREE.Texture( <Image> ),
34031  *
34032  *  specularMap: new THREE.Texture( <Image> ),
34033  *
34034  *  alphaMap: new THREE.Texture( <Image> ),
34035  *
34036  *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
34037  *  combine: THREE.Multiply,
34038  *  reflectivity: <float>,
34039  *  refractionRatio: <float>,
34040  *
34041  *  wireframe: <boolean>,
34042  *  wireframeLinewidth: <float>,
34043  *
34044  *  skinning: <bool>,
34045  *  morphTargets: <bool>,
34046  *  morphNormals: <bool>
34047  * }
34048  */
34049
34050 function MeshLambertMaterial( parameters ) {
34051
34052         Material.call( this );
34053
34054         this.type = 'MeshLambertMaterial';
34055
34056         this.color = new Color( 0xffffff ); // diffuse
34057
34058         this.map = null;
34059
34060         this.lightMap = null;
34061         this.lightMapIntensity = 1.0;
34062
34063         this.aoMap = null;
34064         this.aoMapIntensity = 1.0;
34065
34066         this.emissive = new Color( 0x000000 );
34067         this.emissiveIntensity = 1.0;
34068         this.emissiveMap = null;
34069
34070         this.specularMap = null;
34071
34072         this.alphaMap = null;
34073
34074         this.envMap = null;
34075         this.combine = MultiplyOperation;
34076         this.reflectivity = 1;
34077         this.refractionRatio = 0.98;
34078
34079         this.wireframe = false;
34080         this.wireframeLinewidth = 1;
34081         this.wireframeLinecap = 'round';
34082         this.wireframeLinejoin = 'round';
34083
34084         this.skinning = false;
34085         this.morphTargets = false;
34086         this.morphNormals = false;
34087
34088         this.setValues( parameters );
34089
34090 }
34091
34092 MeshLambertMaterial.prototype = Object.create( Material.prototype );
34093 MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
34094
34095 MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
34096
34097 MeshLambertMaterial.prototype.copy = function ( source ) {
34098
34099         Material.prototype.copy.call( this, source );
34100
34101         this.color.copy( source.color );
34102
34103         this.map = source.map;
34104
34105         this.lightMap = source.lightMap;
34106         this.lightMapIntensity = source.lightMapIntensity;
34107
34108         this.aoMap = source.aoMap;
34109         this.aoMapIntensity = source.aoMapIntensity;
34110
34111         this.emissive.copy( source.emissive );
34112         this.emissiveMap = source.emissiveMap;
34113         this.emissiveIntensity = source.emissiveIntensity;
34114
34115         this.specularMap = source.specularMap;
34116
34117         this.alphaMap = source.alphaMap;
34118
34119         this.envMap = source.envMap;
34120         this.combine = source.combine;
34121         this.reflectivity = source.reflectivity;
34122         this.refractionRatio = source.refractionRatio;
34123
34124         this.wireframe = source.wireframe;
34125         this.wireframeLinewidth = source.wireframeLinewidth;
34126         this.wireframeLinecap = source.wireframeLinecap;
34127         this.wireframeLinejoin = source.wireframeLinejoin;
34128
34129         this.skinning = source.skinning;
34130         this.morphTargets = source.morphTargets;
34131         this.morphNormals = source.morphNormals;
34132
34133         return this;
34134
34135 };
34136
34137 /**
34138  * parameters = {
34139  *  color: <hex>,
34140  *  opacity: <float>,
34141  *
34142  *  matcap: new THREE.Texture( <Image> ),
34143  *
34144  *  map: new THREE.Texture( <Image> ),
34145  *
34146  *  bumpMap: new THREE.Texture( <Image> ),
34147  *  bumpScale: <float>,
34148  *
34149  *  normalMap: new THREE.Texture( <Image> ),
34150  *  normalMapType: THREE.TangentSpaceNormalMap,
34151  *  normalScale: <Vector2>,
34152  *
34153  *  displacementMap: new THREE.Texture( <Image> ),
34154  *  displacementScale: <float>,
34155  *  displacementBias: <float>,
34156  *
34157  *  alphaMap: new THREE.Texture( <Image> ),
34158  *
34159  *  skinning: <bool>,
34160  *  morphTargets: <bool>,
34161  *  morphNormals: <bool>
34162  * }
34163  */
34164
34165 function MeshMatcapMaterial( parameters ) {
34166
34167         Material.call( this );
34168
34169         this.defines = { 'MATCAP': '' };
34170
34171         this.type = 'MeshMatcapMaterial';
34172
34173         this.color = new Color( 0xffffff ); // diffuse
34174
34175         this.matcap = null;
34176
34177         this.map = null;
34178
34179         this.bumpMap = null;
34180         this.bumpScale = 1;
34181
34182         this.normalMap = null;
34183         this.normalMapType = TangentSpaceNormalMap;
34184         this.normalScale = new Vector2( 1, 1 );
34185
34186         this.displacementMap = null;
34187         this.displacementScale = 1;
34188         this.displacementBias = 0;
34189
34190         this.alphaMap = null;
34191
34192         this.skinning = false;
34193         this.morphTargets = false;
34194         this.morphNormals = false;
34195
34196         this.setValues( parameters );
34197
34198 }
34199
34200 MeshMatcapMaterial.prototype = Object.create( Material.prototype );
34201 MeshMatcapMaterial.prototype.constructor = MeshMatcapMaterial;
34202
34203 MeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;
34204
34205 MeshMatcapMaterial.prototype.copy = function ( source ) {
34206
34207         Material.prototype.copy.call( this, source );
34208
34209         this.defines = { 'MATCAP': '' };
34210
34211         this.color.copy( source.color );
34212
34213         this.matcap = source.matcap;
34214
34215         this.map = source.map;
34216
34217         this.bumpMap = source.bumpMap;
34218         this.bumpScale = source.bumpScale;
34219
34220         this.normalMap = source.normalMap;
34221         this.normalMapType = source.normalMapType;
34222         this.normalScale.copy( source.normalScale );
34223
34224         this.displacementMap = source.displacementMap;
34225         this.displacementScale = source.displacementScale;
34226         this.displacementBias = source.displacementBias;
34227
34228         this.alphaMap = source.alphaMap;
34229
34230         this.skinning = source.skinning;
34231         this.morphTargets = source.morphTargets;
34232         this.morphNormals = source.morphNormals;
34233
34234         return this;
34235
34236 };
34237
34238 /**
34239  * parameters = {
34240  *  color: <hex>,
34241  *  opacity: <float>,
34242  *
34243  *  linewidth: <float>,
34244  *
34245  *  scale: <float>,
34246  *  dashSize: <float>,
34247  *  gapSize: <float>
34248  * }
34249  */
34250
34251 function LineDashedMaterial( parameters ) {
34252
34253         LineBasicMaterial.call( this );
34254
34255         this.type = 'LineDashedMaterial';
34256
34257         this.scale = 1;
34258         this.dashSize = 3;
34259         this.gapSize = 1;
34260
34261         this.setValues( parameters );
34262
34263 }
34264
34265 LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
34266 LineDashedMaterial.prototype.constructor = LineDashedMaterial;
34267
34268 LineDashedMaterial.prototype.isLineDashedMaterial = true;
34269
34270 LineDashedMaterial.prototype.copy = function ( source ) {
34271
34272         LineBasicMaterial.prototype.copy.call( this, source );
34273
34274         this.scale = source.scale;
34275         this.dashSize = source.dashSize;
34276         this.gapSize = source.gapSize;
34277
34278         return this;
34279
34280 };
34281
34282 var Materials = /*#__PURE__*/Object.freeze({
34283         __proto__: null,
34284         ShadowMaterial: ShadowMaterial,
34285         SpriteMaterial: SpriteMaterial,
34286         RawShaderMaterial: RawShaderMaterial,
34287         ShaderMaterial: ShaderMaterial,
34288         PointsMaterial: PointsMaterial,
34289         MeshPhysicalMaterial: MeshPhysicalMaterial,
34290         MeshStandardMaterial: MeshStandardMaterial,
34291         MeshPhongMaterial: MeshPhongMaterial,
34292         MeshToonMaterial: MeshToonMaterial,
34293         MeshNormalMaterial: MeshNormalMaterial,
34294         MeshLambertMaterial: MeshLambertMaterial,
34295         MeshDepthMaterial: MeshDepthMaterial,
34296         MeshDistanceMaterial: MeshDistanceMaterial,
34297         MeshBasicMaterial: MeshBasicMaterial,
34298         MeshMatcapMaterial: MeshMatcapMaterial,
34299         LineDashedMaterial: LineDashedMaterial,
34300         LineBasicMaterial: LineBasicMaterial,
34301         Material: Material
34302 });
34303
34304 const AnimationUtils = {
34305
34306         // same as Array.prototype.slice, but also works on typed arrays
34307         arraySlice: function ( array, from, to ) {
34308
34309                 if ( AnimationUtils.isTypedArray( array ) ) {
34310
34311                         // in ios9 array.subarray(from, undefined) will return empty array
34312                         // but array.subarray(from) or array.subarray(from, len) is correct
34313                         return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
34314
34315                 }
34316
34317                 return array.slice( from, to );
34318
34319         },
34320
34321         // converts an array to a specific type
34322         convertArray: function ( array, type, forceClone ) {
34323
34324                 if ( ! array || // let 'undefined' and 'null' pass
34325                         ! forceClone && array.constructor === type ) return array;
34326
34327                 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
34328
34329                         return new type( array ); // create typed array
34330
34331                 }
34332
34333                 return Array.prototype.slice.call( array ); // create Array
34334
34335         },
34336
34337         isTypedArray: function ( object ) {
34338
34339                 return ArrayBuffer.isView( object ) &&
34340                         ! ( object instanceof DataView );
34341
34342         },
34343
34344         // returns an array by which times and values can be sorted
34345         getKeyframeOrder: function ( times ) {
34346
34347                 function compareTime( i, j ) {
34348
34349                         return times[ i ] - times[ j ];
34350
34351                 }
34352
34353                 const n = times.length;
34354                 const result = new Array( n );
34355                 for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
34356
34357                 result.sort( compareTime );
34358
34359                 return result;
34360
34361         },
34362
34363         // uses the array previously returned by 'getKeyframeOrder' to sort data
34364         sortedArray: function ( values, stride, order ) {
34365
34366                 const nValues = values.length;
34367                 const result = new values.constructor( nValues );
34368
34369                 for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
34370
34371                         const srcOffset = order[ i ] * stride;
34372
34373                         for ( let j = 0; j !== stride; ++ j ) {
34374
34375                                 result[ dstOffset ++ ] = values[ srcOffset + j ];
34376
34377                         }
34378
34379                 }
34380
34381                 return result;
34382
34383         },
34384
34385         // function for parsing AOS keyframe formats
34386         flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
34387
34388                 let i = 1, key = jsonKeys[ 0 ];
34389
34390                 while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
34391
34392                         key = jsonKeys[ i ++ ];
34393
34394                 }
34395
34396                 if ( key === undefined ) return; // no data
34397
34398                 let value = key[ valuePropertyName ];
34399                 if ( value === undefined ) return; // no data
34400
34401                 if ( Array.isArray( value ) ) {
34402
34403                         do {
34404
34405                                 value = key[ valuePropertyName ];
34406
34407                                 if ( value !== undefined ) {
34408
34409                                         times.push( key.time );
34410                                         values.push.apply( values, value ); // push all elements
34411
34412                                 }
34413
34414                                 key = jsonKeys[ i ++ ];
34415
34416                         } while ( key !== undefined );
34417
34418                 } else if ( value.toArray !== undefined ) {
34419
34420                         // ...assume THREE.Math-ish
34421
34422                         do {
34423
34424                                 value = key[ valuePropertyName ];
34425
34426                                 if ( value !== undefined ) {
34427
34428                                         times.push( key.time );
34429                                         value.toArray( values, values.length );
34430
34431                                 }
34432
34433                                 key = jsonKeys[ i ++ ];
34434
34435                         } while ( key !== undefined );
34436
34437                 } else {
34438
34439                         // otherwise push as-is
34440
34441                         do {
34442
34443                                 value = key[ valuePropertyName ];
34444
34445                                 if ( value !== undefined ) {
34446
34447                                         times.push( key.time );
34448                                         values.push( value );
34449
34450                                 }
34451
34452                                 key = jsonKeys[ i ++ ];
34453
34454                         } while ( key !== undefined );
34455
34456                 }
34457
34458         },
34459
34460         subclip: function ( sourceClip, name, startFrame, endFrame, fps = 30 ) {
34461
34462                 const clip = sourceClip.clone();
34463
34464                 clip.name = name;
34465
34466                 const tracks = [];
34467
34468                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
34469
34470                         const track = clip.tracks[ i ];
34471                         const valueSize = track.getValueSize();
34472
34473                         const times = [];
34474                         const values = [];
34475
34476                         for ( let j = 0; j < track.times.length; ++ j ) {
34477
34478                                 const frame = track.times[ j ] * fps;
34479
34480                                 if ( frame < startFrame || frame >= endFrame ) continue;
34481
34482                                 times.push( track.times[ j ] );
34483
34484                                 for ( let k = 0; k < valueSize; ++ k ) {
34485
34486                                         values.push( track.values[ j * valueSize + k ] );
34487
34488                                 }
34489
34490                         }
34491
34492                         if ( times.length === 0 ) continue;
34493
34494                         track.times = AnimationUtils.convertArray( times, track.times.constructor );
34495                         track.values = AnimationUtils.convertArray( values, track.values.constructor );
34496
34497                         tracks.push( track );
34498
34499                 }
34500
34501                 clip.tracks = tracks;
34502
34503                 // find minimum .times value across all tracks in the trimmed clip
34504
34505                 let minStartTime = Infinity;
34506
34507                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
34508
34509                         if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
34510
34511                                 minStartTime = clip.tracks[ i ].times[ 0 ];
34512
34513                         }
34514
34515                 }
34516
34517                 // shift all tracks such that clip begins at t=0
34518
34519                 for ( let i = 0; i < clip.tracks.length; ++ i ) {
34520
34521                         clip.tracks[ i ].shift( - 1 * minStartTime );
34522
34523                 }
34524
34525                 clip.resetDuration();
34526
34527                 return clip;
34528
34529         },
34530
34531         makeClipAdditive: function ( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
34532
34533                 if ( fps <= 0 ) fps = 30;
34534
34535                 const numTracks = referenceClip.tracks.length;
34536                 const referenceTime = referenceFrame / fps;
34537
34538                 // Make each track's values relative to the values at the reference frame
34539                 for ( let i = 0; i < numTracks; ++ i ) {
34540
34541                         const referenceTrack = referenceClip.tracks[ i ];
34542                         const referenceTrackType = referenceTrack.ValueTypeName;
34543
34544                         // Skip this track if it's non-numeric
34545                         if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
34546
34547                         // Find the track in the target clip whose name and type matches the reference track
34548                         const targetTrack = targetClip.tracks.find( function ( track ) {
34549
34550                                 return track.name === referenceTrack.name
34551                                         && track.ValueTypeName === referenceTrackType;
34552
34553                         } );
34554
34555                         if ( targetTrack === undefined ) continue;
34556
34557                         let referenceOffset = 0;
34558                         const referenceValueSize = referenceTrack.getValueSize();
34559
34560                         if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
34561
34562                                 referenceOffset = referenceValueSize / 3;
34563
34564                         }
34565
34566                         let targetOffset = 0;
34567                         const targetValueSize = targetTrack.getValueSize();
34568
34569                         if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
34570
34571                                 targetOffset = targetValueSize / 3;
34572
34573                         }
34574
34575                         const lastIndex = referenceTrack.times.length - 1;
34576                         let referenceValue;
34577
34578                         // Find the value to subtract out of the track
34579                         if ( referenceTime <= referenceTrack.times[ 0 ] ) {
34580
34581                                 // Reference frame is earlier than the first keyframe, so just use the first keyframe
34582                                 const startIndex = referenceOffset;
34583                                 const endIndex = referenceValueSize - referenceOffset;
34584                                 referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
34585
34586                         } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
34587
34588                                 // Reference frame is after the last keyframe, so just use the last keyframe
34589                                 const startIndex = lastIndex * referenceValueSize + referenceOffset;
34590                                 const endIndex = startIndex + referenceValueSize - referenceOffset;
34591                                 referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex, endIndex );
34592
34593                         } else {
34594
34595                                 // Interpolate to the reference value
34596                                 const interpolant = referenceTrack.createInterpolant();
34597                                 const startIndex = referenceOffset;
34598                                 const endIndex = referenceValueSize - referenceOffset;
34599                                 interpolant.evaluate( referenceTime );
34600                                 referenceValue = AnimationUtils.arraySlice( interpolant.resultBuffer, startIndex, endIndex );
34601
34602                         }
34603
34604                         // Conjugate the quaternion
34605                         if ( referenceTrackType === 'quaternion' ) {
34606
34607                                 const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
34608                                 referenceQuat.toArray( referenceValue );
34609
34610                         }
34611
34612                         // Subtract the reference value from all of the track values
34613
34614                         const numTimes = targetTrack.times.length;
34615                         for ( let j = 0; j < numTimes; ++ j ) {
34616
34617                                 const valueStart = j * targetValueSize + targetOffset;
34618
34619                                 if ( referenceTrackType === 'quaternion' ) {
34620
34621                                         // Multiply the conjugate for quaternion track types
34622                                         Quaternion.multiplyQuaternionsFlat(
34623                                                 targetTrack.values,
34624                                                 valueStart,
34625                                                 referenceValue,
34626                                                 0,
34627                                                 targetTrack.values,
34628                                                 valueStart
34629                                         );
34630
34631                                 } else {
34632
34633                                         const valueEnd = targetValueSize - targetOffset * 2;
34634
34635                                         // Subtract each value for all other numeric track types
34636                                         for ( let k = 0; k < valueEnd; ++ k ) {
34637
34638                                                 targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
34639
34640                                         }
34641
34642                                 }
34643
34644                         }
34645
34646                 }
34647
34648                 targetClip.blendMode = AdditiveAnimationBlendMode;
34649
34650                 return targetClip;
34651
34652         }
34653
34654 };
34655
34656 /**
34657  * Abstract base class of interpolants over parametric samples.
34658  *
34659  * The parameter domain is one dimensional, typically the time or a path
34660  * along a curve defined by the data.
34661  *
34662  * The sample values can have any dimensionality and derived classes may
34663  * apply special interpretations to the data.
34664  *
34665  * This class provides the interval seek in a Template Method, deferring
34666  * the actual interpolation to derived classes.
34667  *
34668  * Time complexity is O(1) for linear access crossing at most two points
34669  * and O(log N) for random access, where N is the number of positions.
34670  *
34671  * References:
34672  *
34673  *              http://www.oodesign.com/template-method-pattern.html
34674  *
34675  */
34676
34677 function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34678
34679         this.parameterPositions = parameterPositions;
34680         this._cachedIndex = 0;
34681
34682         this.resultBuffer = resultBuffer !== undefined ?
34683                 resultBuffer : new sampleValues.constructor( sampleSize );
34684         this.sampleValues = sampleValues;
34685         this.valueSize = sampleSize;
34686
34687 }
34688
34689 Object.assign( Interpolant.prototype, {
34690
34691         evaluate: function ( t ) {
34692
34693                 const pp = this.parameterPositions;
34694                 let i1 = this._cachedIndex,
34695                         t1 = pp[ i1 ],
34696                         t0 = pp[ i1 - 1 ];
34697
34698                 validate_interval: {
34699
34700                         seek: {
34701
34702                                 let right;
34703
34704                                 linear_scan: {
34705
34706                                         //- See http://jsperf.com/comparison-to-undefined/3
34707                                         //- slower code:
34708                                         //-
34709                                         //-                             if ( t >= t1 || t1 === undefined ) {
34710                                         forward_scan: if ( ! ( t < t1 ) ) {
34711
34712                                                 for ( let giveUpAt = i1 + 2; ; ) {
34713
34714                                                         if ( t1 === undefined ) {
34715
34716                                                                 if ( t < t0 ) break forward_scan;
34717
34718                                                                 // after end
34719
34720                                                                 i1 = pp.length;
34721                                                                 this._cachedIndex = i1;
34722                                                                 return this.afterEnd_( i1 - 1, t, t0 );
34723
34724                                                         }
34725
34726                                                         if ( i1 === giveUpAt ) break; // this loop
34727
34728                                                         t0 = t1;
34729                                                         t1 = pp[ ++ i1 ];
34730
34731                                                         if ( t < t1 ) {
34732
34733                                                                 // we have arrived at the sought interval
34734                                                                 break seek;
34735
34736                                                         }
34737
34738                                                 }
34739
34740                                                 // prepare binary search on the right side of the index
34741                                                 right = pp.length;
34742                                                 break linear_scan;
34743
34744                                         }
34745
34746                                         //- slower code:
34747                                         //-                                     if ( t < t0 || t0 === undefined ) {
34748                                         if ( ! ( t >= t0 ) ) {
34749
34750                                                 // looping?
34751
34752                                                 const t1global = pp[ 1 ];
34753
34754                                                 if ( t < t1global ) {
34755
34756                                                         i1 = 2; // + 1, using the scan for the details
34757                                                         t0 = t1global;
34758
34759                                                 }
34760
34761                                                 // linear reverse scan
34762
34763                                                 for ( let giveUpAt = i1 - 2; ; ) {
34764
34765                                                         if ( t0 === undefined ) {
34766
34767                                                                 // before start
34768
34769                                                                 this._cachedIndex = 0;
34770                                                                 return this.beforeStart_( 0, t, t1 );
34771
34772                                                         }
34773
34774                                                         if ( i1 === giveUpAt ) break; // this loop
34775
34776                                                         t1 = t0;
34777                                                         t0 = pp[ -- i1 - 1 ];
34778
34779                                                         if ( t >= t0 ) {
34780
34781                                                                 // we have arrived at the sought interval
34782                                                                 break seek;
34783
34784                                                         }
34785
34786                                                 }
34787
34788                                                 // prepare binary search on the left side of the index
34789                                                 right = i1;
34790                                                 i1 = 0;
34791                                                 break linear_scan;
34792
34793                                         }
34794
34795                                         // the interval is valid
34796
34797                                         break validate_interval;
34798
34799                                 } // linear scan
34800
34801                                 // binary search
34802
34803                                 while ( i1 < right ) {
34804
34805                                         const mid = ( i1 + right ) >>> 1;
34806
34807                                         if ( t < pp[ mid ] ) {
34808
34809                                                 right = mid;
34810
34811                                         } else {
34812
34813                                                 i1 = mid + 1;
34814
34815                                         }
34816
34817                                 }
34818
34819                                 t1 = pp[ i1 ];
34820                                 t0 = pp[ i1 - 1 ];
34821
34822                                 // check boundary cases, again
34823
34824                                 if ( t0 === undefined ) {
34825
34826                                         this._cachedIndex = 0;
34827                                         return this.beforeStart_( 0, t, t1 );
34828
34829                                 }
34830
34831                                 if ( t1 === undefined ) {
34832
34833                                         i1 = pp.length;
34834                                         this._cachedIndex = i1;
34835                                         return this.afterEnd_( i1 - 1, t0, t );
34836
34837                                 }
34838
34839                         } // seek
34840
34841                         this._cachedIndex = i1;
34842
34843                         this.intervalChanged_( i1, t0, t1 );
34844
34845                 } // validate_interval
34846
34847                 return this.interpolate_( i1, t0, t, t1 );
34848
34849         },
34850
34851         settings: null, // optional, subclass-specific settings structure
34852         // Note: The indirection allows central control of many interpolants.
34853
34854         // --- Protected interface
34855
34856         DefaultSettings_: {},
34857
34858         getSettings_: function () {
34859
34860                 return this.settings || this.DefaultSettings_;
34861
34862         },
34863
34864         copySampleValue_: function ( index ) {
34865
34866                 // copies a sample value to the result buffer
34867
34868                 const result = this.resultBuffer,
34869                         values = this.sampleValues,
34870                         stride = this.valueSize,
34871                         offset = index * stride;
34872
34873                 for ( let i = 0; i !== stride; ++ i ) {
34874
34875                         result[ i ] = values[ offset + i ];
34876
34877                 }
34878
34879                 return result;
34880
34881         },
34882
34883         // Template methods for derived classes:
34884
34885         interpolate_: function ( /* i1, t0, t, t1 */ ) {
34886
34887                 throw new Error( 'call to abstract method' );
34888                 // implementations shall return this.resultBuffer
34889
34890         },
34891
34892         intervalChanged_: function ( /* i1, t0, t1 */ ) {
34893
34894                 // empty
34895
34896         }
34897
34898 } );
34899
34900 // DECLARE ALIAS AFTER assign prototype
34901 Object.assign( Interpolant.prototype, {
34902
34903         //( 0, t, t0 ), returns this.resultBuffer
34904         beforeStart_: Interpolant.prototype.copySampleValue_,
34905
34906         //( N-1, tN-1, t ), returns this.resultBuffer
34907         afterEnd_: Interpolant.prototype.copySampleValue_,
34908
34909 } );
34910
34911 /**
34912  * Fast and simple cubic spline interpolant.
34913  *
34914  * It was derived from a Hermitian construction setting the first derivative
34915  * at each sample position to the linear slope between neighboring positions
34916  * over their parameter interval.
34917  */
34918
34919 function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34920
34921         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34922
34923         this._weightPrev = - 0;
34924         this._offsetPrev = - 0;
34925         this._weightNext = - 0;
34926         this._offsetNext = - 0;
34927
34928 }
34929
34930 CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34931
34932         constructor: CubicInterpolant,
34933
34934         DefaultSettings_: {
34935
34936                 endingStart: ZeroCurvatureEnding,
34937                 endingEnd: ZeroCurvatureEnding
34938
34939         },
34940
34941         intervalChanged_: function ( i1, t0, t1 ) {
34942
34943                 const pp = this.parameterPositions;
34944                 let iPrev = i1 - 2,
34945                         iNext = i1 + 1,
34946
34947                         tPrev = pp[ iPrev ],
34948                         tNext = pp[ iNext ];
34949
34950                 if ( tPrev === undefined ) {
34951
34952                         switch ( this.getSettings_().endingStart ) {
34953
34954                                 case ZeroSlopeEnding:
34955
34956                                         // f'(t0) = 0
34957                                         iPrev = i1;
34958                                         tPrev = 2 * t0 - t1;
34959
34960                                         break;
34961
34962                                 case WrapAroundEnding:
34963
34964                                         // use the other end of the curve
34965                                         iPrev = pp.length - 2;
34966                                         tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
34967
34968                                         break;
34969
34970                                 default: // ZeroCurvatureEnding
34971
34972                                         // f''(t0) = 0 a.k.a. Natural Spline
34973                                         iPrev = i1;
34974                                         tPrev = t1;
34975
34976                         }
34977
34978                 }
34979
34980                 if ( tNext === undefined ) {
34981
34982                         switch ( this.getSettings_().endingEnd ) {
34983
34984                                 case ZeroSlopeEnding:
34985
34986                                         // f'(tN) = 0
34987                                         iNext = i1;
34988                                         tNext = 2 * t1 - t0;
34989
34990                                         break;
34991
34992                                 case WrapAroundEnding:
34993
34994                                         // use the other end of the curve
34995                                         iNext = 1;
34996                                         tNext = t1 + pp[ 1 ] - pp[ 0 ];
34997
34998                                         break;
34999
35000                                 default: // ZeroCurvatureEnding
35001
35002                                         // f''(tN) = 0, a.k.a. Natural Spline
35003                                         iNext = i1 - 1;
35004                                         tNext = t0;
35005
35006                         }
35007
35008                 }
35009
35010                 const halfDt = ( t1 - t0 ) * 0.5,
35011                         stride = this.valueSize;
35012
35013                 this._weightPrev = halfDt / ( t0 - tPrev );
35014                 this._weightNext = halfDt / ( tNext - t1 );
35015                 this._offsetPrev = iPrev * stride;
35016                 this._offsetNext = iNext * stride;
35017
35018         },
35019
35020         interpolate_: function ( i1, t0, t, t1 ) {
35021
35022                 const result = this.resultBuffer,
35023                         values = this.sampleValues,
35024                         stride = this.valueSize,
35025
35026                         o1 = i1 * stride,               o0 = o1 - stride,
35027                         oP = this._offsetPrev,  oN = this._offsetNext,
35028                         wP = this._weightPrev,  wN = this._weightNext,
35029
35030                         p = ( t - t0 ) / ( t1 - t0 ),
35031                         pp = p * p,
35032                         ppp = pp * p;
35033
35034                 // evaluate polynomials
35035
35036                 const sP = - wP * ppp + 2 * wP * pp - wP * p;
35037                 const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
35038                 const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
35039                 const sN = wN * ppp - wN * pp;
35040
35041                 // combine data linearly
35042
35043                 for ( let i = 0; i !== stride; ++ i ) {
35044
35045                         result[ i ] =
35046                                         sP * values[ oP + i ] +
35047                                         s0 * values[ o0 + i ] +
35048                                         s1 * values[ o1 + i ] +
35049                                         sN * values[ oN + i ];
35050
35051                 }
35052
35053                 return result;
35054
35055         }
35056
35057 } );
35058
35059 function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
35060
35061         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
35062
35063 }
35064
35065 LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
35066
35067         constructor: LinearInterpolant,
35068
35069         interpolate_: function ( i1, t0, t, t1 ) {
35070
35071                 const result = this.resultBuffer,
35072                         values = this.sampleValues,
35073                         stride = this.valueSize,
35074
35075                         offset1 = i1 * stride,
35076                         offset0 = offset1 - stride,
35077
35078                         weight1 = ( t - t0 ) / ( t1 - t0 ),
35079                         weight0 = 1 - weight1;
35080
35081                 for ( let i = 0; i !== stride; ++ i ) {
35082
35083                         result[ i ] =
35084                                         values[ offset0 + i ] * weight0 +
35085                                         values[ offset1 + i ] * weight1;
35086
35087                 }
35088
35089                 return result;
35090
35091         }
35092
35093 } );
35094
35095 /**
35096  *
35097  * Interpolant that evaluates to the sample value at the position preceeding
35098  * the parameter.
35099  */
35100
35101 function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
35102
35103         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
35104
35105 }
35106
35107 DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
35108
35109         constructor: DiscreteInterpolant,
35110
35111         interpolate_: function ( i1 /*, t0, t, t1 */ ) {
35112
35113                 return this.copySampleValue_( i1 - 1 );
35114
35115         }
35116
35117 } );
35118
35119 function KeyframeTrack( name, times, values, interpolation ) {
35120
35121         if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
35122         if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
35123
35124         this.name = name;
35125
35126         this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
35127         this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
35128
35129         this.setInterpolation( interpolation || this.DefaultInterpolation );
35130
35131 }
35132
35133 // Static methods
35134
35135 Object.assign( KeyframeTrack, {
35136
35137         // Serialization (in static context, because of constructor invocation
35138         // and automatic invocation of .toJSON):
35139
35140         toJSON: function ( track ) {
35141
35142                 const trackType = track.constructor;
35143
35144                 let json;
35145
35146                 // derived classes can define a static toJSON method
35147                 if ( trackType.toJSON !== undefined ) {
35148
35149                         json = trackType.toJSON( track );
35150
35151                 } else {
35152
35153                         // by default, we assume the data can be serialized as-is
35154                         json = {
35155
35156                                 'name': track.name,
35157                                 'times': AnimationUtils.convertArray( track.times, Array ),
35158                                 'values': AnimationUtils.convertArray( track.values, Array )
35159
35160                         };
35161
35162                         const interpolation = track.getInterpolation();
35163
35164                         if ( interpolation !== track.DefaultInterpolation ) {
35165
35166                                 json.interpolation = interpolation;
35167
35168                         }
35169
35170                 }
35171
35172                 json.type = track.ValueTypeName; // mandatory
35173
35174                 return json;
35175
35176         }
35177
35178 } );
35179
35180 Object.assign( KeyframeTrack.prototype, {
35181
35182         constructor: KeyframeTrack,
35183
35184         TimeBufferType: Float32Array,
35185
35186         ValueBufferType: Float32Array,
35187
35188         DefaultInterpolation: InterpolateLinear,
35189
35190         InterpolantFactoryMethodDiscrete: function ( result ) {
35191
35192                 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
35193
35194         },
35195
35196         InterpolantFactoryMethodLinear: function ( result ) {
35197
35198                 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
35199
35200         },
35201
35202         InterpolantFactoryMethodSmooth: function ( result ) {
35203
35204                 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
35205
35206         },
35207
35208         setInterpolation: function ( interpolation ) {
35209
35210                 let factoryMethod;
35211
35212                 switch ( interpolation ) {
35213
35214                         case InterpolateDiscrete:
35215
35216                                 factoryMethod = this.InterpolantFactoryMethodDiscrete;
35217
35218                                 break;
35219
35220                         case InterpolateLinear:
35221
35222                                 factoryMethod = this.InterpolantFactoryMethodLinear;
35223
35224                                 break;
35225
35226                         case InterpolateSmooth:
35227
35228                                 factoryMethod = this.InterpolantFactoryMethodSmooth;
35229
35230                                 break;
35231
35232                 }
35233
35234                 if ( factoryMethod === undefined ) {
35235
35236                         const message = "unsupported interpolation for " +
35237                                 this.ValueTypeName + " keyframe track named " + this.name;
35238
35239                         if ( this.createInterpolant === undefined ) {
35240
35241                                 // fall back to default, unless the default itself is messed up
35242                                 if ( interpolation !== this.DefaultInterpolation ) {
35243
35244                                         this.setInterpolation( this.DefaultInterpolation );
35245
35246                                 } else {
35247
35248                                         throw new Error( message ); // fatal, in this case
35249
35250                                 }
35251
35252                         }
35253
35254                         console.warn( 'THREE.KeyframeTrack:', message );
35255                         return this;
35256
35257                 }
35258
35259                 this.createInterpolant = factoryMethod;
35260
35261                 return this;
35262
35263         },
35264
35265         getInterpolation: function () {
35266
35267                 switch ( this.createInterpolant ) {
35268
35269                         case this.InterpolantFactoryMethodDiscrete:
35270
35271                                 return InterpolateDiscrete;
35272
35273                         case this.InterpolantFactoryMethodLinear:
35274
35275                                 return InterpolateLinear;
35276
35277                         case this.InterpolantFactoryMethodSmooth:
35278
35279                                 return InterpolateSmooth;
35280
35281                 }
35282
35283         },
35284
35285         getValueSize: function () {
35286
35287                 return this.values.length / this.times.length;
35288
35289         },
35290
35291         // move all keyframes either forwards or backwards in time
35292         shift: function ( timeOffset ) {
35293
35294                 if ( timeOffset !== 0.0 ) {
35295
35296                         const times = this.times;
35297
35298                         for ( let i = 0, n = times.length; i !== n; ++ i ) {
35299
35300                                 times[ i ] += timeOffset;
35301
35302                         }
35303
35304                 }
35305
35306                 return this;
35307
35308         },
35309
35310         // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
35311         scale: function ( timeScale ) {
35312
35313                 if ( timeScale !== 1.0 ) {
35314
35315                         const times = this.times;
35316
35317                         for ( let i = 0, n = times.length; i !== n; ++ i ) {
35318
35319                                 times[ i ] *= timeScale;
35320
35321                         }
35322
35323                 }
35324
35325                 return this;
35326
35327         },
35328
35329         // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
35330         // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
35331         trim: function ( startTime, endTime ) {
35332
35333                 const times = this.times,
35334                         nKeys = times.length;
35335
35336                 let from = 0,
35337                         to = nKeys - 1;
35338
35339                 while ( from !== nKeys && times[ from ] < startTime ) {
35340
35341                         ++ from;
35342
35343                 }
35344
35345                 while ( to !== - 1 && times[ to ] > endTime ) {
35346
35347                         -- to;
35348
35349                 }
35350
35351                 ++ to; // inclusive -> exclusive bound
35352
35353                 if ( from !== 0 || to !== nKeys ) {
35354
35355                         // empty tracks are forbidden, so keep at least one keyframe
35356                         if ( from >= to ) {
35357
35358                                 to = Math.max( to, 1 );
35359                                 from = to - 1;
35360
35361                         }
35362
35363                         const stride = this.getValueSize();
35364                         this.times = AnimationUtils.arraySlice( times, from, to );
35365                         this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
35366
35367                 }
35368
35369                 return this;
35370
35371         },
35372
35373         // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
35374         validate: function () {
35375
35376                 let valid = true;
35377
35378                 const valueSize = this.getValueSize();
35379                 if ( valueSize - Math.floor( valueSize ) !== 0 ) {
35380
35381                         console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
35382                         valid = false;
35383
35384                 }
35385
35386                 const times = this.times,
35387                         values = this.values,
35388
35389                         nKeys = times.length;
35390
35391                 if ( nKeys === 0 ) {
35392
35393                         console.error( 'THREE.KeyframeTrack: Track is empty.', this );
35394                         valid = false;
35395
35396                 }
35397
35398                 let prevTime = null;
35399
35400                 for ( let i = 0; i !== nKeys; i ++ ) {
35401
35402                         const currTime = times[ i ];
35403
35404                         if ( typeof currTime === 'number' && isNaN( currTime ) ) {
35405
35406                                 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
35407                                 valid = false;
35408                                 break;
35409
35410                         }
35411
35412                         if ( prevTime !== null && prevTime > currTime ) {
35413
35414                                 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
35415                                 valid = false;
35416                                 break;
35417
35418                         }
35419
35420                         prevTime = currTime;
35421
35422                 }
35423
35424                 if ( values !== undefined ) {
35425
35426                         if ( AnimationUtils.isTypedArray( values ) ) {
35427
35428                                 for ( let i = 0, n = values.length; i !== n; ++ i ) {
35429
35430                                         const value = values[ i ];
35431
35432                                         if ( isNaN( value ) ) {
35433
35434                                                 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
35435                                                 valid = false;
35436                                                 break;
35437
35438                                         }
35439
35440                                 }
35441
35442                         }
35443
35444                 }
35445
35446                 return valid;
35447
35448         },
35449
35450         // removes equivalent sequential keys as common in morph target sequences
35451         // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
35452         optimize: function () {
35453
35454                 // times or values may be shared with other tracks, so overwriting is unsafe
35455                 const times = AnimationUtils.arraySlice( this.times ),
35456                         values = AnimationUtils.arraySlice( this.values ),
35457                         stride = this.getValueSize(),
35458
35459                         smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
35460
35461                         lastIndex = times.length - 1;
35462
35463                 let writeIndex = 1;
35464
35465                 for ( let i = 1; i < lastIndex; ++ i ) {
35466
35467                         let keep = false;
35468
35469                         const time = times[ i ];
35470                         const timeNext = times[ i + 1 ];
35471
35472                         // remove adjacent keyframes scheduled at the same time
35473
35474                         if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
35475
35476                                 if ( ! smoothInterpolation ) {
35477
35478                                         // remove unnecessary keyframes same as their neighbors
35479
35480                                         const offset = i * stride,
35481                                                 offsetP = offset - stride,
35482                                                 offsetN = offset + stride;
35483
35484                                         for ( let j = 0; j !== stride; ++ j ) {
35485
35486                                                 const value = values[ offset + j ];
35487
35488                                                 if ( value !== values[ offsetP + j ] ||
35489                                                         value !== values[ offsetN + j ] ) {
35490
35491                                                         keep = true;
35492                                                         break;
35493
35494                                                 }
35495
35496                                         }
35497
35498                                 } else {
35499
35500                                         keep = true;
35501
35502                                 }
35503
35504                         }
35505
35506                         // in-place compaction
35507
35508                         if ( keep ) {
35509
35510                                 if ( i !== writeIndex ) {
35511
35512                                         times[ writeIndex ] = times[ i ];
35513
35514                                         const readOffset = i * stride,
35515                                                 writeOffset = writeIndex * stride;
35516
35517                                         for ( let j = 0; j !== stride; ++ j ) {
35518
35519                                                 values[ writeOffset + j ] = values[ readOffset + j ];
35520
35521                                         }
35522
35523                                 }
35524
35525                                 ++ writeIndex;
35526
35527                         }
35528
35529                 }
35530
35531                 // flush last keyframe (compaction looks ahead)
35532
35533                 if ( lastIndex > 0 ) {
35534
35535                         times[ writeIndex ] = times[ lastIndex ];
35536
35537                         for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
35538
35539                                 values[ writeOffset + j ] = values[ readOffset + j ];
35540
35541                         }
35542
35543                         ++ writeIndex;
35544
35545                 }
35546
35547                 if ( writeIndex !== times.length ) {
35548
35549                         this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
35550                         this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
35551
35552                 } else {
35553
35554                         this.times = times;
35555                         this.values = values;
35556
35557                 }
35558
35559                 return this;
35560
35561         },
35562
35563         clone: function () {
35564
35565                 const times = AnimationUtils.arraySlice( this.times, 0 );
35566                 const values = AnimationUtils.arraySlice( this.values, 0 );
35567
35568                 const TypedKeyframeTrack = this.constructor;
35569                 const track = new TypedKeyframeTrack( this.name, times, values );
35570
35571                 // Interpolant argument to constructor is not saved, so copy the factory method directly.
35572                 track.createInterpolant = this.createInterpolant;
35573
35574                 return track;
35575
35576         }
35577
35578 } );
35579
35580 /**
35581  * A Track of Boolean keyframe values.
35582  */
35583
35584 function BooleanKeyframeTrack( name, times, values ) {
35585
35586         KeyframeTrack.call( this, name, times, values );
35587
35588 }
35589
35590 BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35591
35592         constructor: BooleanKeyframeTrack,
35593
35594         ValueTypeName: 'bool',
35595         ValueBufferType: Array,
35596
35597         DefaultInterpolation: InterpolateDiscrete,
35598
35599         InterpolantFactoryMethodLinear: undefined,
35600         InterpolantFactoryMethodSmooth: undefined
35601
35602         // Note: Actually this track could have a optimized / compressed
35603         // representation of a single value and a custom interpolant that
35604         // computes "firstValue ^ isOdd( index )".
35605
35606 } );
35607
35608 /**
35609  * A Track of keyframe values that represent color.
35610  */
35611
35612 function ColorKeyframeTrack( name, times, values, interpolation ) {
35613
35614         KeyframeTrack.call( this, name, times, values, interpolation );
35615
35616 }
35617
35618 ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35619
35620         constructor: ColorKeyframeTrack,
35621
35622         ValueTypeName: 'color'
35623
35624         // ValueBufferType is inherited
35625
35626         // DefaultInterpolation is inherited
35627
35628         // Note: Very basic implementation and nothing special yet.
35629         // However, this is the place for color space parameterization.
35630
35631 } );
35632
35633 /**
35634  * A Track of numeric keyframe values.
35635  */
35636
35637 function NumberKeyframeTrack( name, times, values, interpolation ) {
35638
35639         KeyframeTrack.call( this, name, times, values, interpolation );
35640
35641 }
35642
35643 NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35644
35645         constructor: NumberKeyframeTrack,
35646
35647         ValueTypeName: 'number'
35648
35649         // ValueBufferType is inherited
35650
35651         // DefaultInterpolation is inherited
35652
35653 } );
35654
35655 /**
35656  * Spherical linear unit quaternion interpolant.
35657  */
35658
35659 function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
35660
35661         Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
35662
35663 }
35664
35665 QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
35666
35667         constructor: QuaternionLinearInterpolant,
35668
35669         interpolate_: function ( i1, t0, t, t1 ) {
35670
35671                 const result = this.resultBuffer,
35672                         values = this.sampleValues,
35673                         stride = this.valueSize,
35674
35675                         alpha = ( t - t0 ) / ( t1 - t0 );
35676
35677                 let offset = i1 * stride;
35678
35679                 for ( let end = offset + stride; offset !== end; offset += 4 ) {
35680
35681                         Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
35682
35683                 }
35684
35685                 return result;
35686
35687         }
35688
35689 } );
35690
35691 /**
35692  * A Track of quaternion keyframe values.
35693  */
35694
35695 function QuaternionKeyframeTrack( name, times, values, interpolation ) {
35696
35697         KeyframeTrack.call( this, name, times, values, interpolation );
35698
35699 }
35700
35701 QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35702
35703         constructor: QuaternionKeyframeTrack,
35704
35705         ValueTypeName: 'quaternion',
35706
35707         // ValueBufferType is inherited
35708
35709         DefaultInterpolation: InterpolateLinear,
35710
35711         InterpolantFactoryMethodLinear: function ( result ) {
35712
35713                 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
35714
35715         },
35716
35717         InterpolantFactoryMethodSmooth: undefined // not yet implemented
35718
35719 } );
35720
35721 /**
35722  * A Track that interpolates Strings
35723  */
35724
35725 function StringKeyframeTrack( name, times, values, interpolation ) {
35726
35727         KeyframeTrack.call( this, name, times, values, interpolation );
35728
35729 }
35730
35731 StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35732
35733         constructor: StringKeyframeTrack,
35734
35735         ValueTypeName: 'string',
35736         ValueBufferType: Array,
35737
35738         DefaultInterpolation: InterpolateDiscrete,
35739
35740         InterpolantFactoryMethodLinear: undefined,
35741
35742         InterpolantFactoryMethodSmooth: undefined
35743
35744 } );
35745
35746 /**
35747  * A Track of vectored keyframe values.
35748  */
35749
35750 function VectorKeyframeTrack( name, times, values, interpolation ) {
35751
35752         KeyframeTrack.call( this, name, times, values, interpolation );
35753
35754 }
35755
35756 VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35757
35758         constructor: VectorKeyframeTrack,
35759
35760         ValueTypeName: 'vector'
35761
35762         // ValueBufferType is inherited
35763
35764         // DefaultInterpolation is inherited
35765
35766 } );
35767
35768 function AnimationClip( name, duration, tracks, blendMode ) {
35769
35770         this.name = name;
35771         this.tracks = tracks;
35772         this.duration = ( duration !== undefined ) ? duration : - 1;
35773         this.blendMode = ( blendMode !== undefined ) ? blendMode : NormalAnimationBlendMode;
35774
35775         this.uuid = MathUtils.generateUUID();
35776
35777         // this means it should figure out its duration by scanning the tracks
35778         if ( this.duration < 0 ) {
35779
35780                 this.resetDuration();
35781
35782         }
35783
35784 }
35785
35786 function getTrackTypeForValueTypeName( typeName ) {
35787
35788         switch ( typeName.toLowerCase() ) {
35789
35790                 case 'scalar':
35791                 case 'double':
35792                 case 'float':
35793                 case 'number':
35794                 case 'integer':
35795
35796                         return NumberKeyframeTrack;
35797
35798                 case 'vector':
35799                 case 'vector2':
35800                 case 'vector3':
35801                 case 'vector4':
35802
35803                         return VectorKeyframeTrack;
35804
35805                 case 'color':
35806
35807                         return ColorKeyframeTrack;
35808
35809                 case 'quaternion':
35810
35811                         return QuaternionKeyframeTrack;
35812
35813                 case 'bool':
35814                 case 'boolean':
35815
35816                         return BooleanKeyframeTrack;
35817
35818                 case 'string':
35819
35820                         return StringKeyframeTrack;
35821
35822         }
35823
35824         throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
35825
35826 }
35827
35828 function parseKeyframeTrack( json ) {
35829
35830         if ( json.type === undefined ) {
35831
35832                 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
35833
35834         }
35835
35836         const trackType = getTrackTypeForValueTypeName( json.type );
35837
35838         if ( json.times === undefined ) {
35839
35840                 const times = [], values = [];
35841
35842                 AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
35843
35844                 json.times = times;
35845                 json.values = values;
35846
35847         }
35848
35849         // derived classes can define a static parse method
35850         if ( trackType.parse !== undefined ) {
35851
35852                 return trackType.parse( json );
35853
35854         } else {
35855
35856                 // by default, we assume a constructor compatible with the base
35857                 return new trackType( json.name, json.times, json.values, json.interpolation );
35858
35859         }
35860
35861 }
35862
35863 Object.assign( AnimationClip, {
35864
35865         parse: function ( json ) {
35866
35867                 const tracks = [],
35868                         jsonTracks = json.tracks,
35869                         frameTime = 1.0 / ( json.fps || 1.0 );
35870
35871                 for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
35872
35873                         tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
35874
35875                 }
35876
35877                 const clip = new AnimationClip( json.name, json.duration, tracks, json.blendMode );
35878                 clip.uuid = json.uuid;
35879
35880                 return clip;
35881
35882         },
35883
35884         toJSON: function ( clip ) {
35885
35886                 const tracks = [],
35887                         clipTracks = clip.tracks;
35888
35889                 const json = {
35890
35891                         'name': clip.name,
35892                         'duration': clip.duration,
35893                         'tracks': tracks,
35894                         'uuid': clip.uuid,
35895                         'blendMode': clip.blendMode
35896
35897                 };
35898
35899                 for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
35900
35901                         tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
35902
35903                 }
35904
35905                 return json;
35906
35907         },
35908
35909         CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
35910
35911                 const numMorphTargets = morphTargetSequence.length;
35912                 const tracks = [];
35913
35914                 for ( let i = 0; i < numMorphTargets; i ++ ) {
35915
35916                         let times = [];
35917                         let values = [];
35918
35919                         times.push(
35920                                 ( i + numMorphTargets - 1 ) % numMorphTargets,
35921                                 i,
35922                                 ( i + 1 ) % numMorphTargets );
35923
35924                         values.push( 0, 1, 0 );
35925
35926                         const order = AnimationUtils.getKeyframeOrder( times );
35927                         times = AnimationUtils.sortedArray( times, 1, order );
35928                         values = AnimationUtils.sortedArray( values, 1, order );
35929
35930                         // if there is a key at the first frame, duplicate it as the
35931                         // last frame as well for perfect loop.
35932                         if ( ! noLoop && times[ 0 ] === 0 ) {
35933
35934                                 times.push( numMorphTargets );
35935                                 values.push( values[ 0 ] );
35936
35937                         }
35938
35939                         tracks.push(
35940                                 new NumberKeyframeTrack(
35941                                         '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
35942                                         times, values
35943                                 ).scale( 1.0 / fps ) );
35944
35945                 }
35946
35947                 return new AnimationClip( name, - 1, tracks );
35948
35949         },
35950
35951         findByName: function ( objectOrClipArray, name ) {
35952
35953                 let clipArray = objectOrClipArray;
35954
35955                 if ( ! Array.isArray( objectOrClipArray ) ) {
35956
35957                         const o = objectOrClipArray;
35958                         clipArray = o.geometry && o.geometry.animations || o.animations;
35959
35960                 }
35961
35962                 for ( let i = 0; i < clipArray.length; i ++ ) {
35963
35964                         if ( clipArray[ i ].name === name ) {
35965
35966                                 return clipArray[ i ];
35967
35968                         }
35969
35970                 }
35971
35972                 return null;
35973
35974         },
35975
35976         CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
35977
35978                 const animationToMorphTargets = {};
35979
35980                 // tested with https://regex101.com/ on trick sequences
35981                 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
35982                 const pattern = /^([\w-]*?)([\d]+)$/;
35983
35984                 // sort morph target names into animation groups based
35985                 // patterns like Walk_001, Walk_002, Run_001, Run_002
35986                 for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
35987
35988                         const morphTarget = morphTargets[ i ];
35989                         const parts = morphTarget.name.match( pattern );
35990
35991                         if ( parts && parts.length > 1 ) {
35992
35993                                 const name = parts[ 1 ];
35994
35995                                 let animationMorphTargets = animationToMorphTargets[ name ];
35996
35997                                 if ( ! animationMorphTargets ) {
35998
35999                                         animationToMorphTargets[ name ] = animationMorphTargets = [];
36000
36001                                 }
36002
36003                                 animationMorphTargets.push( morphTarget );
36004
36005                         }
36006
36007                 }
36008
36009                 const clips = [];
36010
36011                 for ( const name in animationToMorphTargets ) {
36012
36013                         clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
36014
36015                 }
36016
36017                 return clips;
36018
36019         },
36020
36021         // parse the animation.hierarchy format
36022         parseAnimation: function ( animation, bones ) {
36023
36024                 if ( ! animation ) {
36025
36026                         console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
36027                         return null;
36028
36029                 }
36030
36031                 const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
36032
36033                         // only return track if there are actually keys.
36034                         if ( animationKeys.length !== 0 ) {
36035
36036                                 const times = [];
36037                                 const values = [];
36038
36039                                 AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
36040
36041                                 // empty keys are filtered out, so check again
36042                                 if ( times.length !== 0 ) {
36043
36044                                         destTracks.push( new trackType( trackName, times, values ) );
36045
36046                                 }
36047
36048                         }
36049
36050                 };
36051
36052                 const tracks = [];
36053
36054                 const clipName = animation.name || 'default';
36055                 const fps = animation.fps || 30;
36056                 const blendMode = animation.blendMode;
36057
36058                 // automatic length determination in AnimationClip.
36059                 let duration = animation.length || - 1;
36060
36061                 const hierarchyTracks = animation.hierarchy || [];
36062
36063                 for ( let h = 0; h < hierarchyTracks.length; h ++ ) {
36064
36065                         const animationKeys = hierarchyTracks[ h ].keys;
36066
36067                         // skip empty tracks
36068                         if ( ! animationKeys || animationKeys.length === 0 ) continue;
36069
36070                         // process morph targets
36071                         if ( animationKeys[ 0 ].morphTargets ) {
36072
36073                                 // figure out all morph targets used in this track
36074                                 const morphTargetNames = {};
36075
36076                                 let k;
36077
36078                                 for ( k = 0; k < animationKeys.length; k ++ ) {
36079
36080                                         if ( animationKeys[ k ].morphTargets ) {
36081
36082                                                 for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
36083
36084                                                         morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
36085
36086                                                 }
36087
36088                                         }
36089
36090                                 }
36091
36092                                 // create a track for each morph target with all zero
36093                                 // morphTargetInfluences except for the keys in which
36094                                 // the morphTarget is named.
36095                                 for ( const morphTargetName in morphTargetNames ) {
36096
36097                                         const times = [];
36098                                         const values = [];
36099
36100                                         for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
36101
36102                                                 const animationKey = animationKeys[ k ];
36103
36104                                                 times.push( animationKey.time );
36105                                                 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
36106
36107                                         }
36108
36109                                         tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
36110
36111                                 }
36112
36113                                 duration = morphTargetNames.length * ( fps || 1.0 );
36114
36115                         } else {
36116
36117                                 // ...assume skeletal animation
36118
36119                                 const boneName = '.bones[' + bones[ h ].name + ']';
36120
36121                                 addNonemptyTrack(
36122                                         VectorKeyframeTrack, boneName + '.position',
36123                                         animationKeys, 'pos', tracks );
36124
36125                                 addNonemptyTrack(
36126                                         QuaternionKeyframeTrack, boneName + '.quaternion',
36127                                         animationKeys, 'rot', tracks );
36128
36129                                 addNonemptyTrack(
36130                                         VectorKeyframeTrack, boneName + '.scale',
36131                                         animationKeys, 'scl', tracks );
36132
36133                         }
36134
36135                 }
36136
36137                 if ( tracks.length === 0 ) {
36138
36139                         return null;
36140
36141                 }
36142
36143                 const clip = new AnimationClip( clipName, duration, tracks, blendMode );
36144
36145                 return clip;
36146
36147         }
36148
36149 } );
36150
36151 Object.assign( AnimationClip.prototype, {
36152
36153         resetDuration: function () {
36154
36155                 const tracks = this.tracks;
36156                 let duration = 0;
36157
36158                 for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
36159
36160                         const track = this.tracks[ i ];
36161
36162                         duration = Math.max( duration, track.times[ track.times.length - 1 ] );
36163
36164                 }
36165
36166                 this.duration = duration;
36167
36168                 return this;
36169
36170         },
36171
36172         trim: function () {
36173
36174                 for ( let i = 0; i < this.tracks.length; i ++ ) {
36175
36176                         this.tracks[ i ].trim( 0, this.duration );
36177
36178                 }
36179
36180                 return this;
36181
36182         },
36183
36184         validate: function () {
36185
36186                 let valid = true;
36187
36188                 for ( let i = 0; i < this.tracks.length; i ++ ) {
36189
36190                         valid = valid && this.tracks[ i ].validate();
36191
36192                 }
36193
36194                 return valid;
36195
36196         },
36197
36198         optimize: function () {
36199
36200                 for ( let i = 0; i < this.tracks.length; i ++ ) {
36201
36202                         this.tracks[ i ].optimize();
36203
36204                 }
36205
36206                 return this;
36207
36208         },
36209
36210         clone: function () {
36211
36212                 const tracks = [];
36213
36214                 for ( let i = 0; i < this.tracks.length; i ++ ) {
36215
36216                         tracks.push( this.tracks[ i ].clone() );
36217
36218                 }
36219
36220                 return new AnimationClip( this.name, this.duration, tracks, this.blendMode );
36221
36222         },
36223
36224         toJSON: function () {
36225
36226                 return AnimationClip.toJSON( this );
36227
36228         }
36229
36230 } );
36231
36232 const Cache = {
36233
36234         enabled: false,
36235
36236         files: {},
36237
36238         add: function ( key, file ) {
36239
36240                 if ( this.enabled === false ) return;
36241
36242                 // console.log( 'THREE.Cache', 'Adding key:', key );
36243
36244                 this.files[ key ] = file;
36245
36246         },
36247
36248         get: function ( key ) {
36249
36250                 if ( this.enabled === false ) return;
36251
36252                 // console.log( 'THREE.Cache', 'Checking key:', key );
36253
36254                 return this.files[ key ];
36255
36256         },
36257
36258         remove: function ( key ) {
36259
36260                 delete this.files[ key ];
36261
36262         },
36263
36264         clear: function () {
36265
36266                 this.files = {};
36267
36268         }
36269
36270 };
36271
36272 function LoadingManager( onLoad, onProgress, onError ) {
36273
36274         const scope = this;
36275
36276         let isLoading = false;
36277         let itemsLoaded = 0;
36278         let itemsTotal = 0;
36279         let urlModifier = undefined;
36280         const handlers = [];
36281
36282         // Refer to #5689 for the reason why we don't set .onStart
36283         // in the constructor
36284
36285         this.onStart = undefined;
36286         this.onLoad = onLoad;
36287         this.onProgress = onProgress;
36288         this.onError = onError;
36289
36290         this.itemStart = function ( url ) {
36291
36292                 itemsTotal ++;
36293
36294                 if ( isLoading === false ) {
36295
36296                         if ( scope.onStart !== undefined ) {
36297
36298                                 scope.onStart( url, itemsLoaded, itemsTotal );
36299
36300                         }
36301
36302                 }
36303
36304                 isLoading = true;
36305
36306         };
36307
36308         this.itemEnd = function ( url ) {
36309
36310                 itemsLoaded ++;
36311
36312                 if ( scope.onProgress !== undefined ) {
36313
36314                         scope.onProgress( url, itemsLoaded, itemsTotal );
36315
36316                 }
36317
36318                 if ( itemsLoaded === itemsTotal ) {
36319
36320                         isLoading = false;
36321
36322                         if ( scope.onLoad !== undefined ) {
36323
36324                                 scope.onLoad();
36325
36326                         }
36327
36328                 }
36329
36330         };
36331
36332         this.itemError = function ( url ) {
36333
36334                 if ( scope.onError !== undefined ) {
36335
36336                         scope.onError( url );
36337
36338                 }
36339
36340         };
36341
36342         this.resolveURL = function ( url ) {
36343
36344                 if ( urlModifier ) {
36345
36346                         return urlModifier( url );
36347
36348                 }
36349
36350                 return url;
36351
36352         };
36353
36354         this.setURLModifier = function ( transform ) {
36355
36356                 urlModifier = transform;
36357
36358                 return this;
36359
36360         };
36361
36362         this.addHandler = function ( regex, loader ) {
36363
36364                 handlers.push( regex, loader );
36365
36366                 return this;
36367
36368         };
36369
36370         this.removeHandler = function ( regex ) {
36371
36372                 const index = handlers.indexOf( regex );
36373
36374                 if ( index !== - 1 ) {
36375
36376                         handlers.splice( index, 2 );
36377
36378                 }
36379
36380                 return this;
36381
36382         };
36383
36384         this.getHandler = function ( file ) {
36385
36386                 for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
36387
36388                         const regex = handlers[ i ];
36389                         const loader = handlers[ i + 1 ];
36390
36391                         if ( regex.global ) regex.lastIndex = 0; // see #17920
36392
36393                         if ( regex.test( file ) ) {
36394
36395                                 return loader;
36396
36397                         }
36398
36399                 }
36400
36401                 return null;
36402
36403         };
36404
36405 }
36406
36407 const DefaultLoadingManager = new LoadingManager();
36408
36409 function Loader( manager ) {
36410
36411         this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
36412
36413         this.crossOrigin = 'anonymous';
36414         this.withCredentials = false;
36415         this.path = '';
36416         this.resourcePath = '';
36417         this.requestHeader = {};
36418
36419 }
36420
36421 Object.assign( Loader.prototype, {
36422
36423         load: function ( /* url, onLoad, onProgress, onError */ ) {},
36424
36425         loadAsync: function ( url, onProgress ) {
36426
36427                 const scope = this;
36428
36429                 return new Promise( function ( resolve, reject ) {
36430
36431                         scope.load( url, resolve, onProgress, reject );
36432
36433                 } );
36434
36435         },
36436
36437         parse: function ( /* data */ ) {},
36438
36439         setCrossOrigin: function ( crossOrigin ) {
36440
36441                 this.crossOrigin = crossOrigin;
36442                 return this;
36443
36444         },
36445
36446         setWithCredentials: function ( value ) {
36447
36448                 this.withCredentials = value;
36449                 return this;
36450
36451         },
36452
36453         setPath: function ( path ) {
36454
36455                 this.path = path;
36456                 return this;
36457
36458         },
36459
36460         setResourcePath: function ( resourcePath ) {
36461
36462                 this.resourcePath = resourcePath;
36463                 return this;
36464
36465         },
36466
36467         setRequestHeader: function ( requestHeader ) {
36468
36469                 this.requestHeader = requestHeader;
36470                 return this;
36471
36472         }
36473
36474 } );
36475
36476 const loading = {};
36477
36478 function FileLoader( manager ) {
36479
36480         Loader.call( this, manager );
36481
36482 }
36483
36484 FileLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36485
36486         constructor: FileLoader,
36487
36488         load: function ( url, onLoad, onProgress, onError ) {
36489
36490                 if ( url === undefined ) url = '';
36491
36492                 if ( this.path !== undefined ) url = this.path + url;
36493
36494                 url = this.manager.resolveURL( url );
36495
36496                 const scope = this;
36497
36498                 const cached = Cache.get( url );
36499
36500                 if ( cached !== undefined ) {
36501
36502                         scope.manager.itemStart( url );
36503
36504                         setTimeout( function () {
36505
36506                                 if ( onLoad ) onLoad( cached );
36507
36508                                 scope.manager.itemEnd( url );
36509
36510                         }, 0 );
36511
36512                         return cached;
36513
36514                 }
36515
36516                 // Check if request is duplicate
36517
36518                 if ( loading[ url ] !== undefined ) {
36519
36520                         loading[ url ].push( {
36521
36522                                 onLoad: onLoad,
36523                                 onProgress: onProgress,
36524                                 onError: onError
36525
36526                         } );
36527
36528                         return;
36529
36530                 }
36531
36532                 // Check for data: URI
36533                 const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
36534                 const dataUriRegexResult = url.match( dataUriRegex );
36535                 let request;
36536
36537                 // Safari can not handle Data URIs through XMLHttpRequest so process manually
36538                 if ( dataUriRegexResult ) {
36539
36540                         const mimeType = dataUriRegexResult[ 1 ];
36541                         const isBase64 = !! dataUriRegexResult[ 2 ];
36542
36543                         let data = dataUriRegexResult[ 3 ];
36544                         data = decodeURIComponent( data );
36545
36546                         if ( isBase64 ) data = atob( data );
36547
36548                         try {
36549
36550                                 let response;
36551                                 const responseType = ( this.responseType || '' ).toLowerCase();
36552
36553                                 switch ( responseType ) {
36554
36555                                         case 'arraybuffer':
36556                                         case 'blob':
36557
36558                                                 const view = new Uint8Array( data.length );
36559
36560                                                 for ( let i = 0; i < data.length; i ++ ) {
36561
36562                                                         view[ i ] = data.charCodeAt( i );
36563
36564                                                 }
36565
36566                                                 if ( responseType === 'blob' ) {
36567
36568                                                         response = new Blob( [ view.buffer ], { type: mimeType } );
36569
36570                                                 } else {
36571
36572                                                         response = view.buffer;
36573
36574                                                 }
36575
36576                                                 break;
36577
36578                                         case 'document':
36579
36580                                                 const parser = new DOMParser();
36581                                                 response = parser.parseFromString( data, mimeType );
36582
36583                                                 break;
36584
36585                                         case 'json':
36586
36587                                                 response = JSON.parse( data );
36588
36589                                                 break;
36590
36591                                         default: // 'text' or other
36592
36593                                                 response = data;
36594
36595                                                 break;
36596
36597                                 }
36598
36599                                 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
36600                                 setTimeout( function () {
36601
36602                                         if ( onLoad ) onLoad( response );
36603
36604                                         scope.manager.itemEnd( url );
36605
36606                                 }, 0 );
36607
36608                         } catch ( error ) {
36609
36610                                 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
36611                                 setTimeout( function () {
36612
36613                                         if ( onError ) onError( error );
36614
36615                                         scope.manager.itemError( url );
36616                                         scope.manager.itemEnd( url );
36617
36618                                 }, 0 );
36619
36620                         }
36621
36622                 } else {
36623
36624                         // Initialise array for duplicate requests
36625
36626                         loading[ url ] = [];
36627
36628                         loading[ url ].push( {
36629
36630                                 onLoad: onLoad,
36631                                 onProgress: onProgress,
36632                                 onError: onError
36633
36634                         } );
36635
36636                         request = new XMLHttpRequest();
36637
36638                         request.open( 'GET', url, true );
36639
36640                         request.addEventListener( 'load', function ( event ) {
36641
36642                                 const response = this.response;
36643
36644                                 const callbacks = loading[ url ];
36645
36646                                 delete loading[ url ];
36647
36648                                 if ( this.status === 200 || this.status === 0 ) {
36649
36650                                         // Some browsers return HTTP Status 0 when using non-http protocol
36651                                         // e.g. 'file://' or 'data://'. Handle as success.
36652
36653                                         if ( this.status === 0 ) console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
36654
36655                                         // Add to cache only on HTTP success, so that we do not cache
36656                                         // error response bodies as proper responses to requests.
36657                                         Cache.add( url, response );
36658
36659                                         for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36660
36661                                                 const callback = callbacks[ i ];
36662                                                 if ( callback.onLoad ) callback.onLoad( response );
36663
36664                                         }
36665
36666                                         scope.manager.itemEnd( url );
36667
36668                                 } else {
36669
36670                                         for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36671
36672                                                 const callback = callbacks[ i ];
36673                                                 if ( callback.onError ) callback.onError( event );
36674
36675                                         }
36676
36677                                         scope.manager.itemError( url );
36678                                         scope.manager.itemEnd( url );
36679
36680                                 }
36681
36682                         }, false );
36683
36684                         request.addEventListener( 'progress', function ( event ) {
36685
36686                                 const callbacks = loading[ url ];
36687
36688                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36689
36690                                         const callback = callbacks[ i ];
36691                                         if ( callback.onProgress ) callback.onProgress( event );
36692
36693                                 }
36694
36695                         }, false );
36696
36697                         request.addEventListener( 'error', function ( event ) {
36698
36699                                 const callbacks = loading[ url ];
36700
36701                                 delete loading[ url ];
36702
36703                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36704
36705                                         const callback = callbacks[ i ];
36706                                         if ( callback.onError ) callback.onError( event );
36707
36708                                 }
36709
36710                                 scope.manager.itemError( url );
36711                                 scope.manager.itemEnd( url );
36712
36713                         }, false );
36714
36715                         request.addEventListener( 'abort', function ( event ) {
36716
36717                                 const callbacks = loading[ url ];
36718
36719                                 delete loading[ url ];
36720
36721                                 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
36722
36723                                         const callback = callbacks[ i ];
36724                                         if ( callback.onError ) callback.onError( event );
36725
36726                                 }
36727
36728                                 scope.manager.itemError( url );
36729                                 scope.manager.itemEnd( url );
36730
36731                         }, false );
36732
36733                         if ( this.responseType !== undefined ) request.responseType = this.responseType;
36734                         if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
36735
36736                         if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
36737
36738                         for ( const header in this.requestHeader ) {
36739
36740                                 request.setRequestHeader( header, this.requestHeader[ header ] );
36741
36742                         }
36743
36744                         request.send( null );
36745
36746                 }
36747
36748                 scope.manager.itemStart( url );
36749
36750                 return request;
36751
36752         },
36753
36754         setResponseType: function ( value ) {
36755
36756                 this.responseType = value;
36757                 return this;
36758
36759         },
36760
36761         setMimeType: function ( value ) {
36762
36763                 this.mimeType = value;
36764                 return this;
36765
36766         }
36767
36768 } );
36769
36770 function AnimationLoader( manager ) {
36771
36772         Loader.call( this, manager );
36773
36774 }
36775
36776 AnimationLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36777
36778         constructor: AnimationLoader,
36779
36780         load: function ( url, onLoad, onProgress, onError ) {
36781
36782                 const scope = this;
36783
36784                 const loader = new FileLoader( scope.manager );
36785                 loader.setPath( scope.path );
36786                 loader.setRequestHeader( scope.requestHeader );
36787                 loader.setWithCredentials( scope.withCredentials );
36788                 loader.load( url, function ( text ) {
36789
36790                         try {
36791
36792                                 onLoad( scope.parse( JSON.parse( text ) ) );
36793
36794                         } catch ( e ) {
36795
36796                                 if ( onError ) {
36797
36798                                         onError( e );
36799
36800                                 } else {
36801
36802                                         console.error( e );
36803
36804                                 }
36805
36806                                 scope.manager.itemError( url );
36807
36808                         }
36809
36810                 }, onProgress, onError );
36811
36812         },
36813
36814         parse: function ( json ) {
36815
36816                 const animations = [];
36817
36818                 for ( let i = 0; i < json.length; i ++ ) {
36819
36820                         const clip = AnimationClip.parse( json[ i ] );
36821
36822                         animations.push( clip );
36823
36824                 }
36825
36826                 return animations;
36827
36828         }
36829
36830 } );
36831
36832 /**
36833  * Abstract Base class to block based textures loader (dds, pvr, ...)
36834  *
36835  * Sub classes have to implement the parse() method which will be used in load().
36836  */
36837
36838 function CompressedTextureLoader( manager ) {
36839
36840         Loader.call( this, manager );
36841
36842 }
36843
36844 CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36845
36846         constructor: CompressedTextureLoader,
36847
36848         load: function ( url, onLoad, onProgress, onError ) {
36849
36850                 const scope = this;
36851
36852                 const images = [];
36853
36854                 const texture = new CompressedTexture();
36855                 texture.image = images;
36856
36857                 const loader = new FileLoader( this.manager );
36858                 loader.setPath( this.path );
36859                 loader.setResponseType( 'arraybuffer' );
36860                 loader.setRequestHeader( this.requestHeader );
36861                 loader.setWithCredentials( scope.withCredentials );
36862
36863                 let loaded = 0;
36864
36865                 function loadTexture( i ) {
36866
36867                         loader.load( url[ i ], function ( buffer ) {
36868
36869                                 const texDatas = scope.parse( buffer, true );
36870
36871                                 images[ i ] = {
36872                                         width: texDatas.width,
36873                                         height: texDatas.height,
36874                                         format: texDatas.format,
36875                                         mipmaps: texDatas.mipmaps
36876                                 };
36877
36878                                 loaded += 1;
36879
36880                                 if ( loaded === 6 ) {
36881
36882                                         if ( texDatas.mipmapCount === 1 )
36883                                                 texture.minFilter = LinearFilter;
36884
36885                                         texture.format = texDatas.format;
36886                                         texture.needsUpdate = true;
36887
36888                                         if ( onLoad ) onLoad( texture );
36889
36890                                 }
36891
36892                         }, onProgress, onError );
36893
36894                 }
36895
36896                 if ( Array.isArray( url ) ) {
36897
36898                         for ( let i = 0, il = url.length; i < il; ++ i ) {
36899
36900                                 loadTexture( i );
36901
36902                         }
36903
36904                 } else {
36905
36906                         // compressed cubemap texture stored in a single DDS file
36907
36908                         loader.load( url, function ( buffer ) {
36909
36910                                 const texDatas = scope.parse( buffer, true );
36911
36912                                 if ( texDatas.isCubemap ) {
36913
36914                                         const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
36915
36916                                         for ( let f = 0; f < faces; f ++ ) {
36917
36918                                                 images[ f ] = { mipmaps: [] };
36919
36920                                                 for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
36921
36922                                                         images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
36923                                                         images[ f ].format = texDatas.format;
36924                                                         images[ f ].width = texDatas.width;
36925                                                         images[ f ].height = texDatas.height;
36926
36927                                                 }
36928
36929                                         }
36930
36931                                 } else {
36932
36933                                         texture.image.width = texDatas.width;
36934                                         texture.image.height = texDatas.height;
36935                                         texture.mipmaps = texDatas.mipmaps;
36936
36937                                 }
36938
36939                                 if ( texDatas.mipmapCount === 1 ) {
36940
36941                                         texture.minFilter = LinearFilter;
36942
36943                                 }
36944
36945                                 texture.format = texDatas.format;
36946                                 texture.needsUpdate = true;
36947
36948                                 if ( onLoad ) onLoad( texture );
36949
36950                         }, onProgress, onError );
36951
36952                 }
36953
36954                 return texture;
36955
36956         }
36957
36958 } );
36959
36960 function ImageLoader( manager ) {
36961
36962         Loader.call( this, manager );
36963
36964 }
36965
36966 ImageLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36967
36968         constructor: ImageLoader,
36969
36970         load: function ( url, onLoad, onProgress, onError ) {
36971
36972                 if ( this.path !== undefined ) url = this.path + url;
36973
36974                 url = this.manager.resolveURL( url );
36975
36976                 const scope = this;
36977
36978                 const cached = Cache.get( url );
36979
36980                 if ( cached !== undefined ) {
36981
36982                         scope.manager.itemStart( url );
36983
36984                         setTimeout( function () {
36985
36986                                 if ( onLoad ) onLoad( cached );
36987
36988                                 scope.manager.itemEnd( url );
36989
36990                         }, 0 );
36991
36992                         return cached;
36993
36994                 }
36995
36996                 const image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
36997
36998                 function onImageLoad() {
36999
37000                         image.removeEventListener( 'load', onImageLoad, false );
37001                         image.removeEventListener( 'error', onImageError, false );
37002
37003                         Cache.add( url, this );
37004
37005                         if ( onLoad ) onLoad( this );
37006
37007                         scope.manager.itemEnd( url );
37008
37009                 }
37010
37011                 function onImageError( event ) {
37012
37013                         image.removeEventListener( 'load', onImageLoad, false );
37014                         image.removeEventListener( 'error', onImageError, false );
37015
37016                         if ( onError ) onError( event );
37017
37018                         scope.manager.itemError( url );
37019                         scope.manager.itemEnd( url );
37020
37021                 }
37022
37023                 image.addEventListener( 'load', onImageLoad, false );
37024                 image.addEventListener( 'error', onImageError, false );
37025
37026                 if ( url.substr( 0, 5 ) !== 'data:' ) {
37027
37028                         if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
37029
37030                 }
37031
37032                 scope.manager.itemStart( url );
37033
37034                 image.src = url;
37035
37036                 return image;
37037
37038         }
37039
37040 } );
37041
37042 function CubeTextureLoader( manager ) {
37043
37044         Loader.call( this, manager );
37045
37046 }
37047
37048 CubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
37049
37050         constructor: CubeTextureLoader,
37051
37052         load: function ( urls, onLoad, onProgress, onError ) {
37053
37054                 const texture = new CubeTexture();
37055
37056                 const loader = new ImageLoader( this.manager );
37057                 loader.setCrossOrigin( this.crossOrigin );
37058                 loader.setPath( this.path );
37059
37060                 let loaded = 0;
37061
37062                 function loadTexture( i ) {
37063
37064                         loader.load( urls[ i ], function ( image ) {
37065
37066                                 texture.images[ i ] = image;
37067
37068                                 loaded ++;
37069
37070                                 if ( loaded === 6 ) {
37071
37072                                         texture.needsUpdate = true;
37073
37074                                         if ( onLoad ) onLoad( texture );
37075
37076                                 }
37077
37078                         }, undefined, onError );
37079
37080                 }
37081
37082                 for ( let i = 0; i < urls.length; ++ i ) {
37083
37084                         loadTexture( i );
37085
37086                 }
37087
37088                 return texture;
37089
37090         }
37091
37092 } );
37093
37094 /**
37095  * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
37096  *
37097  * Sub classes have to implement the parse() method which will be used in load().
37098  */
37099
37100 function DataTextureLoader( manager ) {
37101
37102         Loader.call( this, manager );
37103
37104 }
37105
37106 DataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
37107
37108         constructor: DataTextureLoader,
37109
37110         load: function ( url, onLoad, onProgress, onError ) {
37111
37112                 const scope = this;
37113
37114                 const texture = new DataTexture();
37115
37116                 const loader = new FileLoader( this.manager );
37117                 loader.setResponseType( 'arraybuffer' );
37118                 loader.setRequestHeader( this.requestHeader );
37119                 loader.setPath( this.path );
37120                 loader.setWithCredentials( scope.withCredentials );
37121                 loader.load( url, function ( buffer ) {
37122
37123                         const texData = scope.parse( buffer );
37124
37125                         if ( ! texData ) return;
37126
37127                         if ( texData.image !== undefined ) {
37128
37129                                 texture.image = texData.image;
37130
37131                         } else if ( texData.data !== undefined ) {
37132
37133                                 texture.image.width = texData.width;
37134                                 texture.image.height = texData.height;
37135                                 texture.image.data = texData.data;
37136
37137                         }
37138
37139                         texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
37140                         texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
37141
37142                         texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
37143                         texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
37144
37145                         texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
37146
37147                         if ( texData.format !== undefined ) {
37148
37149                                 texture.format = texData.format;
37150
37151                         }
37152
37153                         if ( texData.type !== undefined ) {
37154
37155                                 texture.type = texData.type;
37156
37157                         }
37158
37159                         if ( texData.mipmaps !== undefined ) {
37160
37161                                 texture.mipmaps = texData.mipmaps;
37162                                 texture.minFilter = LinearMipmapLinearFilter; // presumably...
37163
37164                         }
37165
37166                         if ( texData.mipmapCount === 1 ) {
37167
37168                                 texture.minFilter = LinearFilter;
37169
37170                         }
37171
37172                         texture.needsUpdate = true;
37173
37174                         if ( onLoad ) onLoad( texture, texData );
37175
37176                 }, onProgress, onError );
37177
37178
37179                 return texture;
37180
37181         }
37182
37183 } );
37184
37185 function TextureLoader( manager ) {
37186
37187         Loader.call( this, manager );
37188
37189 }
37190
37191 TextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
37192
37193         constructor: TextureLoader,
37194
37195         load: function ( url, onLoad, onProgress, onError ) {
37196
37197                 const texture = new Texture();
37198
37199                 const loader = new ImageLoader( this.manager );
37200                 loader.setCrossOrigin( this.crossOrigin );
37201                 loader.setPath( this.path );
37202
37203                 loader.load( url, function ( image ) {
37204
37205                         texture.image = image;
37206
37207                         // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
37208                         const isJPEG = url.search( /\.jpe?g($|\?)/i ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
37209
37210                         texture.format = isJPEG ? RGBFormat : RGBAFormat;
37211                         texture.needsUpdate = true;
37212
37213                         if ( onLoad !== undefined ) {
37214
37215                                 onLoad( texture );
37216
37217                         }
37218
37219                 }, onProgress, onError );
37220
37221                 return texture;
37222
37223         }
37224
37225 } );
37226
37227 /**
37228  * Extensible curve object.
37229  *
37230  * Some common of curve methods:
37231  * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
37232  * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
37233  * .getPoints(), .getSpacedPoints()
37234  * .getLength()
37235  * .updateArcLengths()
37236  *
37237  * This following curves inherit from THREE.Curve:
37238  *
37239  * -- 2D curves --
37240  * THREE.ArcCurve
37241  * THREE.CubicBezierCurve
37242  * THREE.EllipseCurve
37243  * THREE.LineCurve
37244  * THREE.QuadraticBezierCurve
37245  * THREE.SplineCurve
37246  *
37247  * -- 3D curves --
37248  * THREE.CatmullRomCurve3
37249  * THREE.CubicBezierCurve3
37250  * THREE.LineCurve3
37251  * THREE.QuadraticBezierCurve3
37252  *
37253  * A series of curves can be represented as a THREE.CurvePath.
37254  *
37255  **/
37256
37257 function Curve() {
37258
37259         this.type = 'Curve';
37260
37261         this.arcLengthDivisions = 200;
37262
37263 }
37264
37265 Object.assign( Curve.prototype, {
37266
37267         // Virtual base class method to overwrite and implement in subclasses
37268         //      - t [0 .. 1]
37269
37270         getPoint: function ( /* t, optionalTarget */ ) {
37271
37272                 console.warn( 'THREE.Curve: .getPoint() not implemented.' );
37273                 return null;
37274
37275         },
37276
37277         // Get point at relative position in curve according to arc length
37278         // - u [0 .. 1]
37279
37280         getPointAt: function ( u, optionalTarget ) {
37281
37282                 const t = this.getUtoTmapping( u );
37283                 return this.getPoint( t, optionalTarget );
37284
37285         },
37286
37287         // Get sequence of points using getPoint( t )
37288
37289         getPoints: function ( divisions = 5 ) {
37290
37291                 const points = [];
37292
37293                 for ( let d = 0; d <= divisions; d ++ ) {
37294
37295                         points.push( this.getPoint( d / divisions ) );
37296
37297                 }
37298
37299                 return points;
37300
37301         },
37302
37303         // Get sequence of points using getPointAt( u )
37304
37305         getSpacedPoints: function ( divisions = 5 ) {
37306
37307                 const points = [];
37308
37309                 for ( let d = 0; d <= divisions; d ++ ) {
37310
37311                         points.push( this.getPointAt( d / divisions ) );
37312
37313                 }
37314
37315                 return points;
37316
37317         },
37318
37319         // Get total curve arc length
37320
37321         getLength: function () {
37322
37323                 const lengths = this.getLengths();
37324                 return lengths[ lengths.length - 1 ];
37325
37326         },
37327
37328         // Get list of cumulative segment lengths
37329
37330         getLengths: function ( divisions ) {
37331
37332                 if ( divisions === undefined ) divisions = this.arcLengthDivisions;
37333
37334                 if ( this.cacheArcLengths &&
37335                         ( this.cacheArcLengths.length === divisions + 1 ) &&
37336                         ! this.needsUpdate ) {
37337
37338                         return this.cacheArcLengths;
37339
37340                 }
37341
37342                 this.needsUpdate = false;
37343
37344                 const cache = [];
37345                 let current, last = this.getPoint( 0 );
37346                 let sum = 0;
37347
37348                 cache.push( 0 );
37349
37350                 for ( let p = 1; p <= divisions; p ++ ) {
37351
37352                         current = this.getPoint( p / divisions );
37353                         sum += current.distanceTo( last );
37354                         cache.push( sum );
37355                         last = current;
37356
37357                 }
37358
37359                 this.cacheArcLengths = cache;
37360
37361                 return cache; // { sums: cache, sum: sum }; Sum is in the last element.
37362
37363         },
37364
37365         updateArcLengths: function () {
37366
37367                 this.needsUpdate = true;
37368                 this.getLengths();
37369
37370         },
37371
37372         // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
37373
37374         getUtoTmapping: function ( u, distance ) {
37375
37376                 const arcLengths = this.getLengths();
37377
37378                 let i = 0;
37379                 const il = arcLengths.length;
37380
37381                 let targetArcLength; // The targeted u distance value to get
37382
37383                 if ( distance ) {
37384
37385                         targetArcLength = distance;
37386
37387                 } else {
37388
37389                         targetArcLength = u * arcLengths[ il - 1 ];
37390
37391                 }
37392
37393                 // binary search for the index with largest value smaller than target u distance
37394
37395                 let low = 0, high = il - 1, comparison;
37396
37397                 while ( low <= high ) {
37398
37399                         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
37400
37401                         comparison = arcLengths[ i ] - targetArcLength;
37402
37403                         if ( comparison < 0 ) {
37404
37405                                 low = i + 1;
37406
37407                         } else if ( comparison > 0 ) {
37408
37409                                 high = i - 1;
37410
37411                         } else {
37412
37413                                 high = i;
37414                                 break;
37415
37416                                 // DONE
37417
37418                         }
37419
37420                 }
37421
37422                 i = high;
37423
37424                 if ( arcLengths[ i ] === targetArcLength ) {
37425
37426                         return i / ( il - 1 );
37427
37428                 }
37429
37430                 // we could get finer grain at lengths, or use simple interpolation between two points
37431
37432                 const lengthBefore = arcLengths[ i ];
37433                 const lengthAfter = arcLengths[ i + 1 ];
37434
37435                 const segmentLength = lengthAfter - lengthBefore;
37436
37437                 // determine where we are between the 'before' and 'after' points
37438
37439                 const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
37440
37441                 // add that fractional amount to t
37442
37443                 const t = ( i + segmentFraction ) / ( il - 1 );
37444
37445                 return t;
37446
37447         },
37448
37449         // Returns a unit vector tangent at t
37450         // In case any sub curve does not implement its tangent derivation,
37451         // 2 points a small delta apart will be used to find its gradient
37452         // which seems to give a reasonable approximation
37453
37454         getTangent: function ( t, optionalTarget ) {
37455
37456                 const delta = 0.0001;
37457                 let t1 = t - delta;
37458                 let t2 = t + delta;
37459
37460                 // Capping in case of danger
37461
37462                 if ( t1 < 0 ) t1 = 0;
37463                 if ( t2 > 1 ) t2 = 1;
37464
37465                 const pt1 = this.getPoint( t1 );
37466                 const pt2 = this.getPoint( t2 );
37467
37468                 const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
37469
37470                 tangent.copy( pt2 ).sub( pt1 ).normalize();
37471
37472                 return tangent;
37473
37474         },
37475
37476         getTangentAt: function ( u, optionalTarget ) {
37477
37478                 const t = this.getUtoTmapping( u );
37479                 return this.getTangent( t, optionalTarget );
37480
37481         },
37482
37483         computeFrenetFrames: function ( segments, closed ) {
37484
37485                 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
37486
37487                 const normal = new Vector3();
37488
37489                 const tangents = [];
37490                 const normals = [];
37491                 const binormals = [];
37492
37493                 const vec = new Vector3();
37494                 const mat = new Matrix4();
37495
37496                 // compute the tangent vectors for each segment on the curve
37497
37498                 for ( let i = 0; i <= segments; i ++ ) {
37499
37500                         const u = i / segments;
37501
37502                         tangents[ i ] = this.getTangentAt( u, new Vector3() );
37503                         tangents[ i ].normalize();
37504
37505                 }
37506
37507                 // select an initial normal vector perpendicular to the first tangent vector,
37508                 // and in the direction of the minimum tangent xyz component
37509
37510                 normals[ 0 ] = new Vector3();
37511                 binormals[ 0 ] = new Vector3();
37512                 let min = Number.MAX_VALUE;
37513                 const tx = Math.abs( tangents[ 0 ].x );
37514                 const ty = Math.abs( tangents[ 0 ].y );
37515                 const tz = Math.abs( tangents[ 0 ].z );
37516
37517                 if ( tx <= min ) {
37518
37519                         min = tx;
37520                         normal.set( 1, 0, 0 );
37521
37522                 }
37523
37524                 if ( ty <= min ) {
37525
37526                         min = ty;
37527                         normal.set( 0, 1, 0 );
37528
37529                 }
37530
37531                 if ( tz <= min ) {
37532
37533                         normal.set( 0, 0, 1 );
37534
37535                 }
37536
37537                 vec.crossVectors( tangents[ 0 ], normal ).normalize();
37538
37539                 normals[ 0 ].crossVectors( tangents[ 0 ], vec );
37540                 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
37541
37542
37543                 // compute the slowly-varying normal and binormal vectors for each segment on the curve
37544
37545                 for ( let i = 1; i <= segments; i ++ ) {
37546
37547                         normals[ i ] = normals[ i - 1 ].clone();
37548
37549                         binormals[ i ] = binormals[ i - 1 ].clone();
37550
37551                         vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
37552
37553                         if ( vec.length() > Number.EPSILON ) {
37554
37555                                 vec.normalize();
37556
37557                                 const theta = Math.acos( MathUtils.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
37558
37559                                 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
37560
37561                         }
37562
37563                         binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
37564
37565                 }
37566
37567                 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
37568
37569                 if ( closed === true ) {
37570
37571                         let theta = Math.acos( MathUtils.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
37572                         theta /= segments;
37573
37574                         if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
37575
37576                                 theta = - theta;
37577
37578                         }
37579
37580                         for ( let i = 1; i <= segments; i ++ ) {
37581
37582                                 // twist a little...
37583                                 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
37584                                 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
37585
37586                         }
37587
37588                 }
37589
37590                 return {
37591                         tangents: tangents,
37592                         normals: normals,
37593                         binormals: binormals
37594                 };
37595
37596         },
37597
37598         clone: function () {
37599
37600                 return new this.constructor().copy( this );
37601
37602         },
37603
37604         copy: function ( source ) {
37605
37606                 this.arcLengthDivisions = source.arcLengthDivisions;
37607
37608                 return this;
37609
37610         },
37611
37612         toJSON: function () {
37613
37614                 const data = {
37615                         metadata: {
37616                                 version: 4.5,
37617                                 type: 'Curve',
37618                                 generator: 'Curve.toJSON'
37619                         }
37620                 };
37621
37622                 data.arcLengthDivisions = this.arcLengthDivisions;
37623                 data.type = this.type;
37624
37625                 return data;
37626
37627         },
37628
37629         fromJSON: function ( json ) {
37630
37631                 this.arcLengthDivisions = json.arcLengthDivisions;
37632
37633                 return this;
37634
37635         }
37636
37637 } );
37638
37639 function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
37640
37641         Curve.call( this );
37642
37643         this.type = 'EllipseCurve';
37644
37645         this.aX = aX || 0;
37646         this.aY = aY || 0;
37647
37648         this.xRadius = xRadius || 1;
37649         this.yRadius = yRadius || 1;
37650
37651         this.aStartAngle = aStartAngle || 0;
37652         this.aEndAngle = aEndAngle || 2 * Math.PI;
37653
37654         this.aClockwise = aClockwise || false;
37655
37656         this.aRotation = aRotation || 0;
37657
37658 }
37659
37660 EllipseCurve.prototype = Object.create( Curve.prototype );
37661 EllipseCurve.prototype.constructor = EllipseCurve;
37662
37663 EllipseCurve.prototype.isEllipseCurve = true;
37664
37665 EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {
37666
37667         const point = optionalTarget || new Vector2();
37668
37669         const twoPi = Math.PI * 2;
37670         let deltaAngle = this.aEndAngle - this.aStartAngle;
37671         const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
37672
37673         // ensures that deltaAngle is 0 .. 2 PI
37674         while ( deltaAngle < 0 ) deltaAngle += twoPi;
37675         while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
37676
37677         if ( deltaAngle < Number.EPSILON ) {
37678
37679                 if ( samePoints ) {
37680
37681                         deltaAngle = 0;
37682
37683                 } else {
37684
37685                         deltaAngle = twoPi;
37686
37687                 }
37688
37689         }
37690
37691         if ( this.aClockwise === true && ! samePoints ) {
37692
37693                 if ( deltaAngle === twoPi ) {
37694
37695                         deltaAngle = - twoPi;
37696
37697                 } else {
37698
37699                         deltaAngle = deltaAngle - twoPi;
37700
37701                 }
37702
37703         }
37704
37705         const angle = this.aStartAngle + t * deltaAngle;
37706         let x = this.aX + this.xRadius * Math.cos( angle );
37707         let y = this.aY + this.yRadius * Math.sin( angle );
37708
37709         if ( this.aRotation !== 0 ) {
37710
37711                 const cos = Math.cos( this.aRotation );
37712                 const sin = Math.sin( this.aRotation );
37713
37714                 const tx = x - this.aX;
37715                 const ty = y - this.aY;
37716
37717                 // Rotate the point about the center of the ellipse.
37718                 x = tx * cos - ty * sin + this.aX;
37719                 y = tx * sin + ty * cos + this.aY;
37720
37721         }
37722
37723         return point.set( x, y );
37724
37725 };
37726
37727 EllipseCurve.prototype.copy = function ( source ) {
37728
37729         Curve.prototype.copy.call( this, source );
37730
37731         this.aX = source.aX;
37732         this.aY = source.aY;
37733
37734         this.xRadius = source.xRadius;
37735         this.yRadius = source.yRadius;
37736
37737         this.aStartAngle = source.aStartAngle;
37738         this.aEndAngle = source.aEndAngle;
37739
37740         this.aClockwise = source.aClockwise;
37741
37742         this.aRotation = source.aRotation;
37743
37744         return this;
37745
37746 };
37747
37748
37749 EllipseCurve.prototype.toJSON = function () {
37750
37751         const data = Curve.prototype.toJSON.call( this );
37752
37753         data.aX = this.aX;
37754         data.aY = this.aY;
37755
37756         data.xRadius = this.xRadius;
37757         data.yRadius = this.yRadius;
37758
37759         data.aStartAngle = this.aStartAngle;
37760         data.aEndAngle = this.aEndAngle;
37761
37762         data.aClockwise = this.aClockwise;
37763
37764         data.aRotation = this.aRotation;
37765
37766         return data;
37767
37768 };
37769
37770 EllipseCurve.prototype.fromJSON = function ( json ) {
37771
37772         Curve.prototype.fromJSON.call( this, json );
37773
37774         this.aX = json.aX;
37775         this.aY = json.aY;
37776
37777         this.xRadius = json.xRadius;
37778         this.yRadius = json.yRadius;
37779
37780         this.aStartAngle = json.aStartAngle;
37781         this.aEndAngle = json.aEndAngle;
37782
37783         this.aClockwise = json.aClockwise;
37784
37785         this.aRotation = json.aRotation;
37786
37787         return this;
37788
37789 };
37790
37791 function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
37792
37793         EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
37794
37795         this.type = 'ArcCurve';
37796
37797 }
37798
37799 ArcCurve.prototype = Object.create( EllipseCurve.prototype );
37800 ArcCurve.prototype.constructor = ArcCurve;
37801
37802 ArcCurve.prototype.isArcCurve = true;
37803
37804 /**
37805  * Centripetal CatmullRom Curve - which is useful for avoiding
37806  * cusps and self-intersections in non-uniform catmull rom curves.
37807  * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
37808  *
37809  * curve.type accepts centripetal(default), chordal and catmullrom
37810  * curve.tension is used for catmullrom which defaults to 0.5
37811  */
37812
37813
37814 /*
37815 Based on an optimized c++ solution in
37816  - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
37817  - http://ideone.com/NoEbVM
37818
37819 This CubicPoly class could be used for reusing some variables and calculations,
37820 but for three.js curve use, it could be possible inlined and flatten into a single function call
37821 which can be placed in CurveUtils.
37822 */
37823
37824 function CubicPoly() {
37825
37826         let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
37827
37828         /*
37829          * Compute coefficients for a cubic polynomial
37830          *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
37831          * such that
37832          *   p(0) = x0, p(1) = x1
37833          *  and
37834          *   p'(0) = t0, p'(1) = t1.
37835          */
37836         function init( x0, x1, t0, t1 ) {
37837
37838                 c0 = x0;
37839                 c1 = t0;
37840                 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
37841                 c3 = 2 * x0 - 2 * x1 + t0 + t1;
37842
37843         }
37844
37845         return {
37846
37847                 initCatmullRom: function ( x0, x1, x2, x3, tension ) {
37848
37849                         init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
37850
37851                 },
37852
37853                 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
37854
37855                         // compute tangents when parameterized in [t1,t2]
37856                         let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
37857                         let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
37858
37859                         // rescale tangents for parametrization in [0,1]
37860                         t1 *= dt1;
37861                         t2 *= dt1;
37862
37863                         init( x1, x2, t1, t2 );
37864
37865                 },
37866
37867                 calc: function ( t ) {
37868
37869                         const t2 = t * t;
37870                         const t3 = t2 * t;
37871                         return c0 + c1 * t + c2 * t2 + c3 * t3;
37872
37873                 }
37874
37875         };
37876
37877 }
37878
37879 //
37880
37881 const tmp = new Vector3();
37882 const px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();
37883
37884 function CatmullRomCurve3( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
37885
37886         Curve.call( this );
37887
37888         this.type = 'CatmullRomCurve3';
37889
37890         this.points = points;
37891         this.closed = closed;
37892         this.curveType = curveType;
37893         this.tension = tension;
37894
37895 }
37896
37897 CatmullRomCurve3.prototype = Object.create( Curve.prototype );
37898 CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
37899
37900 CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
37901
37902 CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
37903
37904         const point = optionalTarget;
37905
37906         const points = this.points;
37907         const l = points.length;
37908
37909         const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
37910         let intPoint = Math.floor( p );
37911         let weight = p - intPoint;
37912
37913         if ( this.closed ) {
37914
37915                 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
37916
37917         } else if ( weight === 0 && intPoint === l - 1 ) {
37918
37919                 intPoint = l - 2;
37920                 weight = 1;
37921
37922         }
37923
37924         let p0, p3; // 4 points (p1 & p2 defined below)
37925
37926         if ( this.closed || intPoint > 0 ) {
37927
37928                 p0 = points[ ( intPoint - 1 ) % l ];
37929
37930         } else {
37931
37932                 // extrapolate first point
37933                 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
37934                 p0 = tmp;
37935
37936         }
37937
37938         const p1 = points[ intPoint % l ];
37939         const p2 = points[ ( intPoint + 1 ) % l ];
37940
37941         if ( this.closed || intPoint + 2 < l ) {
37942
37943                 p3 = points[ ( intPoint + 2 ) % l ];
37944
37945         } else {
37946
37947                 // extrapolate last point
37948                 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
37949                 p3 = tmp;
37950
37951         }
37952
37953         if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
37954
37955                 // init Centripetal / Chordal Catmull-Rom
37956                 const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
37957                 let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
37958                 let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
37959                 let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
37960
37961                 // safety check for repeated points
37962                 if ( dt1 < 1e-4 ) dt1 = 1.0;
37963                 if ( dt0 < 1e-4 ) dt0 = dt1;
37964                 if ( dt2 < 1e-4 ) dt2 = dt1;
37965
37966                 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
37967                 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
37968                 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
37969
37970         } else if ( this.curveType === 'catmullrom' ) {
37971
37972                 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
37973                 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
37974                 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
37975
37976         }
37977
37978         point.set(
37979                 px.calc( weight ),
37980                 py.calc( weight ),
37981                 pz.calc( weight )
37982         );
37983
37984         return point;
37985
37986 };
37987
37988 CatmullRomCurve3.prototype.copy = function ( source ) {
37989
37990         Curve.prototype.copy.call( this, source );
37991
37992         this.points = [];
37993
37994         for ( let i = 0, l = source.points.length; i < l; i ++ ) {
37995
37996                 const point = source.points[ i ];
37997
37998                 this.points.push( point.clone() );
37999
38000         }
38001
38002         this.closed = source.closed;
38003         this.curveType = source.curveType;
38004         this.tension = source.tension;
38005
38006         return this;
38007
38008 };
38009
38010 CatmullRomCurve3.prototype.toJSON = function () {
38011
38012         const data = Curve.prototype.toJSON.call( this );
38013
38014         data.points = [];
38015
38016         for ( let i = 0, l = this.points.length; i < l; i ++ ) {
38017
38018                 const point = this.points[ i ];
38019                 data.points.push( point.toArray() );
38020
38021         }
38022
38023         data.closed = this.closed;
38024         data.curveType = this.curveType;
38025         data.tension = this.tension;
38026
38027         return data;
38028
38029 };
38030
38031 CatmullRomCurve3.prototype.fromJSON = function ( json ) {
38032
38033         Curve.prototype.fromJSON.call( this, json );
38034
38035         this.points = [];
38036
38037         for ( let i = 0, l = json.points.length; i < l; i ++ ) {
38038
38039                 const point = json.points[ i ];
38040                 this.points.push( new Vector3().fromArray( point ) );
38041
38042         }
38043
38044         this.closed = json.closed;
38045         this.curveType = json.curveType;
38046         this.tension = json.tension;
38047
38048         return this;
38049
38050 };
38051
38052 /**
38053  * Bezier Curves formulas obtained from
38054  * http://en.wikipedia.org/wiki/Bézier_curve
38055  */
38056
38057 function CatmullRom( t, p0, p1, p2, p3 ) {
38058
38059         const v0 = ( p2 - p0 ) * 0.5;
38060         const v1 = ( p3 - p1 ) * 0.5;
38061         const t2 = t * t;
38062         const t3 = t * t2;
38063         return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
38064
38065 }
38066
38067 //
38068
38069 function QuadraticBezierP0( t, p ) {
38070
38071         const k = 1 - t;
38072         return k * k * p;
38073
38074 }
38075
38076 function QuadraticBezierP1( t, p ) {
38077
38078         return 2 * ( 1 - t ) * t * p;
38079
38080 }
38081
38082 function QuadraticBezierP2( t, p ) {
38083
38084         return t * t * p;
38085
38086 }
38087
38088 function QuadraticBezier( t, p0, p1, p2 ) {
38089
38090         return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
38091                 QuadraticBezierP2( t, p2 );
38092
38093 }
38094
38095 //
38096
38097 function CubicBezierP0( t, p ) {
38098
38099         const k = 1 - t;
38100         return k * k * k * p;
38101
38102 }
38103
38104 function CubicBezierP1( t, p ) {
38105
38106         const k = 1 - t;
38107         return 3 * k * k * t * p;
38108
38109 }
38110
38111 function CubicBezierP2( t, p ) {
38112
38113         return 3 * ( 1 - t ) * t * t * p;
38114
38115 }
38116
38117 function CubicBezierP3( t, p ) {
38118
38119         return t * t * t * p;
38120
38121 }
38122
38123 function CubicBezier( t, p0, p1, p2, p3 ) {
38124
38125         return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
38126                 CubicBezierP3( t, p3 );
38127
38128 }
38129
38130 function CubicBezierCurve( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
38131
38132         Curve.call( this );
38133
38134         this.type = 'CubicBezierCurve';
38135
38136         this.v0 = v0;
38137         this.v1 = v1;
38138         this.v2 = v2;
38139         this.v3 = v3;
38140
38141 }
38142
38143 CubicBezierCurve.prototype = Object.create( Curve.prototype );
38144 CubicBezierCurve.prototype.constructor = CubicBezierCurve;
38145
38146 CubicBezierCurve.prototype.isCubicBezierCurve = true;
38147
38148 CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
38149
38150         const point = optionalTarget;
38151
38152         const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
38153
38154         point.set(
38155                 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
38156                 CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
38157         );
38158
38159         return point;
38160
38161 };
38162
38163 CubicBezierCurve.prototype.copy = function ( source ) {
38164
38165         Curve.prototype.copy.call( this, source );
38166
38167         this.v0.copy( source.v0 );
38168         this.v1.copy( source.v1 );
38169         this.v2.copy( source.v2 );
38170         this.v3.copy( source.v3 );
38171
38172         return this;
38173
38174 };
38175
38176 CubicBezierCurve.prototype.toJSON = function () {
38177
38178         const data = Curve.prototype.toJSON.call( this );
38179
38180         data.v0 = this.v0.toArray();
38181         data.v1 = this.v1.toArray();
38182         data.v2 = this.v2.toArray();
38183         data.v3 = this.v3.toArray();
38184
38185         return data;
38186
38187 };
38188
38189 CubicBezierCurve.prototype.fromJSON = function ( json ) {
38190
38191         Curve.prototype.fromJSON.call( this, json );
38192
38193         this.v0.fromArray( json.v0 );
38194         this.v1.fromArray( json.v1 );
38195         this.v2.fromArray( json.v2 );
38196         this.v3.fromArray( json.v3 );
38197
38198         return this;
38199
38200 };
38201
38202 function CubicBezierCurve3( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
38203
38204         Curve.call( this );
38205
38206         this.type = 'CubicBezierCurve3';
38207
38208         this.v0 = v0;
38209         this.v1 = v1;
38210         this.v2 = v2;
38211         this.v3 = v3;
38212
38213 }
38214
38215 CubicBezierCurve3.prototype = Object.create( Curve.prototype );
38216 CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
38217
38218 CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
38219
38220 CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
38221
38222         const point = optionalTarget;
38223
38224         const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
38225
38226         point.set(
38227                 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
38228                 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
38229                 CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
38230         );
38231
38232         return point;
38233
38234 };
38235
38236 CubicBezierCurve3.prototype.copy = function ( source ) {
38237
38238         Curve.prototype.copy.call( this, source );
38239
38240         this.v0.copy( source.v0 );
38241         this.v1.copy( source.v1 );
38242         this.v2.copy( source.v2 );
38243         this.v3.copy( source.v3 );
38244
38245         return this;
38246
38247 };
38248
38249 CubicBezierCurve3.prototype.toJSON = function () {
38250
38251         const data = Curve.prototype.toJSON.call( this );
38252
38253         data.v0 = this.v0.toArray();
38254         data.v1 = this.v1.toArray();
38255         data.v2 = this.v2.toArray();
38256         data.v3 = this.v3.toArray();
38257
38258         return data;
38259
38260 };
38261
38262 CubicBezierCurve3.prototype.fromJSON = function ( json ) {
38263
38264         Curve.prototype.fromJSON.call( this, json );
38265
38266         this.v0.fromArray( json.v0 );
38267         this.v1.fromArray( json.v1 );
38268         this.v2.fromArray( json.v2 );
38269         this.v3.fromArray( json.v3 );
38270
38271         return this;
38272
38273 };
38274
38275 function LineCurve( v1 = new Vector2(), v2 = new Vector2() ) {
38276
38277         Curve.call( this );
38278
38279         this.type = 'LineCurve';
38280
38281         this.v1 = v1;
38282         this.v2 = v2;
38283
38284 }
38285
38286 LineCurve.prototype = Object.create( Curve.prototype );
38287 LineCurve.prototype.constructor = LineCurve;
38288
38289 LineCurve.prototype.isLineCurve = true;
38290
38291 LineCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
38292
38293         const point = optionalTarget;
38294
38295         if ( t === 1 ) {
38296
38297                 point.copy( this.v2 );
38298
38299         } else {
38300
38301                 point.copy( this.v2 ).sub( this.v1 );
38302                 point.multiplyScalar( t ).add( this.v1 );
38303
38304         }
38305
38306         return point;
38307
38308 };
38309
38310 // Line curve is linear, so we can overwrite default getPointAt
38311
38312 LineCurve.prototype.getPointAt = function ( u, optionalTarget ) {
38313
38314         return this.getPoint( u, optionalTarget );
38315
38316 };
38317
38318 LineCurve.prototype.getTangent = function ( t, optionalTarget ) {
38319
38320         const tangent = optionalTarget || new Vector2();
38321
38322         tangent.copy( this.v2 ).sub( this.v1 ).normalize();
38323
38324         return tangent;
38325
38326 };
38327
38328 LineCurve.prototype.copy = function ( source ) {
38329
38330         Curve.prototype.copy.call( this, source );
38331
38332         this.v1.copy( source.v1 );
38333         this.v2.copy( source.v2 );
38334
38335         return this;
38336
38337 };
38338
38339 LineCurve.prototype.toJSON = function () {
38340
38341         const data = Curve.prototype.toJSON.call( this );
38342
38343         data.v1 = this.v1.toArray();
38344         data.v2 = this.v2.toArray();
38345
38346         return data;
38347
38348 };
38349
38350 LineCurve.prototype.fromJSON = function ( json ) {
38351
38352         Curve.prototype.fromJSON.call( this, json );
38353
38354         this.v1.fromArray( json.v1 );
38355         this.v2.fromArray( json.v2 );
38356
38357         return this;
38358
38359 };
38360
38361 function LineCurve3( v1 = new Vector3(), v2 = new Vector3() ) {
38362
38363         Curve.call( this );
38364
38365         this.type = 'LineCurve3';
38366
38367         this.v1 = v1;
38368         this.v2 = v2;
38369
38370 }
38371
38372 LineCurve3.prototype = Object.create( Curve.prototype );
38373 LineCurve3.prototype.constructor = LineCurve3;
38374
38375 LineCurve3.prototype.isLineCurve3 = true;
38376
38377 LineCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
38378
38379         const point = optionalTarget;
38380
38381         if ( t === 1 ) {
38382
38383                 point.copy( this.v2 );
38384
38385         } else {
38386
38387                 point.copy( this.v2 ).sub( this.v1 );
38388                 point.multiplyScalar( t ).add( this.v1 );
38389
38390         }
38391
38392         return point;
38393
38394 };
38395
38396 // Line curve is linear, so we can overwrite default getPointAt
38397
38398 LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {
38399
38400         return this.getPoint( u, optionalTarget );
38401
38402 };
38403
38404 LineCurve3.prototype.copy = function ( source ) {
38405
38406         Curve.prototype.copy.call( this, source );
38407
38408         this.v1.copy( source.v1 );
38409         this.v2.copy( source.v2 );
38410
38411         return this;
38412
38413 };
38414
38415 LineCurve3.prototype.toJSON = function () {
38416
38417         const data = Curve.prototype.toJSON.call( this );
38418
38419         data.v1 = this.v1.toArray();
38420         data.v2 = this.v2.toArray();
38421
38422         return data;
38423
38424 };
38425
38426 LineCurve3.prototype.fromJSON = function ( json ) {
38427
38428         Curve.prototype.fromJSON.call( this, json );
38429
38430         this.v1.fromArray( json.v1 );
38431         this.v2.fromArray( json.v2 );
38432
38433         return this;
38434
38435 };
38436
38437 function QuadraticBezierCurve( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
38438
38439         Curve.call( this );
38440
38441         this.type = 'QuadraticBezierCurve';
38442
38443         this.v0 = v0;
38444         this.v1 = v1;
38445         this.v2 = v2;
38446
38447 }
38448
38449 QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
38450 QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
38451
38452 QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
38453
38454 QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
38455
38456         const point = optionalTarget;
38457
38458         const v0 = this.v0, v1 = this.v1, v2 = this.v2;
38459
38460         point.set(
38461                 QuadraticBezier( t, v0.x, v1.x, v2.x ),
38462                 QuadraticBezier( t, v0.y, v1.y, v2.y )
38463         );
38464
38465         return point;
38466
38467 };
38468
38469 QuadraticBezierCurve.prototype.copy = function ( source ) {
38470
38471         Curve.prototype.copy.call( this, source );
38472
38473         this.v0.copy( source.v0 );
38474         this.v1.copy( source.v1 );
38475         this.v2.copy( source.v2 );
38476
38477         return this;
38478
38479 };
38480
38481 QuadraticBezierCurve.prototype.toJSON = function () {
38482
38483         const data = Curve.prototype.toJSON.call( this );
38484
38485         data.v0 = this.v0.toArray();
38486         data.v1 = this.v1.toArray();
38487         data.v2 = this.v2.toArray();
38488
38489         return data;
38490
38491 };
38492
38493 QuadraticBezierCurve.prototype.fromJSON = function ( json ) {
38494
38495         Curve.prototype.fromJSON.call( this, json );
38496
38497         this.v0.fromArray( json.v0 );
38498         this.v1.fromArray( json.v1 );
38499         this.v2.fromArray( json.v2 );
38500
38501         return this;
38502
38503 };
38504
38505 function QuadraticBezierCurve3( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
38506
38507         Curve.call( this );
38508
38509         this.type = 'QuadraticBezierCurve3';
38510
38511         this.v0 = v0;
38512         this.v1 = v1;
38513         this.v2 = v2;
38514
38515 }
38516
38517 QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
38518 QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
38519
38520 QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
38521
38522 QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget = new Vector3() ) {
38523
38524         const point = optionalTarget;
38525
38526         const v0 = this.v0, v1 = this.v1, v2 = this.v2;
38527
38528         point.set(
38529                 QuadraticBezier( t, v0.x, v1.x, v2.x ),
38530                 QuadraticBezier( t, v0.y, v1.y, v2.y ),
38531                 QuadraticBezier( t, v0.z, v1.z, v2.z )
38532         );
38533
38534         return point;
38535
38536 };
38537
38538 QuadraticBezierCurve3.prototype.copy = function ( source ) {
38539
38540         Curve.prototype.copy.call( this, source );
38541
38542         this.v0.copy( source.v0 );
38543         this.v1.copy( source.v1 );
38544         this.v2.copy( source.v2 );
38545
38546         return this;
38547
38548 };
38549
38550 QuadraticBezierCurve3.prototype.toJSON = function () {
38551
38552         const data = Curve.prototype.toJSON.call( this );
38553
38554         data.v0 = this.v0.toArray();
38555         data.v1 = this.v1.toArray();
38556         data.v2 = this.v2.toArray();
38557
38558         return data;
38559
38560 };
38561
38562 QuadraticBezierCurve3.prototype.fromJSON = function ( json ) {
38563
38564         Curve.prototype.fromJSON.call( this, json );
38565
38566         this.v0.fromArray( json.v0 );
38567         this.v1.fromArray( json.v1 );
38568         this.v2.fromArray( json.v2 );
38569
38570         return this;
38571
38572 };
38573
38574 function SplineCurve( points = [] ) {
38575
38576         Curve.call( this );
38577
38578         this.type = 'SplineCurve';
38579
38580         this.points = points;
38581
38582 }
38583
38584 SplineCurve.prototype = Object.create( Curve.prototype );
38585 SplineCurve.prototype.constructor = SplineCurve;
38586
38587 SplineCurve.prototype.isSplineCurve = true;
38588
38589 SplineCurve.prototype.getPoint = function ( t, optionalTarget = new Vector2() ) {
38590
38591         const point = optionalTarget;
38592
38593         const points = this.points;
38594         const p = ( points.length - 1 ) * t;
38595
38596         const intPoint = Math.floor( p );
38597         const weight = p - intPoint;
38598
38599         const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
38600         const p1 = points[ intPoint ];
38601         const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
38602         const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
38603
38604         point.set(
38605                 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
38606                 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
38607         );
38608
38609         return point;
38610
38611 };
38612
38613 SplineCurve.prototype.copy = function ( source ) {
38614
38615         Curve.prototype.copy.call( this, source );
38616
38617         this.points = [];
38618
38619         for ( let i = 0, l = source.points.length; i < l; i ++ ) {
38620
38621                 const point = source.points[ i ];
38622
38623                 this.points.push( point.clone() );
38624
38625         }
38626
38627         return this;
38628
38629 };
38630
38631 SplineCurve.prototype.toJSON = function () {
38632
38633         const data = Curve.prototype.toJSON.call( this );
38634
38635         data.points = [];
38636
38637         for ( let i = 0, l = this.points.length; i < l; i ++ ) {
38638
38639                 const point = this.points[ i ];
38640                 data.points.push( point.toArray() );
38641
38642         }
38643
38644         return data;
38645
38646 };
38647
38648 SplineCurve.prototype.fromJSON = function ( json ) {
38649
38650         Curve.prototype.fromJSON.call( this, json );
38651
38652         this.points = [];
38653
38654         for ( let i = 0, l = json.points.length; i < l; i ++ ) {
38655
38656                 const point = json.points[ i ];
38657                 this.points.push( new Vector2().fromArray( point ) );
38658
38659         }
38660
38661         return this;
38662
38663 };
38664
38665 var Curves = /*#__PURE__*/Object.freeze({
38666         __proto__: null,
38667         ArcCurve: ArcCurve,
38668         CatmullRomCurve3: CatmullRomCurve3,
38669         CubicBezierCurve: CubicBezierCurve,
38670         CubicBezierCurve3: CubicBezierCurve3,
38671         EllipseCurve: EllipseCurve,
38672         LineCurve: LineCurve,
38673         LineCurve3: LineCurve3,
38674         QuadraticBezierCurve: QuadraticBezierCurve,
38675         QuadraticBezierCurve3: QuadraticBezierCurve3,
38676         SplineCurve: SplineCurve
38677 });
38678
38679 /**************************************************************
38680  *      Curved Path - a curve path is simply a array of connected
38681  *  curves, but retains the api of a curve
38682  **************************************************************/
38683
38684 function CurvePath() {
38685
38686         Curve.call( this );
38687
38688         this.type = 'CurvePath';
38689
38690         this.curves = [];
38691         this.autoClose = false; // Automatically closes the path
38692
38693 }
38694
38695 CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
38696
38697         constructor: CurvePath,
38698
38699         add: function ( curve ) {
38700
38701                 this.curves.push( curve );
38702
38703         },
38704
38705         closePath: function () {
38706
38707                 // Add a line curve if start and end of lines are not connected
38708                 const startPoint = this.curves[ 0 ].getPoint( 0 );
38709                 const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
38710
38711                 if ( ! startPoint.equals( endPoint ) ) {
38712
38713                         this.curves.push( new LineCurve( endPoint, startPoint ) );
38714
38715                 }
38716
38717         },
38718
38719         // To get accurate point with reference to
38720         // entire path distance at time t,
38721         // following has to be done:
38722
38723         // 1. Length of each sub path have to be known
38724         // 2. Locate and identify type of curve
38725         // 3. Get t for the curve
38726         // 4. Return curve.getPointAt(t')
38727
38728         getPoint: function ( t ) {
38729
38730                 const d = t * this.getLength();
38731                 const curveLengths = this.getCurveLengths();
38732                 let i = 0;
38733
38734                 // To think about boundaries points.
38735
38736                 while ( i < curveLengths.length ) {
38737
38738                         if ( curveLengths[ i ] >= d ) {
38739
38740                                 const diff = curveLengths[ i ] - d;
38741                                 const curve = this.curves[ i ];
38742
38743                                 const segmentLength = curve.getLength();
38744                                 const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
38745
38746                                 return curve.getPointAt( u );
38747
38748                         }
38749
38750                         i ++;
38751
38752                 }
38753
38754                 return null;
38755
38756                 // loop where sum != 0, sum > d , sum+1 <d
38757
38758         },
38759
38760         // We cannot use the default THREE.Curve getPoint() with getLength() because in
38761         // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
38762         // getPoint() depends on getLength
38763
38764         getLength: function () {
38765
38766                 const lens = this.getCurveLengths();
38767                 return lens[ lens.length - 1 ];
38768
38769         },
38770
38771         // cacheLengths must be recalculated.
38772         updateArcLengths: function () {
38773
38774                 this.needsUpdate = true;
38775                 this.cacheLengths = null;
38776                 this.getCurveLengths();
38777
38778         },
38779
38780         // Compute lengths and cache them
38781         // We cannot overwrite getLengths() because UtoT mapping uses it.
38782
38783         getCurveLengths: function () {
38784
38785                 // We use cache values if curves and cache array are same length
38786
38787                 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
38788
38789                         return this.cacheLengths;
38790
38791                 }
38792
38793                 // Get length of sub-curve
38794                 // Push sums into cached array
38795
38796                 const lengths = [];
38797                 let sums = 0;
38798
38799                 for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
38800
38801                         sums += this.curves[ i ].getLength();
38802                         lengths.push( sums );
38803
38804                 }
38805
38806                 this.cacheLengths = lengths;
38807
38808                 return lengths;
38809
38810         },
38811
38812         getSpacedPoints: function ( divisions = 40 ) {
38813
38814                 const points = [];
38815
38816                 for ( let i = 0; i <= divisions; i ++ ) {
38817
38818                         points.push( this.getPoint( i / divisions ) );
38819
38820                 }
38821
38822                 if ( this.autoClose ) {
38823
38824                         points.push( points[ 0 ] );
38825
38826                 }
38827
38828                 return points;
38829
38830         },
38831
38832         getPoints: function ( divisions = 12 ) {
38833
38834                 const points = [];
38835                 let last;
38836
38837                 for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
38838
38839                         const curve = curves[ i ];
38840                         const resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
38841                                 : ( curve && ( curve.isLineCurve || curve.isLineCurve3 ) ) ? 1
38842                                         : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
38843                                                 : divisions;
38844
38845                         const pts = curve.getPoints( resolution );
38846
38847                         for ( let j = 0; j < pts.length; j ++ ) {
38848
38849                                 const point = pts[ j ];
38850
38851                                 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
38852
38853                                 points.push( point );
38854                                 last = point;
38855
38856                         }
38857
38858                 }
38859
38860                 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
38861
38862                         points.push( points[ 0 ] );
38863
38864                 }
38865
38866                 return points;
38867
38868         },
38869
38870         copy: function ( source ) {
38871
38872                 Curve.prototype.copy.call( this, source );
38873
38874                 this.curves = [];
38875
38876                 for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
38877
38878                         const curve = source.curves[ i ];
38879
38880                         this.curves.push( curve.clone() );
38881
38882                 }
38883
38884                 this.autoClose = source.autoClose;
38885
38886                 return this;
38887
38888         },
38889
38890         toJSON: function () {
38891
38892                 const data = Curve.prototype.toJSON.call( this );
38893
38894                 data.autoClose = this.autoClose;
38895                 data.curves = [];
38896
38897                 for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
38898
38899                         const curve = this.curves[ i ];
38900                         data.curves.push( curve.toJSON() );
38901
38902                 }
38903
38904                 return data;
38905
38906         },
38907
38908         fromJSON: function ( json ) {
38909
38910                 Curve.prototype.fromJSON.call( this, json );
38911
38912                 this.autoClose = json.autoClose;
38913                 this.curves = [];
38914
38915                 for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
38916
38917                         const curve = json.curves[ i ];
38918                         this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
38919
38920                 }
38921
38922                 return this;
38923
38924         }
38925
38926 } );
38927
38928 function Path( points ) {
38929
38930         CurvePath.call( this );
38931
38932         this.type = 'Path';
38933
38934         this.currentPoint = new Vector2();
38935
38936         if ( points ) {
38937
38938                 this.setFromPoints( points );
38939
38940         }
38941
38942 }
38943
38944 Path.prototype = Object.assign( Object.create( CurvePath.prototype ), {
38945
38946         constructor: Path,
38947
38948         setFromPoints: function ( points ) {
38949
38950                 this.moveTo( points[ 0 ].x, points[ 0 ].y );
38951
38952                 for ( let i = 1, l = points.length; i < l; i ++ ) {
38953
38954                         this.lineTo( points[ i ].x, points[ i ].y );
38955
38956                 }
38957
38958                 return this;
38959
38960         },
38961
38962         moveTo: function ( x, y ) {
38963
38964                 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
38965
38966                 return this;
38967
38968         },
38969
38970         lineTo: function ( x, y ) {
38971
38972                 const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
38973                 this.curves.push( curve );
38974
38975                 this.currentPoint.set( x, y );
38976
38977                 return this;
38978
38979         },
38980
38981         quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
38982
38983                 const curve = new QuadraticBezierCurve(
38984                         this.currentPoint.clone(),
38985                         new Vector2( aCPx, aCPy ),
38986                         new Vector2( aX, aY )
38987                 );
38988
38989                 this.curves.push( curve );
38990
38991                 this.currentPoint.set( aX, aY );
38992
38993                 return this;
38994
38995         },
38996
38997         bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
38998
38999                 const curve = new CubicBezierCurve(
39000                         this.currentPoint.clone(),
39001                         new Vector2( aCP1x, aCP1y ),
39002                         new Vector2( aCP2x, aCP2y ),
39003                         new Vector2( aX, aY )
39004                 );
39005
39006                 this.curves.push( curve );
39007
39008                 this.currentPoint.set( aX, aY );
39009
39010                 return this;
39011
39012         },
39013
39014         splineThru: function ( pts /*Array of Vector*/ ) {
39015
39016                 const npts = [ this.currentPoint.clone() ].concat( pts );
39017
39018                 const curve = new SplineCurve( npts );
39019                 this.curves.push( curve );
39020
39021                 this.currentPoint.copy( pts[ pts.length - 1 ] );
39022
39023                 return this;
39024
39025         },
39026
39027         arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
39028
39029                 const x0 = this.currentPoint.x;
39030                 const y0 = this.currentPoint.y;
39031
39032                 this.absarc( aX + x0, aY + y0, aRadius,
39033                         aStartAngle, aEndAngle, aClockwise );
39034
39035                 return this;
39036
39037         },
39038
39039         absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
39040
39041                 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
39042
39043                 return this;
39044
39045         },
39046
39047         ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
39048
39049                 const x0 = this.currentPoint.x;
39050                 const y0 = this.currentPoint.y;
39051
39052                 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
39053
39054                 return this;
39055
39056         },
39057
39058         absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
39059
39060                 const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
39061
39062                 if ( this.curves.length > 0 ) {
39063
39064                         // if a previous curve is present, attempt to join
39065                         const firstPoint = curve.getPoint( 0 );
39066
39067                         if ( ! firstPoint.equals( this.currentPoint ) ) {
39068
39069                                 this.lineTo( firstPoint.x, firstPoint.y );
39070
39071                         }
39072
39073                 }
39074
39075                 this.curves.push( curve );
39076
39077                 const lastPoint = curve.getPoint( 1 );
39078                 this.currentPoint.copy( lastPoint );
39079
39080                 return this;
39081
39082         },
39083
39084         copy: function ( source ) {
39085
39086                 CurvePath.prototype.copy.call( this, source );
39087
39088                 this.currentPoint.copy( source.currentPoint );
39089
39090                 return this;
39091
39092         },
39093
39094         toJSON: function () {
39095
39096                 const data = CurvePath.prototype.toJSON.call( this );
39097
39098                 data.currentPoint = this.currentPoint.toArray();
39099
39100                 return data;
39101
39102         },
39103
39104         fromJSON: function ( json ) {
39105
39106                 CurvePath.prototype.fromJSON.call( this, json );
39107
39108                 this.currentPoint.fromArray( json.currentPoint );
39109
39110                 return this;
39111
39112         }
39113
39114 } );
39115
39116 function Shape( points ) {
39117
39118         Path.call( this, points );
39119
39120         this.uuid = MathUtils.generateUUID();
39121
39122         this.type = 'Shape';
39123
39124         this.holes = [];
39125
39126 }
39127
39128 Shape.prototype = Object.assign( Object.create( Path.prototype ), {
39129
39130         constructor: Shape,
39131
39132         getPointsHoles: function ( divisions ) {
39133
39134                 const holesPts = [];
39135
39136                 for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
39137
39138                         holesPts[ i ] = this.holes[ i ].getPoints( divisions );
39139
39140                 }
39141
39142                 return holesPts;
39143
39144         },
39145
39146         // get points of shape and holes (keypoints based on segments parameter)
39147
39148         extractPoints: function ( divisions ) {
39149
39150                 return {
39151
39152                         shape: this.getPoints( divisions ),
39153                         holes: this.getPointsHoles( divisions )
39154
39155                 };
39156
39157         },
39158
39159         copy: function ( source ) {
39160
39161                 Path.prototype.copy.call( this, source );
39162
39163                 this.holes = [];
39164
39165                 for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
39166
39167                         const hole = source.holes[ i ];
39168
39169                         this.holes.push( hole.clone() );
39170
39171                 }
39172
39173                 return this;
39174
39175         },
39176
39177         toJSON: function () {
39178
39179                 const data = Path.prototype.toJSON.call( this );
39180
39181                 data.uuid = this.uuid;
39182                 data.holes = [];
39183
39184                 for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
39185
39186                         const hole = this.holes[ i ];
39187                         data.holes.push( hole.toJSON() );
39188
39189                 }
39190
39191                 return data;
39192
39193         },
39194
39195         fromJSON: function ( json ) {
39196
39197                 Path.prototype.fromJSON.call( this, json );
39198
39199                 this.uuid = json.uuid;
39200                 this.holes = [];
39201
39202                 for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
39203
39204                         const hole = json.holes[ i ];
39205                         this.holes.push( new Path().fromJSON( hole ) );
39206
39207                 }
39208
39209                 return this;
39210
39211         }
39212
39213 } );
39214
39215 function Light( color, intensity = 1 ) {
39216
39217         Object3D.call( this );
39218
39219         this.type = 'Light';
39220
39221         this.color = new Color( color );
39222         this.intensity = intensity;
39223
39224 }
39225
39226 Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
39227
39228         constructor: Light,
39229
39230         isLight: true,
39231
39232         copy: function ( source ) {
39233
39234                 Object3D.prototype.copy.call( this, source );
39235
39236                 this.color.copy( source.color );
39237                 this.intensity = source.intensity;
39238
39239                 return this;
39240
39241         },
39242
39243         toJSON: function ( meta ) {
39244
39245                 const data = Object3D.prototype.toJSON.call( this, meta );
39246
39247                 data.object.color = this.color.getHex();
39248                 data.object.intensity = this.intensity;
39249
39250                 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
39251
39252                 if ( this.distance !== undefined ) data.object.distance = this.distance;
39253                 if ( this.angle !== undefined ) data.object.angle = this.angle;
39254                 if ( this.decay !== undefined ) data.object.decay = this.decay;
39255                 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
39256
39257                 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
39258
39259                 return data;
39260
39261         }
39262
39263 } );
39264
39265 function HemisphereLight( skyColor, groundColor, intensity ) {
39266
39267         Light.call( this, skyColor, intensity );
39268
39269         this.type = 'HemisphereLight';
39270
39271         this.position.copy( Object3D.DefaultUp );
39272         this.updateMatrix();
39273
39274         this.groundColor = new Color( groundColor );
39275
39276 }
39277
39278 HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
39279
39280         constructor: HemisphereLight,
39281
39282         isHemisphereLight: true,
39283
39284         copy: function ( source ) {
39285
39286                 Light.prototype.copy.call( this, source );
39287
39288                 this.groundColor.copy( source.groundColor );
39289
39290                 return this;
39291
39292         }
39293
39294 } );
39295
39296 function LightShadow( camera ) {
39297
39298         this.camera = camera;
39299
39300         this.bias = 0;
39301         this.normalBias = 0;
39302         this.radius = 1;
39303
39304         this.mapSize = new Vector2( 512, 512 );
39305
39306         this.map = null;
39307         this.mapPass = null;
39308         this.matrix = new Matrix4();
39309
39310         this.autoUpdate = true;
39311         this.needsUpdate = false;
39312
39313         this._frustum = new Frustum();
39314         this._frameExtents = new Vector2( 1, 1 );
39315
39316         this._viewportCount = 1;
39317
39318         this._viewports = [
39319
39320                 new Vector4( 0, 0, 1, 1 )
39321
39322         ];
39323
39324 }
39325
39326 Object.assign( LightShadow.prototype, {
39327
39328         _projScreenMatrix: new Matrix4(),
39329
39330         _lightPositionWorld: new Vector3(),
39331
39332         _lookTarget: new Vector3(),
39333
39334         getViewportCount: function () {
39335
39336                 return this._viewportCount;
39337
39338         },
39339
39340         getFrustum: function () {
39341
39342                 return this._frustum;
39343
39344         },
39345
39346         updateMatrices: function ( light ) {
39347
39348                 const shadowCamera = this.camera,
39349                         shadowMatrix = this.matrix,
39350                         projScreenMatrix = this._projScreenMatrix,
39351                         lookTarget = this._lookTarget,
39352                         lightPositionWorld = this._lightPositionWorld;
39353
39354                 lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
39355                 shadowCamera.position.copy( lightPositionWorld );
39356
39357                 lookTarget.setFromMatrixPosition( light.target.matrixWorld );
39358                 shadowCamera.lookAt( lookTarget );
39359                 shadowCamera.updateMatrixWorld();
39360
39361                 projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
39362                 this._frustum.setFromProjectionMatrix( projScreenMatrix );
39363
39364                 shadowMatrix.set(
39365                         0.5, 0.0, 0.0, 0.5,
39366                         0.0, 0.5, 0.0, 0.5,
39367                         0.0, 0.0, 0.5, 0.5,
39368                         0.0, 0.0, 0.0, 1.0
39369                 );
39370
39371                 shadowMatrix.multiply( shadowCamera.projectionMatrix );
39372                 shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
39373
39374         },
39375
39376         getViewport: function ( viewportIndex ) {
39377
39378                 return this._viewports[ viewportIndex ];
39379
39380         },
39381
39382         getFrameExtents: function () {
39383
39384                 return this._frameExtents;
39385
39386         },
39387
39388         copy: function ( source ) {
39389
39390                 this.camera = source.camera.clone();
39391
39392                 this.bias = source.bias;
39393                 this.radius = source.radius;
39394
39395                 this.mapSize.copy( source.mapSize );
39396
39397                 return this;
39398
39399         },
39400
39401         clone: function () {
39402
39403                 return new this.constructor().copy( this );
39404
39405         },
39406
39407         toJSON: function () {
39408
39409                 const object = {};
39410
39411                 if ( this.bias !== 0 ) object.bias = this.bias;
39412                 if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
39413                 if ( this.radius !== 1 ) object.radius = this.radius;
39414                 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
39415
39416                 object.camera = this.camera.toJSON( false ).object;
39417                 delete object.camera.matrix;
39418
39419                 return object;
39420
39421         }
39422
39423 } );
39424
39425 function SpotLightShadow() {
39426
39427         LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
39428
39429         this.focus = 1;
39430
39431 }
39432
39433 SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
39434
39435         constructor: SpotLightShadow,
39436
39437         isSpotLightShadow: true,
39438
39439         updateMatrices: function ( light ) {
39440
39441                 const camera = this.camera;
39442
39443                 const fov = MathUtils.RAD2DEG * 2 * light.angle * this.focus;
39444                 const aspect = this.mapSize.width / this.mapSize.height;
39445                 const far = light.distance || camera.far;
39446
39447                 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
39448
39449                         camera.fov = fov;
39450                         camera.aspect = aspect;
39451                         camera.far = far;
39452                         camera.updateProjectionMatrix();
39453
39454                 }
39455
39456                 LightShadow.prototype.updateMatrices.call( this, light );
39457
39458         }
39459
39460 } );
39461
39462 function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
39463
39464         Light.call( this, color, intensity );
39465
39466         this.type = 'SpotLight';
39467
39468         this.position.copy( Object3D.DefaultUp );
39469         this.updateMatrix();
39470
39471         this.target = new Object3D();
39472
39473         Object.defineProperty( this, 'power', {
39474                 get: function () {
39475
39476                         // intensity = power per solid angle.
39477                         // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39478                         return this.intensity * Math.PI;
39479
39480                 },
39481                 set: function ( power ) {
39482
39483                         // intensity = power per solid angle.
39484                         // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39485                         this.intensity = power / Math.PI;
39486
39487                 }
39488         } );
39489
39490         this.distance = ( distance !== undefined ) ? distance : 0;
39491         this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
39492         this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
39493         this.decay = ( decay !== undefined ) ? decay : 1;       // for physically correct lights, should be 2.
39494
39495         this.shadow = new SpotLightShadow();
39496
39497 }
39498
39499 SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
39500
39501         constructor: SpotLight,
39502
39503         isSpotLight: true,
39504
39505         copy: function ( source ) {
39506
39507                 Light.prototype.copy.call( this, source );
39508
39509                 this.distance = source.distance;
39510                 this.angle = source.angle;
39511                 this.penumbra = source.penumbra;
39512                 this.decay = source.decay;
39513
39514                 this.target = source.target.clone();
39515
39516                 this.shadow = source.shadow.clone();
39517
39518                 return this;
39519
39520         }
39521
39522 } );
39523
39524 function PointLightShadow() {
39525
39526         LightShadow.call( this, new PerspectiveCamera( 90, 1, 0.5, 500 ) );
39527
39528         this._frameExtents = new Vector2( 4, 2 );
39529
39530         this._viewportCount = 6;
39531
39532         this._viewports = [
39533                 // These viewports map a cube-map onto a 2D texture with the
39534                 // following orientation:
39535                 //
39536                 //  xzXZ
39537                 //   y Y
39538                 //
39539                 // X - Positive x direction
39540                 // x - Negative x direction
39541                 // Y - Positive y direction
39542                 // y - Negative y direction
39543                 // Z - Positive z direction
39544                 // z - Negative z direction
39545
39546                 // positive X
39547                 new Vector4( 2, 1, 1, 1 ),
39548                 // negative X
39549                 new Vector4( 0, 1, 1, 1 ),
39550                 // positive Z
39551                 new Vector4( 3, 1, 1, 1 ),
39552                 // negative Z
39553                 new Vector4( 1, 1, 1, 1 ),
39554                 // positive Y
39555                 new Vector4( 3, 0, 1, 1 ),
39556                 // negative Y
39557                 new Vector4( 1, 0, 1, 1 )
39558         ];
39559
39560         this._cubeDirections = [
39561                 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
39562                 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
39563         ];
39564
39565         this._cubeUps = [
39566                 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
39567                 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
39568         ];
39569
39570 }
39571
39572 PointLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
39573
39574         constructor: PointLightShadow,
39575
39576         isPointLightShadow: true,
39577
39578         updateMatrices: function ( light, viewportIndex = 0 ) {
39579
39580                 const camera = this.camera,
39581                         shadowMatrix = this.matrix,
39582                         lightPositionWorld = this._lightPositionWorld,
39583                         lookTarget = this._lookTarget,
39584                         projScreenMatrix = this._projScreenMatrix;
39585
39586                 lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
39587                 camera.position.copy( lightPositionWorld );
39588
39589                 lookTarget.copy( camera.position );
39590                 lookTarget.add( this._cubeDirections[ viewportIndex ] );
39591                 camera.up.copy( this._cubeUps[ viewportIndex ] );
39592                 camera.lookAt( lookTarget );
39593                 camera.updateMatrixWorld();
39594
39595                 shadowMatrix.makeTranslation( - lightPositionWorld.x, - lightPositionWorld.y, - lightPositionWorld.z );
39596
39597                 projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
39598                 this._frustum.setFromProjectionMatrix( projScreenMatrix );
39599
39600         }
39601
39602 } );
39603
39604 function PointLight( color, intensity, distance, decay ) {
39605
39606         Light.call( this, color, intensity );
39607
39608         this.type = 'PointLight';
39609
39610         Object.defineProperty( this, 'power', {
39611                 get: function () {
39612
39613                         // intensity = power per solid angle.
39614                         // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39615                         return this.intensity * 4 * Math.PI;
39616
39617                 },
39618                 set: function ( power ) {
39619
39620                         // intensity = power per solid angle.
39621                         // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39622                         this.intensity = power / ( 4 * Math.PI );
39623
39624                 }
39625         } );
39626
39627         this.distance = ( distance !== undefined ) ? distance : 0;
39628         this.decay = ( decay !== undefined ) ? decay : 1;       // for physically correct lights, should be 2.
39629
39630         this.shadow = new PointLightShadow();
39631
39632 }
39633
39634 PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
39635
39636         constructor: PointLight,
39637
39638         isPointLight: true,
39639
39640         copy: function ( source ) {
39641
39642                 Light.prototype.copy.call( this, source );
39643
39644                 this.distance = source.distance;
39645                 this.decay = source.decay;
39646
39647                 this.shadow = source.shadow.clone();
39648
39649                 return this;
39650
39651         }
39652
39653 } );
39654
39655 function OrthographicCamera( left, right, top, bottom, near, far ) {
39656
39657         Camera.call( this );
39658
39659         this.type = 'OrthographicCamera';
39660
39661         this.zoom = 1;
39662         this.view = null;
39663
39664         this.left = ( left !== undefined ) ? left : - 1;
39665         this.right = ( right !== undefined ) ? right : 1;
39666         this.top = ( top !== undefined ) ? top : 1;
39667         this.bottom = ( bottom !== undefined ) ? bottom : - 1;
39668
39669         this.near = ( near !== undefined ) ? near : 0.1;
39670         this.far = ( far !== undefined ) ? far : 2000;
39671
39672         this.updateProjectionMatrix();
39673
39674 }
39675
39676 OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
39677
39678         constructor: OrthographicCamera,
39679
39680         isOrthographicCamera: true,
39681
39682         copy: function ( source, recursive ) {
39683
39684                 Camera.prototype.copy.call( this, source, recursive );
39685
39686                 this.left = source.left;
39687                 this.right = source.right;
39688                 this.top = source.top;
39689                 this.bottom = source.bottom;
39690                 this.near = source.near;
39691                 this.far = source.far;
39692
39693                 this.zoom = source.zoom;
39694                 this.view = source.view === null ? null : Object.assign( {}, source.view );
39695
39696                 return this;
39697
39698         },
39699
39700         setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
39701
39702                 if ( this.view === null ) {
39703
39704                         this.view = {
39705                                 enabled: true,
39706                                 fullWidth: 1,
39707                                 fullHeight: 1,
39708                                 offsetX: 0,
39709                                 offsetY: 0,
39710                                 width: 1,
39711                                 height: 1
39712                         };
39713
39714                 }
39715
39716                 this.view.enabled = true;
39717                 this.view.fullWidth = fullWidth;
39718                 this.view.fullHeight = fullHeight;
39719                 this.view.offsetX = x;
39720                 this.view.offsetY = y;
39721                 this.view.width = width;
39722                 this.view.height = height;
39723
39724                 this.updateProjectionMatrix();
39725
39726         },
39727
39728         clearViewOffset: function () {
39729
39730                 if ( this.view !== null ) {
39731
39732                         this.view.enabled = false;
39733
39734                 }
39735
39736                 this.updateProjectionMatrix();
39737
39738         },
39739
39740         updateProjectionMatrix: function () {
39741
39742                 const dx = ( this.right - this.left ) / ( 2 * this.zoom );
39743                 const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
39744                 const cx = ( this.right + this.left ) / 2;
39745                 const cy = ( this.top + this.bottom ) / 2;
39746
39747                 let left = cx - dx;
39748                 let right = cx + dx;
39749                 let top = cy + dy;
39750                 let bottom = cy - dy;
39751
39752                 if ( this.view !== null && this.view.enabled ) {
39753
39754                         const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
39755                         const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
39756
39757                         left += scaleW * this.view.offsetX;
39758                         right = left + scaleW * this.view.width;
39759                         top -= scaleH * this.view.offsetY;
39760                         bottom = top - scaleH * this.view.height;
39761
39762                 }
39763
39764                 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
39765
39766                 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
39767
39768         },
39769
39770         toJSON: function ( meta ) {
39771
39772                 const data = Object3D.prototype.toJSON.call( this, meta );
39773
39774                 data.object.zoom = this.zoom;
39775                 data.object.left = this.left;
39776                 data.object.right = this.right;
39777                 data.object.top = this.top;
39778                 data.object.bottom = this.bottom;
39779                 data.object.near = this.near;
39780                 data.object.far = this.far;
39781
39782                 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
39783
39784                 return data;
39785
39786         }
39787
39788 } );
39789
39790 function DirectionalLightShadow() {
39791
39792         LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
39793
39794 }
39795
39796 DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
39797
39798         constructor: DirectionalLightShadow,
39799
39800         isDirectionalLightShadow: true,
39801
39802         updateMatrices: function ( light ) {
39803
39804                 LightShadow.prototype.updateMatrices.call( this, light );
39805
39806         }
39807
39808 } );
39809
39810 function DirectionalLight( color, intensity ) {
39811
39812         Light.call( this, color, intensity );
39813
39814         this.type = 'DirectionalLight';
39815
39816         this.position.copy( Object3D.DefaultUp );
39817         this.updateMatrix();
39818
39819         this.target = new Object3D();
39820
39821         this.shadow = new DirectionalLightShadow();
39822
39823 }
39824
39825 DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
39826
39827         constructor: DirectionalLight,
39828
39829         isDirectionalLight: true,
39830
39831         copy: function ( source ) {
39832
39833                 Light.prototype.copy.call( this, source );
39834
39835                 this.target = source.target.clone();
39836
39837                 this.shadow = source.shadow.clone();
39838
39839                 return this;
39840
39841         }
39842
39843 } );
39844
39845 function AmbientLight( color, intensity ) {
39846
39847         Light.call( this, color, intensity );
39848
39849         this.type = 'AmbientLight';
39850
39851 }
39852
39853 AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
39854
39855         constructor: AmbientLight,
39856
39857         isAmbientLight: true
39858
39859 } );
39860
39861 function RectAreaLight( color, intensity, width, height ) {
39862
39863         Light.call( this, color, intensity );
39864
39865         this.type = 'RectAreaLight';
39866
39867         this.width = ( width !== undefined ) ? width : 10;
39868         this.height = ( height !== undefined ) ? height : 10;
39869
39870 }
39871
39872 RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
39873
39874         constructor: RectAreaLight,
39875
39876         isRectAreaLight: true,
39877
39878         copy: function ( source ) {
39879
39880                 Light.prototype.copy.call( this, source );
39881
39882                 this.width = source.width;
39883                 this.height = source.height;
39884
39885                 return this;
39886
39887         },
39888
39889         toJSON: function ( meta ) {
39890
39891                 const data = Light.prototype.toJSON.call( this, meta );
39892
39893                 data.object.width = this.width;
39894                 data.object.height = this.height;
39895
39896                 return data;
39897
39898         }
39899
39900 } );
39901
39902 /**
39903  * Primary reference:
39904  *   https://graphics.stanford.edu/papers/envmap/envmap.pdf
39905  *
39906  * Secondary reference:
39907  *   https://www.ppsloan.org/publications/StupidSH36.pdf
39908  */
39909
39910 // 3-band SH defined by 9 coefficients
39911
39912 class SphericalHarmonics3 {
39913
39914         constructor() {
39915
39916                 Object.defineProperty( this, 'isSphericalHarmonics3', { value: true } );
39917
39918                 this.coefficients = [];
39919
39920                 for ( let i = 0; i < 9; i ++ ) {
39921
39922                         this.coefficients.push( new Vector3() );
39923
39924                 }
39925
39926         }
39927
39928         set( coefficients ) {
39929
39930                 for ( let i = 0; i < 9; i ++ ) {
39931
39932                         this.coefficients[ i ].copy( coefficients[ i ] );
39933
39934                 }
39935
39936                 return this;
39937
39938         }
39939
39940         zero() {
39941
39942                 for ( let i = 0; i < 9; i ++ ) {
39943
39944                         this.coefficients[ i ].set( 0, 0, 0 );
39945
39946                 }
39947
39948                 return this;
39949
39950         }
39951
39952         // get the radiance in the direction of the normal
39953         // target is a Vector3
39954         getAt( normal, target ) {
39955
39956                 // normal is assumed to be unit length
39957
39958                 const x = normal.x, y = normal.y, z = normal.z;
39959
39960                 const coeff = this.coefficients;
39961
39962                 // band 0
39963                 target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
39964
39965                 // band 1
39966                 target.addScaledVector( coeff[ 1 ], 0.488603 * y );
39967                 target.addScaledVector( coeff[ 2 ], 0.488603 * z );
39968                 target.addScaledVector( coeff[ 3 ], 0.488603 * x );
39969
39970                 // band 2
39971                 target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
39972                 target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
39973                 target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
39974                 target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
39975                 target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
39976
39977                 return target;
39978
39979         }
39980
39981         // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
39982         // target is a Vector3
39983         // https://graphics.stanford.edu/papers/envmap/envmap.pdf
39984         getIrradianceAt( normal, target ) {
39985
39986                 // normal is assumed to be unit length
39987
39988                 const x = normal.x, y = normal.y, z = normal.z;
39989
39990                 const coeff = this.coefficients;
39991
39992                 // band 0
39993                 target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // Ï€ * 0.282095
39994
39995                 // band 1
39996                 target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * Ï€ / 3 ) * 0.488603
39997                 target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
39998                 target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
39999
40000                 // band 2
40001                 target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( Ï€ / 4 ) * 1.092548
40002                 target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
40003                 target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( Ï€ / 4 ) * 0.315392 * 3
40004                 target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
40005                 target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( Ï€ / 4 ) * 0.546274
40006
40007                 return target;
40008
40009         }
40010
40011         add( sh ) {
40012
40013                 for ( let i = 0; i < 9; i ++ ) {
40014
40015                         this.coefficients[ i ].add( sh.coefficients[ i ] );
40016
40017                 }
40018
40019                 return this;
40020
40021         }
40022
40023         addScaledSH( sh, s ) {
40024
40025                 for ( let i = 0; i < 9; i ++ ) {
40026
40027                         this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
40028
40029                 }
40030
40031                 return this;
40032
40033         }
40034
40035         scale( s ) {
40036
40037                 for ( let i = 0; i < 9; i ++ ) {
40038
40039                         this.coefficients[ i ].multiplyScalar( s );
40040
40041                 }
40042
40043                 return this;
40044
40045         }
40046
40047         lerp( sh, alpha ) {
40048
40049                 for ( let i = 0; i < 9; i ++ ) {
40050
40051                         this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
40052
40053                 }
40054
40055                 return this;
40056
40057         }
40058
40059         equals( sh ) {
40060
40061                 for ( let i = 0; i < 9; i ++ ) {
40062
40063                         if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
40064
40065                                 return false;
40066
40067                         }
40068
40069                 }
40070
40071                 return true;
40072
40073         }
40074
40075         copy( sh ) {
40076
40077                 return this.set( sh.coefficients );
40078
40079         }
40080
40081         clone() {
40082
40083                 return new this.constructor().copy( this );
40084
40085         }
40086
40087         fromArray( array, offset = 0 ) {
40088
40089                 const coefficients = this.coefficients;
40090
40091                 for ( let i = 0; i < 9; i ++ ) {
40092
40093                         coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
40094
40095                 }
40096
40097                 return this;
40098
40099         }
40100
40101         toArray( array = [], offset = 0 ) {
40102
40103                 const coefficients = this.coefficients;
40104
40105                 for ( let i = 0; i < 9; i ++ ) {
40106
40107                         coefficients[ i ].toArray( array, offset + ( i * 3 ) );
40108
40109                 }
40110
40111                 return array;
40112
40113         }
40114
40115         // evaluate the basis functions
40116         // shBasis is an Array[ 9 ]
40117         static getBasisAt( normal, shBasis ) {
40118
40119                 // normal is assumed to be unit length
40120
40121                 const x = normal.x, y = normal.y, z = normal.z;
40122
40123                 // band 0
40124                 shBasis[ 0 ] = 0.282095;
40125
40126                 // band 1
40127                 shBasis[ 1 ] = 0.488603 * y;
40128                 shBasis[ 2 ] = 0.488603 * z;
40129                 shBasis[ 3 ] = 0.488603 * x;
40130
40131                 // band 2
40132                 shBasis[ 4 ] = 1.092548 * x * y;
40133                 shBasis[ 5 ] = 1.092548 * y * z;
40134                 shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
40135                 shBasis[ 7 ] = 1.092548 * x * z;
40136                 shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
40137
40138         }
40139
40140 }
40141
40142 function LightProbe( sh, intensity ) {
40143
40144         Light.call( this, undefined, intensity );
40145
40146         this.type = 'LightProbe';
40147
40148         this.sh = ( sh !== undefined ) ? sh : new SphericalHarmonics3();
40149
40150 }
40151
40152 LightProbe.prototype = Object.assign( Object.create( Light.prototype ), {
40153
40154         constructor: LightProbe,
40155
40156         isLightProbe: true,
40157
40158         copy: function ( source ) {
40159
40160                 Light.prototype.copy.call( this, source );
40161
40162                 this.sh.copy( source.sh );
40163
40164                 return this;
40165
40166         },
40167
40168         fromJSON: function ( json ) {
40169
40170                 this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
40171                 this.sh.fromArray( json.sh );
40172
40173                 return this;
40174
40175         },
40176
40177         toJSON: function ( meta ) {
40178
40179                 const data = Light.prototype.toJSON.call( this, meta );
40180
40181                 data.object.sh = this.sh.toArray();
40182
40183                 return data;
40184
40185         }
40186
40187 } );
40188
40189 function MaterialLoader( manager ) {
40190
40191         Loader.call( this, manager );
40192
40193         this.textures = {};
40194
40195 }
40196
40197 MaterialLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
40198
40199         constructor: MaterialLoader,
40200
40201         load: function ( url, onLoad, onProgress, onError ) {
40202
40203                 const scope = this;
40204
40205                 const loader = new FileLoader( scope.manager );
40206                 loader.setPath( scope.path );
40207                 loader.setRequestHeader( scope.requestHeader );
40208                 loader.setWithCredentials( scope.withCredentials );
40209                 loader.load( url, function ( text ) {
40210
40211                         try {
40212
40213                                 onLoad( scope.parse( JSON.parse( text ) ) );
40214
40215                         } catch ( e ) {
40216
40217                                 if ( onError ) {
40218
40219                                         onError( e );
40220
40221                                 } else {
40222
40223                                         console.error( e );
40224
40225                                 }
40226
40227                                 scope.manager.itemError( url );
40228
40229                         }
40230
40231                 }, onProgress, onError );
40232
40233         },
40234
40235         parse: function ( json ) {
40236
40237                 const textures = this.textures;
40238
40239                 function getTexture( name ) {
40240
40241                         if ( textures[ name ] === undefined ) {
40242
40243                                 console.warn( 'THREE.MaterialLoader: Undefined texture', name );
40244
40245                         }
40246
40247                         return textures[ name ];
40248
40249                 }
40250
40251                 const material = new Materials[ json.type ]();
40252
40253                 if ( json.uuid !== undefined ) material.uuid = json.uuid;
40254                 if ( json.name !== undefined ) material.name = json.name;
40255                 if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color );
40256                 if ( json.roughness !== undefined ) material.roughness = json.roughness;
40257                 if ( json.metalness !== undefined ) material.metalness = json.metalness;
40258                 if ( json.sheen !== undefined ) material.sheen = new Color().setHex( json.sheen );
40259                 if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive );
40260                 if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular );
40261                 if ( json.shininess !== undefined ) material.shininess = json.shininess;
40262                 if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
40263                 if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
40264                 if ( json.fog !== undefined ) material.fog = json.fog;
40265                 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
40266                 if ( json.blending !== undefined ) material.blending = json.blending;
40267                 if ( json.combine !== undefined ) material.combine = json.combine;
40268                 if ( json.side !== undefined ) material.side = json.side;
40269                 if ( json.opacity !== undefined ) material.opacity = json.opacity;
40270                 if ( json.transparent !== undefined ) material.transparent = json.transparent;
40271                 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
40272                 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
40273                 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
40274                 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
40275
40276                 if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
40277                 if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
40278                 if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
40279                 if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
40280                 if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
40281                 if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
40282                 if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
40283                 if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
40284
40285                 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
40286                 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
40287                 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
40288                 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
40289
40290                 if ( json.rotation !== undefined ) material.rotation = json.rotation;
40291
40292                 if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
40293                 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
40294                 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
40295                 if ( json.scale !== undefined ) material.scale = json.scale;
40296
40297                 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
40298                 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
40299                 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
40300
40301                 if ( json.skinning !== undefined ) material.skinning = json.skinning;
40302                 if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
40303                 if ( json.morphNormals !== undefined ) material.morphNormals = json.morphNormals;
40304                 if ( json.dithering !== undefined ) material.dithering = json.dithering;
40305
40306                 if ( json.vertexTangents !== undefined ) material.vertexTangents = json.vertexTangents;
40307
40308                 if ( json.visible !== undefined ) material.visible = json.visible;
40309
40310                 if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
40311
40312                 if ( json.userData !== undefined ) material.userData = json.userData;
40313
40314                 if ( json.vertexColors !== undefined ) {
40315
40316                         if ( typeof json.vertexColors === 'number' ) {
40317
40318                                 material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
40319
40320                         } else {
40321
40322                                 material.vertexColors = json.vertexColors;
40323
40324                         }
40325
40326                 }
40327
40328                 // Shader Material
40329
40330                 if ( json.uniforms !== undefined ) {
40331
40332                         for ( const name in json.uniforms ) {
40333
40334                                 const uniform = json.uniforms[ name ];
40335
40336                                 material.uniforms[ name ] = {};
40337
40338                                 switch ( uniform.type ) {
40339
40340                                         case 't':
40341                                                 material.uniforms[ name ].value = getTexture( uniform.value );
40342                                                 break;
40343
40344                                         case 'c':
40345                                                 material.uniforms[ name ].value = new Color().setHex( uniform.value );
40346                                                 break;
40347
40348                                         case 'v2':
40349                                                 material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
40350                                                 break;
40351
40352                                         case 'v3':
40353                                                 material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
40354                                                 break;
40355
40356                                         case 'v4':
40357                                                 material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
40358                                                 break;
40359
40360                                         case 'm3':
40361                                                 material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
40362                                                 break;
40363
40364                                         case 'm4':
40365                                                 material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
40366                                                 break;
40367
40368                                         default:
40369                                                 material.uniforms[ name ].value = uniform.value;
40370
40371                                 }
40372
40373                         }
40374
40375                 }
40376
40377                 if ( json.defines !== undefined ) material.defines = json.defines;
40378                 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
40379                 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
40380
40381                 if ( json.extensions !== undefined ) {
40382
40383                         for ( const key in json.extensions ) {
40384
40385                                 material.extensions[ key ] = json.extensions[ key ];
40386
40387                         }
40388
40389                 }
40390
40391                 // Deprecated
40392
40393                 if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
40394
40395                 // for PointsMaterial
40396
40397                 if ( json.size !== undefined ) material.size = json.size;
40398                 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
40399
40400                 // maps
40401
40402                 if ( json.map !== undefined ) material.map = getTexture( json.map );
40403                 if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
40404
40405                 if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
40406
40407                 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
40408                 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
40409
40410                 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
40411                 if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
40412                 if ( json.normalScale !== undefined ) {
40413
40414                         let normalScale = json.normalScale;
40415
40416                         if ( Array.isArray( normalScale ) === false ) {
40417
40418                                 // Blender exporter used to export a scalar. See #7459
40419
40420                                 normalScale = [ normalScale, normalScale ];
40421
40422                         }
40423
40424                         material.normalScale = new Vector2().fromArray( normalScale );
40425
40426                 }
40427
40428                 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
40429                 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
40430                 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
40431
40432                 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
40433                 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
40434
40435                 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
40436                 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
40437
40438                 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
40439
40440                 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
40441                 if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
40442
40443                 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
40444                 if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
40445
40446                 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
40447                 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
40448
40449                 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
40450                 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
40451
40452                 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
40453
40454                 if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
40455                 if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
40456                 if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
40457                 if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
40458
40459                 if ( json.transmission !== undefined ) material.transmission = json.transmission;
40460                 if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
40461
40462                 return material;
40463
40464         },
40465
40466         setTextures: function ( value ) {
40467
40468                 this.textures = value;
40469                 return this;
40470
40471         }
40472
40473 } );
40474
40475 const LoaderUtils = {
40476
40477         decodeText: function ( array ) {
40478
40479                 if ( typeof TextDecoder !== 'undefined' ) {
40480
40481                         return new TextDecoder().decode( array );
40482
40483                 }
40484
40485                 // Avoid the String.fromCharCode.apply(null, array) shortcut, which
40486                 // throws a "maximum call stack size exceeded" error for large arrays.
40487
40488                 let s = '';
40489
40490                 for ( let i = 0, il = array.length; i < il; i ++ ) {
40491
40492                         // Implicitly assumes little-endian.
40493                         s += String.fromCharCode( array[ i ] );
40494
40495                 }
40496
40497                 try {
40498
40499                         // merges multi-byte utf-8 characters.
40500
40501                         return decodeURIComponent( escape( s ) );
40502
40503                 } catch ( e ) { // see #16358
40504
40505                         return s;
40506
40507                 }
40508
40509         },
40510
40511         extractUrlBase: function ( url ) {
40512
40513                 const index = url.lastIndexOf( '/' );
40514
40515                 if ( index === - 1 ) return './';
40516
40517                 return url.substr( 0, index + 1 );
40518
40519         }
40520
40521 };
40522
40523 function InstancedBufferGeometry() {
40524
40525         BufferGeometry.call( this );
40526
40527         this.type = 'InstancedBufferGeometry';
40528         this.instanceCount = Infinity;
40529
40530 }
40531
40532 InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
40533
40534         constructor: InstancedBufferGeometry,
40535
40536         isInstancedBufferGeometry: true,
40537
40538         copy: function ( source ) {
40539
40540                 BufferGeometry.prototype.copy.call( this, source );
40541
40542                 this.instanceCount = source.instanceCount;
40543
40544                 return this;
40545
40546         },
40547
40548         clone: function () {
40549
40550                 return new this.constructor().copy( this );
40551
40552         },
40553
40554         toJSON: function () {
40555
40556                 const data = BufferGeometry.prototype.toJSON.call( this );
40557
40558                 data.instanceCount = this.instanceCount;
40559
40560                 data.isInstancedBufferGeometry = true;
40561
40562                 return data;
40563
40564         }
40565
40566 } );
40567
40568 function InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) {
40569
40570         if ( typeof ( normalized ) === 'number' ) {
40571
40572                 meshPerAttribute = normalized;
40573
40574                 normalized = false;
40575
40576                 console.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );
40577
40578         }
40579
40580         BufferAttribute.call( this, array, itemSize, normalized );
40581
40582         this.meshPerAttribute = meshPerAttribute || 1;
40583
40584 }
40585
40586 InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
40587
40588         constructor: InstancedBufferAttribute,
40589
40590         isInstancedBufferAttribute: true,
40591
40592         copy: function ( source ) {
40593
40594                 BufferAttribute.prototype.copy.call( this, source );
40595
40596                 this.meshPerAttribute = source.meshPerAttribute;
40597
40598                 return this;
40599
40600         },
40601
40602         toJSON: function ()     {
40603
40604                 const data = BufferAttribute.prototype.toJSON.call( this );
40605
40606                 data.meshPerAttribute = this.meshPerAttribute;
40607
40608                 data.isInstancedBufferAttribute = true;
40609
40610                 return data;
40611
40612         }
40613
40614 } );
40615
40616 function BufferGeometryLoader( manager ) {
40617
40618         Loader.call( this, manager );
40619
40620 }
40621
40622 BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
40623
40624         constructor: BufferGeometryLoader,
40625
40626         load: function ( url, onLoad, onProgress, onError ) {
40627
40628                 const scope = this;
40629
40630                 const loader = new FileLoader( scope.manager );
40631                 loader.setPath( scope.path );
40632                 loader.setRequestHeader( scope.requestHeader );
40633                 loader.setWithCredentials( scope.withCredentials );
40634                 loader.load( url, function ( text ) {
40635
40636                         try {
40637
40638                                 onLoad( scope.parse( JSON.parse( text ) ) );
40639
40640                         } catch ( e ) {
40641
40642                                 if ( onError ) {
40643
40644                                         onError( e );
40645
40646                                 } else {
40647
40648                                         console.error( e );
40649
40650                                 }
40651
40652                                 scope.manager.itemError( url );
40653
40654                         }
40655
40656                 }, onProgress, onError );
40657
40658         },
40659
40660         parse: function ( json ) {
40661
40662                 const interleavedBufferMap = {};
40663                 const arrayBufferMap = {};
40664
40665                 function getInterleavedBuffer( json, uuid ) {
40666
40667                         if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
40668
40669                         const interleavedBuffers = json.interleavedBuffers;
40670                         const interleavedBuffer = interleavedBuffers[ uuid ];
40671
40672                         const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
40673
40674                         const array = getTypedArray( interleavedBuffer.type, buffer );
40675                         const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
40676                         ib.uuid = interleavedBuffer.uuid;
40677
40678                         interleavedBufferMap[ uuid ] = ib;
40679
40680                         return ib;
40681
40682                 }
40683
40684                 function getArrayBuffer( json, uuid ) {
40685
40686                         if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
40687
40688                         const arrayBuffers = json.arrayBuffers;
40689                         const arrayBuffer = arrayBuffers[ uuid ];
40690
40691                         const ab = new Uint32Array( arrayBuffer ).buffer;
40692
40693                         arrayBufferMap[ uuid ] = ab;
40694
40695                         return ab;
40696
40697                 }
40698
40699                 const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
40700
40701                 const index = json.data.index;
40702
40703                 if ( index !== undefined ) {
40704
40705                         const typedArray = getTypedArray( index.type, index.array );
40706                         geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
40707
40708                 }
40709
40710                 const attributes = json.data.attributes;
40711
40712                 for ( const key in attributes ) {
40713
40714                         const attribute = attributes[ key ];
40715                         let bufferAttribute;
40716
40717                         if ( attribute.isInterleavedBufferAttribute ) {
40718
40719                                 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
40720                                 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
40721
40722                         } else {
40723
40724                                 const typedArray = getTypedArray( attribute.type, attribute.array );
40725                                 const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
40726                                 bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
40727
40728                         }
40729
40730                         if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
40731                         geometry.setAttribute( key, bufferAttribute );
40732
40733                 }
40734
40735                 const morphAttributes = json.data.morphAttributes;
40736
40737                 if ( morphAttributes ) {
40738
40739                         for ( const key in morphAttributes ) {
40740
40741                                 const attributeArray = morphAttributes[ key ];
40742
40743                                 const array = [];
40744
40745                                 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
40746
40747                                         const attribute = attributeArray[ i ];
40748                                         let bufferAttribute;
40749
40750                                         if ( attribute.isInterleavedBufferAttribute ) {
40751
40752                                                 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
40753                                                 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
40754
40755                                         } else {
40756
40757                                                 const typedArray = getTypedArray( attribute.type, attribute.array );
40758                                                 bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
40759
40760                                         }
40761
40762                                         if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
40763                                         array.push( bufferAttribute );
40764
40765                                 }
40766
40767                                 geometry.morphAttributes[ key ] = array;
40768
40769                         }
40770
40771                 }
40772
40773                 const morphTargetsRelative = json.data.morphTargetsRelative;
40774
40775                 if ( morphTargetsRelative ) {
40776
40777                         geometry.morphTargetsRelative = true;
40778
40779                 }
40780
40781                 const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
40782
40783                 if ( groups !== undefined ) {
40784
40785                         for ( let i = 0, n = groups.length; i !== n; ++ i ) {
40786
40787                                 const group = groups[ i ];
40788
40789                                 geometry.addGroup( group.start, group.count, group.materialIndex );
40790
40791                         }
40792
40793                 }
40794
40795                 const boundingSphere = json.data.boundingSphere;
40796
40797                 if ( boundingSphere !== undefined ) {
40798
40799                         const center = new Vector3();
40800
40801                         if ( boundingSphere.center !== undefined ) {
40802
40803                                 center.fromArray( boundingSphere.center );
40804
40805                         }
40806
40807                         geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
40808
40809                 }
40810
40811                 if ( json.name ) geometry.name = json.name;
40812                 if ( json.userData ) geometry.userData = json.userData;
40813
40814                 return geometry;
40815
40816         }
40817
40818 } );
40819
40820 class ObjectLoader extends Loader {
40821
40822         constructor( manager ) {
40823
40824                 super( manager );
40825
40826         }
40827
40828         load( url, onLoad, onProgress, onError ) {
40829
40830                 const scope = this;
40831
40832                 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
40833                 this.resourcePath = this.resourcePath || path;
40834
40835                 const loader = new FileLoader( this.manager );
40836                 loader.setPath( this.path );
40837                 loader.setRequestHeader( this.requestHeader );
40838                 loader.setWithCredentials( this.withCredentials );
40839                 loader.load( url, function ( text ) {
40840
40841                         let json = null;
40842
40843                         try {
40844
40845                                 json = JSON.parse( text );
40846
40847                         } catch ( error ) {
40848
40849                                 if ( onError !== undefined ) onError( error );
40850
40851                                 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
40852
40853                                 return;
40854
40855                         }
40856
40857                         const metadata = json.metadata;
40858
40859                         if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
40860
40861                                 console.error( 'THREE.ObjectLoader: Can\'t load ' + url );
40862                                 return;
40863
40864                         }
40865
40866                         scope.parse( json, onLoad );
40867
40868                 }, onProgress, onError );
40869
40870         }
40871
40872         parse( json, onLoad ) {
40873
40874                 const animations = this.parseAnimations( json.animations );
40875                 const shapes = this.parseShapes( json.shapes );
40876                 const geometries = this.parseGeometries( json.geometries, shapes );
40877
40878                 const images = this.parseImages( json.images, function () {
40879
40880                         if ( onLoad !== undefined ) onLoad( object );
40881
40882                 } );
40883
40884                 const textures = this.parseTextures( json.textures, images );
40885                 const materials = this.parseMaterials( json.materials, textures );
40886
40887                 const object = this.parseObject( json.object, geometries, materials, animations );
40888                 const skeletons = this.parseSkeletons( json.skeletons, object );
40889
40890                 this.bindSkeletons( object, skeletons );
40891
40892                 //
40893
40894                 if ( onLoad !== undefined ) {
40895
40896                         let hasImages = false;
40897
40898                         for ( const uuid in images ) {
40899
40900                                 if ( images[ uuid ] instanceof HTMLImageElement ) {
40901
40902                                         hasImages = true;
40903                                         break;
40904
40905                                 }
40906
40907                         }
40908
40909                         if ( hasImages === false ) onLoad( object );
40910
40911                 }
40912
40913                 return object;
40914
40915         }
40916
40917         parseShapes( json ) {
40918
40919                 const shapes = {};
40920
40921                 if ( json !== undefined ) {
40922
40923                         for ( let i = 0, l = json.length; i < l; i ++ ) {
40924
40925                                 const shape = new Shape().fromJSON( json[ i ] );
40926
40927                                 shapes[ shape.uuid ] = shape;
40928
40929                         }
40930
40931                 }
40932
40933                 return shapes;
40934
40935         }
40936
40937         parseSkeletons( json, object ) {
40938
40939                 const skeletons = {};
40940                 const bones = {};
40941
40942                 // generate bone lookup table
40943
40944                 object.traverse( function ( child ) {
40945
40946                         if ( child.isBone ) bones[ child.uuid ] = child;
40947
40948                 } );
40949
40950                 // create skeletons
40951
40952                 if ( json !== undefined ) {
40953
40954                         for ( let i = 0, l = json.length; i < l; i ++ ) {
40955
40956                                 const skeleton = new Skeleton().fromJSON( json[ i ], bones );
40957
40958                                 skeletons[ skeleton.uuid ] = skeleton;
40959
40960                         }
40961
40962                 }
40963
40964                 return skeletons;
40965
40966         }
40967
40968         parseGeometries( json, shapes ) {
40969
40970                 const geometries = {};
40971                 let geometryShapes;
40972
40973                 if ( json !== undefined ) {
40974
40975                         const bufferGeometryLoader = new BufferGeometryLoader();
40976
40977                         for ( let i = 0, l = json.length; i < l; i ++ ) {
40978
40979                                 let geometry;
40980                                 const data = json[ i ];
40981
40982                                 switch ( data.type ) {
40983
40984                                         case 'PlaneGeometry':
40985                                         case 'PlaneBufferGeometry':
40986
40987                                                 geometry = new Geometries[ data.type ](
40988                                                         data.width,
40989                                                         data.height,
40990                                                         data.widthSegments,
40991                                                         data.heightSegments
40992                                                 );
40993
40994                                                 break;
40995
40996                                         case 'BoxGeometry':
40997                                         case 'BoxBufferGeometry':
40998                                         case 'CubeGeometry': // backwards compatible
40999
41000                                                 geometry = new Geometries[ data.type ](
41001                                                         data.width,
41002                                                         data.height,
41003                                                         data.depth,
41004                                                         data.widthSegments,
41005                                                         data.heightSegments,
41006                                                         data.depthSegments
41007                                                 );
41008
41009                                                 break;
41010
41011                                         case 'CircleGeometry':
41012                                         case 'CircleBufferGeometry':
41013
41014                                                 geometry = new Geometries[ data.type ](
41015                                                         data.radius,
41016                                                         data.segments,
41017                                                         data.thetaStart,
41018                                                         data.thetaLength
41019                                                 );
41020
41021                                                 break;
41022
41023                                         case 'CylinderGeometry':
41024                                         case 'CylinderBufferGeometry':
41025
41026                                                 geometry = new Geometries[ data.type ](
41027                                                         data.radiusTop,
41028                                                         data.radiusBottom,
41029                                                         data.height,
41030                                                         data.radialSegments,
41031                                                         data.heightSegments,
41032                                                         data.openEnded,
41033                                                         data.thetaStart,
41034                                                         data.thetaLength
41035                                                 );
41036
41037                                                 break;
41038
41039                                         case 'ConeGeometry':
41040                                         case 'ConeBufferGeometry':
41041
41042                                                 geometry = new Geometries[ data.type ](
41043                                                         data.radius,
41044                                                         data.height,
41045                                                         data.radialSegments,
41046                                                         data.heightSegments,
41047                                                         data.openEnded,
41048                                                         data.thetaStart,
41049                                                         data.thetaLength
41050                                                 );
41051
41052                                                 break;
41053
41054                                         case 'SphereGeometry':
41055                                         case 'SphereBufferGeometry':
41056
41057                                                 geometry = new Geometries[ data.type ](
41058                                                         data.radius,
41059                                                         data.widthSegments,
41060                                                         data.heightSegments,
41061                                                         data.phiStart,
41062                                                         data.phiLength,
41063                                                         data.thetaStart,
41064                                                         data.thetaLength
41065                                                 );
41066
41067                                                 break;
41068
41069                                         case 'DodecahedronGeometry':
41070                                         case 'DodecahedronBufferGeometry':
41071                                         case 'IcosahedronGeometry':
41072                                         case 'IcosahedronBufferGeometry':
41073                                         case 'OctahedronGeometry':
41074                                         case 'OctahedronBufferGeometry':
41075                                         case 'TetrahedronGeometry':
41076                                         case 'TetrahedronBufferGeometry':
41077
41078                                                 geometry = new Geometries[ data.type ](
41079                                                         data.radius,
41080                                                         data.detail
41081                                                 );
41082
41083                                                 break;
41084
41085                                         case 'RingGeometry':
41086                                         case 'RingBufferGeometry':
41087
41088                                                 geometry = new Geometries[ data.type ](
41089                                                         data.innerRadius,
41090                                                         data.outerRadius,
41091                                                         data.thetaSegments,
41092                                                         data.phiSegments,
41093                                                         data.thetaStart,
41094                                                         data.thetaLength
41095                                                 );
41096
41097                                                 break;
41098
41099                                         case 'TorusGeometry':
41100                                         case 'TorusBufferGeometry':
41101
41102                                                 geometry = new Geometries[ data.type ](
41103                                                         data.radius,
41104                                                         data.tube,
41105                                                         data.radialSegments,
41106                                                         data.tubularSegments,
41107                                                         data.arc
41108                                                 );
41109
41110                                                 break;
41111
41112                                         case 'TorusKnotGeometry':
41113                                         case 'TorusKnotBufferGeometry':
41114
41115                                                 geometry = new Geometries[ data.type ](
41116                                                         data.radius,
41117                                                         data.tube,
41118                                                         data.tubularSegments,
41119                                                         data.radialSegments,
41120                                                         data.p,
41121                                                         data.q
41122                                                 );
41123
41124                                                 break;
41125
41126                                         case 'TubeGeometry':
41127                                         case 'TubeBufferGeometry':
41128
41129                                                 // This only works for built-in curves (e.g. CatmullRomCurve3).
41130                                                 // User defined curves or instances of CurvePath will not be deserialized.
41131                                                 geometry = new Geometries[ data.type ](
41132                                                         new Curves[ data.path.type ]().fromJSON( data.path ),
41133                                                         data.tubularSegments,
41134                                                         data.radius,
41135                                                         data.radialSegments,
41136                                                         data.closed
41137                                                 );
41138
41139                                                 break;
41140
41141                                         case 'LatheGeometry':
41142                                         case 'LatheBufferGeometry':
41143
41144                                                 geometry = new Geometries[ data.type ](
41145                                                         data.points,
41146                                                         data.segments,
41147                                                         data.phiStart,
41148                                                         data.phiLength
41149                                                 );
41150
41151                                                 break;
41152
41153                                         case 'PolyhedronGeometry':
41154                                         case 'PolyhedronBufferGeometry':
41155
41156                                                 geometry = new Geometries[ data.type ](
41157                                                         data.vertices,
41158                                                         data.indices,
41159                                                         data.radius,
41160                                                         data.details
41161                                                 );
41162
41163                                                 break;
41164
41165                                         case 'ShapeGeometry':
41166                                         case 'ShapeBufferGeometry':
41167
41168                                                 geometryShapes = [];
41169
41170                                                 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
41171
41172                                                         const shape = shapes[ data.shapes[ j ] ];
41173
41174                                                         geometryShapes.push( shape );
41175
41176                                                 }
41177
41178                                                 geometry = new Geometries[ data.type ](
41179                                                         geometryShapes,
41180                                                         data.curveSegments
41181                                                 );
41182
41183                                                 break;
41184
41185
41186                                         case 'ExtrudeGeometry':
41187                                         case 'ExtrudeBufferGeometry':
41188
41189                                                 geometryShapes = [];
41190
41191                                                 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
41192
41193                                                         const shape = shapes[ data.shapes[ j ] ];
41194
41195                                                         geometryShapes.push( shape );
41196
41197                                                 }
41198
41199                                                 const extrudePath = data.options.extrudePath;
41200
41201                                                 if ( extrudePath !== undefined ) {
41202
41203                                                         data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
41204
41205                                                 }
41206
41207                                                 geometry = new Geometries[ data.type ](
41208                                                         geometryShapes,
41209                                                         data.options
41210                                                 );
41211
41212                                                 break;
41213
41214                                         case 'BufferGeometry':
41215                                         case 'InstancedBufferGeometry':
41216
41217                                                 geometry = bufferGeometryLoader.parse( data );
41218
41219                                                 break;
41220
41221                                         case 'Geometry':
41222
41223                                                 console.error( 'THREE.ObjectLoader: Loading "Geometry" is not supported anymore.' );
41224
41225                                                 break;
41226
41227                                         default:
41228
41229                                                 console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
41230
41231                                                 continue;
41232
41233                                 }
41234
41235                                 geometry.uuid = data.uuid;
41236
41237                                 if ( data.name !== undefined ) geometry.name = data.name;
41238                                 if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData;
41239
41240                                 geometries[ data.uuid ] = geometry;
41241
41242                         }
41243
41244                 }
41245
41246                 return geometries;
41247
41248         }
41249
41250         parseMaterials( json, textures ) {
41251
41252                 const cache = {}; // MultiMaterial
41253                 const materials = {};
41254
41255                 if ( json !== undefined ) {
41256
41257                         const loader = new MaterialLoader();
41258                         loader.setTextures( textures );
41259
41260                         for ( let i = 0, l = json.length; i < l; i ++ ) {
41261
41262                                 const data = json[ i ];
41263
41264                                 if ( data.type === 'MultiMaterial' ) {
41265
41266                                         // Deprecated
41267
41268                                         const array = [];
41269
41270                                         for ( let j = 0; j < data.materials.length; j ++ ) {
41271
41272                                                 const material = data.materials[ j ];
41273
41274                                                 if ( cache[ material.uuid ] === undefined ) {
41275
41276                                                         cache[ material.uuid ] = loader.parse( material );
41277
41278                                                 }
41279
41280                                                 array.push( cache[ material.uuid ] );
41281
41282                                         }
41283
41284                                         materials[ data.uuid ] = array;
41285
41286                                 } else {
41287
41288                                         if ( cache[ data.uuid ] === undefined ) {
41289
41290                                                 cache[ data.uuid ] = loader.parse( data );
41291
41292                                         }
41293
41294                                         materials[ data.uuid ] = cache[ data.uuid ];
41295
41296                                 }
41297
41298                         }
41299
41300                 }
41301
41302                 return materials;
41303
41304         }
41305
41306         parseAnimations( json ) {
41307
41308                 const animations = {};
41309
41310                 if ( json !== undefined ) {
41311
41312                         for ( let i = 0; i < json.length; i ++ ) {
41313
41314                                 const data = json[ i ];
41315
41316                                 const clip = AnimationClip.parse( data );
41317
41318                                 animations[ clip.uuid ] = clip;
41319
41320                         }
41321
41322                 }
41323
41324                 return animations;
41325
41326         }
41327
41328         parseImages( json, onLoad ) {
41329
41330                 const scope = this;
41331                 const images = {};
41332
41333                 let loader;
41334
41335                 function loadImage( url ) {
41336
41337                         scope.manager.itemStart( url );
41338
41339                         return loader.load( url, function () {
41340
41341                                 scope.manager.itemEnd( url );
41342
41343                         }, undefined, function () {
41344
41345                                 scope.manager.itemError( url );
41346                                 scope.manager.itemEnd( url );
41347
41348                         } );
41349
41350                 }
41351
41352                 function deserializeImage( image ) {
41353
41354                         if ( typeof image === 'string' ) {
41355
41356                                 const url = image;
41357
41358                                 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
41359
41360                                 return loadImage( path );
41361
41362                         } else {
41363
41364                                 if ( image.data ) {
41365
41366                                         return {
41367                                                 data: getTypedArray( image.type, image.data ),
41368                                                 width: image.width,
41369                                                 height: image.height
41370                                         };
41371
41372                                 } else {
41373
41374                                         return null;
41375
41376                                 }
41377
41378                         }
41379
41380                 }
41381
41382                 if ( json !== undefined && json.length > 0 ) {
41383
41384                         const manager = new LoadingManager( onLoad );
41385
41386                         loader = new ImageLoader( manager );
41387                         loader.setCrossOrigin( this.crossOrigin );
41388
41389                         for ( let i = 0, il = json.length; i < il; i ++ ) {
41390
41391                                 const image = json[ i ];
41392                                 const url = image.url;
41393
41394                                 if ( Array.isArray( url ) ) {
41395
41396                                         // load array of images e.g CubeTexture
41397
41398                                         images[ image.uuid ] = [];
41399
41400                                         for ( let j = 0, jl = url.length; j < jl; j ++ ) {
41401
41402                                                 const currentUrl = url[ j ];
41403
41404                                                 const deserializedImage = deserializeImage( currentUrl );
41405
41406                                                 if ( deserializedImage !== null ) {
41407
41408                                                         if ( deserializedImage instanceof HTMLImageElement ) {
41409
41410                                                                 images[ image.uuid ].push( deserializedImage );
41411
41412                                                         } else {
41413
41414                                                                 // special case: handle array of data textures for cube textures
41415
41416                                                                 images[ image.uuid ].push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
41417
41418                                                         }
41419
41420                                                 }
41421
41422                                         }
41423
41424                                 } else {
41425
41426                                         // load single image
41427
41428                                         const deserializedImage = deserializeImage( image.url );
41429
41430                                         if ( deserializedImage !== null ) {
41431
41432                                                 images[ image.uuid ] = deserializedImage;
41433
41434                                         }
41435
41436                                 }
41437
41438                         }
41439
41440                 }
41441
41442                 return images;
41443
41444         }
41445
41446         parseTextures( json, images ) {
41447
41448                 function parseConstant( value, type ) {
41449
41450                         if ( typeof value === 'number' ) return value;
41451
41452                         console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
41453
41454                         return type[ value ];
41455
41456                 }
41457
41458                 const textures = {};
41459
41460                 if ( json !== undefined ) {
41461
41462                         for ( let i = 0, l = json.length; i < l; i ++ ) {
41463
41464                                 const data = json[ i ];
41465
41466                                 if ( data.image === undefined ) {
41467
41468                                         console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
41469
41470                                 }
41471
41472                                 if ( images[ data.image ] === undefined ) {
41473
41474                                         console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
41475
41476                                 }
41477
41478                                 let texture;
41479                                 const image = images[ data.image ];
41480
41481                                 if ( Array.isArray( image ) ) {
41482
41483                                         texture = new CubeTexture( image );
41484
41485                                         if ( image.length === 6 ) texture.needsUpdate = true;
41486
41487                                 } else {
41488
41489                                         if ( image && image.data ) {
41490
41491                                                 texture = new DataTexture( image.data, image.width, image.height );
41492
41493                                         } else {
41494
41495                                                 texture = new Texture( image );
41496
41497                                         }
41498
41499                                         if ( image ) texture.needsUpdate = true; // textures can have undefined image data
41500
41501                                 }
41502
41503                                 texture.uuid = data.uuid;
41504
41505                                 if ( data.name !== undefined ) texture.name = data.name;
41506
41507                                 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
41508
41509                                 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
41510                                 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
41511                                 if ( data.center !== undefined ) texture.center.fromArray( data.center );
41512                                 if ( data.rotation !== undefined ) texture.rotation = data.rotation;
41513
41514                                 if ( data.wrap !== undefined ) {
41515
41516                                         texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
41517                                         texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
41518
41519                                 }
41520
41521                                 if ( data.format !== undefined ) texture.format = data.format;
41522                                 if ( data.type !== undefined ) texture.type = data.type;
41523                                 if ( data.encoding !== undefined ) texture.encoding = data.encoding;
41524
41525                                 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
41526                                 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
41527                                 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
41528
41529                                 if ( data.flipY !== undefined ) texture.flipY = data.flipY;
41530
41531                                 if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
41532                                 if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
41533
41534                                 textures[ data.uuid ] = texture;
41535
41536                         }
41537
41538                 }
41539
41540                 return textures;
41541
41542         }
41543
41544         parseObject( data, geometries, materials, animations ) {
41545
41546                 let object;
41547
41548                 function getGeometry( name ) {
41549
41550                         if ( geometries[ name ] === undefined ) {
41551
41552                                 console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
41553
41554                         }
41555
41556                         return geometries[ name ];
41557
41558                 }
41559
41560                 function getMaterial( name ) {
41561
41562                         if ( name === undefined ) return undefined;
41563
41564                         if ( Array.isArray( name ) ) {
41565
41566                                 const array = [];
41567
41568                                 for ( let i = 0, l = name.length; i < l; i ++ ) {
41569
41570                                         const uuid = name[ i ];
41571
41572                                         if ( materials[ uuid ] === undefined ) {
41573
41574                                                 console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
41575
41576                                         }
41577
41578                                         array.push( materials[ uuid ] );
41579
41580                                 }
41581
41582                                 return array;
41583
41584                         }
41585
41586                         if ( materials[ name ] === undefined ) {
41587
41588                                 console.warn( 'THREE.ObjectLoader: Undefined material', name );
41589
41590                         }
41591
41592                         return materials[ name ];
41593
41594                 }
41595
41596                 let geometry, material;
41597
41598                 switch ( data.type ) {
41599
41600                         case 'Scene':
41601
41602                                 object = new Scene();
41603
41604                                 if ( data.background !== undefined ) {
41605
41606                                         if ( Number.isInteger( data.background ) ) {
41607
41608                                                 object.background = new Color( data.background );
41609
41610                                         }
41611
41612                                 }
41613
41614                                 if ( data.fog !== undefined ) {
41615
41616                                         if ( data.fog.type === 'Fog' ) {
41617
41618                                                 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
41619
41620                                         } else if ( data.fog.type === 'FogExp2' ) {
41621
41622                                                 object.fog = new FogExp2( data.fog.color, data.fog.density );
41623
41624                                         }
41625
41626                                 }
41627
41628                                 break;
41629
41630                         case 'PerspectiveCamera':
41631
41632                                 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
41633
41634                                 if ( data.focus !== undefined ) object.focus = data.focus;
41635                                 if ( data.zoom !== undefined ) object.zoom = data.zoom;
41636                                 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
41637                                 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
41638                                 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
41639
41640                                 break;
41641
41642                         case 'OrthographicCamera':
41643
41644                                 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
41645
41646                                 if ( data.zoom !== undefined ) object.zoom = data.zoom;
41647                                 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
41648
41649                                 break;
41650
41651                         case 'AmbientLight':
41652
41653                                 object = new AmbientLight( data.color, data.intensity );
41654
41655                                 break;
41656
41657                         case 'DirectionalLight':
41658
41659                                 object = new DirectionalLight( data.color, data.intensity );
41660
41661                                 break;
41662
41663                         case 'PointLight':
41664
41665                                 object = new PointLight( data.color, data.intensity, data.distance, data.decay );
41666
41667                                 break;
41668
41669                         case 'RectAreaLight':
41670
41671                                 object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
41672
41673                                 break;
41674
41675                         case 'SpotLight':
41676
41677                                 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
41678
41679                                 break;
41680
41681                         case 'HemisphereLight':
41682
41683                                 object = new HemisphereLight( data.color, data.groundColor, data.intensity );
41684
41685                                 break;
41686
41687                         case 'LightProbe':
41688
41689                                 object = new LightProbe().fromJSON( data );
41690
41691                                 break;
41692
41693                         case 'SkinnedMesh':
41694
41695                                 geometry = getGeometry( data.geometry );
41696                                 material = getMaterial( data.material );
41697
41698                                 object = new SkinnedMesh( geometry, material );
41699
41700                                 if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
41701                                 if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix );
41702                                 if ( data.skeleton !== undefined ) object.skeleton = data.skeleton;
41703
41704                                 break;
41705
41706                         case 'Mesh':
41707
41708                                 geometry = getGeometry( data.geometry );
41709                                 material = getMaterial( data.material );
41710
41711                                 object = new Mesh( geometry, material );
41712
41713                                 break;
41714
41715                         case 'InstancedMesh':
41716
41717                                 geometry = getGeometry( data.geometry );
41718                                 material = getMaterial( data.material );
41719                                 const count = data.count;
41720                                 const instanceMatrix = data.instanceMatrix;
41721
41722                                 object = new InstancedMesh( geometry, material, count );
41723                                 object.instanceMatrix = new BufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
41724
41725                                 break;
41726
41727                         case 'LOD':
41728
41729                                 object = new LOD();
41730
41731                                 break;
41732
41733                         case 'Line':
41734
41735                                 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
41736
41737                                 break;
41738
41739                         case 'LineLoop':
41740
41741                                 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
41742
41743                                 break;
41744
41745                         case 'LineSegments':
41746
41747                                 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
41748
41749                                 break;
41750
41751                         case 'PointCloud':
41752                         case 'Points':
41753
41754                                 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
41755
41756                                 break;
41757
41758                         case 'Sprite':
41759
41760                                 object = new Sprite( getMaterial( data.material ) );
41761
41762                                 break;
41763
41764                         case 'Group':
41765
41766                                 object = new Group();
41767
41768                                 break;
41769
41770                         case 'Bone':
41771
41772                                 object = new Bone();
41773
41774                                 break;
41775
41776                         default:
41777
41778                                 object = new Object3D();
41779
41780                 }
41781
41782                 object.uuid = data.uuid;
41783
41784                 if ( data.name !== undefined ) object.name = data.name;
41785
41786                 if ( data.matrix !== undefined ) {
41787
41788                         object.matrix.fromArray( data.matrix );
41789
41790                         if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
41791                         if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
41792
41793                 } else {
41794
41795                         if ( data.position !== undefined ) object.position.fromArray( data.position );
41796                         if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
41797                         if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
41798                         if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
41799
41800                 }
41801
41802                 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
41803                 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
41804
41805                 if ( data.shadow ) {
41806
41807                         if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
41808                         if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias;
41809                         if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
41810                         if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
41811                         if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
41812
41813                 }
41814
41815                 if ( data.visible !== undefined ) object.visible = data.visible;
41816                 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
41817                 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
41818                 if ( data.userData !== undefined ) object.userData = data.userData;
41819                 if ( data.layers !== undefined ) object.layers.mask = data.layers;
41820
41821                 if ( data.children !== undefined ) {
41822
41823                         const children = data.children;
41824
41825                         for ( let i = 0; i < children.length; i ++ ) {
41826
41827                                 object.add( this.parseObject( children[ i ], geometries, materials, animations ) );
41828
41829                         }
41830
41831                 }
41832
41833                 if ( data.animations !== undefined ) {
41834
41835                         const objectAnimations = data.animations;
41836
41837                         for ( let i = 0; i < objectAnimations.length; i ++ ) {
41838
41839                                 const uuid = objectAnimations[ i ];
41840
41841                                 object.animations.push( animations[ uuid ] );
41842
41843                         }
41844
41845                 }
41846
41847                 if ( data.type === 'LOD' ) {
41848
41849                         if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
41850
41851                         const levels = data.levels;
41852
41853                         for ( let l = 0; l < levels.length; l ++ ) {
41854
41855                                 const level = levels[ l ];
41856                                 const child = object.getObjectByProperty( 'uuid', level.object );
41857
41858                                 if ( child !== undefined ) {
41859
41860                                         object.addLevel( child, level.distance );
41861
41862                                 }
41863
41864                         }
41865
41866                 }
41867
41868                 return object;
41869
41870         }
41871
41872         bindSkeletons( object, skeletons ) {
41873
41874                 if ( Object.keys( skeletons ).length === 0 ) return;
41875
41876                 object.traverse( function ( child ) {
41877
41878                         if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) {
41879
41880                                 const skeleton = skeletons[ child.skeleton ];
41881
41882                                 if ( skeleton === undefined ) {
41883
41884                                         console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton );
41885
41886                                 } else {
41887
41888                                         child.bind( skeleton, child.bindMatrix );
41889
41890                                 }
41891
41892                         }
41893
41894                 } );
41895
41896         }
41897
41898         /* DEPRECATED */
41899
41900         setTexturePath( value ) {
41901
41902                 console.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );
41903                 return this.setResourcePath( value );
41904
41905         }
41906
41907 }
41908
41909 const TEXTURE_MAPPING = {
41910         UVMapping: UVMapping,
41911         CubeReflectionMapping: CubeReflectionMapping,
41912         CubeRefractionMapping: CubeRefractionMapping,
41913         EquirectangularReflectionMapping: EquirectangularReflectionMapping,
41914         EquirectangularRefractionMapping: EquirectangularRefractionMapping,
41915         CubeUVReflectionMapping: CubeUVReflectionMapping,
41916         CubeUVRefractionMapping: CubeUVRefractionMapping
41917 };
41918
41919 const TEXTURE_WRAPPING = {
41920         RepeatWrapping: RepeatWrapping,
41921         ClampToEdgeWrapping: ClampToEdgeWrapping,
41922         MirroredRepeatWrapping: MirroredRepeatWrapping
41923 };
41924
41925 const TEXTURE_FILTER = {
41926         NearestFilter: NearestFilter,
41927         NearestMipmapNearestFilter: NearestMipmapNearestFilter,
41928         NearestMipmapLinearFilter: NearestMipmapLinearFilter,
41929         LinearFilter: LinearFilter,
41930         LinearMipmapNearestFilter: LinearMipmapNearestFilter,
41931         LinearMipmapLinearFilter: LinearMipmapLinearFilter
41932 };
41933
41934 function ImageBitmapLoader( manager ) {
41935
41936         if ( typeof createImageBitmap === 'undefined' ) {
41937
41938                 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
41939
41940         }
41941
41942         if ( typeof fetch === 'undefined' ) {
41943
41944                 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
41945
41946         }
41947
41948         Loader.call( this, manager );
41949
41950         this.options = { premultiplyAlpha: 'none' };
41951
41952 }
41953
41954 ImageBitmapLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
41955
41956         constructor: ImageBitmapLoader,
41957
41958         isImageBitmapLoader: true,
41959
41960         setOptions: function setOptions( options ) {
41961
41962                 this.options = options;
41963
41964                 return this;
41965
41966         },
41967
41968         load: function ( url, onLoad, onProgress, onError ) {
41969
41970                 if ( url === undefined ) url = '';
41971
41972                 if ( this.path !== undefined ) url = this.path + url;
41973
41974                 url = this.manager.resolveURL( url );
41975
41976                 const scope = this;
41977
41978                 const cached = Cache.get( url );
41979
41980                 if ( cached !== undefined ) {
41981
41982                         scope.manager.itemStart( url );
41983
41984                         setTimeout( function () {
41985
41986                                 if ( onLoad ) onLoad( cached );
41987
41988                                 scope.manager.itemEnd( url );
41989
41990                         }, 0 );
41991
41992                         return cached;
41993
41994                 }
41995
41996                 const fetchOptions = {};
41997                 fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
41998
41999                 fetch( url, fetchOptions ).then( function ( res ) {
42000
42001                         return res.blob();
42002
42003                 } ).then( function ( blob ) {
42004
42005                         return createImageBitmap( blob, scope.options );
42006
42007                 } ).then( function ( imageBitmap ) {
42008
42009                         Cache.add( url, imageBitmap );
42010
42011                         if ( onLoad ) onLoad( imageBitmap );
42012
42013                         scope.manager.itemEnd( url );
42014
42015                 } ).catch( function ( e ) {
42016
42017                         if ( onError ) onError( e );
42018
42019                         scope.manager.itemError( url );
42020                         scope.manager.itemEnd( url );
42021
42022                 } );
42023
42024                 scope.manager.itemStart( url );
42025
42026         }
42027
42028 } );
42029
42030 function ShapePath() {
42031
42032         this.type = 'ShapePath';
42033
42034         this.color = new Color();
42035
42036         this.subPaths = [];
42037         this.currentPath = null;
42038
42039 }
42040
42041 Object.assign( ShapePath.prototype, {
42042
42043         moveTo: function ( x, y ) {
42044
42045                 this.currentPath = new Path();
42046                 this.subPaths.push( this.currentPath );
42047                 this.currentPath.moveTo( x, y );
42048
42049                 return this;
42050
42051         },
42052
42053         lineTo: function ( x, y ) {
42054
42055                 this.currentPath.lineTo( x, y );
42056
42057                 return this;
42058
42059         },
42060
42061         quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
42062
42063                 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
42064
42065                 return this;
42066
42067         },
42068
42069         bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
42070
42071                 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
42072
42073                 return this;
42074
42075         },
42076
42077         splineThru: function ( pts ) {
42078
42079                 this.currentPath.splineThru( pts );
42080
42081                 return this;
42082
42083         },
42084
42085         toShapes: function ( isCCW, noHoles ) {
42086
42087                 function toShapesNoHoles( inSubpaths ) {
42088
42089                         const shapes = [];
42090
42091                         for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) {
42092
42093                                 const tmpPath = inSubpaths[ i ];
42094
42095                                 const tmpShape = new Shape();
42096                                 tmpShape.curves = tmpPath.curves;
42097
42098                                 shapes.push( tmpShape );
42099
42100                         }
42101
42102                         return shapes;
42103
42104                 }
42105
42106                 function isPointInsidePolygon( inPt, inPolygon ) {
42107
42108                         const polyLen = inPolygon.length;
42109
42110                         // inPt on polygon contour => immediate success    or
42111                         // toggling of inside/outside at every single! intersection point of an edge
42112                         //  with the horizontal line through inPt, left of inPt
42113                         //  not counting lowerY endpoints of edges and whole edges on that line
42114                         let inside = false;
42115                         for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
42116
42117                                 let edgeLowPt = inPolygon[ p ];
42118                                 let edgeHighPt = inPolygon[ q ];
42119
42120                                 let edgeDx = edgeHighPt.x - edgeLowPt.x;
42121                                 let edgeDy = edgeHighPt.y - edgeLowPt.y;
42122
42123                                 if ( Math.abs( edgeDy ) > Number.EPSILON ) {
42124
42125                                         // not parallel
42126                                         if ( edgeDy < 0 ) {
42127
42128                                                 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
42129                                                 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
42130
42131                                         }
42132
42133                                         if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) )            continue;
42134
42135                                         if ( inPt.y === edgeLowPt.y ) {
42136
42137                                                 if ( inPt.x === edgeLowPt.x )           return  true;           // inPt is on contour ?
42138                                                 // continue;                            // no intersection or edgeLowPt => doesn't count !!!
42139
42140                                         } else {
42141
42142                                                 const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
42143                                                 if ( perpEdge === 0 )                           return  true;           // inPt is on contour ?
42144                                                 if ( perpEdge < 0 )                             continue;
42145                                                 inside = ! inside;              // true intersection left of inPt
42146
42147                                         }
42148
42149                                 } else {
42150
42151                                         // parallel or collinear
42152                                         if ( inPt.y !== edgeLowPt.y )           continue;                       // parallel
42153                                         // edge lies on the same horizontal line as inPt
42154                                         if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
42155                                                  ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )          return  true;   // inPt: Point on contour !
42156                                         // continue;
42157
42158                                 }
42159
42160                         }
42161
42162                         return  inside;
42163
42164                 }
42165
42166                 const isClockWise = ShapeUtils.isClockWise;
42167
42168                 const subPaths = this.subPaths;
42169                 if ( subPaths.length === 0 ) return [];
42170
42171                 if ( noHoles === true ) return  toShapesNoHoles( subPaths );
42172
42173
42174                 let solid, tmpPath, tmpShape;
42175                 const shapes = [];
42176
42177                 if ( subPaths.length === 1 ) {
42178
42179                         tmpPath = subPaths[ 0 ];
42180                         tmpShape = new Shape();
42181                         tmpShape.curves = tmpPath.curves;
42182                         shapes.push( tmpShape );
42183                         return shapes;
42184
42185                 }
42186
42187                 let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
42188                 holesFirst = isCCW ? ! holesFirst : holesFirst;
42189
42190                 // console.log("Holes first", holesFirst);
42191
42192                 const betterShapeHoles = [];
42193                 const newShapes = [];
42194                 let newShapeHoles = [];
42195                 let mainIdx = 0;
42196                 let tmpPoints;
42197
42198                 newShapes[ mainIdx ] = undefined;
42199                 newShapeHoles[ mainIdx ] = [];
42200
42201                 for ( let i = 0, l = subPaths.length; i < l; i ++ ) {
42202
42203                         tmpPath = subPaths[ i ];
42204                         tmpPoints = tmpPath.getPoints();
42205                         solid = isClockWise( tmpPoints );
42206                         solid = isCCW ? ! solid : solid;
42207
42208                         if ( solid ) {
42209
42210                                 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )     mainIdx ++;
42211
42212                                 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
42213                                 newShapes[ mainIdx ].s.curves = tmpPath.curves;
42214
42215                                 if ( holesFirst )       mainIdx ++;
42216                                 newShapeHoles[ mainIdx ] = [];
42217
42218                                 //console.log('cw', i);
42219
42220                         } else {
42221
42222                                 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
42223
42224                                 //console.log('ccw', i);
42225
42226                         }
42227
42228                 }
42229
42230                 // only Holes? -> probably all Shapes with wrong orientation
42231                 if ( ! newShapes[ 0 ] ) return  toShapesNoHoles( subPaths );
42232
42233
42234                 if ( newShapes.length > 1 ) {
42235
42236                         let ambiguous = false;
42237                         const toChange = [];
42238
42239                         for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
42240
42241                                 betterShapeHoles[ sIdx ] = [];
42242
42243                         }
42244
42245                         for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
42246
42247                                 const sho = newShapeHoles[ sIdx ];
42248
42249                                 for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) {
42250
42251                                         const ho = sho[ hIdx ];
42252                                         let hole_unassigned = true;
42253
42254                                         for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
42255
42256                                                 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
42257
42258                                                         if ( sIdx !== s2Idx )   toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
42259                                                         if ( hole_unassigned ) {
42260
42261                                                                 hole_unassigned = false;
42262                                                                 betterShapeHoles[ s2Idx ].push( ho );
42263
42264                                                         } else {
42265
42266                                                                 ambiguous = true;
42267
42268                                                         }
42269
42270                                                 }
42271
42272                                         }
42273
42274                                         if ( hole_unassigned ) {
42275
42276                                                 betterShapeHoles[ sIdx ].push( ho );
42277
42278                                         }
42279
42280                                 }
42281
42282                         }
42283                         // console.log("ambiguous: ", ambiguous);
42284
42285                         if ( toChange.length > 0 ) {
42286
42287                                 // console.log("to change: ", toChange);
42288                                 if ( ! ambiguous )      newShapeHoles = betterShapeHoles;
42289
42290                         }
42291
42292                 }
42293
42294                 let tmpHoles;
42295
42296                 for ( let i = 0, il = newShapes.length; i < il; i ++ ) {
42297
42298                         tmpShape = newShapes[ i ].s;
42299                         shapes.push( tmpShape );
42300                         tmpHoles = newShapeHoles[ i ];
42301
42302                         for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
42303
42304                                 tmpShape.holes.push( tmpHoles[ j ].h );
42305
42306                         }
42307
42308                 }
42309
42310                 //console.log("shape", shapes);
42311
42312                 return shapes;
42313
42314         }
42315
42316 } );
42317
42318 function Font( data ) {
42319
42320         this.type = 'Font';
42321
42322         this.data = data;
42323
42324 }
42325
42326 Object.assign( Font.prototype, {
42327
42328         isFont: true,
42329
42330         generateShapes: function ( text, size = 100 ) {
42331
42332                 const shapes = [];
42333                 const paths = createPaths( text, size, this.data );
42334
42335                 for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
42336
42337                         Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
42338
42339                 }
42340
42341                 return shapes;
42342
42343         }
42344
42345 } );
42346
42347 function createPaths( text, size, data ) {
42348
42349         const chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // workaround for IE11, see #13988
42350         const scale = size / data.resolution;
42351         const line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
42352
42353         const paths = [];
42354
42355         let offsetX = 0, offsetY = 0;
42356
42357         for ( let i = 0; i < chars.length; i ++ ) {
42358
42359                 const char = chars[ i ];
42360
42361                 if ( char === '\n' ) {
42362
42363                         offsetX = 0;
42364                         offsetY -= line_height;
42365
42366                 } else {
42367
42368                         const ret = createPath( char, scale, offsetX, offsetY, data );
42369                         offsetX += ret.offsetX;
42370                         paths.push( ret.path );
42371
42372                 }
42373
42374         }
42375
42376         return paths;
42377
42378 }
42379
42380 function createPath( char, scale, offsetX, offsetY, data ) {
42381
42382         const glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
42383
42384         if ( ! glyph ) {
42385
42386                 console.error( 'THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + '.' );
42387
42388                 return;
42389
42390         }
42391
42392         const path = new ShapePath();
42393
42394         let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
42395
42396         if ( glyph.o ) {
42397
42398                 const outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
42399
42400                 for ( let i = 0, l = outline.length; i < l; ) {
42401
42402                         const action = outline[ i ++ ];
42403
42404                         switch ( action ) {
42405
42406                                 case 'm': // moveTo
42407
42408                                         x = outline[ i ++ ] * scale + offsetX;
42409                                         y = outline[ i ++ ] * scale + offsetY;
42410
42411                                         path.moveTo( x, y );
42412
42413                                         break;
42414
42415                                 case 'l': // lineTo
42416
42417                                         x = outline[ i ++ ] * scale + offsetX;
42418                                         y = outline[ i ++ ] * scale + offsetY;
42419
42420                                         path.lineTo( x, y );
42421
42422                                         break;
42423
42424                                 case 'q': // quadraticCurveTo
42425
42426                                         cpx = outline[ i ++ ] * scale + offsetX;
42427                                         cpy = outline[ i ++ ] * scale + offsetY;
42428                                         cpx1 = outline[ i ++ ] * scale + offsetX;
42429                                         cpy1 = outline[ i ++ ] * scale + offsetY;
42430
42431                                         path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
42432
42433                                         break;
42434
42435                                 case 'b': // bezierCurveTo
42436
42437                                         cpx = outline[ i ++ ] * scale + offsetX;
42438                                         cpy = outline[ i ++ ] * scale + offsetY;
42439                                         cpx1 = outline[ i ++ ] * scale + offsetX;
42440                                         cpy1 = outline[ i ++ ] * scale + offsetY;
42441                                         cpx2 = outline[ i ++ ] * scale + offsetX;
42442                                         cpy2 = outline[ i ++ ] * scale + offsetY;
42443
42444                                         path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
42445
42446                                         break;
42447
42448                         }
42449
42450                 }
42451
42452         }
42453
42454         return { offsetX: glyph.ha * scale, path: path };
42455
42456 }
42457
42458 function FontLoader( manager ) {
42459
42460         Loader.call( this, manager );
42461
42462 }
42463
42464 FontLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
42465
42466         constructor: FontLoader,
42467
42468         load: function ( url, onLoad, onProgress, onError ) {
42469
42470                 const scope = this;
42471
42472                 const loader = new FileLoader( this.manager );
42473                 loader.setPath( this.path );
42474                 loader.setRequestHeader( this.requestHeader );
42475                 loader.setWithCredentials( scope.withCredentials );
42476                 loader.load( url, function ( text ) {
42477
42478                         let json;
42479
42480                         try {
42481
42482                                 json = JSON.parse( text );
42483
42484                         } catch ( e ) {
42485
42486                                 console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
42487                                 json = JSON.parse( text.substring( 65, text.length - 2 ) );
42488
42489                         }
42490
42491                         const font = scope.parse( json );
42492
42493                         if ( onLoad ) onLoad( font );
42494
42495                 }, onProgress, onError );
42496
42497         },
42498
42499         parse: function ( json ) {
42500
42501                 return new Font( json );
42502
42503         }
42504
42505 } );
42506
42507 let _context;
42508
42509 const AudioContext = {
42510
42511         getContext: function () {
42512
42513                 if ( _context === undefined ) {
42514
42515                         _context = new ( window.AudioContext || window.webkitAudioContext )();
42516
42517                 }
42518
42519                 return _context;
42520
42521         },
42522
42523         setContext: function ( value ) {
42524
42525                 _context = value;
42526
42527         }
42528
42529 };
42530
42531 function AudioLoader( manager ) {
42532
42533         Loader.call( this, manager );
42534
42535 }
42536
42537 AudioLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
42538
42539         constructor: AudioLoader,
42540
42541         load: function ( url, onLoad, onProgress, onError ) {
42542
42543                 const scope = this;
42544
42545                 const loader = new FileLoader( scope.manager );
42546                 loader.setResponseType( 'arraybuffer' );
42547                 loader.setPath( scope.path );
42548                 loader.setRequestHeader( scope.requestHeader );
42549                 loader.setWithCredentials( scope.withCredentials );
42550                 loader.load( url, function ( buffer ) {
42551
42552                         try {
42553
42554                                 // Create a copy of the buffer. The `decodeAudioData` method
42555                                 // detaches the buffer when complete, preventing reuse.
42556                                 const bufferCopy = buffer.slice( 0 );
42557
42558                                 const context = AudioContext.getContext();
42559                                 context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
42560
42561                                         onLoad( audioBuffer );
42562
42563                                 } );
42564
42565                         } catch ( e ) {
42566
42567                                 if ( onError ) {
42568
42569                                         onError( e );
42570
42571                                 } else {
42572
42573                                         console.error( e );
42574
42575                                 }
42576
42577                                 scope.manager.itemError( url );
42578
42579                         }
42580
42581                 }, onProgress, onError );
42582
42583         }
42584
42585 } );
42586
42587 function HemisphereLightProbe( skyColor, groundColor, intensity ) {
42588
42589         LightProbe.call( this, undefined, intensity );
42590
42591         const color1 = new Color().set( skyColor );
42592         const color2 = new Color().set( groundColor );
42593
42594         const sky = new Vector3( color1.r, color1.g, color1.b );
42595         const ground = new Vector3( color2.r, color2.g, color2.b );
42596
42597         // without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
42598         const c0 = Math.sqrt( Math.PI );
42599         const c1 = c0 * Math.sqrt( 0.75 );
42600
42601         this.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
42602         this.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
42603
42604 }
42605
42606 HemisphereLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
42607
42608         constructor: HemisphereLightProbe,
42609
42610         isHemisphereLightProbe: true,
42611
42612         copy: function ( source ) { // modifying colors not currently supported
42613
42614                 LightProbe.prototype.copy.call( this, source );
42615
42616                 return this;
42617
42618         },
42619
42620         toJSON: function ( meta ) {
42621
42622                 const data = LightProbe.prototype.toJSON.call( this, meta );
42623
42624                 // data.sh = this.sh.toArray(); // todo
42625
42626                 return data;
42627
42628         }
42629
42630 } );
42631
42632 function AmbientLightProbe( color, intensity ) {
42633
42634         LightProbe.call( this, undefined, intensity );
42635
42636         const color1 = new Color().set( color );
42637
42638         // without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
42639         this.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );
42640
42641 }
42642
42643 AmbientLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
42644
42645         constructor: AmbientLightProbe,
42646
42647         isAmbientLightProbe: true,
42648
42649         copy: function ( source ) { // modifying color not currently supported
42650
42651                 LightProbe.prototype.copy.call( this, source );
42652
42653                 return this;
42654
42655         },
42656
42657         toJSON: function ( meta ) {
42658
42659                 const data = LightProbe.prototype.toJSON.call( this, meta );
42660
42661                 // data.sh = this.sh.toArray(); // todo
42662
42663                 return data;
42664
42665         }
42666
42667 } );
42668
42669 const _eyeRight = new Matrix4();
42670 const _eyeLeft = new Matrix4();
42671
42672 function StereoCamera() {
42673
42674         this.type = 'StereoCamera';
42675
42676         this.aspect = 1;
42677
42678         this.eyeSep = 0.064;
42679
42680         this.cameraL = new PerspectiveCamera();
42681         this.cameraL.layers.enable( 1 );
42682         this.cameraL.matrixAutoUpdate = false;
42683
42684         this.cameraR = new PerspectiveCamera();
42685         this.cameraR.layers.enable( 2 );
42686         this.cameraR.matrixAutoUpdate = false;
42687
42688         this._cache = {
42689                 focus: null,
42690                 fov: null,
42691                 aspect: null,
42692                 near: null,
42693                 far: null,
42694                 zoom: null,
42695                 eyeSep: null
42696         };
42697
42698 }
42699
42700 Object.assign( StereoCamera.prototype, {
42701
42702         update: function ( camera ) {
42703
42704                 const cache = this._cache;
42705
42706                 const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
42707                         cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
42708                         cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
42709
42710                 if ( needsUpdate ) {
42711
42712                         cache.focus = camera.focus;
42713                         cache.fov = camera.fov;
42714                         cache.aspect = camera.aspect * this.aspect;
42715                         cache.near = camera.near;
42716                         cache.far = camera.far;
42717                         cache.zoom = camera.zoom;
42718                         cache.eyeSep = this.eyeSep;
42719
42720                         // Off-axis stereoscopic effect based on
42721                         // http://paulbourke.net/stereographics/stereorender/
42722
42723                         const projectionMatrix = camera.projectionMatrix.clone();
42724                         const eyeSepHalf = cache.eyeSep / 2;
42725                         const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
42726                         const ymax = ( cache.near * Math.tan( MathUtils.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
42727                         let xmin, xmax;
42728
42729                         // translate xOffset
42730
42731                         _eyeLeft.elements[ 12 ] = - eyeSepHalf;
42732                         _eyeRight.elements[ 12 ] = eyeSepHalf;
42733
42734                         // for left eye
42735
42736                         xmin = - ymax * cache.aspect + eyeSepOnProjection;
42737                         xmax = ymax * cache.aspect + eyeSepOnProjection;
42738
42739                         projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
42740                         projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
42741
42742                         this.cameraL.projectionMatrix.copy( projectionMatrix );
42743
42744                         // for right eye
42745
42746                         xmin = - ymax * cache.aspect - eyeSepOnProjection;
42747                         xmax = ymax * cache.aspect - eyeSepOnProjection;
42748
42749                         projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
42750                         projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
42751
42752                         this.cameraR.projectionMatrix.copy( projectionMatrix );
42753
42754                 }
42755
42756                 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
42757                 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
42758
42759         }
42760
42761 } );
42762
42763 class Clock {
42764
42765         constructor( autoStart ) {
42766
42767                 this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
42768
42769                 this.startTime = 0;
42770                 this.oldTime = 0;
42771                 this.elapsedTime = 0;
42772
42773                 this.running = false;
42774
42775         }
42776
42777         start() {
42778
42779                 this.startTime = now();
42780
42781                 this.oldTime = this.startTime;
42782                 this.elapsedTime = 0;
42783                 this.running = true;
42784
42785         }
42786
42787         stop() {
42788
42789                 this.getElapsedTime();
42790                 this.running = false;
42791                 this.autoStart = false;
42792
42793         }
42794
42795         getElapsedTime() {
42796
42797                 this.getDelta();
42798                 return this.elapsedTime;
42799
42800         }
42801
42802         getDelta() {
42803
42804                 let diff = 0;
42805
42806                 if ( this.autoStart && ! this.running ) {
42807
42808                         this.start();
42809                         return 0;
42810
42811                 }
42812
42813                 if ( this.running ) {
42814
42815                         const newTime = now();
42816
42817                         diff = ( newTime - this.oldTime ) / 1000;
42818                         this.oldTime = newTime;
42819
42820                         this.elapsedTime += diff;
42821
42822                 }
42823
42824                 return diff;
42825
42826         }
42827
42828 }
42829
42830 function now() {
42831
42832         return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
42833
42834 }
42835
42836 const _position$2 = /*@__PURE__*/ new Vector3();
42837 const _quaternion$3 = /*@__PURE__*/ new Quaternion();
42838 const _scale$1 = /*@__PURE__*/ new Vector3();
42839 const _orientation = /*@__PURE__*/ new Vector3();
42840
42841 class AudioListener extends Object3D {
42842
42843         constructor() {
42844
42845                 super();
42846
42847                 this.type = 'AudioListener';
42848
42849                 this.context = AudioContext.getContext();
42850
42851                 this.gain = this.context.createGain();
42852                 this.gain.connect( this.context.destination );
42853
42854                 this.filter = null;
42855
42856                 this.timeDelta = 0;
42857
42858                 // private
42859
42860                 this._clock = new Clock();
42861
42862         }
42863
42864         getInput() {
42865
42866                 return this.gain;
42867
42868         }
42869
42870         removeFilter() {
42871
42872                 if ( this.filter !== null ) {
42873
42874                         this.gain.disconnect( this.filter );
42875                         this.filter.disconnect( this.context.destination );
42876                         this.gain.connect( this.context.destination );
42877                         this.filter = null;
42878
42879                 }
42880
42881                 return this;
42882
42883         }
42884
42885         getFilter() {
42886
42887                 return this.filter;
42888
42889         }
42890
42891         setFilter( value ) {
42892
42893                 if ( this.filter !== null ) {
42894
42895                         this.gain.disconnect( this.filter );
42896                         this.filter.disconnect( this.context.destination );
42897
42898                 } else {
42899
42900                         this.gain.disconnect( this.context.destination );
42901
42902                 }
42903
42904                 this.filter = value;
42905                 this.gain.connect( this.filter );
42906                 this.filter.connect( this.context.destination );
42907
42908                 return this;
42909
42910         }
42911
42912         getMasterVolume() {
42913
42914                 return this.gain.gain.value;
42915
42916         }
42917
42918         setMasterVolume( value ) {
42919
42920                 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
42921
42922                 return this;
42923
42924         }
42925
42926         updateMatrixWorld( force ) {
42927
42928                 super.updateMatrixWorld( force );
42929
42930                 const listener = this.context.listener;
42931                 const up = this.up;
42932
42933                 this.timeDelta = this._clock.getDelta();
42934
42935                 this.matrixWorld.decompose( _position$2, _quaternion$3, _scale$1 );
42936
42937                 _orientation.set( 0, 0, - 1 ).applyQuaternion( _quaternion$3 );
42938
42939                 if ( listener.positionX ) {
42940
42941                         // code path for Chrome (see #14393)
42942
42943                         const endTime = this.context.currentTime + this.timeDelta;
42944
42945                         listener.positionX.linearRampToValueAtTime( _position$2.x, endTime );
42946                         listener.positionY.linearRampToValueAtTime( _position$2.y, endTime );
42947                         listener.positionZ.linearRampToValueAtTime( _position$2.z, endTime );
42948                         listener.forwardX.linearRampToValueAtTime( _orientation.x, endTime );
42949                         listener.forwardY.linearRampToValueAtTime( _orientation.y, endTime );
42950                         listener.forwardZ.linearRampToValueAtTime( _orientation.z, endTime );
42951                         listener.upX.linearRampToValueAtTime( up.x, endTime );
42952                         listener.upY.linearRampToValueAtTime( up.y, endTime );
42953                         listener.upZ.linearRampToValueAtTime( up.z, endTime );
42954
42955                 } else {
42956
42957                         listener.setPosition( _position$2.x, _position$2.y, _position$2.z );
42958                         listener.setOrientation( _orientation.x, _orientation.y, _orientation.z, up.x, up.y, up.z );
42959
42960                 }
42961
42962         }
42963
42964 }
42965
42966 class Audio extends Object3D {
42967
42968         constructor( listener ) {
42969
42970                 super();
42971
42972                 this.type = 'Audio';
42973
42974                 this.listener = listener;
42975                 this.context = listener.context;
42976
42977                 this.gain = this.context.createGain();
42978                 this.gain.connect( listener.getInput() );
42979
42980                 this.autoplay = false;
42981
42982                 this.buffer = null;
42983                 this.detune = 0;
42984                 this.loop = false;
42985                 this.loopStart = 0;
42986                 this.loopEnd = 0;
42987                 this.offset = 0;
42988                 this.duration = undefined;
42989                 this.playbackRate = 1;
42990                 this.isPlaying = false;
42991                 this.hasPlaybackControl = true;
42992                 this.source = null;
42993                 this.sourceType = 'empty';
42994
42995                 this._startedAt = 0;
42996                 this._progress = 0;
42997                 this._connected = false;
42998
42999                 this.filters = [];
43000
43001         }
43002
43003         getOutput() {
43004
43005                 return this.gain;
43006
43007         }
43008
43009         setNodeSource( audioNode ) {
43010
43011                 this.hasPlaybackControl = false;
43012                 this.sourceType = 'audioNode';
43013                 this.source = audioNode;
43014                 this.connect();
43015
43016                 return this;
43017
43018         }
43019
43020         setMediaElementSource( mediaElement ) {
43021
43022                 this.hasPlaybackControl = false;
43023                 this.sourceType = 'mediaNode';
43024                 this.source = this.context.createMediaElementSource( mediaElement );
43025                 this.connect();
43026
43027                 return this;
43028
43029         }
43030
43031         setMediaStreamSource( mediaStream ) {
43032
43033                 this.hasPlaybackControl = false;
43034                 this.sourceType = 'mediaStreamNode';
43035                 this.source = this.context.createMediaStreamSource( mediaStream );
43036                 this.connect();
43037
43038                 return this;
43039
43040         }
43041
43042         setBuffer( audioBuffer ) {
43043
43044                 this.buffer = audioBuffer;
43045                 this.sourceType = 'buffer';
43046
43047                 if ( this.autoplay ) this.play();
43048
43049                 return this;
43050
43051         }
43052
43053         play( delay = 0 ) {
43054
43055                 if ( this.isPlaying === true ) {
43056
43057                         console.warn( 'THREE.Audio: Audio is already playing.' );
43058                         return;
43059
43060                 }
43061
43062                 if ( this.hasPlaybackControl === false ) {
43063
43064                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
43065                         return;
43066
43067                 }
43068
43069                 this._startedAt = this.context.currentTime + delay;
43070
43071                 const source = this.context.createBufferSource();
43072                 source.buffer = this.buffer;
43073                 source.loop = this.loop;
43074                 source.loopStart = this.loopStart;
43075                 source.loopEnd = this.loopEnd;
43076                 source.onended = this.onEnded.bind( this );
43077                 source.start( this._startedAt, this._progress + this.offset, this.duration );
43078
43079                 this.isPlaying = true;
43080
43081                 this.source = source;
43082
43083                 this.setDetune( this.detune );
43084                 this.setPlaybackRate( this.playbackRate );
43085
43086                 return this.connect();
43087
43088         }
43089
43090         pause() {
43091
43092                 if ( this.hasPlaybackControl === false ) {
43093
43094                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
43095                         return;
43096
43097                 }
43098
43099                 if ( this.isPlaying === true ) {
43100
43101                         // update current progress
43102
43103                         this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
43104
43105                         if ( this.loop === true ) {
43106
43107                                 // ensure _progress does not exceed duration with looped audios
43108
43109                                 this._progress = this._progress % ( this.duration || this.buffer.duration );
43110
43111                         }
43112
43113                         this.source.stop();
43114                         this.source.onended = null;
43115
43116                         this.isPlaying = false;
43117
43118                 }
43119
43120                 return this;
43121
43122         }
43123
43124         stop() {
43125
43126                 if ( this.hasPlaybackControl === false ) {
43127
43128                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
43129                         return;
43130
43131                 }
43132
43133                 this._progress = 0;
43134
43135                 this.source.stop();
43136                 this.source.onended = null;
43137                 this.isPlaying = false;
43138
43139                 return this;
43140
43141         }
43142
43143         connect() {
43144
43145                 if ( this.filters.length > 0 ) {
43146
43147                         this.source.connect( this.filters[ 0 ] );
43148
43149                         for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
43150
43151                                 this.filters[ i - 1 ].connect( this.filters[ i ] );
43152
43153                         }
43154
43155                         this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
43156
43157                 } else {
43158
43159                         this.source.connect( this.getOutput() );
43160
43161                 }
43162
43163                 this._connected = true;
43164
43165                 return this;
43166
43167         }
43168
43169         disconnect() {
43170
43171                 if ( this.filters.length > 0 ) {
43172
43173                         this.source.disconnect( this.filters[ 0 ] );
43174
43175                         for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
43176
43177                                 this.filters[ i - 1 ].disconnect( this.filters[ i ] );
43178
43179                         }
43180
43181                         this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
43182
43183                 } else {
43184
43185                         this.source.disconnect( this.getOutput() );
43186
43187                 }
43188
43189                 this._connected = false;
43190
43191                 return this;
43192
43193         }
43194
43195         getFilters() {
43196
43197                 return this.filters;
43198
43199         }
43200
43201         setFilters( value ) {
43202
43203                 if ( ! value ) value = [];
43204
43205                 if ( this._connected === true ) {
43206
43207                         this.disconnect();
43208                         this.filters = value.slice();
43209                         this.connect();
43210
43211                 } else {
43212
43213                         this.filters = value.slice();
43214
43215                 }
43216
43217                 return this;
43218
43219         }
43220
43221         setDetune( value ) {
43222
43223                 this.detune = value;
43224
43225                 if ( this.source.detune === undefined ) return; // only set detune when available
43226
43227                 if ( this.isPlaying === true ) {
43228
43229                         this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
43230
43231                 }
43232
43233                 return this;
43234
43235         }
43236
43237         getDetune() {
43238
43239                 return this.detune;
43240
43241         }
43242
43243         getFilter() {
43244
43245                 return this.getFilters()[ 0 ];
43246
43247         }
43248
43249         setFilter( filter ) {
43250
43251                 return this.setFilters( filter ? [ filter ] : [] );
43252
43253         }
43254
43255         setPlaybackRate( value ) {
43256
43257                 if ( this.hasPlaybackControl === false ) {
43258
43259                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
43260                         return;
43261
43262                 }
43263
43264                 this.playbackRate = value;
43265
43266                 if ( this.isPlaying === true ) {
43267
43268                         this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
43269
43270                 }
43271
43272                 return this;
43273
43274         }
43275
43276         getPlaybackRate() {
43277
43278                 return this.playbackRate;
43279
43280         }
43281
43282         onEnded() {
43283
43284                 this.isPlaying = false;
43285
43286         }
43287
43288         getLoop() {
43289
43290                 if ( this.hasPlaybackControl === false ) {
43291
43292                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
43293                         return false;
43294
43295                 }
43296
43297                 return this.loop;
43298
43299         }
43300
43301         setLoop( value ) {
43302
43303                 if ( this.hasPlaybackControl === false ) {
43304
43305                         console.warn( 'THREE.Audio: this Audio has no playback control.' );
43306                         return;
43307
43308                 }
43309
43310                 this.loop = value;
43311
43312                 if ( this.isPlaying === true ) {
43313
43314                         this.source.loop = this.loop;
43315
43316                 }
43317
43318                 return this;
43319
43320         }
43321
43322         setLoopStart( value ) {
43323
43324                 this.loopStart = value;
43325
43326                 return this;
43327
43328         }
43329
43330         setLoopEnd( value ) {
43331
43332                 this.loopEnd = value;
43333
43334                 return this;
43335
43336         }
43337
43338         getVolume() {
43339
43340                 return this.gain.gain.value;
43341
43342         }
43343
43344         setVolume( value ) {
43345
43346                 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
43347
43348                 return this;
43349
43350         }
43351
43352 }
43353
43354 const _position$3 = /*@__PURE__*/ new Vector3();
43355 const _quaternion$4 = /*@__PURE__*/ new Quaternion();
43356 const _scale$2 = /*@__PURE__*/ new Vector3();
43357 const _orientation$1 = /*@__PURE__*/ new Vector3();
43358
43359 class PositionalAudio extends Audio {
43360
43361         constructor( listener ) {
43362
43363                 super( listener );
43364
43365                 this.panner = this.context.createPanner();
43366                 this.panner.panningModel = 'HRTF';
43367                 this.panner.connect( this.gain );
43368
43369         }
43370
43371         getOutput() {
43372
43373                 return this.panner;
43374
43375         }
43376
43377         getRefDistance() {
43378
43379                 return this.panner.refDistance;
43380
43381         }
43382
43383         setRefDistance( value ) {
43384
43385                 this.panner.refDistance = value;
43386
43387                 return this;
43388
43389         }
43390
43391         getRolloffFactor() {
43392
43393                 return this.panner.rolloffFactor;
43394
43395         }
43396
43397         setRolloffFactor( value ) {
43398
43399                 this.panner.rolloffFactor = value;
43400
43401                 return this;
43402
43403         }
43404
43405         getDistanceModel() {
43406
43407                 return this.panner.distanceModel;
43408
43409         }
43410
43411         setDistanceModel( value ) {
43412
43413                 this.panner.distanceModel = value;
43414
43415                 return this;
43416
43417         }
43418
43419         getMaxDistance() {
43420
43421                 return this.panner.maxDistance;
43422
43423         }
43424
43425         setMaxDistance( value ) {
43426
43427                 this.panner.maxDistance = value;
43428
43429                 return this;
43430
43431         }
43432
43433         setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
43434
43435                 this.panner.coneInnerAngle = coneInnerAngle;
43436                 this.panner.coneOuterAngle = coneOuterAngle;
43437                 this.panner.coneOuterGain = coneOuterGain;
43438
43439                 return this;
43440
43441         }
43442
43443         updateMatrixWorld( force ) {
43444
43445                 super.updateMatrixWorld( force );
43446
43447                 if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
43448
43449                 this.matrixWorld.decompose( _position$3, _quaternion$4, _scale$2 );
43450
43451                 _orientation$1.set( 0, 0, 1 ).applyQuaternion( _quaternion$4 );
43452
43453                 const panner = this.panner;
43454
43455                 if ( panner.positionX ) {
43456
43457                         // code path for Chrome and Firefox (see #14393)
43458
43459                         const endTime = this.context.currentTime + this.listener.timeDelta;
43460
43461                         panner.positionX.linearRampToValueAtTime( _position$3.x, endTime );
43462                         panner.positionY.linearRampToValueAtTime( _position$3.y, endTime );
43463                         panner.positionZ.linearRampToValueAtTime( _position$3.z, endTime );
43464                         panner.orientationX.linearRampToValueAtTime( _orientation$1.x, endTime );
43465                         panner.orientationY.linearRampToValueAtTime( _orientation$1.y, endTime );
43466                         panner.orientationZ.linearRampToValueAtTime( _orientation$1.z, endTime );
43467
43468                 } else {
43469
43470                         panner.setPosition( _position$3.x, _position$3.y, _position$3.z );
43471                         panner.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z );
43472
43473                 }
43474
43475         }
43476
43477 }
43478
43479 class AudioAnalyser {
43480
43481         constructor( audio, fftSize = 2048 ) {
43482
43483                 this.analyser = audio.context.createAnalyser();
43484                 this.analyser.fftSize = fftSize;
43485
43486                 this.data = new Uint8Array( this.analyser.frequencyBinCount );
43487
43488                 audio.getOutput().connect( this.analyser );
43489
43490         }
43491
43492
43493         getFrequencyData() {
43494
43495                 this.analyser.getByteFrequencyData( this.data );
43496
43497                 return this.data;
43498
43499         }
43500
43501         getAverageFrequency() {
43502
43503                 let value = 0;
43504                 const data = this.getFrequencyData();
43505
43506                 for ( let i = 0; i < data.length; i ++ ) {
43507
43508                         value += data[ i ];
43509
43510                 }
43511
43512                 return value / data.length;
43513
43514         }
43515
43516 }
43517
43518 function PropertyMixer( binding, typeName, valueSize ) {
43519
43520         this.binding = binding;
43521         this.valueSize = valueSize;
43522
43523         let mixFunction,
43524                 mixFunctionAdditive,
43525                 setIdentity;
43526
43527         // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
43528         //
43529         // interpolators can use .buffer as their .result
43530         // the data then goes to 'incoming'
43531         //
43532         // 'accu0' and 'accu1' are used frame-interleaved for
43533         // the cumulative result and are compared to detect
43534         // changes
43535         //
43536         // 'orig' stores the original state of the property
43537         //
43538         // 'add' is used for additive cumulative results
43539         //
43540         // 'work' is optional and is only present for quaternion types. It is used
43541         // to store intermediate quaternion multiplication results
43542
43543         switch ( typeName ) {
43544
43545                 case 'quaternion':
43546                         mixFunction = this._slerp;
43547                         mixFunctionAdditive = this._slerpAdditive;
43548                         setIdentity = this._setAdditiveIdentityQuaternion;
43549
43550                         this.buffer = new Float64Array( valueSize * 6 );
43551                         this._workIndex = 5;
43552                         break;
43553
43554                 case 'string':
43555                 case 'bool':
43556                         mixFunction = this._select;
43557
43558                         // Use the regular mix function and for additive on these types,
43559                         // additive is not relevant for non-numeric types
43560                         mixFunctionAdditive = this._select;
43561
43562                         setIdentity = this._setAdditiveIdentityOther;
43563
43564                         this.buffer = new Array( valueSize * 5 );
43565                         break;
43566
43567                 default:
43568                         mixFunction = this._lerp;
43569                         mixFunctionAdditive = this._lerpAdditive;
43570                         setIdentity = this._setAdditiveIdentityNumeric;
43571
43572                         this.buffer = new Float64Array( valueSize * 5 );
43573
43574         }
43575
43576         this._mixBufferRegion = mixFunction;
43577         this._mixBufferRegionAdditive = mixFunctionAdditive;
43578         this._setIdentity = setIdentity;
43579         this._origIndex = 3;
43580         this._addIndex = 4;
43581
43582         this.cumulativeWeight = 0;
43583         this.cumulativeWeightAdditive = 0;
43584
43585         this.useCount = 0;
43586         this.referenceCount = 0;
43587
43588 }
43589
43590 Object.assign( PropertyMixer.prototype, {
43591
43592         // accumulate data in the 'incoming' region into 'accu<i>'
43593         accumulate: function ( accuIndex, weight ) {
43594
43595                 // note: happily accumulating nothing when weight = 0, the caller knows
43596                 // the weight and shouldn't have made the call in the first place
43597
43598                 const buffer = this.buffer,
43599                         stride = this.valueSize,
43600                         offset = accuIndex * stride + stride;
43601
43602                 let currentWeight = this.cumulativeWeight;
43603
43604                 if ( currentWeight === 0 ) {
43605
43606                         // accuN := incoming * weight
43607
43608                         for ( let i = 0; i !== stride; ++ i ) {
43609
43610                                 buffer[ offset + i ] = buffer[ i ];
43611
43612                         }
43613
43614                         currentWeight = weight;
43615
43616                 } else {
43617
43618                         // accuN := accuN + incoming * weight
43619
43620                         currentWeight += weight;
43621                         const mix = weight / currentWeight;
43622                         this._mixBufferRegion( buffer, offset, 0, mix, stride );
43623
43624                 }
43625
43626                 this.cumulativeWeight = currentWeight;
43627
43628         },
43629
43630         // accumulate data in the 'incoming' region into 'add'
43631         accumulateAdditive: function ( weight ) {
43632
43633                 const buffer = this.buffer,
43634                         stride = this.valueSize,
43635                         offset = stride * this._addIndex;
43636
43637                 if ( this.cumulativeWeightAdditive === 0 ) {
43638
43639                         // add = identity
43640
43641                         this._setIdentity();
43642
43643                 }
43644
43645                 // add := add + incoming * weight
43646
43647                 this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
43648                 this.cumulativeWeightAdditive += weight;
43649
43650         },
43651
43652         // apply the state of 'accu<i>' to the binding when accus differ
43653         apply: function ( accuIndex ) {
43654
43655                 const stride = this.valueSize,
43656                         buffer = this.buffer,
43657                         offset = accuIndex * stride + stride,
43658
43659                         weight = this.cumulativeWeight,
43660                         weightAdditive = this.cumulativeWeightAdditive,
43661
43662                         binding = this.binding;
43663
43664                 this.cumulativeWeight = 0;
43665                 this.cumulativeWeightAdditive = 0;
43666
43667                 if ( weight < 1 ) {
43668
43669                         // accuN := accuN + original * ( 1 - cumulativeWeight )
43670
43671                         const originalValueOffset = stride * this._origIndex;
43672
43673                         this._mixBufferRegion(
43674                                 buffer, offset, originalValueOffset, 1 - weight, stride );
43675
43676                 }
43677
43678                 if ( weightAdditive > 0 ) {
43679
43680                         // accuN := accuN + additive accuN
43681
43682                         this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
43683
43684                 }
43685
43686                 for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
43687
43688                         if ( buffer[ i ] !== buffer[ i + stride ] ) {
43689
43690                                 // value has changed -> update scene graph
43691
43692                                 binding.setValue( buffer, offset );
43693                                 break;
43694
43695                         }
43696
43697                 }
43698
43699         },
43700
43701         // remember the state of the bound property and copy it to both accus
43702         saveOriginalState: function () {
43703
43704                 const binding = this.binding;
43705
43706                 const buffer = this.buffer,
43707                         stride = this.valueSize,
43708
43709                         originalValueOffset = stride * this._origIndex;
43710
43711                 binding.getValue( buffer, originalValueOffset );
43712
43713                 // accu[0..1] := orig -- initially detect changes against the original
43714                 for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
43715
43716                         buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
43717
43718                 }
43719
43720                 // Add to identity for additive
43721                 this._setIdentity();
43722
43723                 this.cumulativeWeight = 0;
43724                 this.cumulativeWeightAdditive = 0;
43725
43726         },
43727
43728         // apply the state previously taken via 'saveOriginalState' to the binding
43729         restoreOriginalState: function () {
43730
43731                 const originalValueOffset = this.valueSize * 3;
43732                 this.binding.setValue( this.buffer, originalValueOffset );
43733
43734         },
43735
43736         _setAdditiveIdentityNumeric: function () {
43737
43738                 const startIndex = this._addIndex * this.valueSize;
43739                 const endIndex = startIndex + this.valueSize;
43740
43741                 for ( let i = startIndex; i < endIndex; i ++ ) {
43742
43743                         this.buffer[ i ] = 0;
43744
43745                 }
43746
43747         },
43748
43749         _setAdditiveIdentityQuaternion: function () {
43750
43751                 this._setAdditiveIdentityNumeric();
43752                 this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
43753
43754         },
43755
43756         _setAdditiveIdentityOther: function () {
43757
43758                 const startIndex = this._origIndex * this.valueSize;
43759                 const targetIndex = this._addIndex * this.valueSize;
43760
43761                 for ( let i = 0; i < this.valueSize; i ++ ) {
43762
43763                         this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
43764
43765                 }
43766
43767         },
43768
43769
43770         // mix functions
43771
43772         _select: function ( buffer, dstOffset, srcOffset, t, stride ) {
43773
43774                 if ( t >= 0.5 ) {
43775
43776                         for ( let i = 0; i !== stride; ++ i ) {
43777
43778                                 buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
43779
43780                         }
43781
43782                 }
43783
43784         },
43785
43786         _slerp: function ( buffer, dstOffset, srcOffset, t ) {
43787
43788                 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
43789
43790         },
43791
43792         _slerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
43793
43794                 const workOffset = this._workIndex * stride;
43795
43796                 // Store result in intermediate buffer offset
43797                 Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
43798
43799                 // Slerp to the intermediate result
43800                 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
43801
43802         },
43803
43804         _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
43805
43806                 const s = 1 - t;
43807
43808                 for ( let i = 0; i !== stride; ++ i ) {
43809
43810                         const j = dstOffset + i;
43811
43812                         buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
43813
43814                 }
43815
43816         },
43817
43818         _lerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
43819
43820                 for ( let i = 0; i !== stride; ++ i ) {
43821
43822                         const j = dstOffset + i;
43823
43824                         buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
43825
43826                 }
43827
43828         }
43829
43830 } );
43831
43832 // Characters [].:/ are reserved for track binding syntax.
43833 const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
43834 const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
43835
43836 // Attempts to allow node names from any language. ES5's `\w` regexp matches
43837 // only latin characters, and the unicode \p{L} is not yet supported. So
43838 // instead, we exclude reserved characters and match everything else.
43839 const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
43840 const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
43841
43842 // Parent directories, delimited by '/' or ':'. Currently unused, but must
43843 // be matched to parse the rest of the track name.
43844 const _directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
43845
43846 // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
43847 const _nodeRe = /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
43848
43849 // Object on target node, and accessor. May not contain reserved
43850 // characters. Accessor may contain any character except closing bracket.
43851 const _objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
43852
43853 // Property and accessor. May not contain reserved characters. Accessor may
43854 // contain any non-bracket characters.
43855 const _propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
43856
43857 const _trackRe = new RegExp( ''
43858         + '^'
43859         + _directoryRe
43860         + _nodeRe
43861         + _objectRe
43862         + _propertyRe
43863         + '$'
43864 );
43865
43866 const _supportedObjectNames = [ 'material', 'materials', 'bones' ];
43867
43868 function Composite( targetGroup, path, optionalParsedPath ) {
43869
43870         const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
43871
43872         this._targetGroup = targetGroup;
43873         this._bindings = targetGroup.subscribe_( path, parsedPath );
43874
43875 }
43876
43877 Object.assign( Composite.prototype, {
43878
43879         getValue: function ( array, offset ) {
43880
43881                 this.bind(); // bind all binding
43882
43883                 const firstValidIndex = this._targetGroup.nCachedObjects_,
43884                         binding = this._bindings[ firstValidIndex ];
43885
43886                 // and only call .getValue on the first
43887                 if ( binding !== undefined ) binding.getValue( array, offset );
43888
43889         },
43890
43891         setValue: function ( array, offset ) {
43892
43893                 const bindings = this._bindings;
43894
43895                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
43896
43897                         bindings[ i ].setValue( array, offset );
43898
43899                 }
43900
43901         },
43902
43903         bind: function () {
43904
43905                 const bindings = this._bindings;
43906
43907                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
43908
43909                         bindings[ i ].bind();
43910
43911                 }
43912
43913         },
43914
43915         unbind: function () {
43916
43917                 const bindings = this._bindings;
43918
43919                 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
43920
43921                         bindings[ i ].unbind();
43922
43923                 }
43924
43925         }
43926
43927 } );
43928
43929
43930 function PropertyBinding( rootNode, path, parsedPath ) {
43931
43932         this.path = path;
43933         this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
43934
43935         this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
43936
43937         this.rootNode = rootNode;
43938
43939 }
43940
43941 Object.assign( PropertyBinding, {
43942
43943         Composite: Composite,
43944
43945         create: function ( root, path, parsedPath ) {
43946
43947                 if ( ! ( root && root.isAnimationObjectGroup ) ) {
43948
43949                         return new PropertyBinding( root, path, parsedPath );
43950
43951                 } else {
43952
43953                         return new PropertyBinding.Composite( root, path, parsedPath );
43954
43955                 }
43956
43957         },
43958
43959         /**
43960          * Replaces spaces with underscores and removes unsupported characters from
43961          * node names, to ensure compatibility with parseTrackName().
43962          *
43963          * @param {string} name Node name to be sanitized.
43964          * @return {string}
43965          */
43966         sanitizeNodeName: function ( name ) {
43967
43968                 return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
43969
43970         },
43971
43972         parseTrackName: function ( trackName ) {
43973
43974                 const matches = _trackRe.exec( trackName );
43975
43976                 if ( ! matches ) {
43977
43978                         throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
43979
43980                 }
43981
43982                 const results = {
43983                         // directoryName: matches[ 1 ], // (tschw) currently unused
43984                         nodeName: matches[ 2 ],
43985                         objectName: matches[ 3 ],
43986                         objectIndex: matches[ 4 ],
43987                         propertyName: matches[ 5 ], // required
43988                         propertyIndex: matches[ 6 ]
43989                 };
43990
43991                 const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
43992
43993                 if ( lastDot !== undefined && lastDot !== - 1 ) {
43994
43995                         const objectName = results.nodeName.substring( lastDot + 1 );
43996
43997                         // Object names must be checked against an allowlist. Otherwise, there
43998                         // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
43999                         // 'bar' could be the objectName, or part of a nodeName (which can
44000                         // include '.' characters).
44001                         if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
44002
44003                                 results.nodeName = results.nodeName.substring( 0, lastDot );
44004                                 results.objectName = objectName;
44005
44006                         }
44007
44008                 }
44009
44010                 if ( results.propertyName === null || results.propertyName.length === 0 ) {
44011
44012                         throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
44013
44014                 }
44015
44016                 return results;
44017
44018         },
44019
44020         findNode: function ( root, nodeName ) {
44021
44022                 if ( ! nodeName || nodeName === "" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
44023
44024                         return root;
44025
44026                 }
44027
44028                 // search into skeleton bones.
44029                 if ( root.skeleton ) {
44030
44031                         const bone = root.skeleton.getBoneByName( nodeName );
44032
44033                         if ( bone !== undefined ) {
44034
44035                                 return bone;
44036
44037                         }
44038
44039                 }
44040
44041                 // search into node subtree.
44042                 if ( root.children ) {
44043
44044                         const searchNodeSubtree = function ( children ) {
44045
44046                                 for ( let i = 0; i < children.length; i ++ ) {
44047
44048                                         const childNode = children[ i ];
44049
44050                                         if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
44051
44052                                                 return childNode;
44053
44054                                         }
44055
44056                                         const result = searchNodeSubtree( childNode.children );
44057
44058                                         if ( result ) return result;
44059
44060                                 }
44061
44062                                 return null;
44063
44064                         };
44065
44066                         const subTreeNode = searchNodeSubtree( root.children );
44067
44068                         if ( subTreeNode ) {
44069
44070                                 return subTreeNode;
44071
44072                         }
44073
44074                 }
44075
44076                 return null;
44077
44078         }
44079
44080 } );
44081
44082 Object.assign( PropertyBinding.prototype, { // prototype, continued
44083
44084         // these are used to "bind" a nonexistent property
44085         _getValue_unavailable: function () {},
44086         _setValue_unavailable: function () {},
44087
44088         BindingType: {
44089                 Direct: 0,
44090                 EntireArray: 1,
44091                 ArrayElement: 2,
44092                 HasFromToArray: 3
44093         },
44094
44095         Versioning: {
44096                 None: 0,
44097                 NeedsUpdate: 1,
44098                 MatrixWorldNeedsUpdate: 2
44099         },
44100
44101         GetterByBindingType: [
44102
44103                 function getValue_direct( buffer, offset ) {
44104
44105                         buffer[ offset ] = this.node[ this.propertyName ];
44106
44107                 },
44108
44109                 function getValue_array( buffer, offset ) {
44110
44111                         const source = this.resolvedProperty;
44112
44113                         for ( let i = 0, n = source.length; i !== n; ++ i ) {
44114
44115                                 buffer[ offset ++ ] = source[ i ];
44116
44117                         }
44118
44119                 },
44120
44121                 function getValue_arrayElement( buffer, offset ) {
44122
44123                         buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
44124
44125                 },
44126
44127                 function getValue_toArray( buffer, offset ) {
44128
44129                         this.resolvedProperty.toArray( buffer, offset );
44130
44131                 }
44132
44133         ],
44134
44135         SetterByBindingTypeAndVersioning: [
44136
44137                 [
44138                         // Direct
44139
44140                         function setValue_direct( buffer, offset ) {
44141
44142                                 this.targetObject[ this.propertyName ] = buffer[ offset ];
44143
44144                         },
44145
44146                         function setValue_direct_setNeedsUpdate( buffer, offset ) {
44147
44148                                 this.targetObject[ this.propertyName ] = buffer[ offset ];
44149                                 this.targetObject.needsUpdate = true;
44150
44151                         },
44152
44153                         function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
44154
44155                                 this.targetObject[ this.propertyName ] = buffer[ offset ];
44156                                 this.targetObject.matrixWorldNeedsUpdate = true;
44157
44158                         }
44159
44160                 ], [
44161
44162                         // EntireArray
44163
44164                         function setValue_array( buffer, offset ) {
44165
44166                                 const dest = this.resolvedProperty;
44167
44168                                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
44169
44170                                         dest[ i ] = buffer[ offset ++ ];
44171
44172                                 }
44173
44174                         },
44175
44176                         function setValue_array_setNeedsUpdate( buffer, offset ) {
44177
44178                                 const dest = this.resolvedProperty;
44179
44180                                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
44181
44182                                         dest[ i ] = buffer[ offset ++ ];
44183
44184                                 }
44185
44186                                 this.targetObject.needsUpdate = true;
44187
44188                         },
44189
44190                         function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
44191
44192                                 const dest = this.resolvedProperty;
44193
44194                                 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
44195
44196                                         dest[ i ] = buffer[ offset ++ ];
44197
44198                                 }
44199
44200                                 this.targetObject.matrixWorldNeedsUpdate = true;
44201
44202                         }
44203
44204                 ], [
44205
44206                         // ArrayElement
44207
44208                         function setValue_arrayElement( buffer, offset ) {
44209
44210                                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
44211
44212                         },
44213
44214                         function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
44215
44216                                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
44217                                 this.targetObject.needsUpdate = true;
44218
44219                         },
44220
44221                         function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
44222
44223                                 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
44224                                 this.targetObject.matrixWorldNeedsUpdate = true;
44225
44226                         }
44227
44228                 ], [
44229
44230                         // HasToFromArray
44231
44232                         function setValue_fromArray( buffer, offset ) {
44233
44234                                 this.resolvedProperty.fromArray( buffer, offset );
44235
44236                         },
44237
44238                         function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
44239
44240                                 this.resolvedProperty.fromArray( buffer, offset );
44241                                 this.targetObject.needsUpdate = true;
44242
44243                         },
44244
44245                         function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
44246
44247                                 this.resolvedProperty.fromArray( buffer, offset );
44248                                 this.targetObject.matrixWorldNeedsUpdate = true;
44249
44250                         }
44251
44252                 ]
44253
44254         ],
44255
44256         getValue: function getValue_unbound( targetArray, offset ) {
44257
44258                 this.bind();
44259                 this.getValue( targetArray, offset );
44260
44261                 // Note: This class uses a State pattern on a per-method basis:
44262                 // 'bind' sets 'this.getValue' / 'setValue' and shadows the
44263                 // prototype version of these methods with one that represents
44264                 // the bound state. When the property is not found, the methods
44265                 // become no-ops.
44266
44267         },
44268
44269         setValue: function getValue_unbound( sourceArray, offset ) {
44270
44271                 this.bind();
44272                 this.setValue( sourceArray, offset );
44273
44274         },
44275
44276         // create getter / setter pair for a property in the scene graph
44277         bind: function () {
44278
44279                 let targetObject = this.node;
44280                 const parsedPath = this.parsedPath;
44281
44282                 const objectName = parsedPath.objectName;
44283                 const propertyName = parsedPath.propertyName;
44284                 let propertyIndex = parsedPath.propertyIndex;
44285
44286                 if ( ! targetObject ) {
44287
44288                         targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
44289
44290                         this.node = targetObject;
44291
44292                 }
44293
44294                 // set fail state so we can just 'return' on error
44295                 this.getValue = this._getValue_unavailable;
44296                 this.setValue = this._setValue_unavailable;
44297
44298                 // ensure there is a value node
44299                 if ( ! targetObject ) {
44300
44301                         console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
44302                         return;
44303
44304                 }
44305
44306                 if ( objectName ) {
44307
44308                         let objectIndex = parsedPath.objectIndex;
44309
44310                         // special cases were we need to reach deeper into the hierarchy to get the face materials....
44311                         switch ( objectName ) {
44312
44313                                 case 'materials':
44314
44315                                         if ( ! targetObject.material ) {
44316
44317                                                 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
44318                                                 return;
44319
44320                                         }
44321
44322                                         if ( ! targetObject.material.materials ) {
44323
44324                                                 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
44325                                                 return;
44326
44327                                         }
44328
44329                                         targetObject = targetObject.material.materials;
44330
44331                                         break;
44332
44333                                 case 'bones':
44334
44335                                         if ( ! targetObject.skeleton ) {
44336
44337                                                 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
44338                                                 return;
44339
44340                                         }
44341
44342                                         // potential future optimization: skip this if propertyIndex is already an integer
44343                                         // and convert the integer string to a true integer.
44344
44345                                         targetObject = targetObject.skeleton.bones;
44346
44347                                         // support resolving morphTarget names into indices.
44348                                         for ( let i = 0; i < targetObject.length; i ++ ) {
44349
44350                                                 if ( targetObject[ i ].name === objectIndex ) {
44351
44352                                                         objectIndex = i;
44353                                                         break;
44354
44355                                                 }
44356
44357                                         }
44358
44359                                         break;
44360
44361                                 default:
44362
44363                                         if ( targetObject[ objectName ] === undefined ) {
44364
44365                                                 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
44366                                                 return;
44367
44368                                         }
44369
44370                                         targetObject = targetObject[ objectName ];
44371
44372                         }
44373
44374
44375                         if ( objectIndex !== undefined ) {
44376
44377                                 if ( targetObject[ objectIndex ] === undefined ) {
44378
44379                                         console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
44380                                         return;
44381
44382                                 }
44383
44384                                 targetObject = targetObject[ objectIndex ];
44385
44386                         }
44387
44388                 }
44389
44390                 // resolve property
44391                 const nodeProperty = targetObject[ propertyName ];
44392
44393                 if ( nodeProperty === undefined ) {
44394
44395                         const nodeName = parsedPath.nodeName;
44396
44397                         console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
44398                                 '.' + propertyName + ' but it wasn\'t found.', targetObject );
44399                         return;
44400
44401                 }
44402
44403                 // determine versioning scheme
44404                 let versioning = this.Versioning.None;
44405
44406                 this.targetObject = targetObject;
44407
44408                 if ( targetObject.needsUpdate !== undefined ) { // material
44409
44410                         versioning = this.Versioning.NeedsUpdate;
44411
44412                 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
44413
44414                         versioning = this.Versioning.MatrixWorldNeedsUpdate;
44415
44416                 }
44417
44418                 // determine how the property gets bound
44419                 let bindingType = this.BindingType.Direct;
44420
44421                 if ( propertyIndex !== undefined ) {
44422
44423                         // access a sub element of the property array (only primitives are supported right now)
44424
44425                         if ( propertyName === "morphTargetInfluences" ) {
44426
44427                                 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
44428
44429                                 // support resolving morphTarget names into indices.
44430                                 if ( ! targetObject.geometry ) {
44431
44432                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
44433                                         return;
44434
44435                                 }
44436
44437                                 if ( targetObject.geometry.isBufferGeometry ) {
44438
44439                                         if ( ! targetObject.geometry.morphAttributes ) {
44440
44441                                                 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
44442                                                 return;
44443
44444                                         }
44445
44446                                         if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
44447
44448                                                 propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
44449
44450                                         }
44451
44452
44453                                 } else {
44454
44455                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences on THREE.Geometry. Use THREE.BufferGeometry instead.', this );
44456                                         return;
44457
44458                                 }
44459
44460                         }
44461
44462                         bindingType = this.BindingType.ArrayElement;
44463
44464                         this.resolvedProperty = nodeProperty;
44465                         this.propertyIndex = propertyIndex;
44466
44467                 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
44468
44469                         // must use copy for Object3D.Euler/Quaternion
44470
44471                         bindingType = this.BindingType.HasFromToArray;
44472
44473                         this.resolvedProperty = nodeProperty;
44474
44475                 } else if ( Array.isArray( nodeProperty ) ) {
44476
44477                         bindingType = this.BindingType.EntireArray;
44478
44479                         this.resolvedProperty = nodeProperty;
44480
44481                 } else {
44482
44483                         this.propertyName = propertyName;
44484
44485                 }
44486
44487                 // select getter / setter
44488                 this.getValue = this.GetterByBindingType[ bindingType ];
44489                 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
44490
44491         },
44492
44493         unbind: function () {
44494
44495                 this.node = null;
44496
44497                 // back to the prototype version of getValue / setValue
44498                 // note: avoiding to mutate the shape of 'this' via 'delete'
44499                 this.getValue = this._getValue_unbound;
44500                 this.setValue = this._setValue_unbound;
44501
44502         }
44503
44504 } );
44505
44506 // DECLARE ALIAS AFTER assign prototype
44507 Object.assign( PropertyBinding.prototype, {
44508
44509         // initial state of these methods that calls 'bind'
44510         _getValue_unbound: PropertyBinding.prototype.getValue,
44511         _setValue_unbound: PropertyBinding.prototype.setValue,
44512
44513 } );
44514
44515 /**
44516  *
44517  * A group of objects that receives a shared animation state.
44518  *
44519  * Usage:
44520  *
44521  *  - Add objects you would otherwise pass as 'root' to the
44522  *    constructor or the .clipAction method of AnimationMixer.
44523  *
44524  *  - Instead pass this object as 'root'.
44525  *
44526  *  - You can also add and remove objects later when the mixer
44527  *    is running.
44528  *
44529  * Note:
44530  *
44531  *    Objects of this class appear as one object to the mixer,
44532  *    so cache control of the individual objects must be done
44533  *    on the group.
44534  *
44535  * Limitation:
44536  *
44537  *  - The animated properties must be compatible among the
44538  *    all objects in the group.
44539  *
44540  *  - A single property can either be controlled through a
44541  *    target group or directly, but not both.
44542  */
44543
44544 function AnimationObjectGroup() {
44545
44546         this.uuid = MathUtils.generateUUID();
44547
44548         // cached objects followed by the active ones
44549         this._objects = Array.prototype.slice.call( arguments );
44550
44551         this.nCachedObjects_ = 0; // threshold
44552         // note: read by PropertyBinding.Composite
44553
44554         const indices = {};
44555         this._indicesByUUID = indices; // for bookkeeping
44556
44557         for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
44558
44559                 indices[ arguments[ i ].uuid ] = i;
44560
44561         }
44562
44563         this._paths = []; // inside: string
44564         this._parsedPaths = []; // inside: { we don't care, here }
44565         this._bindings = []; // inside: Array< PropertyBinding >
44566         this._bindingsIndicesByPath = {}; // inside: indices in these arrays
44567
44568         const scope = this;
44569
44570         this.stats = {
44571
44572                 objects: {
44573                         get total() {
44574
44575                                 return scope._objects.length;
44576
44577                         },
44578                         get inUse() {
44579
44580                                 return this.total - scope.nCachedObjects_;
44581
44582                         }
44583                 },
44584                 get bindingsPerObject() {
44585
44586                         return scope._bindings.length;
44587
44588                 }
44589
44590         };
44591
44592 }
44593
44594 Object.assign( AnimationObjectGroup.prototype, {
44595
44596         isAnimationObjectGroup: true,
44597
44598         add: function () {
44599
44600                 const objects = this._objects,
44601                         indicesByUUID = this._indicesByUUID,
44602                         paths = this._paths,
44603                         parsedPaths = this._parsedPaths,
44604                         bindings = this._bindings,
44605                         nBindings = bindings.length;
44606
44607                 let knownObject = undefined,
44608                         nObjects = objects.length,
44609                         nCachedObjects = this.nCachedObjects_;
44610
44611                 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
44612
44613                         const object = arguments[ i ],
44614                                 uuid = object.uuid;
44615                         let index = indicesByUUID[ uuid ];
44616
44617                         if ( index === undefined ) {
44618
44619                                 // unknown object -> add it to the ACTIVE region
44620
44621                                 index = nObjects ++;
44622                                 indicesByUUID[ uuid ] = index;
44623                                 objects.push( object );
44624
44625                                 // accounting is done, now do the same for all bindings
44626
44627                                 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
44628
44629                                         bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
44630
44631                                 }
44632
44633                         } else if ( index < nCachedObjects ) {
44634
44635                                 knownObject = objects[ index ];
44636
44637                                 // move existing object to the ACTIVE region
44638
44639                                 const firstActiveIndex = -- nCachedObjects,
44640                                         lastCachedObject = objects[ firstActiveIndex ];
44641
44642                                 indicesByUUID[ lastCachedObject.uuid ] = index;
44643                                 objects[ index ] = lastCachedObject;
44644
44645                                 indicesByUUID[ uuid ] = firstActiveIndex;
44646                                 objects[ firstActiveIndex ] = object;
44647
44648                                 // accounting is done, now do the same for all bindings
44649
44650                                 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
44651
44652                                         const bindingsForPath = bindings[ j ],
44653                                                 lastCached = bindingsForPath[ firstActiveIndex ];
44654
44655                                         let binding = bindingsForPath[ index ];
44656
44657                                         bindingsForPath[ index ] = lastCached;
44658
44659                                         if ( binding === undefined ) {
44660
44661                                                 // since we do not bother to create new bindings
44662                                                 // for objects that are cached, the binding may
44663                                                 // or may not exist
44664
44665                                                 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
44666
44667                                         }
44668
44669                                         bindingsForPath[ firstActiveIndex ] = binding;
44670
44671                                 }
44672
44673                         } else if ( objects[ index ] !== knownObject ) {
44674
44675                                 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
44676                                         'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
44677
44678                         } // else the object is already where we want it to be
44679
44680                 } // for arguments
44681
44682                 this.nCachedObjects_ = nCachedObjects;
44683
44684         },
44685
44686         remove: function () {
44687
44688                 const objects = this._objects,
44689                         indicesByUUID = this._indicesByUUID,
44690                         bindings = this._bindings,
44691                         nBindings = bindings.length;
44692
44693                 let nCachedObjects = this.nCachedObjects_;
44694
44695                 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
44696
44697                         const object = arguments[ i ],
44698                                 uuid = object.uuid,
44699                                 index = indicesByUUID[ uuid ];
44700
44701                         if ( index !== undefined && index >= nCachedObjects ) {
44702
44703                                 // move existing object into the CACHED region
44704
44705                                 const lastCachedIndex = nCachedObjects ++,
44706                                         firstActiveObject = objects[ lastCachedIndex ];
44707
44708                                 indicesByUUID[ firstActiveObject.uuid ] = index;
44709                                 objects[ index ] = firstActiveObject;
44710
44711                                 indicesByUUID[ uuid ] = lastCachedIndex;
44712                                 objects[ lastCachedIndex ] = object;
44713
44714                                 // accounting is done, now do the same for all bindings
44715
44716                                 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
44717
44718                                         const bindingsForPath = bindings[ j ],
44719                                                 firstActive = bindingsForPath[ lastCachedIndex ],
44720                                                 binding = bindingsForPath[ index ];
44721
44722                                         bindingsForPath[ index ] = firstActive;
44723                                         bindingsForPath[ lastCachedIndex ] = binding;
44724
44725                                 }
44726
44727                         }
44728
44729                 } // for arguments
44730
44731                 this.nCachedObjects_ = nCachedObjects;
44732
44733         },
44734
44735         // remove & forget
44736         uncache: function () {
44737
44738                 const objects = this._objects,
44739                         indicesByUUID = this._indicesByUUID,
44740                         bindings = this._bindings,
44741                         nBindings = bindings.length;
44742
44743                 let nCachedObjects = this.nCachedObjects_,
44744                         nObjects = objects.length;
44745
44746                 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
44747
44748                         const object = arguments[ i ],
44749                                 uuid = object.uuid,
44750                                 index = indicesByUUID[ uuid ];
44751
44752                         if ( index !== undefined ) {
44753
44754                                 delete indicesByUUID[ uuid ];
44755
44756                                 if ( index < nCachedObjects ) {
44757
44758                                         // object is cached, shrink the CACHED region
44759
44760                                         const firstActiveIndex = -- nCachedObjects,
44761                                                 lastCachedObject = objects[ firstActiveIndex ],
44762                                                 lastIndex = -- nObjects,
44763                                                 lastObject = objects[ lastIndex ];
44764
44765                                         // last cached object takes this object's place
44766                                         indicesByUUID[ lastCachedObject.uuid ] = index;
44767                                         objects[ index ] = lastCachedObject;
44768
44769                                         // last object goes to the activated slot and pop
44770                                         indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
44771                                         objects[ firstActiveIndex ] = lastObject;
44772                                         objects.pop();
44773
44774                                         // accounting is done, now do the same for all bindings
44775
44776                                         for ( let j = 0, m = nBindings; j !== m; ++ j ) {
44777
44778                                                 const bindingsForPath = bindings[ j ],
44779                                                         lastCached = bindingsForPath[ firstActiveIndex ],
44780                                                         last = bindingsForPath[ lastIndex ];
44781
44782                                                 bindingsForPath[ index ] = lastCached;
44783                                                 bindingsForPath[ firstActiveIndex ] = last;
44784                                                 bindingsForPath.pop();
44785
44786                                         }
44787
44788                                 } else {
44789
44790                                         // object is active, just swap with the last and pop
44791
44792                                         const lastIndex = -- nObjects,
44793                                                 lastObject = objects[ lastIndex ];
44794
44795                                         if ( lastIndex > 0 ) {
44796
44797                                                 indicesByUUID[ lastObject.uuid ] = index;
44798
44799                                         }
44800
44801                                         objects[ index ] = lastObject;
44802                                         objects.pop();
44803
44804                                         // accounting is done, now do the same for all bindings
44805
44806                                         for ( let j = 0, m = nBindings; j !== m; ++ j ) {
44807
44808                                                 const bindingsForPath = bindings[ j ];
44809
44810                                                 bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
44811                                                 bindingsForPath.pop();
44812
44813                                         }
44814
44815                                 } // cached or active
44816
44817                         } // if object is known
44818
44819                 } // for arguments
44820
44821                 this.nCachedObjects_ = nCachedObjects;
44822
44823         },
44824
44825         // Internal interface used by befriended PropertyBinding.Composite:
44826
44827         subscribe_: function ( path, parsedPath ) {
44828
44829                 // returns an array of bindings for the given path that is changed
44830                 // according to the contained objects in the group
44831
44832                 const indicesByPath = this._bindingsIndicesByPath;
44833                 let index = indicesByPath[ path ];
44834                 const bindings = this._bindings;
44835
44836                 if ( index !== undefined ) return bindings[ index ];
44837
44838                 const paths = this._paths,
44839                         parsedPaths = this._parsedPaths,
44840                         objects = this._objects,
44841                         nObjects = objects.length,
44842                         nCachedObjects = this.nCachedObjects_,
44843                         bindingsForPath = new Array( nObjects );
44844
44845                 index = bindings.length;
44846
44847                 indicesByPath[ path ] = index;
44848
44849                 paths.push( path );
44850                 parsedPaths.push( parsedPath );
44851                 bindings.push( bindingsForPath );
44852
44853                 for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
44854
44855                         const object = objects[ i ];
44856                         bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
44857
44858                 }
44859
44860                 return bindingsForPath;
44861
44862         },
44863
44864         unsubscribe_: function ( path ) {
44865
44866                 // tells the group to forget about a property path and no longer
44867                 // update the array previously obtained with 'subscribe_'
44868
44869                 const indicesByPath = this._bindingsIndicesByPath,
44870                         index = indicesByPath[ path ];
44871
44872                 if ( index !== undefined ) {
44873
44874                         const paths = this._paths,
44875                                 parsedPaths = this._parsedPaths,
44876                                 bindings = this._bindings,
44877                                 lastBindingsIndex = bindings.length - 1,
44878                                 lastBindings = bindings[ lastBindingsIndex ],
44879                                 lastBindingsPath = path[ lastBindingsIndex ];
44880
44881                         indicesByPath[ lastBindingsPath ] = index;
44882
44883                         bindings[ index ] = lastBindings;
44884                         bindings.pop();
44885
44886                         parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
44887                         parsedPaths.pop();
44888
44889                         paths[ index ] = paths[ lastBindingsIndex ];
44890                         paths.pop();
44891
44892                 }
44893
44894         }
44895
44896 } );
44897
44898 class AnimationAction {
44899
44900         constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
44901
44902                 this._mixer = mixer;
44903                 this._clip = clip;
44904                 this._localRoot = localRoot;
44905                 this.blendMode = blendMode;
44906
44907                 const tracks = clip.tracks,
44908                         nTracks = tracks.length,
44909                         interpolants = new Array( nTracks );
44910
44911                 const interpolantSettings = {
44912                         endingStart: ZeroCurvatureEnding,
44913                         endingEnd: ZeroCurvatureEnding
44914                 };
44915
44916                 for ( let i = 0; i !== nTracks; ++ i ) {
44917
44918                         const interpolant = tracks[ i ].createInterpolant( null );
44919                         interpolants[ i ] = interpolant;
44920                         interpolant.settings = interpolantSettings;
44921
44922                 }
44923
44924                 this._interpolantSettings = interpolantSettings;
44925
44926                 this._interpolants = interpolants; // bound by the mixer
44927
44928                 // inside: PropertyMixer (managed by the mixer)
44929                 this._propertyBindings = new Array( nTracks );
44930
44931                 this._cacheIndex = null; // for the memory manager
44932                 this._byClipCacheIndex = null; // for the memory manager
44933
44934                 this._timeScaleInterpolant = null;
44935                 this._weightInterpolant = null;
44936
44937                 this.loop = LoopRepeat;
44938                 this._loopCount = - 1;
44939
44940                 // global mixer time when the action is to be started
44941                 // it's set back to 'null' upon start of the action
44942                 this._startTime = null;
44943
44944                 // scaled local time of the action
44945                 // gets clamped or wrapped to 0..clip.duration according to loop
44946                 this.time = 0;
44947
44948                 this.timeScale = 1;
44949                 this._effectiveTimeScale = 1;
44950
44951                 this.weight = 1;
44952                 this._effectiveWeight = 1;
44953
44954                 this.repetitions = Infinity; // no. of repetitions when looping
44955
44956                 this.paused = false; // true -> zero effective time scale
44957                 this.enabled = true; // false -> zero effective weight
44958
44959                 this.clampWhenFinished = false;// keep feeding the last frame?
44960
44961                 this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
44962                 this.zeroSlopeAtEnd = true;// clips for start, loop and end
44963
44964         }
44965
44966         // State & Scheduling
44967
44968         play() {
44969
44970                 this._mixer._activateAction( this );
44971
44972                 return this;
44973
44974         }
44975
44976         stop() {
44977
44978                 this._mixer._deactivateAction( this );
44979
44980                 return this.reset();
44981
44982         }
44983
44984         reset() {
44985
44986                 this.paused = false;
44987                 this.enabled = true;
44988
44989                 this.time = 0; // restart clip
44990                 this._loopCount = - 1;// forget previous loops
44991                 this._startTime = null;// forget scheduling
44992
44993                 return this.stopFading().stopWarping();
44994
44995         }
44996
44997         isRunning() {
44998
44999                 return this.enabled && ! this.paused && this.timeScale !== 0 &&
45000                         this._startTime === null && this._mixer._isActiveAction( this );
45001
45002         }
45003
45004         // return true when play has been called
45005         isScheduled() {
45006
45007                 return this._mixer._isActiveAction( this );
45008
45009         }
45010
45011         startAt( time ) {
45012
45013                 this._startTime = time;
45014
45015                 return this;
45016
45017         }
45018
45019         setLoop( mode, repetitions ) {
45020
45021                 this.loop = mode;
45022                 this.repetitions = repetitions;
45023
45024                 return this;
45025
45026         }
45027
45028         // Weight
45029
45030         // set the weight stopping any scheduled fading
45031         // although .enabled = false yields an effective weight of zero, this
45032         // method does *not* change .enabled, because it would be confusing
45033         setEffectiveWeight( weight ) {
45034
45035                 this.weight = weight;
45036
45037                 // note: same logic as when updated at runtime
45038                 this._effectiveWeight = this.enabled ? weight : 0;
45039
45040                 return this.stopFading();
45041
45042         }
45043
45044         // return the weight considering fading and .enabled
45045         getEffectiveWeight() {
45046
45047                 return this._effectiveWeight;
45048
45049         }
45050
45051         fadeIn( duration ) {
45052
45053                 return this._scheduleFading( duration, 0, 1 );
45054
45055         }
45056
45057         fadeOut( duration ) {
45058
45059                 return this._scheduleFading( duration, 1, 0 );
45060
45061         }
45062
45063         crossFadeFrom( fadeOutAction, duration, warp ) {
45064
45065                 fadeOutAction.fadeOut( duration );
45066                 this.fadeIn( duration );
45067
45068                 if ( warp ) {
45069
45070                         const fadeInDuration = this._clip.duration,
45071                                 fadeOutDuration = fadeOutAction._clip.duration,
45072
45073                                 startEndRatio = fadeOutDuration / fadeInDuration,
45074                                 endStartRatio = fadeInDuration / fadeOutDuration;
45075
45076                         fadeOutAction.warp( 1.0, startEndRatio, duration );
45077                         this.warp( endStartRatio, 1.0, duration );
45078
45079                 }
45080
45081                 return this;
45082
45083         }
45084
45085         crossFadeTo( fadeInAction, duration, warp ) {
45086
45087                 return fadeInAction.crossFadeFrom( this, duration, warp );
45088
45089         }
45090
45091         stopFading() {
45092
45093                 const weightInterpolant = this._weightInterpolant;
45094
45095                 if ( weightInterpolant !== null ) {
45096
45097                         this._weightInterpolant = null;
45098                         this._mixer._takeBackControlInterpolant( weightInterpolant );
45099
45100                 }
45101
45102                 return this;
45103
45104         }
45105
45106         // Time Scale Control
45107
45108         // set the time scale stopping any scheduled warping
45109         // although .paused = true yields an effective time scale of zero, this
45110         // method does *not* change .paused, because it would be confusing
45111         setEffectiveTimeScale( timeScale ) {
45112
45113                 this.timeScale = timeScale;
45114                 this._effectiveTimeScale = this.paused ? 0 : timeScale;
45115
45116                 return this.stopWarping();
45117
45118         }
45119
45120         // return the time scale considering warping and .paused
45121         getEffectiveTimeScale() {
45122
45123                 return this._effectiveTimeScale;
45124
45125         }
45126
45127         setDuration( duration ) {
45128
45129                 this.timeScale = this._clip.duration / duration;
45130
45131                 return this.stopWarping();
45132
45133         }
45134
45135         syncWith( action ) {
45136
45137                 this.time = action.time;
45138                 this.timeScale = action.timeScale;
45139
45140                 return this.stopWarping();
45141
45142         }
45143
45144         halt( duration ) {
45145
45146                 return this.warp( this._effectiveTimeScale, 0, duration );
45147
45148         }
45149
45150         warp( startTimeScale, endTimeScale, duration ) {
45151
45152                 const mixer = this._mixer,
45153                         now = mixer.time,
45154                         timeScale = this.timeScale;
45155
45156                 let interpolant = this._timeScaleInterpolant;
45157
45158                 if ( interpolant === null ) {
45159
45160                         interpolant = mixer._lendControlInterpolant();
45161                         this._timeScaleInterpolant = interpolant;
45162
45163                 }
45164
45165                 const times = interpolant.parameterPositions,
45166                         values = interpolant.sampleValues;
45167
45168                 times[ 0 ] = now;
45169                 times[ 1 ] = now + duration;
45170
45171                 values[ 0 ] = startTimeScale / timeScale;
45172                 values[ 1 ] = endTimeScale / timeScale;
45173
45174                 return this;
45175
45176         }
45177
45178         stopWarping() {
45179
45180                 const timeScaleInterpolant = this._timeScaleInterpolant;
45181
45182                 if ( timeScaleInterpolant !== null ) {
45183
45184                         this._timeScaleInterpolant = null;
45185                         this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
45186
45187                 }
45188
45189                 return this;
45190
45191         }
45192
45193         // Object Accessors
45194
45195         getMixer() {
45196
45197                 return this._mixer;
45198
45199         }
45200
45201         getClip() {
45202
45203                 return this._clip;
45204
45205         }
45206
45207         getRoot() {
45208
45209                 return this._localRoot || this._mixer._root;
45210
45211         }
45212
45213         // Interna
45214
45215         _update( time, deltaTime, timeDirection, accuIndex ) {
45216
45217                 // called by the mixer
45218
45219                 if ( ! this.enabled ) {
45220
45221                         // call ._updateWeight() to update ._effectiveWeight
45222
45223                         this._updateWeight( time );
45224                         return;
45225
45226                 }
45227
45228                 const startTime = this._startTime;
45229
45230                 if ( startTime !== null ) {
45231
45232                         // check for scheduled start of action
45233
45234                         const timeRunning = ( time - startTime ) * timeDirection;
45235                         if ( timeRunning < 0 || timeDirection === 0 ) {
45236
45237                                 return; // yet to come / don't decide when delta = 0
45238
45239                         }
45240
45241                         // start
45242
45243                         this._startTime = null; // unschedule
45244                         deltaTime = timeDirection * timeRunning;
45245
45246                 }
45247
45248                 // apply time scale and advance time
45249
45250                 deltaTime *= this._updateTimeScale( time );
45251                 const clipTime = this._updateTime( deltaTime );
45252
45253                 // note: _updateTime may disable the action resulting in
45254                 // an effective weight of 0
45255
45256                 const weight = this._updateWeight( time );
45257
45258                 if ( weight > 0 ) {
45259
45260                         const interpolants = this._interpolants;
45261                         const propertyMixers = this._propertyBindings;
45262
45263                         switch ( this.blendMode ) {
45264
45265                                 case AdditiveAnimationBlendMode:
45266
45267                                         for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
45268
45269                                                 interpolants[ j ].evaluate( clipTime );
45270                                                 propertyMixers[ j ].accumulateAdditive( weight );
45271
45272                                         }
45273
45274                                         break;
45275
45276                                 case NormalAnimationBlendMode:
45277                                 default:
45278
45279                                         for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
45280
45281                                                 interpolants[ j ].evaluate( clipTime );
45282                                                 propertyMixers[ j ].accumulate( accuIndex, weight );
45283
45284                                         }
45285
45286                         }
45287
45288                 }
45289
45290         }
45291
45292         _updateWeight( time ) {
45293
45294                 let weight = 0;
45295
45296                 if ( this.enabled ) {
45297
45298                         weight = this.weight;
45299                         const interpolant = this._weightInterpolant;
45300
45301                         if ( interpolant !== null ) {
45302
45303                                 const interpolantValue = interpolant.evaluate( time )[ 0 ];
45304
45305                                 weight *= interpolantValue;
45306
45307                                 if ( time > interpolant.parameterPositions[ 1 ] ) {
45308
45309                                         this.stopFading();
45310
45311                                         if ( interpolantValue === 0 ) {
45312
45313                                                 // faded out, disable
45314                                                 this.enabled = false;
45315
45316                                         }
45317
45318                                 }
45319
45320                         }
45321
45322                 }
45323
45324                 this._effectiveWeight = weight;
45325                 return weight;
45326
45327         }
45328
45329         _updateTimeScale( time ) {
45330
45331                 let timeScale = 0;
45332
45333                 if ( ! this.paused ) {
45334
45335                         timeScale = this.timeScale;
45336
45337                         const interpolant = this._timeScaleInterpolant;
45338
45339                         if ( interpolant !== null ) {
45340
45341                                 const interpolantValue = interpolant.evaluate( time )[ 0 ];
45342
45343                                 timeScale *= interpolantValue;
45344
45345                                 if ( time > interpolant.parameterPositions[ 1 ] ) {
45346
45347                                         this.stopWarping();
45348
45349                                         if ( timeScale === 0 ) {
45350
45351                                                 // motion has halted, pause
45352                                                 this.paused = true;
45353
45354                                         } else {
45355
45356                                                 // warp done - apply final time scale
45357                                                 this.timeScale = timeScale;
45358
45359                                         }
45360
45361                                 }
45362
45363                         }
45364
45365                 }
45366
45367                 this._effectiveTimeScale = timeScale;
45368                 return timeScale;
45369
45370         }
45371
45372         _updateTime( deltaTime ) {
45373
45374                 const duration = this._clip.duration;
45375                 const loop = this.loop;
45376
45377                 let time = this.time + deltaTime;
45378                 let loopCount = this._loopCount;
45379
45380                 const pingPong = ( loop === LoopPingPong );
45381
45382                 if ( deltaTime === 0 ) {
45383
45384                         if ( loopCount === - 1 ) return time;
45385
45386                         return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
45387
45388                 }
45389
45390                 if ( loop === LoopOnce ) {
45391
45392                         if ( loopCount === - 1 ) {
45393
45394                                 // just started
45395
45396                                 this._loopCount = 0;
45397                                 this._setEndings( true, true, false );
45398
45399                         }
45400
45401                         handle_stop: {
45402
45403                                 if ( time >= duration ) {
45404
45405                                         time = duration;
45406
45407                                 } else if ( time < 0 ) {
45408
45409                                         time = 0;
45410
45411                                 } else {
45412
45413                                         this.time = time;
45414
45415                                         break handle_stop;
45416
45417                                 }
45418
45419                                 if ( this.clampWhenFinished ) this.paused = true;
45420                                 else this.enabled = false;
45421
45422                                 this.time = time;
45423
45424                                 this._mixer.dispatchEvent( {
45425                                         type: 'finished', action: this,
45426                                         direction: deltaTime < 0 ? - 1 : 1
45427                                 } );
45428
45429                         }
45430
45431                 } else { // repetitive Repeat or PingPong
45432
45433                         if ( loopCount === - 1 ) {
45434
45435                                 // just started
45436
45437                                 if ( deltaTime >= 0 ) {
45438
45439                                         loopCount = 0;
45440
45441                                         this._setEndings( true, this.repetitions === 0, pingPong );
45442
45443                                 } else {
45444
45445                                         // when looping in reverse direction, the initial
45446                                         // transition through zero counts as a repetition,
45447                                         // so leave loopCount at -1
45448
45449                                         this._setEndings( this.repetitions === 0, true, pingPong );
45450
45451                                 }
45452
45453                         }
45454
45455                         if ( time >= duration || time < 0 ) {
45456
45457                                 // wrap around
45458
45459                                 const loopDelta = Math.floor( time / duration ); // signed
45460                                 time -= duration * loopDelta;
45461
45462                                 loopCount += Math.abs( loopDelta );
45463
45464                                 const pending = this.repetitions - loopCount;
45465
45466                                 if ( pending <= 0 ) {
45467
45468                                         // have to stop (switch state, clamp time, fire event)
45469
45470                                         if ( this.clampWhenFinished ) this.paused = true;
45471                                         else this.enabled = false;
45472
45473                                         time = deltaTime > 0 ? duration : 0;
45474
45475                                         this.time = time;
45476
45477                                         this._mixer.dispatchEvent( {
45478                                                 type: 'finished', action: this,
45479                                                 direction: deltaTime > 0 ? 1 : - 1
45480                                         } );
45481
45482                                 } else {
45483
45484                                         // keep running
45485
45486                                         if ( pending === 1 ) {
45487
45488                                                 // entering the last round
45489
45490                                                 const atStart = deltaTime < 0;
45491                                                 this._setEndings( atStart, ! atStart, pingPong );
45492
45493                                         } else {
45494
45495                                                 this._setEndings( false, false, pingPong );
45496
45497                                         }
45498
45499                                         this._loopCount = loopCount;
45500
45501                                         this.time = time;
45502
45503                                         this._mixer.dispatchEvent( {
45504                                                 type: 'loop', action: this, loopDelta: loopDelta
45505                                         } );
45506
45507                                 }
45508
45509                         } else {
45510
45511                                 this.time = time;
45512
45513                         }
45514
45515                         if ( pingPong && ( loopCount & 1 ) === 1 ) {
45516
45517                                 // invert time for the "pong round"
45518
45519                                 return duration - time;
45520
45521                         }
45522
45523                 }
45524
45525                 return time;
45526
45527         }
45528
45529         _setEndings( atStart, atEnd, pingPong ) {
45530
45531                 const settings = this._interpolantSettings;
45532
45533                 if ( pingPong ) {
45534
45535                         settings.endingStart = ZeroSlopeEnding;
45536                         settings.endingEnd = ZeroSlopeEnding;
45537
45538                 } else {
45539
45540                         // assuming for LoopOnce atStart == atEnd == true
45541
45542                         if ( atStart ) {
45543
45544                                 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
45545
45546                         } else {
45547
45548                                 settings.endingStart = WrapAroundEnding;
45549
45550                         }
45551
45552                         if ( atEnd ) {
45553
45554                                 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
45555
45556                         } else {
45557
45558                                 settings.endingEnd       = WrapAroundEnding;
45559
45560                         }
45561
45562                 }
45563
45564         }
45565
45566         _scheduleFading( duration, weightNow, weightThen ) {
45567
45568                 const mixer = this._mixer, now = mixer.time;
45569                 let interpolant = this._weightInterpolant;
45570
45571                 if ( interpolant === null ) {
45572
45573                         interpolant = mixer._lendControlInterpolant();
45574                         this._weightInterpolant = interpolant;
45575
45576                 }
45577
45578                 const times = interpolant.parameterPositions,
45579                         values = interpolant.sampleValues;
45580
45581                 times[ 0 ] = now;
45582                 values[ 0 ] = weightNow;
45583                 times[ 1 ] = now + duration;
45584                 values[ 1 ] = weightThen;
45585
45586                 return this;
45587
45588         }
45589
45590 }
45591
45592 function AnimationMixer( root ) {
45593
45594         this._root = root;
45595         this._initMemoryManager();
45596         this._accuIndex = 0;
45597
45598         this.time = 0;
45599
45600         this.timeScale = 1.0;
45601
45602 }
45603
45604 AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
45605
45606         constructor: AnimationMixer,
45607
45608         _bindAction: function ( action, prototypeAction ) {
45609
45610                 const root = action._localRoot || this._root,
45611                         tracks = action._clip.tracks,
45612                         nTracks = tracks.length,
45613                         bindings = action._propertyBindings,
45614                         interpolants = action._interpolants,
45615                         rootUuid = root.uuid,
45616                         bindingsByRoot = this._bindingsByRootAndName;
45617
45618                 let bindingsByName = bindingsByRoot[ rootUuid ];
45619
45620                 if ( bindingsByName === undefined ) {
45621
45622                         bindingsByName = {};
45623                         bindingsByRoot[ rootUuid ] = bindingsByName;
45624
45625                 }
45626
45627                 for ( let i = 0; i !== nTracks; ++ i ) {
45628
45629                         const track = tracks[ i ],
45630                                 trackName = track.name;
45631
45632                         let binding = bindingsByName[ trackName ];
45633
45634                         if ( binding !== undefined ) {
45635
45636                                 bindings[ i ] = binding;
45637
45638                         } else {
45639
45640                                 binding = bindings[ i ];
45641
45642                                 if ( binding !== undefined ) {
45643
45644                                         // existing binding, make sure the cache knows
45645
45646                                         if ( binding._cacheIndex === null ) {
45647
45648                                                 ++ binding.referenceCount;
45649                                                 this._addInactiveBinding( binding, rootUuid, trackName );
45650
45651                                         }
45652
45653                                         continue;
45654
45655                                 }
45656
45657                                 const path = prototypeAction && prototypeAction.
45658                                         _propertyBindings[ i ].binding.parsedPath;
45659
45660                                 binding = new PropertyMixer(
45661                                         PropertyBinding.create( root, trackName, path ),
45662                                         track.ValueTypeName, track.getValueSize() );
45663
45664                                 ++ binding.referenceCount;
45665                                 this._addInactiveBinding( binding, rootUuid, trackName );
45666
45667                                 bindings[ i ] = binding;
45668
45669                         }
45670
45671                         interpolants[ i ].resultBuffer = binding.buffer;
45672
45673                 }
45674
45675         },
45676
45677         _activateAction: function ( action ) {
45678
45679                 if ( ! this._isActiveAction( action ) ) {
45680
45681                         if ( action._cacheIndex === null ) {
45682
45683                                 // this action has been forgotten by the cache, but the user
45684                                 // appears to be still using it -> rebind
45685
45686                                 const rootUuid = ( action._localRoot || this._root ).uuid,
45687                                         clipUuid = action._clip.uuid,
45688                                         actionsForClip = this._actionsByClip[ clipUuid ];
45689
45690                                 this._bindAction( action,
45691                                         actionsForClip && actionsForClip.knownActions[ 0 ] );
45692
45693                                 this._addInactiveAction( action, clipUuid, rootUuid );
45694
45695                         }
45696
45697                         const bindings = action._propertyBindings;
45698
45699                         // increment reference counts / sort out state
45700                         for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
45701
45702                                 const binding = bindings[ i ];
45703
45704                                 if ( binding.useCount ++ === 0 ) {
45705
45706                                         this._lendBinding( binding );
45707                                         binding.saveOriginalState();
45708
45709                                 }
45710
45711                         }
45712
45713                         this._lendAction( action );
45714
45715                 }
45716
45717         },
45718
45719         _deactivateAction: function ( action ) {
45720
45721                 if ( this._isActiveAction( action ) ) {
45722
45723                         const bindings = action._propertyBindings;
45724
45725                         // decrement reference counts / sort out state
45726                         for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
45727
45728                                 const binding = bindings[ i ];
45729
45730                                 if ( -- binding.useCount === 0 ) {
45731
45732                                         binding.restoreOriginalState();
45733                                         this._takeBackBinding( binding );
45734
45735                                 }
45736
45737                         }
45738
45739                         this._takeBackAction( action );
45740
45741                 }
45742
45743         },
45744
45745         // Memory manager
45746
45747         _initMemoryManager: function () {
45748
45749                 this._actions = []; // 'nActiveActions' followed by inactive ones
45750                 this._nActiveActions = 0;
45751
45752                 this._actionsByClip = {};
45753                 // inside:
45754                 // {
45755                 //      knownActions: Array< AnimationAction > - used as prototypes
45756                 //      actionByRoot: AnimationAction - lookup
45757                 // }
45758
45759
45760                 this._bindings = []; // 'nActiveBindings' followed by inactive ones
45761                 this._nActiveBindings = 0;
45762
45763                 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
45764
45765
45766                 this._controlInterpolants = []; // same game as above
45767                 this._nActiveControlInterpolants = 0;
45768
45769                 const scope = this;
45770
45771                 this.stats = {
45772
45773                         actions: {
45774                                 get total() {
45775
45776                                         return scope._actions.length;
45777
45778                                 },
45779                                 get inUse() {
45780
45781                                         return scope._nActiveActions;
45782
45783                                 }
45784                         },
45785                         bindings: {
45786                                 get total() {
45787
45788                                         return scope._bindings.length;
45789
45790                                 },
45791                                 get inUse() {
45792
45793                                         return scope._nActiveBindings;
45794
45795                                 }
45796                         },
45797                         controlInterpolants: {
45798                                 get total() {
45799
45800                                         return scope._controlInterpolants.length;
45801
45802                                 },
45803                                 get inUse() {
45804
45805                                         return scope._nActiveControlInterpolants;
45806
45807                                 }
45808                         }
45809
45810                 };
45811
45812         },
45813
45814         // Memory management for AnimationAction objects
45815
45816         _isActiveAction: function ( action ) {
45817
45818                 const index = action._cacheIndex;
45819                 return index !== null && index < this._nActiveActions;
45820
45821         },
45822
45823         _addInactiveAction: function ( action, clipUuid, rootUuid ) {
45824
45825                 const actions = this._actions,
45826                         actionsByClip = this._actionsByClip;
45827
45828                 let actionsForClip = actionsByClip[ clipUuid ];
45829
45830                 if ( actionsForClip === undefined ) {
45831
45832                         actionsForClip = {
45833
45834                                 knownActions: [ action ],
45835                                 actionByRoot: {}
45836
45837                         };
45838
45839                         action._byClipCacheIndex = 0;
45840
45841                         actionsByClip[ clipUuid ] = actionsForClip;
45842
45843                 } else {
45844
45845                         const knownActions = actionsForClip.knownActions;
45846
45847                         action._byClipCacheIndex = knownActions.length;
45848                         knownActions.push( action );
45849
45850                 }
45851
45852                 action._cacheIndex = actions.length;
45853                 actions.push( action );
45854
45855                 actionsForClip.actionByRoot[ rootUuid ] = action;
45856
45857         },
45858
45859         _removeInactiveAction: function ( action ) {
45860
45861                 const actions = this._actions,
45862                         lastInactiveAction = actions[ actions.length - 1 ],
45863                         cacheIndex = action._cacheIndex;
45864
45865                 lastInactiveAction._cacheIndex = cacheIndex;
45866                 actions[ cacheIndex ] = lastInactiveAction;
45867                 actions.pop();
45868
45869                 action._cacheIndex = null;
45870
45871
45872                 const clipUuid = action._clip.uuid,
45873                         actionsByClip = this._actionsByClip,
45874                         actionsForClip = actionsByClip[ clipUuid ],
45875                         knownActionsForClip = actionsForClip.knownActions,
45876
45877                         lastKnownAction =
45878                                 knownActionsForClip[ knownActionsForClip.length - 1 ],
45879
45880                         byClipCacheIndex = action._byClipCacheIndex;
45881
45882                 lastKnownAction._byClipCacheIndex = byClipCacheIndex;
45883                 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
45884                 knownActionsForClip.pop();
45885
45886                 action._byClipCacheIndex = null;
45887
45888
45889                 const actionByRoot = actionsForClip.actionByRoot,
45890                         rootUuid = ( action._localRoot || this._root ).uuid;
45891
45892                 delete actionByRoot[ rootUuid ];
45893
45894                 if ( knownActionsForClip.length === 0 ) {
45895
45896                         delete actionsByClip[ clipUuid ];
45897
45898                 }
45899
45900                 this._removeInactiveBindingsForAction( action );
45901
45902         },
45903
45904         _removeInactiveBindingsForAction: function ( action ) {
45905
45906                 const bindings = action._propertyBindings;
45907
45908                 for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
45909
45910                         const binding = bindings[ i ];
45911
45912                         if ( -- binding.referenceCount === 0 ) {
45913
45914                                 this._removeInactiveBinding( binding );
45915
45916                         }
45917
45918                 }
45919
45920         },
45921
45922         _lendAction: function ( action ) {
45923
45924                 // [ active actions |  inactive actions  ]
45925                 // [  active actions >| inactive actions ]
45926                 //                 s        a
45927                 //                  <-swap->
45928                 //                 a        s
45929
45930                 const actions = this._actions,
45931                         prevIndex = action._cacheIndex,
45932
45933                         lastActiveIndex = this._nActiveActions ++,
45934
45935                         firstInactiveAction = actions[ lastActiveIndex ];
45936
45937                 action._cacheIndex = lastActiveIndex;
45938                 actions[ lastActiveIndex ] = action;
45939
45940                 firstInactiveAction._cacheIndex = prevIndex;
45941                 actions[ prevIndex ] = firstInactiveAction;
45942
45943         },
45944
45945         _takeBackAction: function ( action ) {
45946
45947                 // [  active actions  | inactive actions ]
45948                 // [ active actions |< inactive actions  ]
45949                 //        a        s
45950                 //         <-swap->
45951                 //        s        a
45952
45953                 const actions = this._actions,
45954                         prevIndex = action._cacheIndex,
45955
45956                         firstInactiveIndex = -- this._nActiveActions,
45957
45958                         lastActiveAction = actions[ firstInactiveIndex ];
45959
45960                 action._cacheIndex = firstInactiveIndex;
45961                 actions[ firstInactiveIndex ] = action;
45962
45963                 lastActiveAction._cacheIndex = prevIndex;
45964                 actions[ prevIndex ] = lastActiveAction;
45965
45966         },
45967
45968         // Memory management for PropertyMixer objects
45969
45970         _addInactiveBinding: function ( binding, rootUuid, trackName ) {
45971
45972                 const bindingsByRoot = this._bindingsByRootAndName,
45973                         bindings = this._bindings;
45974
45975                 let bindingByName = bindingsByRoot[ rootUuid ];
45976
45977                 if ( bindingByName === undefined ) {
45978
45979                         bindingByName = {};
45980                         bindingsByRoot[ rootUuid ] = bindingByName;
45981
45982                 }
45983
45984                 bindingByName[ trackName ] = binding;
45985
45986                 binding._cacheIndex = bindings.length;
45987                 bindings.push( binding );
45988
45989         },
45990
45991         _removeInactiveBinding: function ( binding ) {
45992
45993                 const bindings = this._bindings,
45994                         propBinding = binding.binding,
45995                         rootUuid = propBinding.rootNode.uuid,
45996                         trackName = propBinding.path,
45997                         bindingsByRoot = this._bindingsByRootAndName,
45998                         bindingByName = bindingsByRoot[ rootUuid ],
45999
46000                         lastInactiveBinding = bindings[ bindings.length - 1 ],
46001                         cacheIndex = binding._cacheIndex;
46002
46003                 lastInactiveBinding._cacheIndex = cacheIndex;
46004                 bindings[ cacheIndex ] = lastInactiveBinding;
46005                 bindings.pop();
46006
46007                 delete bindingByName[ trackName ];
46008
46009                 if ( Object.keys( bindingByName ).length === 0 ) {
46010
46011                         delete bindingsByRoot[ rootUuid ];
46012
46013                 }
46014
46015         },
46016
46017         _lendBinding: function ( binding ) {
46018
46019                 const bindings = this._bindings,
46020                         prevIndex = binding._cacheIndex,
46021
46022                         lastActiveIndex = this._nActiveBindings ++,
46023
46024                         firstInactiveBinding = bindings[ lastActiveIndex ];
46025
46026                 binding._cacheIndex = lastActiveIndex;
46027                 bindings[ lastActiveIndex ] = binding;
46028
46029                 firstInactiveBinding._cacheIndex = prevIndex;
46030                 bindings[ prevIndex ] = firstInactiveBinding;
46031
46032         },
46033
46034         _takeBackBinding: function ( binding ) {
46035
46036                 const bindings = this._bindings,
46037                         prevIndex = binding._cacheIndex,
46038
46039                         firstInactiveIndex = -- this._nActiveBindings,
46040
46041                         lastActiveBinding = bindings[ firstInactiveIndex ];
46042
46043                 binding._cacheIndex = firstInactiveIndex;
46044                 bindings[ firstInactiveIndex ] = binding;
46045
46046                 lastActiveBinding._cacheIndex = prevIndex;
46047                 bindings[ prevIndex ] = lastActiveBinding;
46048
46049         },
46050
46051
46052         // Memory management of Interpolants for weight and time scale
46053
46054         _lendControlInterpolant: function () {
46055
46056                 const interpolants = this._controlInterpolants,
46057                         lastActiveIndex = this._nActiveControlInterpolants ++;
46058
46059                 let interpolant = interpolants[ lastActiveIndex ];
46060
46061                 if ( interpolant === undefined ) {
46062
46063                         interpolant = new LinearInterpolant(
46064                                 new Float32Array( 2 ), new Float32Array( 2 ),
46065                                 1, this._controlInterpolantsResultBuffer );
46066
46067                         interpolant.__cacheIndex = lastActiveIndex;
46068                         interpolants[ lastActiveIndex ] = interpolant;
46069
46070                 }
46071
46072                 return interpolant;
46073
46074         },
46075
46076         _takeBackControlInterpolant: function ( interpolant ) {
46077
46078                 const interpolants = this._controlInterpolants,
46079                         prevIndex = interpolant.__cacheIndex,
46080
46081                         firstInactiveIndex = -- this._nActiveControlInterpolants,
46082
46083                         lastActiveInterpolant = interpolants[ firstInactiveIndex ];
46084
46085                 interpolant.__cacheIndex = firstInactiveIndex;
46086                 interpolants[ firstInactiveIndex ] = interpolant;
46087
46088                 lastActiveInterpolant.__cacheIndex = prevIndex;
46089                 interpolants[ prevIndex ] = lastActiveInterpolant;
46090
46091         },
46092
46093         _controlInterpolantsResultBuffer: new Float32Array( 1 ),
46094
46095         // return an action for a clip optionally using a custom root target
46096         // object (this method allocates a lot of dynamic memory in case a
46097         // previously unknown clip/root combination is specified)
46098         clipAction: function ( clip, optionalRoot, blendMode ) {
46099
46100                 const root = optionalRoot || this._root,
46101                         rootUuid = root.uuid;
46102
46103                 let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
46104
46105                 const clipUuid = clipObject !== null ? clipObject.uuid : clip;
46106
46107                 const actionsForClip = this._actionsByClip[ clipUuid ];
46108                 let prototypeAction = null;
46109
46110                 if ( blendMode === undefined ) {
46111
46112                         if ( clipObject !== null ) {
46113
46114                                 blendMode = clipObject.blendMode;
46115
46116                         } else {
46117
46118                                 blendMode = NormalAnimationBlendMode;
46119
46120                         }
46121
46122                 }
46123
46124                 if ( actionsForClip !== undefined ) {
46125
46126                         const existingAction = actionsForClip.actionByRoot[ rootUuid ];
46127
46128                         if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
46129
46130                                 return existingAction;
46131
46132                         }
46133
46134                         // we know the clip, so we don't have to parse all
46135                         // the bindings again but can just copy
46136                         prototypeAction = actionsForClip.knownActions[ 0 ];
46137
46138                         // also, take the clip from the prototype action
46139                         if ( clipObject === null )
46140                                 clipObject = prototypeAction._clip;
46141
46142                 }
46143
46144                 // clip must be known when specified via string
46145                 if ( clipObject === null ) return null;
46146
46147                 // allocate all resources required to run it
46148                 const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
46149
46150                 this._bindAction( newAction, prototypeAction );
46151
46152                 // and make the action known to the memory manager
46153                 this._addInactiveAction( newAction, clipUuid, rootUuid );
46154
46155                 return newAction;
46156
46157         },
46158
46159         // get an existing action
46160         existingAction: function ( clip, optionalRoot ) {
46161
46162                 const root = optionalRoot || this._root,
46163                         rootUuid = root.uuid,
46164
46165                         clipObject = typeof clip === 'string' ?
46166                                 AnimationClip.findByName( root, clip ) : clip,
46167
46168                         clipUuid = clipObject ? clipObject.uuid : clip,
46169
46170                         actionsForClip = this._actionsByClip[ clipUuid ];
46171
46172                 if ( actionsForClip !== undefined ) {
46173
46174                         return actionsForClip.actionByRoot[ rootUuid ] || null;
46175
46176                 }
46177
46178                 return null;
46179
46180         },
46181
46182         // deactivates all previously scheduled actions
46183         stopAllAction: function () {
46184
46185                 const actions = this._actions,
46186                         nActions = this._nActiveActions;
46187
46188                 for ( let i = nActions - 1; i >= 0; -- i ) {
46189
46190                         actions[ i ].stop();
46191
46192                 }
46193
46194                 return this;
46195
46196         },
46197
46198         // advance the time and update apply the animation
46199         update: function ( deltaTime ) {
46200
46201                 deltaTime *= this.timeScale;
46202
46203                 const actions = this._actions,
46204                         nActions = this._nActiveActions,
46205
46206                         time = this.time += deltaTime,
46207                         timeDirection = Math.sign( deltaTime ),
46208
46209                         accuIndex = this._accuIndex ^= 1;
46210
46211                 // run active actions
46212
46213                 for ( let i = 0; i !== nActions; ++ i ) {
46214
46215                         const action = actions[ i ];
46216
46217                         action._update( time, deltaTime, timeDirection, accuIndex );
46218
46219                 }
46220
46221                 // update scene graph
46222
46223                 const bindings = this._bindings,
46224                         nBindings = this._nActiveBindings;
46225
46226                 for ( let i = 0; i !== nBindings; ++ i ) {
46227
46228                         bindings[ i ].apply( accuIndex );
46229
46230                 }
46231
46232                 return this;
46233
46234         },
46235
46236         // Allows you to seek to a specific time in an animation.
46237         setTime: function ( timeInSeconds ) {
46238
46239                 this.time = 0; // Zero out time attribute for AnimationMixer object;
46240                 for ( let i = 0; i < this._actions.length; i ++ ) {
46241
46242                         this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
46243
46244                 }
46245
46246                 return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
46247
46248         },
46249
46250         // return this mixer's root target object
46251         getRoot: function () {
46252
46253                 return this._root;
46254
46255         },
46256
46257         // free all resources specific to a particular clip
46258         uncacheClip: function ( clip ) {
46259
46260                 const actions = this._actions,
46261                         clipUuid = clip.uuid,
46262                         actionsByClip = this._actionsByClip,
46263                         actionsForClip = actionsByClip[ clipUuid ];
46264
46265                 if ( actionsForClip !== undefined ) {
46266
46267                         // note: just calling _removeInactiveAction would mess up the
46268                         // iteration state and also require updating the state we can
46269                         // just throw away
46270
46271                         const actionsToRemove = actionsForClip.knownActions;
46272
46273                         for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
46274
46275                                 const action = actionsToRemove[ i ];
46276
46277                                 this._deactivateAction( action );
46278
46279                                 const cacheIndex = action._cacheIndex,
46280                                         lastInactiveAction = actions[ actions.length - 1 ];
46281
46282                                 action._cacheIndex = null;
46283                                 action._byClipCacheIndex = null;
46284
46285                                 lastInactiveAction._cacheIndex = cacheIndex;
46286                                 actions[ cacheIndex ] = lastInactiveAction;
46287                                 actions.pop();
46288
46289                                 this._removeInactiveBindingsForAction( action );
46290
46291                         }
46292
46293                         delete actionsByClip[ clipUuid ];
46294
46295                 }
46296
46297         },
46298
46299         // free all resources specific to a particular root target object
46300         uncacheRoot: function ( root ) {
46301
46302                 const rootUuid = root.uuid,
46303                         actionsByClip = this._actionsByClip;
46304
46305                 for ( const clipUuid in actionsByClip ) {
46306
46307                         const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
46308                                 action = actionByRoot[ rootUuid ];
46309
46310                         if ( action !== undefined ) {
46311
46312                                 this._deactivateAction( action );
46313                                 this._removeInactiveAction( action );
46314
46315                         }
46316
46317                 }
46318
46319                 const bindingsByRoot = this._bindingsByRootAndName,
46320                         bindingByName = bindingsByRoot[ rootUuid ];
46321
46322                 if ( bindingByName !== undefined ) {
46323
46324                         for ( const trackName in bindingByName ) {
46325
46326                                 const binding = bindingByName[ trackName ];
46327                                 binding.restoreOriginalState();
46328                                 this._removeInactiveBinding( binding );
46329
46330                         }
46331
46332                 }
46333
46334         },
46335
46336         // remove a targeted clip from the cache
46337         uncacheAction: function ( clip, optionalRoot ) {
46338
46339                 const action = this.existingAction( clip, optionalRoot );
46340
46341                 if ( action !== null ) {
46342
46343                         this._deactivateAction( action );
46344                         this._removeInactiveAction( action );
46345
46346                 }
46347
46348         }
46349
46350 } );
46351
46352 class Uniform {
46353
46354         constructor( value ) {
46355
46356                 if ( typeof value === 'string' ) {
46357
46358                         console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
46359                         value = arguments[ 1 ];
46360
46361                 }
46362
46363                 this.value = value;
46364
46365         }
46366
46367         clone() {
46368
46369                 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
46370
46371         }
46372
46373 }
46374
46375 function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
46376
46377         InterleavedBuffer.call( this, array, stride );
46378
46379         this.meshPerAttribute = meshPerAttribute || 1;
46380
46381 }
46382
46383 InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
46384
46385         constructor: InstancedInterleavedBuffer,
46386
46387         isInstancedInterleavedBuffer: true,
46388
46389         copy: function ( source ) {
46390
46391                 InterleavedBuffer.prototype.copy.call( this, source );
46392
46393                 this.meshPerAttribute = source.meshPerAttribute;
46394
46395                 return this;
46396
46397         },
46398
46399         clone: function ( data ) {
46400
46401                 const ib = InterleavedBuffer.prototype.clone.call( this, data );
46402
46403                 ib.meshPerAttribute = this.meshPerAttribute;
46404
46405                 return ib;
46406
46407         },
46408
46409         toJSON: function ( data ) {
46410
46411                 const json = InterleavedBuffer.prototype.toJSON.call( this, data );
46412
46413                 json.isInstancedInterleavedBuffer = true;
46414                 json.meshPerAttribute = this.meshPerAttribute;
46415
46416                 return json;
46417
46418         }
46419
46420 } );
46421
46422 function GLBufferAttribute( buffer, type, itemSize, elementSize, count ) {
46423
46424         this.buffer = buffer;
46425         this.type = type;
46426         this.itemSize = itemSize;
46427         this.elementSize = elementSize;
46428         this.count = count;
46429
46430         this.version = 0;
46431
46432 }
46433
46434 Object.defineProperty( GLBufferAttribute.prototype, 'needsUpdate', {
46435
46436         set: function ( value ) {
46437
46438                 if ( value === true ) this.version ++;
46439
46440         }
46441
46442 } );
46443
46444 Object.assign( GLBufferAttribute.prototype, {
46445
46446         isGLBufferAttribute: true,
46447
46448         setBuffer: function ( buffer ) {
46449
46450                 this.buffer = buffer;
46451
46452                 return this;
46453
46454         },
46455
46456         setType: function ( type, elementSize ) {
46457
46458                 this.type = type;
46459                 this.elementSize = elementSize;
46460
46461                 return this;
46462
46463         },
46464
46465         setItemSize: function ( itemSize ) {
46466
46467                 this.itemSize = itemSize;
46468
46469                 return this;
46470
46471         },
46472
46473         setCount: function ( count ) {
46474
46475                 this.count = count;
46476
46477                 return this;
46478
46479         },
46480
46481 } );
46482
46483 function Raycaster( origin, direction, near, far ) {
46484
46485         this.ray = new Ray( origin, direction );
46486         // direction is assumed to be normalized (for accurate distance calculations)
46487
46488         this.near = near || 0;
46489         this.far = far || Infinity;
46490         this.camera = null;
46491         this.layers = new Layers();
46492
46493         this.params = {
46494                 Mesh: {},
46495                 Line: { threshold: 1 },
46496                 LOD: {},
46497                 Points: { threshold: 1 },
46498                 Sprite: {}
46499         };
46500
46501         Object.defineProperties( this.params, {
46502                 PointCloud: {
46503                         get: function () {
46504
46505                                 console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
46506                                 return this.Points;
46507
46508                         }
46509                 }
46510         } );
46511
46512 }
46513
46514 function ascSort( a, b ) {
46515
46516         return a.distance - b.distance;
46517
46518 }
46519
46520 function intersectObject( object, raycaster, intersects, recursive ) {
46521
46522         if ( object.layers.test( raycaster.layers ) ) {
46523
46524                 object.raycast( raycaster, intersects );
46525
46526         }
46527
46528         if ( recursive === true ) {
46529
46530                 const children = object.children;
46531
46532                 for ( let i = 0, l = children.length; i < l; i ++ ) {
46533
46534                         intersectObject( children[ i ], raycaster, intersects, true );
46535
46536                 }
46537
46538         }
46539
46540 }
46541
46542 Object.assign( Raycaster.prototype, {
46543
46544         set: function ( origin, direction ) {
46545
46546                 // direction is assumed to be normalized (for accurate distance calculations)
46547
46548                 this.ray.set( origin, direction );
46549
46550         },
46551
46552         setFromCamera: function ( coords, camera ) {
46553
46554                 if ( ( camera && camera.isPerspectiveCamera ) ) {
46555
46556                         this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
46557                         this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
46558                         this.camera = camera;
46559
46560                 } else if ( ( camera && camera.isOrthographicCamera ) ) {
46561
46562                         this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
46563                         this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
46564                         this.camera = camera;
46565
46566                 } else {
46567
46568                         console.error( 'THREE.Raycaster: Unsupported camera type.' );
46569
46570                 }
46571
46572         },
46573
46574         intersectObject: function ( object, recursive, optionalTarget ) {
46575
46576                 const intersects = optionalTarget || [];
46577
46578                 intersectObject( object, this, intersects, recursive );
46579
46580                 intersects.sort( ascSort );
46581
46582                 return intersects;
46583
46584         },
46585
46586         intersectObjects: function ( objects, recursive, optionalTarget ) {
46587
46588                 const intersects = optionalTarget || [];
46589
46590                 if ( Array.isArray( objects ) === false ) {
46591
46592                         console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
46593                         return intersects;
46594
46595                 }
46596
46597                 for ( let i = 0, l = objects.length; i < l; i ++ ) {
46598
46599                         intersectObject( objects[ i ], this, intersects, recursive );
46600
46601                 }
46602
46603                 intersects.sort( ascSort );
46604
46605                 return intersects;
46606
46607         }
46608
46609 } );
46610
46611 /**
46612  * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
46613  *
46614  * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.
46615  * The azimuthal angle (theta) is measured from the positive z-axis.
46616  */
46617
46618 class Spherical {
46619
46620         constructor( radius = 1, phi = 0, theta = 0 ) {
46621
46622                 this.radius = radius;
46623                 this.phi = phi; // polar angle
46624                 this.theta = theta; // azimuthal angle
46625
46626                 return this;
46627
46628         }
46629
46630         set( radius, phi, theta ) {
46631
46632                 this.radius = radius;
46633                 this.phi = phi;
46634                 this.theta = theta;
46635
46636                 return this;
46637
46638         }
46639
46640         clone() {
46641
46642                 return new this.constructor().copy( this );
46643
46644         }
46645
46646         copy( other ) {
46647
46648                 this.radius = other.radius;
46649                 this.phi = other.phi;
46650                 this.theta = other.theta;
46651
46652                 return this;
46653
46654         }
46655
46656         // restrict phi to be betwee EPS and PI-EPS
46657         makeSafe() {
46658
46659                 const EPS = 0.000001;
46660                 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
46661
46662                 return this;
46663
46664         }
46665
46666         setFromVector3( v ) {
46667
46668                 return this.setFromCartesianCoords( v.x, v.y, v.z );
46669
46670         }
46671
46672         setFromCartesianCoords( x, y, z ) {
46673
46674                 this.radius = Math.sqrt( x * x + y * y + z * z );
46675
46676                 if ( this.radius === 0 ) {
46677
46678                         this.theta = 0;
46679                         this.phi = 0;
46680
46681                 } else {
46682
46683                         this.theta = Math.atan2( x, z );
46684                         this.phi = Math.acos( MathUtils.clamp( y / this.radius, - 1, 1 ) );
46685
46686                 }
46687
46688                 return this;
46689
46690         }
46691
46692 }
46693
46694 /**
46695  * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
46696  */
46697
46698 class Cylindrical {
46699
46700         constructor( radius, theta, y ) {
46701
46702                 this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane
46703                 this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
46704                 this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane
46705
46706                 return this;
46707
46708         }
46709
46710         set( radius, theta, y ) {
46711
46712                 this.radius = radius;
46713                 this.theta = theta;
46714                 this.y = y;
46715
46716                 return this;
46717
46718         }
46719
46720         clone() {
46721
46722                 return new this.constructor().copy( this );
46723
46724         }
46725
46726         copy( other ) {
46727
46728                 this.radius = other.radius;
46729                 this.theta = other.theta;
46730                 this.y = other.y;
46731
46732                 return this;
46733
46734         }
46735
46736         setFromVector3( v ) {
46737
46738                 return this.setFromCartesianCoords( v.x, v.y, v.z );
46739
46740         }
46741
46742         setFromCartesianCoords( x, y, z ) {
46743
46744                 this.radius = Math.sqrt( x * x + z * z );
46745                 this.theta = Math.atan2( x, z );
46746                 this.y = y;
46747
46748                 return this;
46749
46750         }
46751
46752 }
46753
46754 const _vector$7 = /*@__PURE__*/ new Vector2();
46755
46756 class Box2 {
46757
46758         constructor( min, max ) {
46759
46760                 Object.defineProperty( this, 'isBox2', { value: true } );
46761
46762                 this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
46763                 this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
46764
46765         }
46766
46767         set( min, max ) {
46768
46769                 this.min.copy( min );
46770                 this.max.copy( max );
46771
46772                 return this;
46773
46774         }
46775
46776         setFromPoints( points ) {
46777
46778                 this.makeEmpty();
46779
46780                 for ( let i = 0, il = points.length; i < il; i ++ ) {
46781
46782                         this.expandByPoint( points[ i ] );
46783
46784                 }
46785
46786                 return this;
46787
46788         }
46789
46790         setFromCenterAndSize( center, size ) {
46791
46792                 const halfSize = _vector$7.copy( size ).multiplyScalar( 0.5 );
46793                 this.min.copy( center ).sub( halfSize );
46794                 this.max.copy( center ).add( halfSize );
46795
46796                 return this;
46797
46798         }
46799
46800         clone() {
46801
46802                 return new this.constructor().copy( this );
46803
46804         }
46805
46806         copy( box ) {
46807
46808                 this.min.copy( box.min );
46809                 this.max.copy( box.max );
46810
46811                 return this;
46812
46813         }
46814
46815         makeEmpty() {
46816
46817                 this.min.x = this.min.y = + Infinity;
46818                 this.max.x = this.max.y = - Infinity;
46819
46820                 return this;
46821
46822         }
46823
46824         isEmpty() {
46825
46826                 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
46827
46828                 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
46829
46830         }
46831
46832         getCenter( target ) {
46833
46834                 if ( target === undefined ) {
46835
46836                         console.warn( 'THREE.Box2: .getCenter() target is now required' );
46837                         target = new Vector2();
46838
46839                 }
46840
46841                 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
46842
46843         }
46844
46845         getSize( target ) {
46846
46847                 if ( target === undefined ) {
46848
46849                         console.warn( 'THREE.Box2: .getSize() target is now required' );
46850                         target = new Vector2();
46851
46852                 }
46853
46854                 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
46855
46856         }
46857
46858         expandByPoint( point ) {
46859
46860                 this.min.min( point );
46861                 this.max.max( point );
46862
46863                 return this;
46864
46865         }
46866
46867         expandByVector( vector ) {
46868
46869                 this.min.sub( vector );
46870                 this.max.add( vector );
46871
46872                 return this;
46873
46874         }
46875
46876         expandByScalar( scalar ) {
46877
46878                 this.min.addScalar( - scalar );
46879                 this.max.addScalar( scalar );
46880
46881                 return this;
46882
46883         }
46884
46885         containsPoint( point ) {
46886
46887                 return point.x < this.min.x || point.x > this.max.x ||
46888                         point.y < this.min.y || point.y > this.max.y ? false : true;
46889
46890         }
46891
46892         containsBox( box ) {
46893
46894                 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
46895                         this.min.y <= box.min.y && box.max.y <= this.max.y;
46896
46897         }
46898
46899         getParameter( point, target ) {
46900
46901                 // This can potentially have a divide by zero if the box
46902                 // has a size dimension of 0.
46903
46904                 if ( target === undefined ) {
46905
46906                         console.warn( 'THREE.Box2: .getParameter() target is now required' );
46907                         target = new Vector2();
46908
46909                 }
46910
46911                 return target.set(
46912                         ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
46913                         ( point.y - this.min.y ) / ( this.max.y - this.min.y )
46914                 );
46915
46916         }
46917
46918         intersectsBox( box ) {
46919
46920                 // using 4 splitting planes to rule out intersections
46921
46922                 return box.max.x < this.min.x || box.min.x > this.max.x ||
46923                         box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
46924
46925         }
46926
46927         clampPoint( point, target ) {
46928
46929                 if ( target === undefined ) {
46930
46931                         console.warn( 'THREE.Box2: .clampPoint() target is now required' );
46932                         target = new Vector2();
46933
46934                 }
46935
46936                 return target.copy( point ).clamp( this.min, this.max );
46937
46938         }
46939
46940         distanceToPoint( point ) {
46941
46942                 const clampedPoint = _vector$7.copy( point ).clamp( this.min, this.max );
46943                 return clampedPoint.sub( point ).length();
46944
46945         }
46946
46947         intersect( box ) {
46948
46949                 this.min.max( box.min );
46950                 this.max.min( box.max );
46951
46952                 return this;
46953
46954         }
46955
46956         union( box ) {
46957
46958                 this.min.min( box.min );
46959                 this.max.max( box.max );
46960
46961                 return this;
46962
46963         }
46964
46965         translate( offset ) {
46966
46967                 this.min.add( offset );
46968                 this.max.add( offset );
46969
46970                 return this;
46971
46972         }
46973
46974         equals( box ) {
46975
46976                 return box.min.equals( this.min ) && box.max.equals( this.max );
46977
46978         }
46979
46980 }
46981
46982 const _startP = /*@__PURE__*/ new Vector3();
46983 const _startEnd = /*@__PURE__*/ new Vector3();
46984
46985 class Line3 {
46986
46987         constructor( start, end ) {
46988
46989                 this.start = ( start !== undefined ) ? start : new Vector3();
46990                 this.end = ( end !== undefined ) ? end : new Vector3();
46991
46992         }
46993
46994         set( start, end ) {
46995
46996                 this.start.copy( start );
46997                 this.end.copy( end );
46998
46999                 return this;
47000
47001         }
47002
47003         clone() {
47004
47005                 return new this.constructor().copy( this );
47006
47007         }
47008
47009         copy( line ) {
47010
47011                 this.start.copy( line.start );
47012                 this.end.copy( line.end );
47013
47014                 return this;
47015
47016         }
47017
47018         getCenter( target ) {
47019
47020                 if ( target === undefined ) {
47021
47022                         console.warn( 'THREE.Line3: .getCenter() target is now required' );
47023                         target = new Vector3();
47024
47025                 }
47026
47027                 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
47028
47029         }
47030
47031         delta( target ) {
47032
47033                 if ( target === undefined ) {
47034
47035                         console.warn( 'THREE.Line3: .delta() target is now required' );
47036                         target = new Vector3();
47037
47038                 }
47039
47040                 return target.subVectors( this.end, this.start );
47041
47042         }
47043
47044         distanceSq() {
47045
47046                 return this.start.distanceToSquared( this.end );
47047
47048         }
47049
47050         distance() {
47051
47052                 return this.start.distanceTo( this.end );
47053
47054         }
47055
47056         at( t, target ) {
47057
47058                 if ( target === undefined ) {
47059
47060                         console.warn( 'THREE.Line3: .at() target is now required' );
47061                         target = new Vector3();
47062
47063                 }
47064
47065                 return this.delta( target ).multiplyScalar( t ).add( this.start );
47066
47067         }
47068
47069         closestPointToPointParameter( point, clampToLine ) {
47070
47071                 _startP.subVectors( point, this.start );
47072                 _startEnd.subVectors( this.end, this.start );
47073
47074                 const startEnd2 = _startEnd.dot( _startEnd );
47075                 const startEnd_startP = _startEnd.dot( _startP );
47076
47077                 let t = startEnd_startP / startEnd2;
47078
47079                 if ( clampToLine ) {
47080
47081                         t = MathUtils.clamp( t, 0, 1 );
47082
47083                 }
47084
47085                 return t;
47086
47087         }
47088
47089         closestPointToPoint( point, clampToLine, target ) {
47090
47091                 const t = this.closestPointToPointParameter( point, clampToLine );
47092
47093                 if ( target === undefined ) {
47094
47095                         console.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );
47096                         target = new Vector3();
47097
47098                 }
47099
47100                 return this.delta( target ).multiplyScalar( t ).add( this.start );
47101
47102         }
47103
47104         applyMatrix4( matrix ) {
47105
47106                 this.start.applyMatrix4( matrix );
47107                 this.end.applyMatrix4( matrix );
47108
47109                 return this;
47110
47111         }
47112
47113         equals( line ) {
47114
47115                 return line.start.equals( this.start ) && line.end.equals( this.end );
47116
47117         }
47118
47119 }
47120
47121 function ImmediateRenderObject( material ) {
47122
47123         Object3D.call( this );
47124
47125         this.material = material;
47126         this.render = function ( /* renderCallback */ ) {};
47127
47128         this.hasPositions = false;
47129         this.hasNormals = false;
47130         this.hasColors = false;
47131         this.hasUvs = false;
47132
47133         this.positionArray = null;
47134         this.normalArray = null;
47135         this.colorArray = null;
47136         this.uvArray = null;
47137
47138         this.count = 0;
47139
47140 }
47141
47142 ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
47143 ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
47144
47145 ImmediateRenderObject.prototype.isImmediateRenderObject = true;
47146
47147 const _vector$8 = /*@__PURE__*/ new Vector3();
47148
47149 class SpotLightHelper extends Object3D {
47150
47151         constructor( light, color ) {
47152
47153                 super();
47154                 this.light = light;
47155                 this.light.updateMatrixWorld();
47156
47157                 this.matrix = light.matrixWorld;
47158                 this.matrixAutoUpdate = false;
47159
47160                 this.color = color;
47161
47162                 const geometry = new BufferGeometry();
47163
47164                 const positions = [
47165                         0, 0, 0,        0, 0, 1,
47166                         0, 0, 0,        1, 0, 1,
47167                         0, 0, 0,        - 1, 0, 1,
47168                         0, 0, 0,        0, 1, 1,
47169                         0, 0, 0,        0, - 1, 1
47170                 ];
47171
47172                 for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
47173
47174                         const p1 = ( i / l ) * Math.PI * 2;
47175                         const p2 = ( j / l ) * Math.PI * 2;
47176
47177                         positions.push(
47178                                 Math.cos( p1 ), Math.sin( p1 ), 1,
47179                                 Math.cos( p2 ), Math.sin( p2 ), 1
47180                         );
47181
47182                 }
47183
47184                 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
47185
47186                 const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
47187
47188                 this.cone = new LineSegments( geometry, material );
47189                 this.add( this.cone );
47190
47191                 this.update();
47192
47193         }
47194
47195         dispose() {
47196
47197                 this.cone.geometry.dispose();
47198                 this.cone.material.dispose();
47199
47200         }
47201
47202         update() {
47203
47204                 this.light.updateMatrixWorld();
47205
47206                 const coneLength = this.light.distance ? this.light.distance : 1000;
47207                 const coneWidth = coneLength * Math.tan( this.light.angle );
47208
47209                 this.cone.scale.set( coneWidth, coneWidth, coneLength );
47210
47211                 _vector$8.setFromMatrixPosition( this.light.target.matrixWorld );
47212
47213                 this.cone.lookAt( _vector$8 );
47214
47215                 if ( this.color !== undefined ) {
47216
47217                         this.cone.material.color.set( this.color );
47218
47219                 } else {
47220
47221                         this.cone.material.color.copy( this.light.color );
47222
47223                 }
47224
47225         }
47226
47227 }
47228
47229 const _vector$9 = /*@__PURE__*/ new Vector3();
47230 const _boneMatrix = /*@__PURE__*/ new Matrix4();
47231 const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
47232
47233
47234 class SkeletonHelper extends LineSegments {
47235
47236         constructor( object ) {
47237
47238                 const bones = getBoneList( object );
47239
47240                 const geometry = new BufferGeometry();
47241
47242                 const vertices = [];
47243                 const colors = [];
47244
47245                 const color1 = new Color( 0, 0, 1 );
47246                 const color2 = new Color( 0, 1, 0 );
47247
47248                 for ( let i = 0; i < bones.length; i ++ ) {
47249
47250                         const bone = bones[ i ];
47251
47252                         if ( bone.parent && bone.parent.isBone ) {
47253
47254                                 vertices.push( 0, 0, 0 );
47255                                 vertices.push( 0, 0, 0 );
47256                                 colors.push( color1.r, color1.g, color1.b );
47257                                 colors.push( color2.r, color2.g, color2.b );
47258
47259                         }
47260
47261                 }
47262
47263                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
47264                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
47265
47266                 const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
47267
47268                 super( geometry, material );
47269
47270                 this.type = 'SkeletonHelper';
47271                 this.isSkeletonHelper = true;
47272
47273                 this.root = object;
47274                 this.bones = bones;
47275
47276                 this.matrix = object.matrixWorld;
47277                 this.matrixAutoUpdate = false;
47278
47279         }
47280
47281         updateMatrixWorld( force ) {
47282
47283                 const bones = this.bones;
47284
47285                 const geometry = this.geometry;
47286                 const position = geometry.getAttribute( 'position' );
47287
47288                 _matrixWorldInv.copy( this.root.matrixWorld ).invert();
47289
47290                 for ( let i = 0, j = 0; i < bones.length; i ++ ) {
47291
47292                         const bone = bones[ i ];
47293
47294                         if ( bone.parent && bone.parent.isBone ) {
47295
47296                                 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
47297                                 _vector$9.setFromMatrixPosition( _boneMatrix );
47298                                 position.setXYZ( j, _vector$9.x, _vector$9.y, _vector$9.z );
47299
47300                                 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
47301                                 _vector$9.setFromMatrixPosition( _boneMatrix );
47302                                 position.setXYZ( j + 1, _vector$9.x, _vector$9.y, _vector$9.z );
47303
47304                                 j += 2;
47305
47306                         }
47307
47308                 }
47309
47310                 geometry.getAttribute( 'position' ).needsUpdate = true;
47311
47312                 super.updateMatrixWorld( force );
47313
47314         }
47315
47316 }
47317
47318
47319 function getBoneList( object ) {
47320
47321         const boneList = [];
47322
47323         if ( object && object.isBone ) {
47324
47325                 boneList.push( object );
47326
47327         }
47328
47329         for ( let i = 0; i < object.children.length; i ++ ) {
47330
47331                 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
47332
47333         }
47334
47335         return boneList;
47336
47337 }
47338
47339 class PointLightHelper extends Mesh {
47340
47341         constructor( light, sphereSize, color ) {
47342
47343                 const geometry = new SphereBufferGeometry( sphereSize, 4, 2 );
47344                 const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
47345
47346                 super( geometry, material );
47347
47348                 this.light = light;
47349                 this.light.updateMatrixWorld();
47350
47351                 this.color = color;
47352
47353                 this.type = 'PointLightHelper';
47354
47355                 this.matrix = this.light.matrixWorld;
47356                 this.matrixAutoUpdate = false;
47357
47358                 this.update();
47359
47360
47361                 /*
47362         // TODO: delete this comment?
47363         const distanceGeometry = new THREE.IcosahedronBufferGeometry( 1, 2 );
47364         const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
47365
47366         this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
47367         this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
47368
47369         const d = light.distance;
47370
47371         if ( d === 0.0 ) {
47372
47373                 this.lightDistance.visible = false;
47374
47375         } else {
47376
47377                 this.lightDistance.scale.set( d, d, d );
47378
47379         }
47380
47381         this.add( this.lightDistance );
47382         */
47383
47384         }
47385
47386         dispose() {
47387
47388                 this.geometry.dispose();
47389                 this.material.dispose();
47390
47391         }
47392
47393         update() {
47394
47395                 if ( this.color !== undefined ) {
47396
47397                         this.material.color.set( this.color );
47398
47399                 } else {
47400
47401                         this.material.color.copy( this.light.color );
47402
47403                 }
47404
47405                 /*
47406                 const d = this.light.distance;
47407
47408                 if ( d === 0.0 ) {
47409
47410                         this.lightDistance.visible = false;
47411
47412                 } else {
47413
47414                         this.lightDistance.visible = true;
47415                         this.lightDistance.scale.set( d, d, d );
47416
47417                 }
47418                 */
47419
47420         }
47421
47422 }
47423
47424 const _vector$a = /*@__PURE__*/ new Vector3();
47425 const _color1 = /*@__PURE__*/ new Color();
47426 const _color2 = /*@__PURE__*/ new Color();
47427
47428 class HemisphereLightHelper extends Object3D {
47429
47430         constructor( light, size, color ) {
47431
47432                 super();
47433                 this.light = light;
47434                 this.light.updateMatrixWorld();
47435
47436                 this.matrix = light.matrixWorld;
47437                 this.matrixAutoUpdate = false;
47438
47439                 this.color = color;
47440
47441                 const geometry = new OctahedronBufferGeometry( size );
47442                 geometry.rotateY( Math.PI * 0.5 );
47443
47444                 this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
47445                 if ( this.color === undefined ) this.material.vertexColors = true;
47446
47447                 const position = geometry.getAttribute( 'position' );
47448                 const colors = new Float32Array( position.count * 3 );
47449
47450                 geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
47451
47452                 this.add( new Mesh( geometry, this.material ) );
47453
47454                 this.update();
47455
47456         }
47457
47458         dispose() {
47459
47460                 this.children[ 0 ].geometry.dispose();
47461                 this.children[ 0 ].material.dispose();
47462
47463         }
47464
47465         update() {
47466
47467                 const mesh = this.children[ 0 ];
47468
47469                 if ( this.color !== undefined ) {
47470
47471                         this.material.color.set( this.color );
47472
47473                 } else {
47474
47475                         const colors = mesh.geometry.getAttribute( 'color' );
47476
47477                         _color1.copy( this.light.color );
47478                         _color2.copy( this.light.groundColor );
47479
47480                         for ( let i = 0, l = colors.count; i < l; i ++ ) {
47481
47482                                 const color = ( i < ( l / 2 ) ) ? _color1 : _color2;
47483
47484                                 colors.setXYZ( i, color.r, color.g, color.b );
47485
47486                         }
47487
47488                         colors.needsUpdate = true;
47489
47490                 }
47491
47492                 mesh.lookAt( _vector$a.setFromMatrixPosition( this.light.matrixWorld ).negate() );
47493
47494         }
47495
47496 }
47497
47498 class GridHelper extends LineSegments {
47499
47500         constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
47501
47502                 color1 = new Color( color1 );
47503                 color2 = new Color( color2 );
47504
47505                 const center = divisions / 2;
47506                 const step = size / divisions;
47507                 const halfSize = size / 2;
47508
47509                 const vertices = [], colors = [];
47510
47511                 for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
47512
47513                         vertices.push( - halfSize, 0, k, halfSize, 0, k );
47514                         vertices.push( k, 0, - halfSize, k, 0, halfSize );
47515
47516                         const color = i === center ? color1 : color2;
47517
47518                         color.toArray( colors, j ); j += 3;
47519                         color.toArray( colors, j ); j += 3;
47520                         color.toArray( colors, j ); j += 3;
47521                         color.toArray( colors, j ); j += 3;
47522
47523                 }
47524
47525                 const geometry = new BufferGeometry();
47526                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
47527                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
47528
47529                 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
47530
47531                 super( geometry, material );
47532
47533                 this.type = 'GridHelper';
47534
47535         }
47536
47537 }
47538
47539 class PolarGridHelper extends LineSegments {
47540
47541         constructor( radius = 10, radials = 16, circles = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) {
47542
47543                 color1 = new Color( color1 );
47544                 color2 = new Color( color2 );
47545
47546                 const vertices = [];
47547                 const colors = [];
47548
47549                 // create the radials
47550
47551                 for ( let i = 0; i <= radials; i ++ ) {
47552
47553                         const v = ( i / radials ) * ( Math.PI * 2 );
47554
47555                         const x = Math.sin( v ) * radius;
47556                         const z = Math.cos( v ) * radius;
47557
47558                         vertices.push( 0, 0, 0 );
47559                         vertices.push( x, 0, z );
47560
47561                         const color = ( i & 1 ) ? color1 : color2;
47562
47563                         colors.push( color.r, color.g, color.b );
47564                         colors.push( color.r, color.g, color.b );
47565
47566                 }
47567
47568                 // create the circles
47569
47570                 for ( let i = 0; i <= circles; i ++ ) {
47571
47572                         const color = ( i & 1 ) ? color1 : color2;
47573
47574                         const r = radius - ( radius / circles * i );
47575
47576                         for ( let j = 0; j < divisions; j ++ ) {
47577
47578                                 // first vertex
47579
47580                                 let v = ( j / divisions ) * ( Math.PI * 2 );
47581
47582                                 let x = Math.sin( v ) * r;
47583                                 let z = Math.cos( v ) * r;
47584
47585                                 vertices.push( x, 0, z );
47586                                 colors.push( color.r, color.g, color.b );
47587
47588                                 // second vertex
47589
47590                                 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
47591
47592                                 x = Math.sin( v ) * r;
47593                                 z = Math.cos( v ) * r;
47594
47595                                 vertices.push( x, 0, z );
47596                                 colors.push( color.r, color.g, color.b );
47597
47598                         }
47599
47600                 }
47601
47602                 const geometry = new BufferGeometry();
47603                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
47604                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
47605
47606                 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
47607
47608                 super( geometry, material );
47609
47610                 this.type = 'PolarGridHelper';
47611
47612         }
47613
47614 }
47615
47616 const _v1$6 = /*@__PURE__*/ new Vector3();
47617 const _v2$3 = /*@__PURE__*/ new Vector3();
47618 const _v3$1 = /*@__PURE__*/ new Vector3();
47619
47620 class DirectionalLightHelper extends Object3D {
47621
47622         constructor( light, size, color ) {
47623
47624                 super();
47625                 this.light = light;
47626                 this.light.updateMatrixWorld();
47627
47628                 this.matrix = light.matrixWorld;
47629                 this.matrixAutoUpdate = false;
47630
47631                 this.color = color;
47632
47633                 if ( size === undefined ) size = 1;
47634
47635                 let geometry = new BufferGeometry();
47636                 geometry.setAttribute( 'position', new Float32BufferAttribute( [
47637                         - size, size, 0,
47638                         size, size, 0,
47639                         size, - size, 0,
47640                         - size, - size, 0,
47641                         - size, size, 0
47642                 ], 3 ) );
47643
47644                 const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
47645
47646                 this.lightPlane = new Line( geometry, material );
47647                 this.add( this.lightPlane );
47648
47649                 geometry = new BufferGeometry();
47650                 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
47651
47652                 this.targetLine = new Line( geometry, material );
47653                 this.add( this.targetLine );
47654
47655                 this.update();
47656
47657         }
47658
47659         dispose() {
47660
47661                 this.lightPlane.geometry.dispose();
47662                 this.lightPlane.material.dispose();
47663                 this.targetLine.geometry.dispose();
47664                 this.targetLine.material.dispose();
47665
47666         }
47667
47668         update() {
47669
47670                 _v1$6.setFromMatrixPosition( this.light.matrixWorld );
47671                 _v2$3.setFromMatrixPosition( this.light.target.matrixWorld );
47672                 _v3$1.subVectors( _v2$3, _v1$6 );
47673
47674                 this.lightPlane.lookAt( _v2$3 );
47675
47676                 if ( this.color !== undefined ) {
47677
47678                         this.lightPlane.material.color.set( this.color );
47679                         this.targetLine.material.color.set( this.color );
47680
47681                 } else {
47682
47683                         this.lightPlane.material.color.copy( this.light.color );
47684                         this.targetLine.material.color.copy( this.light.color );
47685
47686                 }
47687
47688                 this.targetLine.lookAt( _v2$3 );
47689                 this.targetLine.scale.z = _v3$1.length();
47690
47691         }
47692
47693 }
47694
47695 const _vector$b = /*@__PURE__*/ new Vector3();
47696 const _camera = /*@__PURE__*/ new Camera();
47697
47698 /**
47699  *      - shows frustum, line of sight and up of the camera
47700  *      - suitable for fast updates
47701  *      - based on frustum visualization in lightgl.js shadowmap example
47702  *              http://evanw.github.com/lightgl.js/tests/shadowmap.html
47703  */
47704
47705 class CameraHelper extends LineSegments {
47706
47707         constructor( camera ) {
47708
47709                 const geometry = new BufferGeometry();
47710                 const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
47711
47712                 const vertices = [];
47713                 const colors = [];
47714
47715                 const pointMap = {};
47716
47717                 // colors
47718
47719                 const colorFrustum = new Color( 0xffaa00 );
47720                 const colorCone = new Color( 0xff0000 );
47721                 const colorUp = new Color( 0x00aaff );
47722                 const colorTarget = new Color( 0xffffff );
47723                 const colorCross = new Color( 0x333333 );
47724
47725                 // near
47726
47727                 addLine( 'n1', 'n2', colorFrustum );
47728                 addLine( 'n2', 'n4', colorFrustum );
47729                 addLine( 'n4', 'n3', colorFrustum );
47730                 addLine( 'n3', 'n1', colorFrustum );
47731
47732                 // far
47733
47734                 addLine( 'f1', 'f2', colorFrustum );
47735                 addLine( 'f2', 'f4', colorFrustum );
47736                 addLine( 'f4', 'f3', colorFrustum );
47737                 addLine( 'f3', 'f1', colorFrustum );
47738
47739                 // sides
47740
47741                 addLine( 'n1', 'f1', colorFrustum );
47742                 addLine( 'n2', 'f2', colorFrustum );
47743                 addLine( 'n3', 'f3', colorFrustum );
47744                 addLine( 'n4', 'f4', colorFrustum );
47745
47746                 // cone
47747
47748                 addLine( 'p', 'n1', colorCone );
47749                 addLine( 'p', 'n2', colorCone );
47750                 addLine( 'p', 'n3', colorCone );
47751                 addLine( 'p', 'n4', colorCone );
47752
47753                 // up
47754
47755                 addLine( 'u1', 'u2', colorUp );
47756                 addLine( 'u2', 'u3', colorUp );
47757                 addLine( 'u3', 'u1', colorUp );
47758
47759                 // target
47760
47761                 addLine( 'c', 't', colorTarget );
47762                 addLine( 'p', 'c', colorCross );
47763
47764                 // cross
47765
47766                 addLine( 'cn1', 'cn2', colorCross );
47767                 addLine( 'cn3', 'cn4', colorCross );
47768
47769                 addLine( 'cf1', 'cf2', colorCross );
47770                 addLine( 'cf3', 'cf4', colorCross );
47771
47772                 function addLine( a, b, color ) {
47773
47774                         addPoint( a, color );
47775                         addPoint( b, color );
47776
47777                 }
47778
47779                 function addPoint( id, color ) {
47780
47781                         vertices.push( 0, 0, 0 );
47782                         colors.push( color.r, color.g, color.b );
47783
47784                         if ( pointMap[ id ] === undefined ) {
47785
47786                                 pointMap[ id ] = [];
47787
47788                         }
47789
47790                         pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
47791
47792                 }
47793
47794                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
47795                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
47796
47797                 super( geometry, material );
47798
47799                 this.type = 'CameraHelper';
47800
47801                 this.camera = camera;
47802                 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
47803
47804                 this.matrix = camera.matrixWorld;
47805                 this.matrixAutoUpdate = false;
47806
47807                 this.pointMap = pointMap;
47808
47809                 this.update();
47810
47811         }
47812
47813         update() {
47814
47815                 const geometry = this.geometry;
47816                 const pointMap = this.pointMap;
47817
47818                 const w = 1, h = 1;
47819
47820                 // we need just camera projection matrix inverse
47821                 // world matrix must be identity
47822
47823                 _camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
47824
47825                 // center / target
47826
47827                 setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );
47828                 setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );
47829
47830                 // near
47831
47832                 setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );
47833                 setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );
47834                 setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );
47835                 setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );
47836
47837                 // far
47838
47839                 setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );
47840                 setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );
47841                 setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );
47842                 setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );
47843
47844                 // up
47845
47846                 setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );
47847                 setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );
47848                 setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );
47849
47850                 // cross
47851
47852                 setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );
47853                 setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );
47854                 setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );
47855                 setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );
47856
47857                 setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );
47858                 setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );
47859                 setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );
47860                 setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );
47861
47862                 geometry.getAttribute( 'position' ).needsUpdate = true;
47863
47864         }
47865
47866 }
47867
47868
47869 function setPoint( point, pointMap, geometry, camera, x, y, z ) {
47870
47871         _vector$b.set( x, y, z ).unproject( camera );
47872
47873         const points = pointMap[ point ];
47874
47875         if ( points !== undefined ) {
47876
47877                 const position = geometry.getAttribute( 'position' );
47878
47879                 for ( let i = 0, l = points.length; i < l; i ++ ) {
47880
47881                         position.setXYZ( points[ i ], _vector$b.x, _vector$b.y, _vector$b.z );
47882
47883                 }
47884
47885         }
47886
47887 }
47888
47889 const _box$3 = /*@__PURE__*/ new Box3();
47890
47891 class BoxHelper extends LineSegments {
47892
47893         constructor( object, color = 0xffff00 ) {
47894
47895                 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 ] );
47896                 const positions = new Float32Array( 8 * 3 );
47897
47898                 const geometry = new BufferGeometry();
47899                 geometry.setIndex( new BufferAttribute( indices, 1 ) );
47900                 geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
47901
47902                 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
47903
47904                 this.object = object;
47905                 this.type = 'BoxHelper';
47906
47907                 this.matrixAutoUpdate = false;
47908
47909                 this.update();
47910
47911         }
47912
47913         update( object ) {
47914
47915                 if ( object !== undefined ) {
47916
47917                         console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
47918
47919                 }
47920
47921                 if ( this.object !== undefined ) {
47922
47923                         _box$3.setFromObject( this.object );
47924
47925                 }
47926
47927                 if ( _box$3.isEmpty() ) return;
47928
47929                 const min = _box$3.min;
47930                 const max = _box$3.max;
47931
47932                 /*
47933                         5____4
47934                 1/___0/|
47935                 | 6__|_7
47936                 2/___3/
47937
47938                 0: max.x, max.y, max.z
47939                 1: min.x, max.y, max.z
47940                 2: min.x, min.y, max.z
47941                 3: max.x, min.y, max.z
47942                 4: max.x, max.y, min.z
47943                 5: min.x, max.y, min.z
47944                 6: min.x, min.y, min.z
47945                 7: max.x, min.y, min.z
47946                 */
47947
47948                 const position = this.geometry.attributes.position;
47949                 const array = position.array;
47950
47951                 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
47952                 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
47953                 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
47954                 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
47955                 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
47956                 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
47957                 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
47958                 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
47959
47960                 position.needsUpdate = true;
47961
47962                 this.geometry.computeBoundingSphere();
47963
47964
47965         }
47966
47967         setFromObject( object ) {
47968
47969                 this.object = object;
47970                 this.update();
47971
47972                 return this;
47973
47974         }
47975
47976         copy( source ) {
47977
47978                 LineSegments.prototype.copy.call( this, source );
47979
47980                 this.object = source.object;
47981
47982                 return this;
47983
47984         }
47985
47986 }
47987
47988 class Box3Helper extends LineSegments {
47989
47990         constructor( box, color = 0xffff00 ) {
47991
47992                 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 ] );
47993
47994                 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 ];
47995
47996                 const geometry = new BufferGeometry();
47997
47998                 geometry.setIndex( new BufferAttribute( indices, 1 ) );
47999
48000                 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
48001
48002                 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
48003
48004                 this.box = box;
48005
48006                 this.type = 'Box3Helper';
48007
48008                 this.geometry.computeBoundingSphere();
48009
48010         }
48011
48012         updateMatrixWorld( force ) {
48013
48014                 const box = this.box;
48015
48016                 if ( box.isEmpty() ) return;
48017
48018                 box.getCenter( this.position );
48019
48020                 box.getSize( this.scale );
48021
48022                 this.scale.multiplyScalar( 0.5 );
48023
48024                 super.updateMatrixWorld( force );
48025
48026         }
48027
48028 }
48029
48030 class PlaneHelper extends Line {
48031
48032         constructor( plane, size = 1, hex = 0xffff00 ) {
48033
48034                 const color = hex;
48035
48036                 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 ];
48037
48038                 const geometry = new BufferGeometry();
48039                 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
48040                 geometry.computeBoundingSphere();
48041
48042                 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
48043
48044                 this.type = 'PlaneHelper';
48045
48046                 this.plane = plane;
48047
48048                 this.size = size;
48049
48050                 const positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];
48051
48052                 const geometry2 = new BufferGeometry();
48053                 geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
48054                 geometry2.computeBoundingSphere();
48055
48056                 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
48057
48058         }
48059
48060         updateMatrixWorld( force ) {
48061
48062                 let scale = - this.plane.constant;
48063
48064                 if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter
48065
48066                 this.scale.set( 0.5 * this.size, 0.5 * this.size, scale );
48067
48068                 this.children[ 0 ].material.side = ( scale < 0 ) ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here
48069
48070                 this.lookAt( this.plane.normal );
48071
48072                 super.updateMatrixWorld( force );
48073
48074         }
48075
48076 }
48077
48078 const _axis = /*@__PURE__*/ new Vector3();
48079 let _lineGeometry, _coneGeometry;
48080
48081 class ArrowHelper extends Object3D {
48082
48083         constructor( dir, origin, length, color, headLength, headWidth ) {
48084
48085                 super();
48086                 // dir is assumed to be normalized
48087
48088                 this.type = 'ArrowHelper';
48089
48090                 if ( dir === undefined ) dir = new Vector3( 0, 0, 1 );
48091                 if ( origin === undefined ) origin = new Vector3( 0, 0, 0 );
48092                 if ( length === undefined ) length = 1;
48093                 if ( color === undefined ) color = 0xffff00;
48094                 if ( headLength === undefined ) headLength = 0.2 * length;
48095                 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
48096
48097                 if ( _lineGeometry === undefined ) {
48098
48099                         _lineGeometry = new BufferGeometry();
48100                         _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
48101
48102                         _coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );
48103                         _coneGeometry.translate( 0, - 0.5, 0 );
48104
48105                 }
48106
48107                 this.position.copy( origin );
48108
48109                 this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
48110                 this.line.matrixAutoUpdate = false;
48111                 this.add( this.line );
48112
48113                 this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
48114                 this.cone.matrixAutoUpdate = false;
48115                 this.add( this.cone );
48116
48117                 this.setDirection( dir );
48118                 this.setLength( length, headLength, headWidth );
48119
48120         }
48121
48122         setDirection( dir ) {
48123
48124                 // dir is assumed to be normalized
48125
48126                 if ( dir.y > 0.99999 ) {
48127
48128                         this.quaternion.set( 0, 0, 0, 1 );
48129
48130                 } else if ( dir.y < - 0.99999 ) {
48131
48132                         this.quaternion.set( 1, 0, 0, 0 );
48133
48134                 } else {
48135
48136                         _axis.set( dir.z, 0, - dir.x ).normalize();
48137
48138                         const radians = Math.acos( dir.y );
48139
48140                         this.quaternion.setFromAxisAngle( _axis, radians );
48141
48142                 }
48143
48144         }
48145
48146         setLength( length, headLength, headWidth ) {
48147
48148                 if ( headLength === undefined ) headLength = 0.2 * length;
48149                 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
48150
48151                 this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
48152                 this.line.updateMatrix();
48153
48154                 this.cone.scale.set( headWidth, headLength, headWidth );
48155                 this.cone.position.y = length;
48156                 this.cone.updateMatrix();
48157
48158         }
48159
48160         setColor( color ) {
48161
48162                 this.line.material.color.set( color );
48163                 this.cone.material.color.set( color );
48164
48165         }
48166
48167         copy( source ) {
48168
48169                 super.copy( source, false );
48170
48171                 this.line.copy( source.line );
48172                 this.cone.copy( source.cone );
48173
48174                 return this;
48175
48176         }
48177
48178 }
48179
48180 class AxesHelper extends LineSegments {
48181
48182         constructor( size = 1 ) {
48183
48184                 const vertices = [
48185                         0, 0, 0,        size, 0, 0,
48186                         0, 0, 0,        0, size, 0,
48187                         0, 0, 0,        0, 0, size
48188                 ];
48189
48190                 const colors = [
48191                         1, 0, 0,        1, 0.6, 0,
48192                         0, 1, 0,        0.6, 1, 0,
48193                         0, 0, 1,        0, 0.6, 1
48194                 ];
48195
48196                 const geometry = new BufferGeometry();
48197                 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
48198                 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
48199
48200                 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
48201
48202                 super( geometry, material );
48203
48204                 this.type = 'AxesHelper';
48205
48206         }
48207
48208 }
48209
48210 const _floatView = new Float32Array( 1 );
48211 const _int32View = new Int32Array( _floatView.buffer );
48212
48213 const DataUtils = {
48214
48215         // Converts float32 to float16 (stored as uint16 value).
48216
48217         toHalfFloat: function ( val ) {
48218
48219                 // Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410
48220
48221                 /* This method is faster than the OpenEXR implementation (very often
48222                 * used, eg. in Ogre), with the additional benefit of rounding, inspired
48223                 * by James Tursa?s half-precision code. */
48224
48225                 _floatView[ 0 ] = val;
48226                 const x = _int32View[ 0 ];
48227
48228                 let bits = ( x >> 16 ) & 0x8000; /* Get the sign */
48229                 let m = ( x >> 12 ) & 0x07ff; /* Keep one extra bit for rounding */
48230                 const e = ( x >> 23 ) & 0xff; /* Using int is faster here */
48231
48232                 /* If zero, or denormal, or exponent underflows too much for a denormal
48233                         * half, return signed zero. */
48234                 if ( e < 103 ) return bits;
48235
48236                 /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
48237                 if ( e > 142 ) {
48238
48239                         bits |= 0x7c00;
48240                         /* If exponent was 0xff and one mantissa bit was set, it means NaN,
48241                                                 * not Inf, so make sure we set one mantissa bit too. */
48242                         bits |= ( ( e == 255 ) ? 0 : 1 ) && ( x & 0x007fffff );
48243                         return bits;
48244
48245                 }
48246
48247                 /* If exponent underflows but not too much, return a denormal */
48248                 if ( e < 113 ) {
48249
48250                         m |= 0x0800;
48251                         /* Extra rounding may overflow and set mantissa to 0 and exponent
48252                                 * to 1, which is OK. */
48253                         bits |= ( m >> ( 114 - e ) ) + ( ( m >> ( 113 - e ) ) & 1 );
48254                         return bits;
48255
48256                 }
48257
48258                 bits |= ( ( e - 112 ) << 10 ) | ( m >> 1 );
48259                 /* Extra rounding. An overflow will set mantissa to 0 and increment
48260                         * the exponent, which is OK. */
48261                 bits += m & 1;
48262                 return bits;
48263
48264         }
48265
48266 };
48267
48268 const LOD_MIN = 4;
48269 const LOD_MAX = 8;
48270 const SIZE_MAX = Math.pow( 2, LOD_MAX );
48271
48272 // The standard deviations (radians) associated with the extra mips. These are
48273 // chosen to approximate a Trowbridge-Reitz distribution function times the
48274 // geometric shadowing function. These sigma values squared must match the
48275 // variance #defines in cube_uv_reflection_fragment.glsl.js.
48276 const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
48277
48278 const TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
48279
48280 // The maximum length of the blur for loop. Smaller sigmas will use fewer
48281 // samples and exit early, but not recompile the shader.
48282 const MAX_SAMPLES = 20;
48283
48284 const ENCODINGS = {
48285         [ LinearEncoding ]: 0,
48286         [ sRGBEncoding ]: 1,
48287         [ RGBEEncoding ]: 2,
48288         [ RGBM7Encoding ]: 3,
48289         [ RGBM16Encoding ]: 4,
48290         [ RGBDEncoding ]: 5,
48291         [ GammaEncoding ]: 6
48292 };
48293
48294 const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
48295 const { _lodPlanes, _sizeLods, _sigmas } = /*@__PURE__*/ _createPlanes();
48296 let _oldTarget = null;
48297
48298 // Golden Ratio
48299 const PHI = ( 1 + Math.sqrt( 5 ) ) / 2;
48300 const INV_PHI = 1 / PHI;
48301
48302 // Vertices of a dodecahedron (except the opposites, which represent the
48303 // same axis), used as axis directions evenly spread on a sphere.
48304 const _axisDirections = [
48305         /*@__PURE__*/ new Vector3( 1, 1, 1 ),
48306         /*@__PURE__*/ new Vector3( - 1, 1, 1 ),
48307         /*@__PURE__*/ new Vector3( 1, 1, - 1 ),
48308         /*@__PURE__*/ new Vector3( - 1, 1, - 1 ),
48309         /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ),
48310         /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ),
48311         /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ),
48312         /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ),
48313         /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ),
48314         /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ];
48315
48316 /**
48317  * This class generates a Prefiltered, Mipmapped Radiance Environment Map
48318  * (PMREM) from a cubeMap environment texture. This allows different levels of
48319  * blur to be quickly accessed based on material roughness. It is packed into a
48320  * special CubeUV format that allows us to perform custom interpolation so that
48321  * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
48322  * chain, it only goes down to the LOD_MIN level (above), and then creates extra
48323  * even more filtered 'mips' at the same LOD_MIN resolution, associated with
48324  * higher roughness levels. In this way we maintain resolution to smoothly
48325  * interpolate diffuse lighting while limiting sampling computation.
48326  */
48327
48328 class PMREMGenerator {
48329
48330         constructor( renderer ) {
48331
48332                 this._renderer = renderer;
48333                 this._pingPongRenderTarget = null;
48334
48335                 this._blurMaterial = _getBlurShader( MAX_SAMPLES );
48336                 this._equirectShader = null;
48337                 this._cubemapShader = null;
48338
48339                 this._compileMaterial( this._blurMaterial );
48340
48341         }
48342
48343         /**
48344          * Generates a PMREM from a supplied Scene, which can be faster than using an
48345          * image if networking bandwidth is low. Optional sigma specifies a blur radius
48346          * in radians to be applied to the scene before PMREM generation. Optional near
48347          * and far planes ensure the scene is rendered in its entirety (the cubeCamera
48348          * is placed at the origin).
48349          */
48350         fromScene( scene, sigma = 0, near = 0.1, far = 100 ) {
48351
48352                 _oldTarget = this._renderer.getRenderTarget();
48353                 const cubeUVRenderTarget = this._allocateTargets();
48354
48355                 this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
48356                 if ( sigma > 0 ) {
48357
48358                         this._blur( cubeUVRenderTarget, 0, 0, sigma );
48359
48360                 }
48361
48362                 this._applyPMREM( cubeUVRenderTarget );
48363                 this._cleanup( cubeUVRenderTarget );
48364
48365                 return cubeUVRenderTarget;
48366
48367         }
48368
48369         /**
48370          * Generates a PMREM from an equirectangular texture, which can be either LDR
48371          * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512),
48372          * as this matches best with the 256 x 256 cubemap output.
48373          */
48374         fromEquirectangular( equirectangular ) {
48375
48376                 return this._fromTexture( equirectangular );
48377
48378         }
48379
48380         /**
48381          * Generates a PMREM from an cubemap texture, which can be either LDR
48382          * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256,
48383          * as this matches best with the 256 x 256 cubemap output.
48384          */
48385         fromCubemap( cubemap ) {
48386
48387                 return this._fromTexture( cubemap );
48388
48389         }
48390
48391         /**
48392          * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
48393          * your texture's network fetch for increased concurrency.
48394          */
48395         compileCubemapShader() {
48396
48397                 if ( this._cubemapShader === null ) {
48398
48399                         this._cubemapShader = _getCubemapShader();
48400                         this._compileMaterial( this._cubemapShader );
48401
48402                 }
48403
48404         }
48405
48406         /**
48407          * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
48408          * your texture's network fetch for increased concurrency.
48409          */
48410         compileEquirectangularShader() {
48411
48412                 if ( this._equirectShader === null ) {
48413
48414                         this._equirectShader = _getEquirectShader();
48415                         this._compileMaterial( this._equirectShader );
48416
48417                 }
48418
48419         }
48420
48421         /**
48422          * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
48423          * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
48424          * one of them will cause any others to also become unusable.
48425          */
48426         dispose() {
48427
48428                 this._blurMaterial.dispose();
48429
48430                 if ( this._cubemapShader !== null ) this._cubemapShader.dispose();
48431                 if ( this._equirectShader !== null ) this._equirectShader.dispose();
48432
48433                 for ( let i = 0; i < _lodPlanes.length; i ++ ) {
48434
48435                         _lodPlanes[ i ].dispose();
48436
48437                 }
48438
48439         }
48440
48441         // private interface
48442
48443         _cleanup( outputTarget ) {
48444
48445                 this._pingPongRenderTarget.dispose();
48446                 this._renderer.setRenderTarget( _oldTarget );
48447                 outputTarget.scissorTest = false;
48448                 _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
48449
48450         }
48451
48452         _fromTexture( texture ) {
48453
48454                 _oldTarget = this._renderer.getRenderTarget();
48455                 const cubeUVRenderTarget = this._allocateTargets( texture );
48456                 this._textureToCubeUV( texture, cubeUVRenderTarget );
48457                 this._applyPMREM( cubeUVRenderTarget );
48458                 this._cleanup( cubeUVRenderTarget );
48459
48460                 return cubeUVRenderTarget;
48461
48462         }
48463
48464         _allocateTargets( texture ) { // warning: null texture is valid
48465
48466                 const params = {
48467                         magFilter: NearestFilter,
48468                         minFilter: NearestFilter,
48469                         generateMipmaps: false,
48470                         type: UnsignedByteType,
48471                         format: RGBEFormat,
48472                         encoding: _isLDR( texture ) ? texture.encoding : RGBEEncoding,
48473                         depthBuffer: false
48474                 };
48475
48476                 const cubeUVRenderTarget = _createRenderTarget( params );
48477                 cubeUVRenderTarget.depthBuffer = texture ? false : true;
48478                 this._pingPongRenderTarget = _createRenderTarget( params );
48479                 return cubeUVRenderTarget;
48480
48481         }
48482
48483         _compileMaterial( material ) {
48484
48485                 const tmpMesh = new Mesh( _lodPlanes[ 0 ], material );
48486                 this._renderer.compile( tmpMesh, _flatCamera );
48487
48488         }
48489
48490         _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
48491
48492                 const fov = 90;
48493                 const aspect = 1;
48494                 const cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
48495                 const upSign = [ 1, - 1, 1, 1, 1, 1 ];
48496                 const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ];
48497                 const renderer = this._renderer;
48498
48499                 const outputEncoding = renderer.outputEncoding;
48500                 const toneMapping = renderer.toneMapping;
48501                 const clearColor = renderer.getClearColor();
48502                 const clearAlpha = renderer.getClearAlpha();
48503
48504                 renderer.toneMapping = NoToneMapping;
48505                 renderer.outputEncoding = LinearEncoding;
48506
48507                 let background = scene.background;
48508                 if ( background && background.isColor ) {
48509
48510                         background.convertSRGBToLinear();
48511                         // Convert linear to RGBE
48512                         const maxComponent = Math.max( background.r, background.g, background.b );
48513                         const fExp = Math.min( Math.max( Math.ceil( Math.log2( maxComponent ) ), - 128.0 ), 127.0 );
48514                         background = background.multiplyScalar( Math.pow( 2.0, - fExp ) );
48515                         const alpha = ( fExp + 128.0 ) / 255.0;
48516                         renderer.setClearColor( background, alpha );
48517                         scene.background = null;
48518
48519                 }
48520
48521                 for ( let i = 0; i < 6; i ++ ) {
48522
48523                         const col = i % 3;
48524                         if ( col == 0 ) {
48525
48526                                 cubeCamera.up.set( 0, upSign[ i ], 0 );
48527                                 cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
48528
48529                         } else if ( col == 1 ) {
48530
48531                                 cubeCamera.up.set( 0, 0, upSign[ i ] );
48532                                 cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
48533
48534                         } else {
48535
48536                                 cubeCamera.up.set( 0, upSign[ i ], 0 );
48537                                 cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
48538
48539                         }
48540
48541                         _setViewport( cubeUVRenderTarget,
48542                                 col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX );
48543                         renderer.setRenderTarget( cubeUVRenderTarget );
48544                         renderer.render( scene, cubeCamera );
48545
48546                 }
48547
48548                 renderer.toneMapping = toneMapping;
48549                 renderer.outputEncoding = outputEncoding;
48550                 renderer.setClearColor( clearColor, clearAlpha );
48551
48552         }
48553
48554         _textureToCubeUV( texture, cubeUVRenderTarget ) {
48555
48556                 const renderer = this._renderer;
48557
48558                 if ( texture.isCubeTexture ) {
48559
48560                         if ( this._cubemapShader == null ) {
48561
48562                                 this._cubemapShader = _getCubemapShader();
48563
48564                         }
48565
48566                 } else {
48567
48568                         if ( this._equirectShader == null ) {
48569
48570                                 this._equirectShader = _getEquirectShader();
48571
48572                         }
48573
48574                 }
48575
48576                 const material = texture.isCubeTexture ? this._cubemapShader : this._equirectShader;
48577                 const mesh = new Mesh( _lodPlanes[ 0 ], material );
48578
48579                 const uniforms = material.uniforms;
48580
48581                 uniforms[ 'envMap' ].value = texture;
48582
48583                 if ( ! texture.isCubeTexture ) {
48584
48585                         uniforms[ 'texelSize' ].value.set( 1.0 / texture.image.width, 1.0 / texture.image.height );
48586
48587                 }
48588
48589                 uniforms[ 'inputEncoding' ].value = ENCODINGS[ texture.encoding ];
48590                 uniforms[ 'outputEncoding' ].value = ENCODINGS[ cubeUVRenderTarget.texture.encoding ];
48591
48592                 _setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
48593
48594                 renderer.setRenderTarget( cubeUVRenderTarget );
48595                 renderer.render( mesh, _flatCamera );
48596
48597         }
48598
48599         _applyPMREM( cubeUVRenderTarget ) {
48600
48601                 const renderer = this._renderer;
48602                 const autoClear = renderer.autoClear;
48603                 renderer.autoClear = false;
48604
48605                 for ( let i = 1; i < TOTAL_LODS; i ++ ) {
48606
48607                         const sigma = Math.sqrt( _sigmas[ i ] * _sigmas[ i ] - _sigmas[ i - 1 ] * _sigmas[ i - 1 ] );
48608
48609                         const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ];
48610
48611                         this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
48612
48613                 }
48614
48615                 renderer.autoClear = autoClear;
48616
48617         }
48618
48619         /**
48620          * This is a two-pass Gaussian blur for a cubemap. Normally this is done
48621          * vertically and horizontally, but this breaks down on a cube. Here we apply
48622          * the blur latitudinally (around the poles), and then longitudinally (towards
48623          * the poles) to approximate the orthogonally-separable blur. It is least
48624          * accurate at the poles, but still does a decent job.
48625          */
48626         _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
48627
48628                 const pingPongRenderTarget = this._pingPongRenderTarget;
48629
48630                 this._halfBlur(
48631                         cubeUVRenderTarget,
48632                         pingPongRenderTarget,
48633                         lodIn,
48634                         lodOut,
48635                         sigma,
48636                         'latitudinal',
48637                         poleAxis );
48638
48639                 this._halfBlur(
48640                         pingPongRenderTarget,
48641                         cubeUVRenderTarget,
48642                         lodOut,
48643                         lodOut,
48644                         sigma,
48645                         'longitudinal',
48646                         poleAxis );
48647
48648         }
48649
48650         _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
48651
48652                 const renderer = this._renderer;
48653                 const blurMaterial = this._blurMaterial;
48654
48655                 if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
48656
48657                         console.error(
48658                                 'blur direction must be either latitudinal or longitudinal!' );
48659
48660                 }
48661
48662                 // Number of standard deviations at which to cut off the discrete approximation.
48663                 const STANDARD_DEVIATIONS = 3;
48664
48665                 const blurMesh = new Mesh( _lodPlanes[ lodOut ], blurMaterial );
48666                 const blurUniforms = blurMaterial.uniforms;
48667
48668                 const pixels = _sizeLods[ lodIn ] - 1;
48669                 const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
48670                 const sigmaPixels = sigmaRadians / radiansPerPixel;
48671                 const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
48672
48673                 if ( samples > MAX_SAMPLES ) {
48674
48675                         console.warn( `sigmaRadians, ${
48676                                 sigmaRadians}, is too large and will clip, as it requested ${
48677                                 samples} samples when the maximum is set to ${MAX_SAMPLES}` );
48678
48679                 }
48680
48681                 const weights = [];
48682                 let sum = 0;
48683
48684                 for ( let i = 0; i < MAX_SAMPLES; ++ i ) {
48685
48686                         const x = i / sigmaPixels;
48687                         const weight = Math.exp( - x * x / 2 );
48688                         weights.push( weight );
48689
48690                         if ( i == 0 ) {
48691
48692                                 sum += weight;
48693
48694                         } else if ( i < samples ) {
48695
48696                                 sum += 2 * weight;
48697
48698                         }
48699
48700                 }
48701
48702                 for ( let i = 0; i < weights.length; i ++ ) {
48703
48704                         weights[ i ] = weights[ i ] / sum;
48705
48706                 }
48707
48708                 blurUniforms[ 'envMap' ].value = targetIn.texture;
48709                 blurUniforms[ 'samples' ].value = samples;
48710                 blurUniforms[ 'weights' ].value = weights;
48711                 blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal';
48712
48713                 if ( poleAxis ) {
48714
48715                         blurUniforms[ 'poleAxis' ].value = poleAxis;
48716
48717                 }
48718
48719                 blurUniforms[ 'dTheta' ].value = radiansPerPixel;
48720                 blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn;
48721                 blurUniforms[ 'inputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
48722                 blurUniforms[ 'outputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
48723
48724                 const outputSize = _sizeLods[ lodOut ];
48725                 const x = 3 * Math.max( 0, SIZE_MAX - 2 * outputSize );
48726                 const y = ( lodOut === 0 ? 0 : 2 * SIZE_MAX ) + 2 * outputSize * ( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 );
48727
48728                 _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
48729                 renderer.setRenderTarget( targetOut );
48730                 renderer.render( blurMesh, _flatCamera );
48731
48732         }
48733
48734 }
48735
48736 function _isLDR( texture ) {
48737
48738         if ( texture === undefined || texture.type !== UnsignedByteType ) return false;
48739
48740         return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding;
48741
48742 }
48743
48744 function _createPlanes() {
48745
48746         const _lodPlanes = [];
48747         const _sizeLods = [];
48748         const _sigmas = [];
48749
48750         let lod = LOD_MAX;
48751
48752         for ( let i = 0; i < TOTAL_LODS; i ++ ) {
48753
48754                 const sizeLod = Math.pow( 2, lod );
48755                 _sizeLods.push( sizeLod );
48756                 let sigma = 1.0 / sizeLod;
48757
48758                 if ( i > LOD_MAX - LOD_MIN ) {
48759
48760                         sigma = EXTRA_LOD_SIGMA[ i - LOD_MAX + LOD_MIN - 1 ];
48761
48762                 } else if ( i == 0 ) {
48763
48764                         sigma = 0;
48765
48766                 }
48767
48768                 _sigmas.push( sigma );
48769
48770                 const texelSize = 1.0 / ( sizeLod - 1 );
48771                 const min = - texelSize / 2;
48772                 const max = 1 + texelSize / 2;
48773                 const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
48774
48775                 const cubeFaces = 6;
48776                 const vertices = 6;
48777                 const positionSize = 3;
48778                 const uvSize = 2;
48779                 const faceIndexSize = 1;
48780
48781                 const position = new Float32Array( positionSize * vertices * cubeFaces );
48782                 const uv = new Float32Array( uvSize * vertices * cubeFaces );
48783                 const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
48784
48785                 for ( let face = 0; face < cubeFaces; face ++ ) {
48786
48787                         const x = ( face % 3 ) * 2 / 3 - 1;
48788                         const y = face > 2 ? 0 : - 1;
48789                         const coordinates = [
48790                                 x, y, 0,
48791                                 x + 2 / 3, y, 0,
48792                                 x + 2 / 3, y + 1, 0,
48793                                 x, y, 0,
48794                                 x + 2 / 3, y + 1, 0,
48795                                 x, y + 1, 0
48796                         ];
48797                         position.set( coordinates, positionSize * vertices * face );
48798                         uv.set( uv1, uvSize * vertices * face );
48799                         const fill = [ face, face, face, face, face, face ];
48800                         faceIndex.set( fill, faceIndexSize * vertices * face );
48801
48802                 }
48803
48804                 const planes = new BufferGeometry();
48805                 planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
48806                 planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
48807                 planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
48808                 _lodPlanes.push( planes );
48809
48810                 if ( lod > LOD_MIN ) {
48811
48812                         lod --;
48813
48814                 }
48815
48816         }
48817
48818         return { _lodPlanes, _sizeLods, _sigmas };
48819
48820 }
48821
48822 function _createRenderTarget( params ) {
48823
48824         const cubeUVRenderTarget = new WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
48825         cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
48826         cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
48827         cubeUVRenderTarget.scissorTest = true;
48828         return cubeUVRenderTarget;
48829
48830 }
48831
48832 function _setViewport( target, x, y, width, height ) {
48833
48834         target.viewport.set( x, y, width, height );
48835         target.scissor.set( x, y, width, height );
48836
48837 }
48838
48839 function _getBlurShader( maxSamples ) {
48840
48841         const weights = new Float32Array( maxSamples );
48842         const poleAxis = new Vector3( 0, 1, 0 );
48843         const shaderMaterial = new RawShaderMaterial( {
48844
48845                 name: 'SphericalGaussianBlur',
48846
48847                 defines: { 'n': maxSamples },
48848
48849                 uniforms: {
48850                         'envMap': { value: null },
48851                         'samples': { value: 1 },
48852                         'weights': { value: weights },
48853                         'latitudinal': { value: false },
48854                         'dTheta': { value: 0 },
48855                         'mipInt': { value: 0 },
48856                         'poleAxis': { value: poleAxis },
48857                         'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
48858                         'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
48859                 },
48860
48861                 vertexShader: _getCommonVertexShader(),
48862
48863                 fragmentShader: /* glsl */`
48864
48865                         precision mediump float;
48866                         precision mediump int;
48867
48868                         varying vec3 vOutputDirection;
48869
48870                         uniform sampler2D envMap;
48871                         uniform int samples;
48872                         uniform float weights[ n ];
48873                         uniform bool latitudinal;
48874                         uniform float dTheta;
48875                         uniform float mipInt;
48876                         uniform vec3 poleAxis;
48877
48878                         ${ _getEncodings() }
48879
48880                         #define ENVMAP_TYPE_CUBE_UV
48881                         #include <cube_uv_reflection_fragment>
48882
48883                         vec3 getSample( float theta, vec3 axis ) {
48884
48885                                 float cosTheta = cos( theta );
48886                                 // Rodrigues' axis-angle rotation
48887                                 vec3 sampleDirection = vOutputDirection * cosTheta
48888                                         + cross( axis, vOutputDirection ) * sin( theta )
48889                                         + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
48890
48891                                 return bilinearCubeUV( envMap, sampleDirection, mipInt );
48892
48893                         }
48894
48895                         void main() {
48896
48897                                 vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
48898
48899                                 if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
48900
48901                                         axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
48902
48903                                 }
48904
48905                                 axis = normalize( axis );
48906
48907                                 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
48908                                 gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
48909
48910                                 for ( int i = 1; i < n; i++ ) {
48911
48912                                         if ( i >= samples ) {
48913
48914                                                 break;
48915
48916                                         }
48917
48918                                         float theta = dTheta * float( i );
48919                                         gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
48920                                         gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
48921
48922                                 }
48923
48924                                 gl_FragColor = linearToOutputTexel( gl_FragColor );
48925
48926                         }
48927                 `,
48928
48929                 blending: NoBlending,
48930                 depthTest: false,
48931                 depthWrite: false
48932
48933         } );
48934
48935         return shaderMaterial;
48936
48937 }
48938
48939 function _getEquirectShader() {
48940
48941         const texelSize = new Vector2( 1, 1 );
48942         const shaderMaterial = new RawShaderMaterial( {
48943
48944                 name: 'EquirectangularToCubeUV',
48945
48946                 uniforms: {
48947                         'envMap': { value: null },
48948                         'texelSize': { value: texelSize },
48949                         'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
48950                         'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
48951                 },
48952
48953                 vertexShader: _getCommonVertexShader(),
48954
48955                 fragmentShader: /* glsl */`
48956
48957                         precision mediump float;
48958                         precision mediump int;
48959
48960                         varying vec3 vOutputDirection;
48961
48962                         uniform sampler2D envMap;
48963                         uniform vec2 texelSize;
48964
48965                         ${ _getEncodings() }
48966
48967                         #include <common>
48968
48969                         void main() {
48970
48971                                 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
48972
48973                                 vec3 outputDirection = normalize( vOutputDirection );
48974                                 vec2 uv = equirectUv( outputDirection );
48975
48976                                 vec2 f = fract( uv / texelSize - 0.5 );
48977                                 uv -= f * texelSize;
48978                                 vec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
48979                                 uv.x += texelSize.x;
48980                                 vec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
48981                                 uv.y += texelSize.y;
48982                                 vec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
48983                                 uv.x -= texelSize.x;
48984                                 vec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
48985
48986                                 vec3 tm = mix( tl, tr, f.x );
48987                                 vec3 bm = mix( bl, br, f.x );
48988                                 gl_FragColor.rgb = mix( tm, bm, f.y );
48989
48990                                 gl_FragColor = linearToOutputTexel( gl_FragColor );
48991
48992                         }
48993                 `,
48994
48995                 blending: NoBlending,
48996                 depthTest: false,
48997                 depthWrite: false
48998
48999         } );
49000
49001         return shaderMaterial;
49002
49003 }
49004
49005 function _getCubemapShader() {
49006
49007         const shaderMaterial = new RawShaderMaterial( {
49008
49009                 name: 'CubemapToCubeUV',
49010
49011                 uniforms: {
49012                         'envMap': { value: null },
49013                         'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
49014                         'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
49015                 },
49016
49017                 vertexShader: _getCommonVertexShader(),
49018
49019                 fragmentShader: /* glsl */`
49020
49021                         precision mediump float;
49022                         precision mediump int;
49023
49024                         varying vec3 vOutputDirection;
49025
49026                         uniform samplerCube envMap;
49027
49028                         ${ _getEncodings() }
49029
49030                         void main() {
49031
49032                                 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
49033                                 gl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb;
49034                                 gl_FragColor = linearToOutputTexel( gl_FragColor );
49035
49036                         }
49037                 `,
49038
49039                 blending: NoBlending,
49040                 depthTest: false,
49041                 depthWrite: false
49042
49043         } );
49044
49045         return shaderMaterial;
49046
49047 }
49048
49049 function _getCommonVertexShader() {
49050
49051         return /* glsl */`
49052
49053                 precision mediump float;
49054                 precision mediump int;
49055
49056                 attribute vec3 position;
49057                 attribute vec2 uv;
49058                 attribute float faceIndex;
49059
49060                 varying vec3 vOutputDirection;
49061
49062                 // RH coordinate system; PMREM face-indexing convention
49063                 vec3 getDirection( vec2 uv, float face ) {
49064
49065                         uv = 2.0 * uv - 1.0;
49066
49067                         vec3 direction = vec3( uv, 1.0 );
49068
49069                         if ( face == 0.0 ) {
49070
49071                                 direction = direction.zyx; // ( 1, v, u ) pos x
49072
49073                         } else if ( face == 1.0 ) {
49074
49075                                 direction = direction.xzy;
49076                                 direction.xz *= -1.0; // ( -u, 1, -v ) pos y
49077
49078                         } else if ( face == 2.0 ) {
49079
49080                                 direction.x *= -1.0; // ( -u, v, 1 ) pos z
49081
49082                         } else if ( face == 3.0 ) {
49083
49084                                 direction = direction.zyx;
49085                                 direction.xz *= -1.0; // ( -1, v, -u ) neg x
49086
49087                         } else if ( face == 4.0 ) {
49088
49089                                 direction = direction.xzy;
49090                                 direction.xy *= -1.0; // ( -u, -1, v ) neg y
49091
49092                         } else if ( face == 5.0 ) {
49093
49094                                 direction.z *= -1.0; // ( u, v, -1 ) neg z
49095
49096                         }
49097
49098                         return direction;
49099
49100                 }
49101
49102                 void main() {
49103
49104                         vOutputDirection = getDirection( uv, faceIndex );
49105                         gl_Position = vec4( position, 1.0 );
49106
49107                 }
49108         `;
49109
49110 }
49111
49112 function _getEncodings() {
49113
49114         return /* glsl */`
49115
49116                 uniform int inputEncoding;
49117                 uniform int outputEncoding;
49118
49119                 #include <encodings_pars_fragment>
49120
49121                 vec4 inputTexelToLinear( vec4 value ) {
49122
49123                         if ( inputEncoding == 0 ) {
49124
49125                                 return value;
49126
49127                         } else if ( inputEncoding == 1 ) {
49128
49129                                 return sRGBToLinear( value );
49130
49131                         } else if ( inputEncoding == 2 ) {
49132
49133                                 return RGBEToLinear( value );
49134
49135                         } else if ( inputEncoding == 3 ) {
49136
49137                                 return RGBMToLinear( value, 7.0 );
49138
49139                         } else if ( inputEncoding == 4 ) {
49140
49141                                 return RGBMToLinear( value, 16.0 );
49142
49143                         } else if ( inputEncoding == 5 ) {
49144
49145                                 return RGBDToLinear( value, 256.0 );
49146
49147                         } else {
49148
49149                                 return GammaToLinear( value, 2.2 );
49150
49151                         }
49152
49153                 }
49154
49155                 vec4 linearToOutputTexel( vec4 value ) {
49156
49157                         if ( outputEncoding == 0 ) {
49158
49159                                 return value;
49160
49161                         } else if ( outputEncoding == 1 ) {
49162
49163                                 return LinearTosRGB( value );
49164
49165                         } else if ( outputEncoding == 2 ) {
49166
49167                                 return LinearToRGBE( value );
49168
49169                         } else if ( outputEncoding == 3 ) {
49170
49171                                 return LinearToRGBM( value, 7.0 );
49172
49173                         } else if ( outputEncoding == 4 ) {
49174
49175                                 return LinearToRGBM( value, 16.0 );
49176
49177                         } else if ( outputEncoding == 5 ) {
49178
49179                                 return LinearToRGBD( value, 256.0 );
49180
49181                         } else {
49182
49183                                 return LinearToGamma( value, 2.2 );
49184
49185                         }
49186
49187                 }
49188
49189                 vec4 envMapTexelToLinear( vec4 color ) {
49190
49191                         return inputTexelToLinear( color );
49192
49193                 }
49194         `;
49195
49196 }
49197
49198 function Face4( a, b, c, d, normal, color, materialIndex ) {
49199
49200         console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
49201         return new Face3( a, b, c, normal, color, materialIndex );
49202
49203 }
49204
49205 const LineStrip = 0;
49206 const LinePieces = 1;
49207 const NoColors = 0;
49208 const FaceColors = 1;
49209 const VertexColors = 2;
49210
49211 function MeshFaceMaterial( materials ) {
49212
49213         console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );
49214         return materials;
49215
49216 }
49217
49218 function MultiMaterial( materials = [] ) {
49219
49220         console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );
49221         materials.isMultiMaterial = true;
49222         materials.materials = materials;
49223         materials.clone = function () {
49224
49225                 return materials.slice();
49226
49227         };
49228
49229         return materials;
49230
49231 }
49232
49233 function PointCloud( geometry, material ) {
49234
49235         console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
49236         return new Points( geometry, material );
49237
49238 }
49239
49240 function Particle( material ) {
49241
49242         console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );
49243         return new Sprite( material );
49244
49245 }
49246
49247 function ParticleSystem( geometry, material ) {
49248
49249         console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
49250         return new Points( geometry, material );
49251
49252 }
49253
49254 function PointCloudMaterial( parameters ) {
49255
49256         console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
49257         return new PointsMaterial( parameters );
49258
49259 }
49260
49261 function ParticleBasicMaterial( parameters ) {
49262
49263         console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
49264         return new PointsMaterial( parameters );
49265
49266 }
49267
49268 function ParticleSystemMaterial( parameters ) {
49269
49270         console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
49271         return new PointsMaterial( parameters );
49272
49273 }
49274
49275 function Vertex( x, y, z ) {
49276
49277         console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );
49278         return new Vector3( x, y, z );
49279
49280 }
49281
49282 //
49283
49284 function DynamicBufferAttribute( array, itemSize ) {
49285
49286         console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setUsage( THREE.DynamicDrawUsage ) instead.' );
49287         return new BufferAttribute( array, itemSize ).setUsage( DynamicDrawUsage );
49288
49289 }
49290
49291 function Int8Attribute( array, itemSize ) {
49292
49293         console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );
49294         return new Int8BufferAttribute( array, itemSize );
49295
49296 }
49297
49298 function Uint8Attribute( array, itemSize ) {
49299
49300         console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );
49301         return new Uint8BufferAttribute( array, itemSize );
49302
49303 }
49304
49305 function Uint8ClampedAttribute( array, itemSize ) {
49306
49307         console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );
49308         return new Uint8ClampedBufferAttribute( array, itemSize );
49309
49310 }
49311
49312 function Int16Attribute( array, itemSize ) {
49313
49314         console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );
49315         return new Int16BufferAttribute( array, itemSize );
49316
49317 }
49318
49319 function Uint16Attribute( array, itemSize ) {
49320
49321         console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );
49322         return new Uint16BufferAttribute( array, itemSize );
49323
49324 }
49325
49326 function Int32Attribute( array, itemSize ) {
49327
49328         console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );
49329         return new Int32BufferAttribute( array, itemSize );
49330
49331 }
49332
49333 function Uint32Attribute( array, itemSize ) {
49334
49335         console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );
49336         return new Uint32BufferAttribute( array, itemSize );
49337
49338 }
49339
49340 function Float32Attribute( array, itemSize ) {
49341
49342         console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );
49343         return new Float32BufferAttribute( array, itemSize );
49344
49345 }
49346
49347 function Float64Attribute( array, itemSize ) {
49348
49349         console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );
49350         return new Float64BufferAttribute( array, itemSize );
49351
49352 }
49353
49354 //
49355
49356 Curve.create = function ( construct, getPoint ) {
49357
49358         console.log( 'THREE.Curve.create() has been deprecated' );
49359
49360         construct.prototype = Object.create( Curve.prototype );
49361         construct.prototype.constructor = construct;
49362         construct.prototype.getPoint = getPoint;
49363
49364         return construct;
49365
49366 };
49367
49368 //
49369
49370 Object.assign( CurvePath.prototype, {
49371
49372         createPointsGeometry: function ( divisions ) {
49373
49374                 console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
49375
49376                 // generate geometry from path points (for Line or Points objects)
49377
49378                 const pts = this.getPoints( divisions );
49379                 return this.createGeometry( pts );
49380
49381         },
49382
49383         createSpacedPointsGeometry: function ( divisions ) {
49384
49385                 console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
49386
49387                 // generate geometry from equidistant sampling along the path
49388
49389                 const pts = this.getSpacedPoints( divisions );
49390                 return this.createGeometry( pts );
49391
49392         },
49393
49394         createGeometry: function ( points ) {
49395
49396                 console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
49397
49398                 const geometry = new Geometry();
49399
49400                 for ( let i = 0, l = points.length; i < l; i ++ ) {
49401
49402                         const point = points[ i ];
49403                         geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
49404
49405                 }
49406
49407                 return geometry;
49408
49409         }
49410
49411 } );
49412
49413 //
49414
49415 Object.assign( Path.prototype, {
49416
49417         fromPoints: function ( points ) {
49418
49419                 console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
49420                 return this.setFromPoints( points );
49421
49422         }
49423
49424 } );
49425
49426 //
49427
49428 function ClosedSplineCurve3( points ) {
49429
49430         console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
49431
49432         CatmullRomCurve3.call( this, points );
49433         this.type = 'catmullrom';
49434         this.closed = true;
49435
49436 }
49437
49438 ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
49439
49440 //
49441
49442 function SplineCurve3( points ) {
49443
49444         console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
49445
49446         CatmullRomCurve3.call( this, points );
49447         this.type = 'catmullrom';
49448
49449 }
49450
49451 SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
49452
49453 //
49454
49455 function Spline( points ) {
49456
49457         console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
49458
49459         CatmullRomCurve3.call( this, points );
49460         this.type = 'catmullrom';
49461
49462 }
49463
49464 Spline.prototype = Object.create( CatmullRomCurve3.prototype );
49465
49466 Object.assign( Spline.prototype, {
49467
49468         initFromArray: function ( /* a */ ) {
49469
49470                 console.error( 'THREE.Spline: .initFromArray() has been removed.' );
49471
49472         },
49473         getControlPointsArray: function ( /* optionalTarget */ ) {
49474
49475                 console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
49476
49477         },
49478         reparametrizeByArcLength: function ( /* samplingCoef */ ) {
49479
49480                 console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
49481
49482         }
49483
49484 } );
49485
49486 //
49487
49488 function AxisHelper( size ) {
49489
49490         console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );
49491         return new AxesHelper( size );
49492
49493 }
49494
49495 function BoundingBoxHelper( object, color ) {
49496
49497         console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );
49498         return new BoxHelper( object, color );
49499
49500 }
49501
49502 function EdgesHelper( object, hex ) {
49503
49504         console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );
49505         return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
49506
49507 }
49508
49509 GridHelper.prototype.setColors = function () {
49510
49511         console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
49512
49513 };
49514
49515 SkeletonHelper.prototype.update = function () {
49516
49517         console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
49518
49519 };
49520
49521 function WireframeHelper( object, hex ) {
49522
49523         console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );
49524         return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
49525
49526 }
49527
49528 //
49529
49530 Object.assign( Loader.prototype, {
49531
49532         extractUrlBase: function ( url ) {
49533
49534                 console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
49535                 return LoaderUtils.extractUrlBase( url );
49536
49537         }
49538
49539 } );
49540
49541 Loader.Handlers = {
49542
49543         add: function ( /* regex, loader */ ) {
49544
49545                 console.error( 'THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.' );
49546
49547         },
49548
49549         get: function ( /* file */ ) {
49550
49551                 console.error( 'THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.' );
49552
49553         }
49554
49555 };
49556
49557 function XHRLoader( manager ) {
49558
49559         console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );
49560         return new FileLoader( manager );
49561
49562 }
49563
49564 function BinaryTextureLoader( manager ) {
49565
49566         console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );
49567         return new DataTextureLoader( manager );
49568
49569 }
49570
49571 //
49572
49573 Object.assign( Box2.prototype, {
49574
49575         center: function ( optionalTarget ) {
49576
49577                 console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
49578                 return this.getCenter( optionalTarget );
49579
49580         },
49581         empty: function () {
49582
49583                 console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
49584                 return this.isEmpty();
49585
49586         },
49587         isIntersectionBox: function ( box ) {
49588
49589                 console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
49590                 return this.intersectsBox( box );
49591
49592         },
49593         size: function ( optionalTarget ) {
49594
49595                 console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
49596                 return this.getSize( optionalTarget );
49597
49598         }
49599 } );
49600
49601 Object.assign( Box3.prototype, {
49602
49603         center: function ( optionalTarget ) {
49604
49605                 console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
49606                 return this.getCenter( optionalTarget );
49607
49608         },
49609         empty: function () {
49610
49611                 console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
49612                 return this.isEmpty();
49613
49614         },
49615         isIntersectionBox: function ( box ) {
49616
49617                 console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
49618                 return this.intersectsBox( box );
49619
49620         },
49621         isIntersectionSphere: function ( sphere ) {
49622
49623                 console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
49624                 return this.intersectsSphere( sphere );
49625
49626         },
49627         size: function ( optionalTarget ) {
49628
49629                 console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
49630                 return this.getSize( optionalTarget );
49631
49632         }
49633 } );
49634
49635 Object.assign( Sphere.prototype, {
49636
49637         empty: function () {
49638
49639                 console.warn( 'THREE.Sphere: .empty() has been renamed to .isEmpty().' );
49640                 return this.isEmpty();
49641
49642         },
49643
49644 } );
49645
49646 Frustum.prototype.setFromMatrix = function ( m ) {
49647
49648         console.warn( 'THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix().' );
49649         return this.setFromProjectionMatrix( m );
49650
49651 };
49652
49653 Line3.prototype.center = function ( optionalTarget ) {
49654
49655         console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );
49656         return this.getCenter( optionalTarget );
49657
49658 };
49659
49660 Object.assign( MathUtils, {
49661
49662         random16: function () {
49663
49664                 console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );
49665                 return Math.random();
49666
49667         },
49668
49669         nearestPowerOfTwo: function ( value ) {
49670
49671                 console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );
49672                 return MathUtils.floorPowerOfTwo( value );
49673
49674         },
49675
49676         nextPowerOfTwo: function ( value ) {
49677
49678                 console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );
49679                 return MathUtils.ceilPowerOfTwo( value );
49680
49681         }
49682
49683 } );
49684
49685 Object.assign( Matrix3.prototype, {
49686
49687         flattenToArrayOffset: function ( array, offset ) {
49688
49689                 console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
49690                 return this.toArray( array, offset );
49691
49692         },
49693         multiplyVector3: function ( vector ) {
49694
49695                 console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
49696                 return vector.applyMatrix3( this );
49697
49698         },
49699         multiplyVector3Array: function ( /* a */ ) {
49700
49701                 console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
49702
49703         },
49704         applyToBufferAttribute: function ( attribute ) {
49705
49706                 console.warn( 'THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead.' );
49707                 return attribute.applyMatrix3( this );
49708
49709         },
49710         applyToVector3Array: function ( /* array, offset, length */ ) {
49711
49712                 console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
49713
49714         },
49715         getInverse: function ( matrix ) {
49716
49717                 console.warn( 'THREE.Matrix3: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
49718                 return this.copy( matrix ).invert();
49719
49720         }
49721
49722 } );
49723
49724 Object.assign( Matrix4.prototype, {
49725
49726         extractPosition: function ( m ) {
49727
49728                 console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
49729                 return this.copyPosition( m );
49730
49731         },
49732         flattenToArrayOffset: function ( array, offset ) {
49733
49734                 console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
49735                 return this.toArray( array, offset );
49736
49737         },
49738         getPosition: function () {
49739
49740                 console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
49741                 return new Vector3().setFromMatrixColumn( this, 3 );
49742
49743         },
49744         setRotationFromQuaternion: function ( q ) {
49745
49746                 console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
49747                 return this.makeRotationFromQuaternion( q );
49748
49749         },
49750         multiplyToArray: function () {
49751
49752                 console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
49753
49754         },
49755         multiplyVector3: function ( vector ) {
49756
49757                 console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
49758                 return vector.applyMatrix4( this );
49759
49760         },
49761         multiplyVector4: function ( vector ) {
49762
49763                 console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
49764                 return vector.applyMatrix4( this );
49765
49766         },
49767         multiplyVector3Array: function ( /* a */ ) {
49768
49769                 console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
49770
49771         },
49772         rotateAxis: function ( v ) {
49773
49774                 console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
49775                 v.transformDirection( this );
49776
49777         },
49778         crossVector: function ( vector ) {
49779
49780                 console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
49781                 return vector.applyMatrix4( this );
49782
49783         },
49784         translate: function () {
49785
49786                 console.error( 'THREE.Matrix4: .translate() has been removed.' );
49787
49788         },
49789         rotateX: function () {
49790
49791                 console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
49792
49793         },
49794         rotateY: function () {
49795
49796                 console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
49797
49798         },
49799         rotateZ: function () {
49800
49801                 console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
49802
49803         },
49804         rotateByAxis: function () {
49805
49806                 console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
49807
49808         },
49809         applyToBufferAttribute: function ( attribute ) {
49810
49811                 console.warn( 'THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead.' );
49812                 return attribute.applyMatrix4( this );
49813
49814         },
49815         applyToVector3Array: function ( /* array, offset, length */ ) {
49816
49817                 console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
49818
49819         },
49820         makeFrustum: function ( left, right, bottom, top, near, far ) {
49821
49822                 console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
49823                 return this.makePerspective( left, right, top, bottom, near, far );
49824
49825         },
49826         getInverse: function ( matrix ) {
49827
49828                 console.warn( 'THREE.Matrix4: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.' );
49829                 return this.copy( matrix ).invert();
49830
49831         }
49832
49833 } );
49834
49835 Plane.prototype.isIntersectionLine = function ( line ) {
49836
49837         console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
49838         return this.intersectsLine( line );
49839
49840 };
49841
49842 Object.assign( Quaternion.prototype, {
49843
49844         multiplyVector3: function ( vector ) {
49845
49846                 console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
49847                 return vector.applyQuaternion( this );
49848
49849         },
49850         inverse: function ( ) {
49851
49852                 console.warn( 'THREE.Quaternion: .inverse() has been renamed to invert().' );
49853                 return this.invert();
49854
49855         }
49856
49857 } );
49858
49859 Object.assign( Ray.prototype, {
49860
49861         isIntersectionBox: function ( box ) {
49862
49863                 console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
49864                 return this.intersectsBox( box );
49865
49866         },
49867         isIntersectionPlane: function ( plane ) {
49868
49869                 console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
49870                 return this.intersectsPlane( plane );
49871
49872         },
49873         isIntersectionSphere: function ( sphere ) {
49874
49875                 console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
49876                 return this.intersectsSphere( sphere );
49877
49878         }
49879
49880 } );
49881
49882 Object.assign( Triangle.prototype, {
49883
49884         area: function () {
49885
49886                 console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
49887                 return this.getArea();
49888
49889         },
49890         barycoordFromPoint: function ( point, target ) {
49891
49892                 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
49893                 return this.getBarycoord( point, target );
49894
49895         },
49896         midpoint: function ( target ) {
49897
49898                 console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
49899                 return this.getMidpoint( target );
49900
49901         },
49902         normal: function ( target ) {
49903
49904                 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
49905                 return this.getNormal( target );
49906
49907         },
49908         plane: function ( target ) {
49909
49910                 console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
49911                 return this.getPlane( target );
49912
49913         }
49914
49915 } );
49916
49917 Object.assign( Triangle, {
49918
49919         barycoordFromPoint: function ( point, a, b, c, target ) {
49920
49921                 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
49922                 return Triangle.getBarycoord( point, a, b, c, target );
49923
49924         },
49925         normal: function ( a, b, c, target ) {
49926
49927                 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
49928                 return Triangle.getNormal( a, b, c, target );
49929
49930         }
49931
49932 } );
49933
49934 Object.assign( Shape.prototype, {
49935
49936         extractAllPoints: function ( divisions ) {
49937
49938                 console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
49939                 return this.extractPoints( divisions );
49940
49941         },
49942         extrude: function ( options ) {
49943
49944                 console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
49945                 return new ExtrudeGeometry( this, options );
49946
49947         },
49948         makeGeometry: function ( options ) {
49949
49950                 console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
49951                 return new ShapeGeometry( this, options );
49952
49953         }
49954
49955 } );
49956
49957 Object.assign( Vector2.prototype, {
49958
49959         fromAttribute: function ( attribute, index, offset ) {
49960
49961                 console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
49962                 return this.fromBufferAttribute( attribute, index, offset );
49963
49964         },
49965         distanceToManhattan: function ( v ) {
49966
49967                 console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
49968                 return this.manhattanDistanceTo( v );
49969
49970         },
49971         lengthManhattan: function () {
49972
49973                 console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
49974                 return this.manhattanLength();
49975
49976         }
49977
49978 } );
49979
49980 Object.assign( Vector3.prototype, {
49981
49982         setEulerFromRotationMatrix: function () {
49983
49984                 console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
49985
49986         },
49987         setEulerFromQuaternion: function () {
49988
49989                 console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
49990
49991         },
49992         getPositionFromMatrix: function ( m ) {
49993
49994                 console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
49995                 return this.setFromMatrixPosition( m );
49996
49997         },
49998         getScaleFromMatrix: function ( m ) {
49999
50000                 console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
50001                 return this.setFromMatrixScale( m );
50002
50003         },
50004         getColumnFromMatrix: function ( index, matrix ) {
50005
50006                 console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
50007                 return this.setFromMatrixColumn( matrix, index );
50008
50009         },
50010         applyProjection: function ( m ) {
50011
50012                 console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
50013                 return this.applyMatrix4( m );
50014
50015         },
50016         fromAttribute: function ( attribute, index, offset ) {
50017
50018                 console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
50019                 return this.fromBufferAttribute( attribute, index, offset );
50020
50021         },
50022         distanceToManhattan: function ( v ) {
50023
50024                 console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
50025                 return this.manhattanDistanceTo( v );
50026
50027         },
50028         lengthManhattan: function () {
50029
50030                 console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
50031                 return this.manhattanLength();
50032
50033         }
50034
50035 } );
50036
50037 Object.assign( Vector4.prototype, {
50038
50039         fromAttribute: function ( attribute, index, offset ) {
50040
50041                 console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
50042                 return this.fromBufferAttribute( attribute, index, offset );
50043
50044         },
50045         lengthManhattan: function () {
50046
50047                 console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
50048                 return this.manhattanLength();
50049
50050         }
50051
50052 } );
50053
50054 //
50055
50056 Object.assign( Geometry.prototype, {
50057
50058         computeTangents: function () {
50059
50060                 console.error( 'THREE.Geometry: .computeTangents() has been removed.' );
50061
50062         },
50063         computeLineDistances: function () {
50064
50065                 console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );
50066
50067         },
50068         applyMatrix: function ( matrix ) {
50069
50070                 console.warn( 'THREE.Geometry: .applyMatrix() has been renamed to .applyMatrix4().' );
50071                 return this.applyMatrix4( matrix );
50072
50073         }
50074
50075 } );
50076
50077 Object.assign( Object3D.prototype, {
50078
50079         getChildByName: function ( name ) {
50080
50081                 console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
50082                 return this.getObjectByName( name );
50083
50084         },
50085         renderDepth: function () {
50086
50087                 console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
50088
50089         },
50090         translate: function ( distance, axis ) {
50091
50092                 console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
50093                 return this.translateOnAxis( axis, distance );
50094
50095         },
50096         getWorldRotation: function () {
50097
50098                 console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
50099
50100         },
50101         applyMatrix: function ( matrix ) {
50102
50103                 console.warn( 'THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4().' );
50104                 return this.applyMatrix4( matrix );
50105
50106         }
50107
50108 } );
50109
50110 Object.defineProperties( Object3D.prototype, {
50111
50112         eulerOrder: {
50113                 get: function () {
50114
50115                         console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
50116                         return this.rotation.order;
50117
50118                 },
50119                 set: function ( value ) {
50120
50121                         console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
50122                         this.rotation.order = value;
50123
50124                 }
50125         },
50126         useQuaternion: {
50127                 get: function () {
50128
50129                         console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
50130
50131                 },
50132                 set: function () {
50133
50134                         console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
50135
50136                 }
50137         }
50138
50139 } );
50140
50141 Object.assign( Mesh.prototype, {
50142
50143         setDrawMode: function () {
50144
50145                 console.error( 'THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
50146
50147         },
50148
50149 } );
50150
50151 Object.defineProperties( Mesh.prototype, {
50152
50153         drawMode: {
50154                 get: function () {
50155
50156                         console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.' );
50157                         return TrianglesDrawMode;
50158
50159                 },
50160                 set: function () {
50161
50162                         console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
50163
50164                 }
50165         }
50166
50167 } );
50168
50169 Object.defineProperties( LOD.prototype, {
50170
50171         objects: {
50172                 get: function () {
50173
50174                         console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
50175                         return this.levels;
50176
50177                 }
50178         }
50179
50180 } );
50181
50182 Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
50183
50184         get: function () {
50185
50186                 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
50187
50188         },
50189         set: function () {
50190
50191                 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
50192
50193         }
50194
50195 } );
50196
50197 SkinnedMesh.prototype.initBones = function () {
50198
50199         console.error( 'THREE.SkinnedMesh: initBones() has been removed.' );
50200
50201 };
50202
50203 Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
50204
50205         get: function () {
50206
50207                 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
50208                 return this.arcLengthDivisions;
50209
50210         },
50211         set: function ( value ) {
50212
50213                 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
50214                 this.arcLengthDivisions = value;
50215
50216         }
50217
50218 } );
50219
50220 //
50221
50222 PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
50223
50224         console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
50225                         "Use .setFocalLength and .filmGauge for a photographic setup." );
50226
50227         if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
50228         this.setFocalLength( focalLength );
50229
50230 };
50231
50232 //
50233
50234 Object.defineProperties( Light.prototype, {
50235         onlyShadow: {
50236                 set: function () {
50237
50238                         console.warn( 'THREE.Light: .onlyShadow has been removed.' );
50239
50240                 }
50241         },
50242         shadowCameraFov: {
50243                 set: function ( value ) {
50244
50245                         console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
50246                         this.shadow.camera.fov = value;
50247
50248                 }
50249         },
50250         shadowCameraLeft: {
50251                 set: function ( value ) {
50252
50253                         console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
50254                         this.shadow.camera.left = value;
50255
50256                 }
50257         },
50258         shadowCameraRight: {
50259                 set: function ( value ) {
50260
50261                         console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
50262                         this.shadow.camera.right = value;
50263
50264                 }
50265         },
50266         shadowCameraTop: {
50267                 set: function ( value ) {
50268
50269                         console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
50270                         this.shadow.camera.top = value;
50271
50272                 }
50273         },
50274         shadowCameraBottom: {
50275                 set: function ( value ) {
50276
50277                         console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
50278                         this.shadow.camera.bottom = value;
50279
50280                 }
50281         },
50282         shadowCameraNear: {
50283                 set: function ( value ) {
50284
50285                         console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
50286                         this.shadow.camera.near = value;
50287
50288                 }
50289         },
50290         shadowCameraFar: {
50291                 set: function ( value ) {
50292
50293                         console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
50294                         this.shadow.camera.far = value;
50295
50296                 }
50297         },
50298         shadowCameraVisible: {
50299                 set: function () {
50300
50301                         console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
50302
50303                 }
50304         },
50305         shadowBias: {
50306                 set: function ( value ) {
50307
50308                         console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
50309                         this.shadow.bias = value;
50310
50311                 }
50312         },
50313         shadowDarkness: {
50314                 set: function () {
50315
50316                         console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
50317
50318                 }
50319         },
50320         shadowMapWidth: {
50321                 set: function ( value ) {
50322
50323                         console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
50324                         this.shadow.mapSize.width = value;
50325
50326                 }
50327         },
50328         shadowMapHeight: {
50329                 set: function ( value ) {
50330
50331                         console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
50332                         this.shadow.mapSize.height = value;
50333
50334                 }
50335         }
50336 } );
50337
50338 //
50339
50340 Object.defineProperties( BufferAttribute.prototype, {
50341
50342         length: {
50343                 get: function () {
50344
50345                         console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
50346                         return this.array.length;
50347
50348                 }
50349         },
50350         dynamic: {
50351                 get: function () {
50352
50353                         console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
50354                         return this.usage === DynamicDrawUsage;
50355
50356                 },
50357                 set: function ( /* value */ ) {
50358
50359                         console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
50360                         this.setUsage( DynamicDrawUsage );
50361
50362                 }
50363         }
50364
50365 } );
50366
50367 Object.assign( BufferAttribute.prototype, {
50368         setDynamic: function ( value ) {
50369
50370                 console.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );
50371                 this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
50372                 return this;
50373
50374         },
50375         copyIndicesArray: function ( /* indices */ ) {
50376
50377                 console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
50378
50379         },
50380         setArray: function ( /* array */ ) {
50381
50382                 console.error( 'THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
50383
50384         }
50385 } );
50386
50387 Object.assign( BufferGeometry.prototype, {
50388
50389         addIndex: function ( index ) {
50390
50391                 console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
50392                 this.setIndex( index );
50393
50394         },
50395         addAttribute: function ( name, attribute ) {
50396
50397                 console.warn( 'THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().' );
50398
50399                 if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
50400
50401                         console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
50402
50403                         return this.setAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
50404
50405                 }
50406
50407                 if ( name === 'index' ) {
50408
50409                         console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
50410                         this.setIndex( attribute );
50411
50412                         return this;
50413
50414                 }
50415
50416                 return this.setAttribute( name, attribute );
50417
50418         },
50419         addDrawCall: function ( start, count, indexOffset ) {
50420
50421                 if ( indexOffset !== undefined ) {
50422
50423                         console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
50424
50425                 }
50426
50427                 console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
50428                 this.addGroup( start, count );
50429
50430         },
50431         clearDrawCalls: function () {
50432
50433                 console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
50434                 this.clearGroups();
50435
50436         },
50437         computeTangents: function () {
50438
50439                 console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
50440
50441         },
50442         computeOffsets: function () {
50443
50444                 console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
50445
50446         },
50447         removeAttribute: function ( name ) {
50448
50449                 console.warn( 'THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().' );
50450
50451                 return this.deleteAttribute( name );
50452
50453         },
50454         applyMatrix: function ( matrix ) {
50455
50456                 console.warn( 'THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4().' );
50457                 return this.applyMatrix4( matrix );
50458
50459         }
50460
50461 } );
50462
50463 Object.defineProperties( BufferGeometry.prototype, {
50464
50465         drawcalls: {
50466                 get: function () {
50467
50468                         console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
50469                         return this.groups;
50470
50471                 }
50472         },
50473         offsets: {
50474                 get: function () {
50475
50476                         console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
50477                         return this.groups;
50478
50479                 }
50480         }
50481
50482 } );
50483
50484 Object.defineProperties( InstancedBufferGeometry.prototype, {
50485
50486         maxInstancedCount: {
50487                 get: function () {
50488
50489                         console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
50490                         return this.instanceCount;
50491
50492                 },
50493                 set: function ( value ) {
50494
50495                         console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
50496                         this.instanceCount = value;
50497
50498                 }
50499         }
50500
50501 } );
50502
50503 Object.defineProperties( Raycaster.prototype, {
50504
50505         linePrecision: {
50506                 get: function () {
50507
50508                         console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
50509                         return this.params.Line.threshold;
50510
50511                 },
50512                 set: function ( value ) {
50513
50514                         console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
50515                         this.params.Line.threshold = value;
50516
50517                 }
50518         }
50519
50520 } );
50521
50522 Object.defineProperties( InterleavedBuffer.prototype, {
50523
50524         dynamic: {
50525                 get: function () {
50526
50527                         console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
50528                         return this.usage === DynamicDrawUsage;
50529
50530                 },
50531                 set: function ( value ) {
50532
50533                         console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
50534                         this.setUsage( value );
50535
50536                 }
50537         }
50538
50539 } );
50540
50541 Object.assign( InterleavedBuffer.prototype, {
50542         setDynamic: function ( value ) {
50543
50544                 console.warn( 'THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.' );
50545                 this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
50546                 return this;
50547
50548         },
50549         setArray: function ( /* array */ ) {
50550
50551                 console.error( 'THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
50552
50553         }
50554 } );
50555
50556 //
50557
50558 Object.assign( ExtrudeBufferGeometry.prototype, {
50559
50560         getArrays: function () {
50561
50562                 console.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );
50563
50564         },
50565
50566         addShapeList: function () {
50567
50568                 console.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );
50569
50570         },
50571
50572         addShape: function () {
50573
50574                 console.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );
50575
50576         }
50577
50578 } );
50579
50580 //
50581
50582 Object.assign( Scene.prototype, {
50583
50584         dispose: function () {
50585
50586                 console.error( 'THREE.Scene: .dispose() has been removed.' );
50587
50588         }
50589
50590 } );
50591
50592 //
50593
50594 Object.defineProperties( Uniform.prototype, {
50595
50596         dynamic: {
50597                 set: function () {
50598
50599                         console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
50600
50601                 }
50602         },
50603         onUpdate: {
50604                 value: function () {
50605
50606                         console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
50607                         return this;
50608
50609                 }
50610         }
50611
50612 } );
50613
50614 //
50615
50616 Object.defineProperties( Material.prototype, {
50617
50618         wrapAround: {
50619                 get: function () {
50620
50621                         console.warn( 'THREE.Material: .wrapAround has been removed.' );
50622
50623                 },
50624                 set: function () {
50625
50626                         console.warn( 'THREE.Material: .wrapAround has been removed.' );
50627
50628                 }
50629         },
50630
50631         overdraw: {
50632                 get: function () {
50633
50634                         console.warn( 'THREE.Material: .overdraw has been removed.' );
50635
50636                 },
50637                 set: function () {
50638
50639                         console.warn( 'THREE.Material: .overdraw has been removed.' );
50640
50641                 }
50642         },
50643
50644         wrapRGB: {
50645                 get: function () {
50646
50647                         console.warn( 'THREE.Material: .wrapRGB has been removed.' );
50648                         return new Color();
50649
50650                 }
50651         },
50652
50653         shading: {
50654                 get: function () {
50655
50656                         console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
50657
50658                 },
50659                 set: function ( value ) {
50660
50661                         console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
50662                         this.flatShading = ( value === FlatShading );
50663
50664                 }
50665         },
50666
50667         stencilMask: {
50668                 get: function () {
50669
50670                         console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
50671                         return this.stencilFuncMask;
50672
50673                 },
50674                 set: function ( value ) {
50675
50676                         console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
50677                         this.stencilFuncMask = value;
50678
50679                 }
50680         }
50681
50682 } );
50683
50684 Object.defineProperties( MeshPhongMaterial.prototype, {
50685
50686         metal: {
50687                 get: function () {
50688
50689                         console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
50690                         return false;
50691
50692                 },
50693                 set: function () {
50694
50695                         console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
50696
50697                 }
50698         }
50699
50700 } );
50701
50702 Object.defineProperties( MeshPhysicalMaterial.prototype, {
50703
50704         transparency: {
50705                 get: function () {
50706
50707                         console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' );
50708                         return this.transmission;
50709
50710                 },
50711                 set: function ( value ) {
50712
50713                         console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' );
50714                         this.transmission = value;
50715
50716                 }
50717         }
50718
50719 } );
50720
50721 Object.defineProperties( ShaderMaterial.prototype, {
50722
50723         derivatives: {
50724                 get: function () {
50725
50726                         console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
50727                         return this.extensions.derivatives;
50728
50729                 },
50730                 set: function ( value ) {
50731
50732                         console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
50733                         this.extensions.derivatives = value;
50734
50735                 }
50736         }
50737
50738 } );
50739
50740 //
50741
50742 Object.assign( WebGLRenderer.prototype, {
50743
50744         clearTarget: function ( renderTarget, color, depth, stencil ) {
50745
50746                 console.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );
50747                 this.setRenderTarget( renderTarget );
50748                 this.clear( color, depth, stencil );
50749
50750         },
50751         animate: function ( callback ) {
50752
50753                 console.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );
50754                 this.setAnimationLoop( callback );
50755
50756         },
50757         getCurrentRenderTarget: function () {
50758
50759                 console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
50760                 return this.getRenderTarget();
50761
50762         },
50763         getMaxAnisotropy: function () {
50764
50765                 console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
50766                 return this.capabilities.getMaxAnisotropy();
50767
50768         },
50769         getPrecision: function () {
50770
50771                 console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
50772                 return this.capabilities.precision;
50773
50774         },
50775         resetGLState: function () {
50776
50777                 console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
50778                 return this.state.reset();
50779
50780         },
50781         supportsFloatTextures: function () {
50782
50783                 console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
50784                 return this.extensions.get( 'OES_texture_float' );
50785
50786         },
50787         supportsHalfFloatTextures: function () {
50788
50789                 console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
50790                 return this.extensions.get( 'OES_texture_half_float' );
50791
50792         },
50793         supportsStandardDerivatives: function () {
50794
50795                 console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
50796                 return this.extensions.get( 'OES_standard_derivatives' );
50797
50798         },
50799         supportsCompressedTextureS3TC: function () {
50800
50801                 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
50802                 return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
50803
50804         },
50805         supportsCompressedTexturePVRTC: function () {
50806
50807                 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
50808                 return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
50809
50810         },
50811         supportsBlendMinMax: function () {
50812
50813                 console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
50814                 return this.extensions.get( 'EXT_blend_minmax' );
50815
50816         },
50817         supportsVertexTextures: function () {
50818
50819                 console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
50820                 return this.capabilities.vertexTextures;
50821
50822         },
50823         supportsInstancedArrays: function () {
50824
50825                 console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
50826                 return this.extensions.get( 'ANGLE_instanced_arrays' );
50827
50828         },
50829         enableScissorTest: function ( boolean ) {
50830
50831                 console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
50832                 this.setScissorTest( boolean );
50833
50834         },
50835         initMaterial: function () {
50836
50837                 console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
50838
50839         },
50840         addPrePlugin: function () {
50841
50842                 console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
50843
50844         },
50845         addPostPlugin: function () {
50846
50847                 console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
50848
50849         },
50850         updateShadowMap: function () {
50851
50852                 console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
50853
50854         },
50855         setFaceCulling: function () {
50856
50857                 console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
50858
50859         },
50860         allocTextureUnit: function () {
50861
50862                 console.warn( 'THREE.WebGLRenderer: .allocTextureUnit() has been removed.' );
50863
50864         },
50865         setTexture: function () {
50866
50867                 console.warn( 'THREE.WebGLRenderer: .setTexture() has been removed.' );
50868
50869         },
50870         setTexture2D: function () {
50871
50872                 console.warn( 'THREE.WebGLRenderer: .setTexture2D() has been removed.' );
50873
50874         },
50875         setTextureCube: function () {
50876
50877                 console.warn( 'THREE.WebGLRenderer: .setTextureCube() has been removed.' );
50878
50879         },
50880         getActiveMipMapLevel: function () {
50881
50882                 console.warn( 'THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().' );
50883                 return this.getActiveMipmapLevel();
50884
50885         }
50886
50887 } );
50888
50889 Object.defineProperties( WebGLRenderer.prototype, {
50890
50891         shadowMapEnabled: {
50892                 get: function () {
50893
50894                         return this.shadowMap.enabled;
50895
50896                 },
50897                 set: function ( value ) {
50898
50899                         console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
50900                         this.shadowMap.enabled = value;
50901
50902                 }
50903         },
50904         shadowMapType: {
50905                 get: function () {
50906
50907                         return this.shadowMap.type;
50908
50909                 },
50910                 set: function ( value ) {
50911
50912                         console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
50913                         this.shadowMap.type = value;
50914
50915                 }
50916         },
50917         shadowMapCullFace: {
50918                 get: function () {
50919
50920                         console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
50921                         return undefined;
50922
50923                 },
50924                 set: function ( /* value */ ) {
50925
50926                         console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
50927
50928                 }
50929         },
50930         context: {
50931                 get: function () {
50932
50933                         console.warn( 'THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.' );
50934                         return this.getContext();
50935
50936                 }
50937         },
50938         vr: {
50939                 get: function () {
50940
50941                         console.warn( 'THREE.WebGLRenderer: .vr has been renamed to .xr' );
50942                         return this.xr;
50943
50944                 }
50945         },
50946         gammaInput: {
50947                 get: function () {
50948
50949                         console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
50950                         return false;
50951
50952                 },
50953                 set: function () {
50954
50955                         console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
50956
50957                 }
50958         },
50959         gammaOutput: {
50960                 get: function () {
50961
50962                         console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
50963                         return false;
50964
50965                 },
50966                 set: function ( value ) {
50967
50968                         console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
50969                         this.outputEncoding = ( value === true ) ? sRGBEncoding : LinearEncoding;
50970
50971                 }
50972         },
50973         toneMappingWhitePoint: {
50974                 get: function () {
50975
50976                         console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
50977                         return 1.0;
50978
50979                 },
50980                 set: function () {
50981
50982                         console.warn( 'THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.' );
50983
50984                 }
50985         },
50986
50987 } );
50988
50989 Object.defineProperties( WebGLShadowMap.prototype, {
50990
50991         cullFace: {
50992                 get: function () {
50993
50994                         console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
50995                         return undefined;
50996
50997                 },
50998                 set: function ( /* cullFace */ ) {
50999
51000                         console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
51001
51002                 }
51003         },
51004         renderReverseSided: {
51005                 get: function () {
51006
51007                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
51008                         return undefined;
51009
51010                 },
51011                 set: function () {
51012
51013                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
51014
51015                 }
51016         },
51017         renderSingleSided: {
51018                 get: function () {
51019
51020                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
51021                         return undefined;
51022
51023                 },
51024                 set: function () {
51025
51026                         console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
51027
51028                 }
51029         }
51030
51031 } );
51032
51033 function WebGLRenderTargetCube( width, height, options ) {
51034
51035         console.warn( 'THREE.WebGLRenderTargetCube( width, height, options ) is now WebGLCubeRenderTarget( size, options ).' );
51036         return new WebGLCubeRenderTarget( width, options );
51037
51038 }
51039
51040 //
51041
51042 Object.defineProperties( WebGLRenderTarget.prototype, {
51043
51044         wrapS: {
51045                 get: function () {
51046
51047                         console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
51048                         return this.texture.wrapS;
51049
51050                 },
51051                 set: function ( value ) {
51052
51053                         console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
51054                         this.texture.wrapS = value;
51055
51056                 }
51057         },
51058         wrapT: {
51059                 get: function () {
51060
51061                         console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
51062                         return this.texture.wrapT;
51063
51064                 },
51065                 set: function ( value ) {
51066
51067                         console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
51068                         this.texture.wrapT = value;
51069
51070                 }
51071         },
51072         magFilter: {
51073                 get: function () {
51074
51075                         console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
51076                         return this.texture.magFilter;
51077
51078                 },
51079                 set: function ( value ) {
51080
51081                         console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
51082                         this.texture.magFilter = value;
51083
51084                 }
51085         },
51086         minFilter: {
51087                 get: function () {
51088
51089                         console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
51090                         return this.texture.minFilter;
51091
51092                 },
51093                 set: function ( value ) {
51094
51095                         console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
51096                         this.texture.minFilter = value;
51097
51098                 }
51099         },
51100         anisotropy: {
51101                 get: function () {
51102
51103                         console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
51104                         return this.texture.anisotropy;
51105
51106                 },
51107                 set: function ( value ) {
51108
51109                         console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
51110                         this.texture.anisotropy = value;
51111
51112                 }
51113         },
51114         offset: {
51115                 get: function () {
51116
51117                         console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
51118                         return this.texture.offset;
51119
51120                 },
51121                 set: function ( value ) {
51122
51123                         console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
51124                         this.texture.offset = value;
51125
51126                 }
51127         },
51128         repeat: {
51129                 get: function () {
51130
51131                         console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
51132                         return this.texture.repeat;
51133
51134                 },
51135                 set: function ( value ) {
51136
51137                         console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
51138                         this.texture.repeat = value;
51139
51140                 }
51141         },
51142         format: {
51143                 get: function () {
51144
51145                         console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
51146                         return this.texture.format;
51147
51148                 },
51149                 set: function ( value ) {
51150
51151                         console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
51152                         this.texture.format = value;
51153
51154                 }
51155         },
51156         type: {
51157                 get: function () {
51158
51159                         console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
51160                         return this.texture.type;
51161
51162                 },
51163                 set: function ( value ) {
51164
51165                         console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
51166                         this.texture.type = value;
51167
51168                 }
51169         },
51170         generateMipmaps: {
51171                 get: function () {
51172
51173                         console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
51174                         return this.texture.generateMipmaps;
51175
51176                 },
51177                 set: function ( value ) {
51178
51179                         console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
51180                         this.texture.generateMipmaps = value;
51181
51182                 }
51183         }
51184
51185 } );
51186
51187 //
51188
51189 Object.defineProperties( Audio.prototype, {
51190
51191         load: {
51192                 value: function ( file ) {
51193
51194                         console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
51195                         const scope = this;
51196                         const audioLoader = new AudioLoader();
51197                         audioLoader.load( file, function ( buffer ) {
51198
51199                                 scope.setBuffer( buffer );
51200
51201                         } );
51202                         return this;
51203
51204                 }
51205         },
51206         startTime: {
51207                 set: function () {
51208
51209                         console.warn( 'THREE.Audio: .startTime is now .play( delay ).' );
51210
51211                 }
51212         }
51213
51214 } );
51215
51216 AudioAnalyser.prototype.getData = function () {
51217
51218         console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );
51219         return this.getFrequencyData();
51220
51221 };
51222
51223 //
51224
51225 CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
51226
51227         console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
51228         return this.update( renderer, scene );
51229
51230 };
51231
51232 CubeCamera.prototype.clear = function ( renderer, color, depth, stencil ) {
51233
51234         console.warn( 'THREE.CubeCamera: .clear() is now .renderTarget.clear().' );
51235         return this.renderTarget.clear( renderer, color, depth, stencil );
51236
51237 };
51238
51239 //
51240
51241 const GeometryUtils = {
51242
51243         merge: function ( geometry1, geometry2, materialIndexOffset ) {
51244
51245                 console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
51246                 let matrix;
51247
51248                 if ( geometry2.isMesh ) {
51249
51250                         geometry2.matrixAutoUpdate && geometry2.updateMatrix();
51251
51252                         matrix = geometry2.matrix;
51253                         geometry2 = geometry2.geometry;
51254
51255                 }
51256
51257                 geometry1.merge( geometry2, matrix, materialIndexOffset );
51258
51259         },
51260
51261         center: function ( geometry ) {
51262
51263                 console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
51264                 return geometry.center();
51265
51266         }
51267
51268 };
51269
51270 ImageUtils.crossOrigin = undefined;
51271
51272 ImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {
51273
51274         console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
51275
51276         const loader = new TextureLoader();
51277         loader.setCrossOrigin( this.crossOrigin );
51278
51279         const texture = loader.load( url, onLoad, undefined, onError );
51280
51281         if ( mapping ) texture.mapping = mapping;
51282
51283         return texture;
51284
51285 };
51286
51287 ImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {
51288
51289         console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
51290
51291         const loader = new CubeTextureLoader();
51292         loader.setCrossOrigin( this.crossOrigin );
51293
51294         const texture = loader.load( urls, onLoad, undefined, onError );
51295
51296         if ( mapping ) texture.mapping = mapping;
51297
51298         return texture;
51299
51300 };
51301
51302 ImageUtils.loadCompressedTexture = function () {
51303
51304         console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
51305
51306 };
51307
51308 ImageUtils.loadCompressedTextureCube = function () {
51309
51310         console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
51311
51312 };
51313
51314 //
51315
51316 function CanvasRenderer() {
51317
51318         console.error( 'THREE.CanvasRenderer has been removed' );
51319
51320 }
51321
51322 //
51323
51324 function JSONLoader() {
51325
51326         console.error( 'THREE.JSONLoader has been removed.' );
51327
51328 }
51329
51330 //
51331
51332 const SceneUtils = {
51333
51334         createMultiMaterialObject: function ( /* geometry, materials */ ) {
51335
51336                 console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
51337
51338         },
51339
51340         detach: function ( /* child, parent, scene */ ) {
51341
51342                 console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
51343
51344         },
51345
51346         attach: function ( /* child, scene, parent */ ) {
51347
51348                 console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
51349
51350         }
51351
51352 };
51353
51354 //
51355
51356 function LensFlare() {
51357
51358         console.error( 'THREE.LensFlare has been moved to /examples/jsm/objects/Lensflare.js' );
51359
51360 }
51361
51362 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
51363
51364         /* eslint-disable no-undef */
51365         __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
51366                 revision: REVISION,
51367         } } ) );
51368         /* eslint-enable no-undef */
51369
51370 }
51371
51372 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, BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasRenderer, CanvasTexture, CatmullRomCurve3, CineonToneMapping, CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, ClosedSplineCurve3, Color, ColorKeyframeTrack, CompressedTexture, CompressedTextureLoader, ConeBufferGeometry, ConeGeometry, CubeCamera, BoxGeometry as CubeGeometry, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubeUVRefractionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderBufferGeometry, CylinderGeometry, Cylindrical, DataTexture, DataTexture2DArray, DataTexture3D, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicBufferAttribute, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EdgesHelper, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeBufferGeometry, ExtrudeGeometry, Face3, Face4, FaceColors, FileLoader, FlatShading, Float16BufferAttribute, Float32Attribute, Float32BufferAttribute, Float64Attribute, Float64BufferAttribute, FloatType, Fog, FogExp2, Font, FontLoader, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GammaEncoding, Geometry, GeometryUtils, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, 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, 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, OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, ParametricBufferGeometry, ParametricGeometry, Particle, ParticleBasicMaterial, ParticleSystem, ParticleSystemMaterial, Path, PerspectiveCamera, Plane, PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointCloud, PointCloudMaterial, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, 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, 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, ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SmoothShading, Sphere, 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, TetrahedronBufferGeometry, TetrahedronGeometry, TextBufferGeometry, TextGeometry, Texture, TextureLoader, TorusBufferGeometry, TorusGeometry, TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, 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 };