OSDN Git Service

three.jsをThirdPartyに追加
[webglgame/webgl_framework.git] / webglFramework / Thirdparty / three.js-master / build / three.js
1 (function (global, factory) {
2         typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3         typeof define === 'function' && define.amd ? define(['exports'], factory) :
4         (factory((global.THREE = global.THREE || {})));
5 }(this, (function (exports) { 'use strict';
6
7         // Polyfills
8
9         if ( Number.EPSILON === undefined ) {
10
11                 Number.EPSILON = Math.pow( 2, - 52 );
12
13         }
14
15         if ( Number.isInteger === undefined ) {
16
17                 // Missing in IE
18                 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
19
20                 Number.isInteger = function ( value ) {
21
22                         return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value;
23
24                 };
25
26         }
27
28         //
29
30         if ( Math.sign === undefined ) {
31
32                 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
33
34                 Math.sign = function ( x ) {
35
36                         return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
37
38                 };
39
40         }
41
42         if ( Function.prototype.name === undefined ) {
43
44                 // Missing in IE
45                 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
46
47                 Object.defineProperty( Function.prototype, 'name', {
48
49                         get: function () {
50
51                                 return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ];
52
53                         }
54
55                 } );
56
57         }
58
59         if ( Object.assign === undefined ) {
60
61                 // Missing in IE
62                 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
63
64                 ( function () {
65
66                         Object.assign = function ( target ) {
67
68                                 'use strict';
69
70                                 if ( target === undefined || target === null ) {
71
72                                         throw new TypeError( 'Cannot convert undefined or null to object' );
73
74                                 }
75
76                                 var output = Object( target );
77
78                                 for ( var index = 1; index < arguments.length; index ++ ) {
79
80                                         var source = arguments[ index ];
81
82                                         if ( source !== undefined && source !== null ) {
83
84                                                 for ( var nextKey in source ) {
85
86                                                         if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {
87
88                                                                 output[ nextKey ] = source[ nextKey ];
89
90                                                         }
91
92                                                 }
93
94                                         }
95
96                                 }
97
98                                 return output;
99
100                         };
101
102                 } )();
103
104         }
105
106         /**
107          * https://github.com/mrdoob/eventdispatcher.js/
108          */
109
110         function EventDispatcher() {}
111
112         Object.assign( EventDispatcher.prototype, {
113
114                 addEventListener: function ( type, listener ) {
115
116                         if ( this._listeners === undefined ) this._listeners = {};
117
118                         var listeners = this._listeners;
119
120                         if ( listeners[ type ] === undefined ) {
121
122                                 listeners[ type ] = [];
123
124                         }
125
126                         if ( listeners[ type ].indexOf( listener ) === - 1 ) {
127
128                                 listeners[ type ].push( listener );
129
130                         }
131
132                 },
133
134                 hasEventListener: function ( type, listener ) {
135
136                         if ( this._listeners === undefined ) return false;
137
138                         var listeners = this._listeners;
139
140                         return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
141
142                 },
143
144                 removeEventListener: function ( type, listener ) {
145
146                         if ( this._listeners === undefined ) return;
147
148                         var listeners = this._listeners;
149                         var listenerArray = listeners[ type ];
150
151                         if ( listenerArray !== undefined ) {
152
153                                 var index = listenerArray.indexOf( listener );
154
155                                 if ( index !== - 1 ) {
156
157                                         listenerArray.splice( index, 1 );
158
159                                 }
160
161                         }
162
163                 },
164
165                 dispatchEvent: function ( event ) {
166
167                         if ( this._listeners === undefined ) return;
168
169                         var listeners = this._listeners;
170                         var listenerArray = listeners[ event.type ];
171
172                         if ( listenerArray !== undefined ) {
173
174                                 event.target = this;
175
176                                 var array = listenerArray.slice( 0 );
177
178                                 for ( var i = 0, l = array.length; i < l; i ++ ) {
179
180                                         array[ i ].call( this, event );
181
182                                 }
183
184                         }
185
186                 }
187
188         } );
189
190         var REVISION = '87';
191         var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
192         var CullFaceNone = 0;
193         var CullFaceBack = 1;
194         var CullFaceFront = 2;
195         var CullFaceFrontBack = 3;
196         var FrontFaceDirectionCW = 0;
197         var FrontFaceDirectionCCW = 1;
198         var BasicShadowMap = 0;
199         var PCFShadowMap = 1;
200         var PCFSoftShadowMap = 2;
201         var FrontSide = 0;
202         var BackSide = 1;
203         var DoubleSide = 2;
204         var FlatShading = 1;
205         var SmoothShading = 2;
206         var NoColors = 0;
207         var FaceColors = 1;
208         var VertexColors = 2;
209         var NoBlending = 0;
210         var NormalBlending = 1;
211         var AdditiveBlending = 2;
212         var SubtractiveBlending = 3;
213         var MultiplyBlending = 4;
214         var CustomBlending = 5;
215         var AddEquation = 100;
216         var SubtractEquation = 101;
217         var ReverseSubtractEquation = 102;
218         var MinEquation = 103;
219         var MaxEquation = 104;
220         var ZeroFactor = 200;
221         var OneFactor = 201;
222         var SrcColorFactor = 202;
223         var OneMinusSrcColorFactor = 203;
224         var SrcAlphaFactor = 204;
225         var OneMinusSrcAlphaFactor = 205;
226         var DstAlphaFactor = 206;
227         var OneMinusDstAlphaFactor = 207;
228         var DstColorFactor = 208;
229         var OneMinusDstColorFactor = 209;
230         var SrcAlphaSaturateFactor = 210;
231         var NeverDepth = 0;
232         var AlwaysDepth = 1;
233         var LessDepth = 2;
234         var LessEqualDepth = 3;
235         var EqualDepth = 4;
236         var GreaterEqualDepth = 5;
237         var GreaterDepth = 6;
238         var NotEqualDepth = 7;
239         var MultiplyOperation = 0;
240         var MixOperation = 1;
241         var AddOperation = 2;
242         var NoToneMapping = 0;
243         var LinearToneMapping = 1;
244         var ReinhardToneMapping = 2;
245         var Uncharted2ToneMapping = 3;
246         var CineonToneMapping = 4;
247         var UVMapping = 300;
248         var CubeReflectionMapping = 301;
249         var CubeRefractionMapping = 302;
250         var EquirectangularReflectionMapping = 303;
251         var EquirectangularRefractionMapping = 304;
252         var SphericalReflectionMapping = 305;
253         var CubeUVReflectionMapping = 306;
254         var CubeUVRefractionMapping = 307;
255         var RepeatWrapping = 1000;
256         var ClampToEdgeWrapping = 1001;
257         var MirroredRepeatWrapping = 1002;
258         var NearestFilter = 1003;
259         var NearestMipMapNearestFilter = 1004;
260         var NearestMipMapLinearFilter = 1005;
261         var LinearFilter = 1006;
262         var LinearMipMapNearestFilter = 1007;
263         var LinearMipMapLinearFilter = 1008;
264         var UnsignedByteType = 1009;
265         var ByteType = 1010;
266         var ShortType = 1011;
267         var UnsignedShortType = 1012;
268         var IntType = 1013;
269         var UnsignedIntType = 1014;
270         var FloatType = 1015;
271         var HalfFloatType = 1016;
272         var UnsignedShort4444Type = 1017;
273         var UnsignedShort5551Type = 1018;
274         var UnsignedShort565Type = 1019;
275         var UnsignedInt248Type = 1020;
276         var AlphaFormat = 1021;
277         var RGBFormat = 1022;
278         var RGBAFormat = 1023;
279         var LuminanceFormat = 1024;
280         var LuminanceAlphaFormat = 1025;
281         var RGBEFormat = RGBAFormat;
282         var DepthFormat = 1026;
283         var DepthStencilFormat = 1027;
284         var RGB_S3TC_DXT1_Format = 2001;
285         var RGBA_S3TC_DXT1_Format = 2002;
286         var RGBA_S3TC_DXT3_Format = 2003;
287         var RGBA_S3TC_DXT5_Format = 2004;
288         var RGB_PVRTC_4BPPV1_Format = 2100;
289         var RGB_PVRTC_2BPPV1_Format = 2101;
290         var RGBA_PVRTC_4BPPV1_Format = 2102;
291         var RGBA_PVRTC_2BPPV1_Format = 2103;
292         var RGB_ETC1_Format = 2151;
293         var LoopOnce = 2200;
294         var LoopRepeat = 2201;
295         var LoopPingPong = 2202;
296         var InterpolateDiscrete = 2300;
297         var InterpolateLinear = 2301;
298         var InterpolateSmooth = 2302;
299         var ZeroCurvatureEnding = 2400;
300         var ZeroSlopeEnding = 2401;
301         var WrapAroundEnding = 2402;
302         var TrianglesDrawMode = 0;
303         var TriangleStripDrawMode = 1;
304         var TriangleFanDrawMode = 2;
305         var LinearEncoding = 3000;
306         var sRGBEncoding = 3001;
307         var GammaEncoding = 3007;
308         var RGBEEncoding = 3002;
309         var LogLuvEncoding = 3003;
310         var RGBM7Encoding = 3004;
311         var RGBM16Encoding = 3005;
312         var RGBDEncoding = 3006;
313         var BasicDepthPacking = 3200;
314         var RGBADepthPacking = 3201;
315
316         /**
317          * @author alteredq / http://alteredqualia.com/
318          * @author mrdoob / http://mrdoob.com/
319          */
320
321         var _Math = {
322
323                 DEG2RAD: Math.PI / 180,
324                 RAD2DEG: 180 / Math.PI,
325
326                 generateUUID: function () {
327
328                         // http://www.broofa.com/Tools/Math.uuid.htm
329
330                         var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split( '' );
331                         var uuid = new Array( 36 );
332                         var rnd = 0, r;
333
334                         return function generateUUID() {
335
336                                 for ( var i = 0; i < 36; i ++ ) {
337
338                                         if ( i === 8 || i === 13 || i === 18 || i === 23 ) {
339
340                                                 uuid[ i ] = '-';
341
342                                         } else if ( i === 14 ) {
343
344                                                 uuid[ i ] = '4';
345
346                                         } else {
347
348                                                 if ( rnd <= 0x02 ) rnd = 0x2000000 + ( Math.random() * 0x1000000 ) | 0;
349                                                 r = rnd & 0xf;
350                                                 rnd = rnd >> 4;
351                                                 uuid[ i ] = chars[ ( i === 19 ) ? ( r & 0x3 ) | 0x8 : r ];
352
353                                         }
354
355                                 }
356
357                                 return uuid.join( '' );
358
359                         };
360
361                 }(),
362
363                 clamp: function ( value, min, max ) {
364
365                         return Math.max( min, Math.min( max, value ) );
366
367                 },
368
369                 // compute euclidian modulo of m % n
370                 // https://en.wikipedia.org/wiki/Modulo_operation
371
372                 euclideanModulo: function ( n, m ) {
373
374                         return ( ( n % m ) + m ) % m;
375
376                 },
377
378                 // Linear mapping from range <a1, a2> to range <b1, b2>
379
380                 mapLinear: function ( x, a1, a2, b1, b2 ) {
381
382                         return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
383
384                 },
385
386                 // https://en.wikipedia.org/wiki/Linear_interpolation
387
388                 lerp: function ( x, y, t ) {
389
390                         return ( 1 - t ) * x + t * y;
391
392                 },
393
394                 // http://en.wikipedia.org/wiki/Smoothstep
395
396                 smoothstep: function ( x, min, max ) {
397
398                         if ( x <= min ) return 0;
399                         if ( x >= max ) return 1;
400
401                         x = ( x - min ) / ( max - min );
402
403                         return x * x * ( 3 - 2 * x );
404
405                 },
406
407                 smootherstep: function ( x, min, max ) {
408
409                         if ( x <= min ) return 0;
410                         if ( x >= max ) return 1;
411
412                         x = ( x - min ) / ( max - min );
413
414                         return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
415
416                 },
417
418                 // Random integer from <low, high> interval
419
420                 randInt: function ( low, high ) {
421
422                         return low + Math.floor( Math.random() * ( high - low + 1 ) );
423
424                 },
425
426                 // Random float from <low, high> interval
427
428                 randFloat: function ( low, high ) {
429
430                         return low + Math.random() * ( high - low );
431
432                 },
433
434                 // Random float from <-range/2, range/2> interval
435
436                 randFloatSpread: function ( range ) {
437
438                         return range * ( 0.5 - Math.random() );
439
440                 },
441
442                 degToRad: function ( degrees ) {
443
444                         return degrees * _Math.DEG2RAD;
445
446                 },
447
448                 radToDeg: function ( radians ) {
449
450                         return radians * _Math.RAD2DEG;
451
452                 },
453
454                 isPowerOfTwo: function ( value ) {
455
456                         return ( value & ( value - 1 ) ) === 0 && value !== 0;
457
458                 },
459
460                 nearestPowerOfTwo: function ( value ) {
461
462                         return Math.pow( 2, Math.round( Math.log( value ) / Math.LN2 ) );
463
464                 },
465
466                 nextPowerOfTwo: function ( value ) {
467
468                         value --;
469                         value |= value >> 1;
470                         value |= value >> 2;
471                         value |= value >> 4;
472                         value |= value >> 8;
473                         value |= value >> 16;
474                         value ++;
475
476                         return value;
477
478                 }
479
480         };
481
482         /**
483          * @author mrdoob / http://mrdoob.com/
484          * @author philogb / http://blog.thejit.org/
485          * @author egraether / http://egraether.com/
486          * @author zz85 / http://www.lab4games.net/zz85/blog
487          */
488
489         function Vector2( x, y ) {
490
491                 this.x = x || 0;
492                 this.y = y || 0;
493
494         }
495
496         Object.defineProperties( Vector2.prototype, {
497
498                 "width" : {
499
500                         get: function () {
501
502                                 return this.x;
503
504                         },
505
506                         set: function ( value ) {
507
508                                 this.x = value;
509
510                         }
511
512                 },
513
514                 "height" : {
515
516                         get: function () {
517
518                                 return this.y;
519
520                         },
521
522                         set: function ( value ) {
523
524                                 this.y = value;
525
526                         }
527
528                 }
529
530         } );
531
532         Object.assign( Vector2.prototype, {
533
534                 isVector2: true,
535
536                 set: function ( x, y ) {
537
538                         this.x = x;
539                         this.y = y;
540
541                         return this;
542
543                 },
544
545                 setScalar: function ( scalar ) {
546
547                         this.x = scalar;
548                         this.y = scalar;
549
550                         return this;
551
552                 },
553
554                 setX: function ( x ) {
555
556                         this.x = x;
557
558                         return this;
559
560                 },
561
562                 setY: function ( y ) {
563
564                         this.y = y;
565
566                         return this;
567
568                 },
569
570                 setComponent: function ( index, value ) {
571
572                         switch ( index ) {
573
574                                 case 0: this.x = value; break;
575                                 case 1: this.y = value; break;
576                                 default: throw new Error( 'index is out of range: ' + index );
577
578                         }
579
580                         return this;
581
582                 },
583
584                 getComponent: function ( index ) {
585
586                         switch ( index ) {
587
588                                 case 0: return this.x;
589                                 case 1: return this.y;
590                                 default: throw new Error( 'index is out of range: ' + index );
591
592                         }
593
594                 },
595
596                 clone: function () {
597
598                         return new this.constructor( this.x, this.y );
599
600                 },
601
602                 copy: function ( v ) {
603
604                         this.x = v.x;
605                         this.y = v.y;
606
607                         return this;
608
609                 },
610
611                 add: function ( v, w ) {
612
613                         if ( w !== undefined ) {
614
615                                 console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
616                                 return this.addVectors( v, w );
617
618                         }
619
620                         this.x += v.x;
621                         this.y += v.y;
622
623                         return this;
624
625                 },
626
627                 addScalar: function ( s ) {
628
629                         this.x += s;
630                         this.y += s;
631
632                         return this;
633
634                 },
635
636                 addVectors: function ( a, b ) {
637
638                         this.x = a.x + b.x;
639                         this.y = a.y + b.y;
640
641                         return this;
642
643                 },
644
645                 addScaledVector: function ( v, s ) {
646
647                         this.x += v.x * s;
648                         this.y += v.y * s;
649
650                         return this;
651
652                 },
653
654                 sub: function ( v, w ) {
655
656                         if ( w !== undefined ) {
657
658                                 console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
659                                 return this.subVectors( v, w );
660
661                         }
662
663                         this.x -= v.x;
664                         this.y -= v.y;
665
666                         return this;
667
668                 },
669
670                 subScalar: function ( s ) {
671
672                         this.x -= s;
673                         this.y -= s;
674
675                         return this;
676
677                 },
678
679                 subVectors: function ( a, b ) {
680
681                         this.x = a.x - b.x;
682                         this.y = a.y - b.y;
683
684                         return this;
685
686                 },
687
688                 multiply: function ( v ) {
689
690                         this.x *= v.x;
691                         this.y *= v.y;
692
693                         return this;
694
695                 },
696
697                 multiplyScalar: function ( scalar ) {
698
699                         this.x *= scalar;
700                         this.y *= scalar;
701
702                         return this;
703
704                 },
705
706                 divide: function ( v ) {
707
708                         this.x /= v.x;
709                         this.y /= v.y;
710
711                         return this;
712
713                 },
714
715                 divideScalar: function ( scalar ) {
716
717                         return this.multiplyScalar( 1 / scalar );
718
719                 },
720
721                 min: function ( v ) {
722
723                         this.x = Math.min( this.x, v.x );
724                         this.y = Math.min( this.y, v.y );
725
726                         return this;
727
728                 },
729
730                 max: function ( v ) {
731
732                         this.x = Math.max( this.x, v.x );
733                         this.y = Math.max( this.y, v.y );
734
735                         return this;
736
737                 },
738
739                 clamp: function ( min, max ) {
740
741                         // assumes min < max, componentwise
742
743                         this.x = Math.max( min.x, Math.min( max.x, this.x ) );
744                         this.y = Math.max( min.y, Math.min( max.y, this.y ) );
745
746                         return this;
747
748                 },
749
750                 clampScalar: function () {
751
752                         var min = new Vector2();
753                         var max = new Vector2();
754
755                         return function clampScalar( minVal, maxVal ) {
756
757                                 min.set( minVal, minVal );
758                                 max.set( maxVal, maxVal );
759
760                                 return this.clamp( min, max );
761
762                         };
763
764                 }(),
765
766                 clampLength: function ( min, max ) {
767
768                         var length = this.length();
769
770                         return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
771
772                 },
773
774                 floor: function () {
775
776                         this.x = Math.floor( this.x );
777                         this.y = Math.floor( this.y );
778
779                         return this;
780
781                 },
782
783                 ceil: function () {
784
785                         this.x = Math.ceil( this.x );
786                         this.y = Math.ceil( this.y );
787
788                         return this;
789
790                 },
791
792                 round: function () {
793
794                         this.x = Math.round( this.x );
795                         this.y = Math.round( this.y );
796
797                         return this;
798
799                 },
800
801                 roundToZero: function () {
802
803                         this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
804                         this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
805
806                         return this;
807
808                 },
809
810                 negate: function () {
811
812                         this.x = - this.x;
813                         this.y = - this.y;
814
815                         return this;
816
817                 },
818
819                 dot: function ( v ) {
820
821                         return this.x * v.x + this.y * v.y;
822
823                 },
824
825                 lengthSq: function () {
826
827                         return this.x * this.x + this.y * this.y;
828
829                 },
830
831                 length: function () {
832
833                         return Math.sqrt( this.x * this.x + this.y * this.y );
834
835                 },
836
837                 lengthManhattan: function() {
838
839                         return Math.abs( this.x ) + Math.abs( this.y );
840
841                 },
842
843                 normalize: function () {
844
845                         return this.divideScalar( this.length() || 1 );
846
847                 },
848
849                 angle: function () {
850
851                         // computes the angle in radians with respect to the positive x-axis
852
853                         var angle = Math.atan2( this.y, this.x );
854
855                         if ( angle < 0 ) angle += 2 * Math.PI;
856
857                         return angle;
858
859                 },
860
861                 distanceTo: function ( v ) {
862
863                         return Math.sqrt( this.distanceToSquared( v ) );
864
865                 },
866
867                 distanceToSquared: function ( v ) {
868
869                         var dx = this.x - v.x, dy = this.y - v.y;
870                         return dx * dx + dy * dy;
871
872                 },
873
874                 distanceToManhattan: function ( v ) {
875
876                         return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
877
878                 },
879
880                 setLength: function ( length ) {
881
882                         return this.normalize().multiplyScalar( length );
883
884                 },
885
886                 lerp: function ( v, alpha ) {
887
888                         this.x += ( v.x - this.x ) * alpha;
889                         this.y += ( v.y - this.y ) * alpha;
890
891                         return this;
892
893                 },
894
895                 lerpVectors: function ( v1, v2, alpha ) {
896
897                         return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
898
899                 },
900
901                 equals: function ( v ) {
902
903                         return ( ( v.x === this.x ) && ( v.y === this.y ) );
904
905                 },
906
907                 fromArray: function ( array, offset ) {
908
909                         if ( offset === undefined ) offset = 0;
910
911                         this.x = array[ offset ];
912                         this.y = array[ offset + 1 ];
913
914                         return this;
915
916                 },
917
918                 toArray: function ( array, offset ) {
919
920                         if ( array === undefined ) array = [];
921                         if ( offset === undefined ) offset = 0;
922
923                         array[ offset ] = this.x;
924                         array[ offset + 1 ] = this.y;
925
926                         return array;
927
928                 },
929
930                 fromBufferAttribute: function ( attribute, index, offset ) {
931
932                         if ( offset !== undefined ) {
933
934                                 console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
935
936                         }
937
938                         this.x = attribute.getX( index );
939                         this.y = attribute.getY( index );
940
941                         return this;
942
943                 },
944
945                 rotateAround: function ( center, angle ) {
946
947                         var c = Math.cos( angle ), s = Math.sin( angle );
948
949                         var x = this.x - center.x;
950                         var y = this.y - center.y;
951
952                         this.x = x * c - y * s + center.x;
953                         this.y = x * s + y * c + center.y;
954
955                         return this;
956
957                 }
958
959         } );
960
961         /**
962          * @author mrdoob / http://mrdoob.com/
963          * @author alteredq / http://alteredqualia.com/
964          * @author szimek / https://github.com/szimek/
965          */
966
967         var textureId = 0;
968
969         function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
970
971                 Object.defineProperty( this, 'id', { value: textureId ++ } );
972
973                 this.uuid = _Math.generateUUID();
974
975                 this.name = '';
976
977                 this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
978                 this.mipmaps = [];
979
980                 this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
981
982                 this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
983                 this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
984
985                 this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
986                 this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter;
987
988                 this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
989
990                 this.format = format !== undefined ? format : RGBAFormat;
991                 this.type = type !== undefined ? type : UnsignedByteType;
992
993                 this.offset = new Vector2( 0, 0 );
994                 this.repeat = new Vector2( 1, 1 );
995
996                 this.generateMipmaps = true;
997                 this.premultiplyAlpha = false;
998                 this.flipY = true;
999                 this.unpackAlignment = 4;       // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
1000
1001                 // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
1002                 //
1003                 // Also changing the encoding after already used by a Material will not automatically make the Material
1004                 // update.  You need to explicitly call Material.needsUpdate to trigger it to recompile.
1005                 this.encoding = encoding !== undefined ? encoding : LinearEncoding;
1006
1007                 this.version = 0;
1008                 this.onUpdate = null;
1009
1010         }
1011
1012         Texture.DEFAULT_IMAGE = undefined;
1013         Texture.DEFAULT_MAPPING = UVMapping;
1014
1015         Object.defineProperty( Texture.prototype, "needsUpdate", {
1016
1017                 set: function ( value ) {
1018
1019                         if ( value === true ) this.version ++;
1020
1021                 }
1022
1023         } );
1024
1025         Object.assign( Texture.prototype, EventDispatcher.prototype, {
1026
1027                 constructor: Texture,
1028
1029                 isTexture: true,
1030
1031                 clone: function () {
1032
1033                         return new this.constructor().copy( this );
1034
1035                 },
1036
1037                 copy: function ( source ) {
1038
1039                         this.name = source.name;
1040
1041                         this.image = source.image;
1042                         this.mipmaps = source.mipmaps.slice( 0 );
1043
1044                         this.mapping = source.mapping;
1045
1046                         this.wrapS = source.wrapS;
1047                         this.wrapT = source.wrapT;
1048
1049                         this.magFilter = source.magFilter;
1050                         this.minFilter = source.minFilter;
1051
1052                         this.anisotropy = source.anisotropy;
1053
1054                         this.format = source.format;
1055                         this.type = source.type;
1056
1057                         this.offset.copy( source.offset );
1058                         this.repeat.copy( source.repeat );
1059
1060                         this.generateMipmaps = source.generateMipmaps;
1061                         this.premultiplyAlpha = source.premultiplyAlpha;
1062                         this.flipY = source.flipY;
1063                         this.unpackAlignment = source.unpackAlignment;
1064                         this.encoding = source.encoding;
1065
1066                         return this;
1067
1068                 },
1069
1070                 toJSON: function ( meta ) {
1071
1072                         if ( meta.textures[ this.uuid ] !== undefined ) {
1073
1074                                 return meta.textures[ this.uuid ];
1075
1076                         }
1077
1078                         function getDataURL( image ) {
1079
1080                                 var canvas;
1081
1082                                 if ( image instanceof HTMLCanvasElement ) {
1083
1084                                         canvas = image;
1085
1086                                 } else {
1087
1088                                         canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
1089                                         canvas.width = image.width;
1090                                         canvas.height = image.height;
1091
1092                                         var context = canvas.getContext( '2d' );
1093
1094                                         if ( image instanceof ImageData ) {
1095
1096                                                 context.putImageData( image, 0, 0 );
1097
1098                                         } else {
1099
1100                                                 context.drawImage( image, 0, 0, image.width, image.height );
1101
1102                                         }
1103
1104                                 }
1105
1106                                 if ( canvas.width > 2048 || canvas.height > 2048 ) {
1107
1108                                         return canvas.toDataURL( 'image/jpeg', 0.6 );
1109
1110                                 } else {
1111
1112                                         return canvas.toDataURL( 'image/png' );
1113
1114                                 }
1115
1116                         }
1117
1118                         var output = {
1119                                 metadata: {
1120                                         version: 4.5,
1121                                         type: 'Texture',
1122                                         generator: 'Texture.toJSON'
1123                                 },
1124
1125                                 uuid: this.uuid,
1126                                 name: this.name,
1127
1128                                 mapping: this.mapping,
1129
1130                                 repeat: [ this.repeat.x, this.repeat.y ],
1131                                 offset: [ this.offset.x, this.offset.y ],
1132                                 wrap: [ this.wrapS, this.wrapT ],
1133
1134                                 minFilter: this.minFilter,
1135                                 magFilter: this.magFilter,
1136                                 anisotropy: this.anisotropy,
1137
1138                                 flipY: this.flipY
1139                         };
1140
1141                         if ( this.image !== undefined ) {
1142
1143                                 // TODO: Move to THREE.Image
1144
1145                                 var image = this.image;
1146
1147                                 if ( image.uuid === undefined ) {
1148
1149                                         image.uuid = _Math.generateUUID(); // UGH
1150
1151                                 }
1152
1153                                 if ( meta.images[ image.uuid ] === undefined ) {
1154
1155                                         meta.images[ image.uuid ] = {
1156                                                 uuid: image.uuid,
1157                                                 url: getDataURL( image )
1158                                         };
1159
1160                                 }
1161
1162                                 output.image = image.uuid;
1163
1164                         }
1165
1166                         meta.textures[ this.uuid ] = output;
1167
1168                         return output;
1169
1170                 },
1171
1172                 dispose: function () {
1173
1174                         this.dispatchEvent( { type: 'dispose' } );
1175
1176                 },
1177
1178                 transformUv: function ( uv ) {
1179
1180                         if ( this.mapping !== UVMapping ) return;
1181
1182                         uv.multiply( this.repeat );
1183                         uv.add( this.offset );
1184
1185                         if ( uv.x < 0 || uv.x > 1 ) {
1186
1187                                 switch ( this.wrapS ) {
1188
1189                                         case RepeatWrapping:
1190
1191                                                 uv.x = uv.x - Math.floor( uv.x );
1192                                                 break;
1193
1194                                         case ClampToEdgeWrapping:
1195
1196                                                 uv.x = uv.x < 0 ? 0 : 1;
1197                                                 break;
1198
1199                                         case MirroredRepeatWrapping:
1200
1201                                                 if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
1202
1203                                                         uv.x = Math.ceil( uv.x ) - uv.x;
1204
1205                                                 } else {
1206
1207                                                         uv.x = uv.x - Math.floor( uv.x );
1208
1209                                                 }
1210                                                 break;
1211
1212                                 }
1213
1214                         }
1215
1216                         if ( uv.y < 0 || uv.y > 1 ) {
1217
1218                                 switch ( this.wrapT ) {
1219
1220                                         case RepeatWrapping:
1221
1222                                                 uv.y = uv.y - Math.floor( uv.y );
1223                                                 break;
1224
1225                                         case ClampToEdgeWrapping:
1226
1227                                                 uv.y = uv.y < 0 ? 0 : 1;
1228                                                 break;
1229
1230                                         case MirroredRepeatWrapping:
1231
1232                                                 if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
1233
1234                                                         uv.y = Math.ceil( uv.y ) - uv.y;
1235
1236                                                 } else {
1237
1238                                                         uv.y = uv.y - Math.floor( uv.y );
1239
1240                                                 }
1241                                                 break;
1242
1243                                 }
1244
1245                         }
1246
1247                         if ( this.flipY ) {
1248
1249                                 uv.y = 1 - uv.y;
1250
1251                         }
1252
1253                 }
1254
1255         } );
1256
1257         /**
1258          * @author supereggbert / http://www.paulbrunt.co.uk/
1259          * @author philogb / http://blog.thejit.org/
1260          * @author mikael emtinger / http://gomo.se/
1261          * @author egraether / http://egraether.com/
1262          * @author WestLangley / http://github.com/WestLangley
1263          */
1264
1265         function Vector4( x, y, z, w ) {
1266
1267                 this.x = x || 0;
1268                 this.y = y || 0;
1269                 this.z = z || 0;
1270                 this.w = ( w !== undefined ) ? w : 1;
1271
1272         }
1273
1274         Object.assign( Vector4.prototype, {
1275
1276                 isVector4: true,
1277
1278                 set: function ( x, y, z, w ) {
1279
1280                         this.x = x;
1281                         this.y = y;
1282                         this.z = z;
1283                         this.w = w;
1284
1285                         return this;
1286
1287                 },
1288
1289                 setScalar: function ( scalar ) {
1290
1291                         this.x = scalar;
1292                         this.y = scalar;
1293                         this.z = scalar;
1294                         this.w = scalar;
1295
1296                         return this;
1297
1298                 },
1299
1300                 setX: function ( x ) {
1301
1302                         this.x = x;
1303
1304                         return this;
1305
1306                 },
1307
1308                 setY: function ( y ) {
1309
1310                         this.y = y;
1311
1312                         return this;
1313
1314                 },
1315
1316                 setZ: function ( z ) {
1317
1318                         this.z = z;
1319
1320                         return this;
1321
1322                 },
1323
1324                 setW: function ( w ) {
1325
1326                         this.w = w;
1327
1328                         return this;
1329
1330                 },
1331
1332                 setComponent: function ( index, value ) {
1333
1334                         switch ( index ) {
1335
1336                                 case 0: this.x = value; break;
1337                                 case 1: this.y = value; break;
1338                                 case 2: this.z = value; break;
1339                                 case 3: this.w = value; break;
1340                                 default: throw new Error( 'index is out of range: ' + index );
1341
1342                         }
1343
1344                         return this;
1345
1346                 },
1347
1348                 getComponent: function ( index ) {
1349
1350                         switch ( index ) {
1351
1352                                 case 0: return this.x;
1353                                 case 1: return this.y;
1354                                 case 2: return this.z;
1355                                 case 3: return this.w;
1356                                 default: throw new Error( 'index is out of range: ' + index );
1357
1358                         }
1359
1360                 },
1361
1362                 clone: function () {
1363
1364                         return new this.constructor( this.x, this.y, this.z, this.w );
1365
1366                 },
1367
1368                 copy: function ( v ) {
1369
1370                         this.x = v.x;
1371                         this.y = v.y;
1372                         this.z = v.z;
1373                         this.w = ( v.w !== undefined ) ? v.w : 1;
1374
1375                         return this;
1376
1377                 },
1378
1379                 add: function ( v, w ) {
1380
1381                         if ( w !== undefined ) {
1382
1383                                 console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
1384                                 return this.addVectors( v, w );
1385
1386                         }
1387
1388                         this.x += v.x;
1389                         this.y += v.y;
1390                         this.z += v.z;
1391                         this.w += v.w;
1392
1393                         return this;
1394
1395                 },
1396
1397                 addScalar: function ( s ) {
1398
1399                         this.x += s;
1400                         this.y += s;
1401                         this.z += s;
1402                         this.w += s;
1403
1404                         return this;
1405
1406                 },
1407
1408                 addVectors: function ( a, b ) {
1409
1410                         this.x = a.x + b.x;
1411                         this.y = a.y + b.y;
1412                         this.z = a.z + b.z;
1413                         this.w = a.w + b.w;
1414
1415                         return this;
1416
1417                 },
1418
1419                 addScaledVector: function ( v, s ) {
1420
1421                         this.x += v.x * s;
1422                         this.y += v.y * s;
1423                         this.z += v.z * s;
1424                         this.w += v.w * s;
1425
1426                         return this;
1427
1428                 },
1429
1430                 sub: function ( v, w ) {
1431
1432                         if ( w !== undefined ) {
1433
1434                                 console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
1435                                 return this.subVectors( v, w );
1436
1437                         }
1438
1439                         this.x -= v.x;
1440                         this.y -= v.y;
1441                         this.z -= v.z;
1442                         this.w -= v.w;
1443
1444                         return this;
1445
1446                 },
1447
1448                 subScalar: function ( s ) {
1449
1450                         this.x -= s;
1451                         this.y -= s;
1452                         this.z -= s;
1453                         this.w -= s;
1454
1455                         return this;
1456
1457                 },
1458
1459                 subVectors: function ( a, b ) {
1460
1461                         this.x = a.x - b.x;
1462                         this.y = a.y - b.y;
1463                         this.z = a.z - b.z;
1464                         this.w = a.w - b.w;
1465
1466                         return this;
1467
1468                 },
1469
1470                 multiplyScalar: function ( scalar ) {
1471
1472                         this.x *= scalar;
1473                         this.y *= scalar;
1474                         this.z *= scalar;
1475                         this.w *= scalar;
1476
1477                         return this;
1478
1479                 },
1480
1481                 applyMatrix4: function ( m ) {
1482
1483                         var x = this.x, y = this.y, z = this.z, w = this.w;
1484                         var e = m.elements;
1485
1486                         this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
1487                         this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
1488                         this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
1489                         this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
1490
1491                         return this;
1492
1493                 },
1494
1495                 divideScalar: function ( scalar ) {
1496
1497                         return this.multiplyScalar( 1 / scalar );
1498
1499                 },
1500
1501                 setAxisAngleFromQuaternion: function ( q ) {
1502
1503                         // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
1504
1505                         // q is assumed to be normalized
1506
1507                         this.w = 2 * Math.acos( q.w );
1508
1509                         var s = Math.sqrt( 1 - q.w * q.w );
1510
1511                         if ( s < 0.0001 ) {
1512
1513                                  this.x = 1;
1514                                  this.y = 0;
1515                                  this.z = 0;
1516
1517                         } else {
1518
1519                                  this.x = q.x / s;
1520                                  this.y = q.y / s;
1521                                  this.z = q.z / s;
1522
1523                         }
1524
1525                         return this;
1526
1527                 },
1528
1529                 setAxisAngleFromRotationMatrix: function ( m ) {
1530
1531                         // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
1532
1533                         // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
1534
1535                         var angle, x, y, z,             // variables for result
1536                                 epsilon = 0.01,         // margin to allow for rounding errors
1537                                 epsilon2 = 0.1,         // margin to distinguish between 0 and 180 degrees
1538
1539                                 te = m.elements,
1540
1541                                 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
1542                                 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
1543                                 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
1544
1545                         if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
1546                              ( Math.abs( m13 - m31 ) < epsilon ) &&
1547                              ( Math.abs( m23 - m32 ) < epsilon ) ) {
1548
1549                                 // singularity found
1550                                 // first check for identity matrix which must have +1 for all terms
1551                                 // in leading diagonal and zero in other terms
1552
1553                                 if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
1554                                      ( Math.abs( m13 + m31 ) < epsilon2 ) &&
1555                                      ( Math.abs( m23 + m32 ) < epsilon2 ) &&
1556                                      ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
1557
1558                                         // this singularity is identity matrix so angle = 0
1559
1560                                         this.set( 1, 0, 0, 0 );
1561
1562                                         return this; // zero angle, arbitrary axis
1563
1564                                 }
1565
1566                                 // otherwise this singularity is angle = 180
1567
1568                                 angle = Math.PI;
1569
1570                                 var xx = ( m11 + 1 ) / 2;
1571                                 var yy = ( m22 + 1 ) / 2;
1572                                 var zz = ( m33 + 1 ) / 2;
1573                                 var xy = ( m12 + m21 ) / 4;
1574                                 var xz = ( m13 + m31 ) / 4;
1575                                 var yz = ( m23 + m32 ) / 4;
1576
1577                                 if ( ( xx > yy ) && ( xx > zz ) ) {
1578
1579                                         // m11 is the largest diagonal term
1580
1581                                         if ( xx < epsilon ) {
1582
1583                                                 x = 0;
1584                                                 y = 0.707106781;
1585                                                 z = 0.707106781;
1586
1587                                         } else {
1588
1589                                                 x = Math.sqrt( xx );
1590                                                 y = xy / x;
1591                                                 z = xz / x;
1592
1593                                         }
1594
1595                                 } else if ( yy > zz ) {
1596
1597                                         // m22 is the largest diagonal term
1598
1599                                         if ( yy < epsilon ) {
1600
1601                                                 x = 0.707106781;
1602                                                 y = 0;
1603                                                 z = 0.707106781;
1604
1605                                         } else {
1606
1607                                                 y = Math.sqrt( yy );
1608                                                 x = xy / y;
1609                                                 z = yz / y;
1610
1611                                         }
1612
1613                                 } else {
1614
1615                                         // m33 is the largest diagonal term so base result on this
1616
1617                                         if ( zz < epsilon ) {
1618
1619                                                 x = 0.707106781;
1620                                                 y = 0.707106781;
1621                                                 z = 0;
1622
1623                                         } else {
1624
1625                                                 z = Math.sqrt( zz );
1626                                                 x = xz / z;
1627                                                 y = yz / z;
1628
1629                                         }
1630
1631                                 }
1632
1633                                 this.set( x, y, z, angle );
1634
1635                                 return this; // return 180 deg rotation
1636
1637                         }
1638
1639                         // as we have reached here there are no singularities so we can handle normally
1640
1641                         var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
1642                                            ( m13 - m31 ) * ( m13 - m31 ) +
1643                                            ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
1644
1645                         if ( Math.abs( s ) < 0.001 ) s = 1;
1646
1647                         // prevent divide by zero, should not happen if matrix is orthogonal and should be
1648                         // caught by singularity test above, but I've left it in just in case
1649
1650                         this.x = ( m32 - m23 ) / s;
1651                         this.y = ( m13 - m31 ) / s;
1652                         this.z = ( m21 - m12 ) / s;
1653                         this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
1654
1655                         return this;
1656
1657                 },
1658
1659                 min: function ( v ) {
1660
1661                         this.x = Math.min( this.x, v.x );
1662                         this.y = Math.min( this.y, v.y );
1663                         this.z = Math.min( this.z, v.z );
1664                         this.w = Math.min( this.w, v.w );
1665
1666                         return this;
1667
1668                 },
1669
1670                 max: function ( v ) {
1671
1672                         this.x = Math.max( this.x, v.x );
1673                         this.y = Math.max( this.y, v.y );
1674                         this.z = Math.max( this.z, v.z );
1675                         this.w = Math.max( this.w, v.w );
1676
1677                         return this;
1678
1679                 },
1680
1681                 clamp: function ( min, max ) {
1682
1683                         // assumes min < max, componentwise
1684
1685                         this.x = Math.max( min.x, Math.min( max.x, this.x ) );
1686                         this.y = Math.max( min.y, Math.min( max.y, this.y ) );
1687                         this.z = Math.max( min.z, Math.min( max.z, this.z ) );
1688                         this.w = Math.max( min.w, Math.min( max.w, this.w ) );
1689
1690                         return this;
1691
1692                 },
1693
1694                 clampScalar: function () {
1695
1696                         var min, max;
1697
1698                         return function clampScalar( minVal, maxVal ) {
1699
1700                                 if ( min === undefined ) {
1701
1702                                         min = new Vector4();
1703                                         max = new Vector4();
1704
1705                                 }
1706
1707                                 min.set( minVal, minVal, minVal, minVal );
1708                                 max.set( maxVal, maxVal, maxVal, maxVal );
1709
1710                                 return this.clamp( min, max );
1711
1712                         };
1713
1714                 }(),
1715
1716                 clampLength: function ( min, max ) {
1717
1718                         var length = this.length();
1719
1720                         return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
1721
1722                 },
1723
1724                 floor: function () {
1725
1726                         this.x = Math.floor( this.x );
1727                         this.y = Math.floor( this.y );
1728                         this.z = Math.floor( this.z );
1729                         this.w = Math.floor( this.w );
1730
1731                         return this;
1732
1733                 },
1734
1735                 ceil: function () {
1736
1737                         this.x = Math.ceil( this.x );
1738                         this.y = Math.ceil( this.y );
1739                         this.z = Math.ceil( this.z );
1740                         this.w = Math.ceil( this.w );
1741
1742                         return this;
1743
1744                 },
1745
1746                 round: function () {
1747
1748                         this.x = Math.round( this.x );
1749                         this.y = Math.round( this.y );
1750                         this.z = Math.round( this.z );
1751                         this.w = Math.round( this.w );
1752
1753                         return this;
1754
1755                 },
1756
1757                 roundToZero: function () {
1758
1759                         this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
1760                         this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
1761                         this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
1762                         this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
1763
1764                         return this;
1765
1766                 },
1767
1768                 negate: function () {
1769
1770                         this.x = - this.x;
1771                         this.y = - this.y;
1772                         this.z = - this.z;
1773                         this.w = - this.w;
1774
1775                         return this;
1776
1777                 },
1778
1779                 dot: function ( v ) {
1780
1781                         return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
1782
1783                 },
1784
1785                 lengthSq: function () {
1786
1787                         return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
1788
1789                 },
1790
1791                 length: function () {
1792
1793                         return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
1794
1795                 },
1796
1797                 lengthManhattan: function () {
1798
1799                         return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
1800
1801                 },
1802
1803                 normalize: function () {
1804
1805                         return this.divideScalar( this.length() || 1 );
1806
1807                 },
1808
1809                 setLength: function ( length ) {
1810
1811                         return this.normalize().multiplyScalar( length );
1812
1813                 },
1814
1815                 lerp: function ( v, alpha ) {
1816
1817                         this.x += ( v.x - this.x ) * alpha;
1818                         this.y += ( v.y - this.y ) * alpha;
1819                         this.z += ( v.z - this.z ) * alpha;
1820                         this.w += ( v.w - this.w ) * alpha;
1821
1822                         return this;
1823
1824                 },
1825
1826                 lerpVectors: function ( v1, v2, alpha ) {
1827
1828                         return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
1829
1830                 },
1831
1832                 equals: function ( v ) {
1833
1834                         return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
1835
1836                 },
1837
1838                 fromArray: function ( array, offset ) {
1839
1840                         if ( offset === undefined ) offset = 0;
1841
1842                         this.x = array[ offset ];
1843                         this.y = array[ offset + 1 ];
1844                         this.z = array[ offset + 2 ];
1845                         this.w = array[ offset + 3 ];
1846
1847                         return this;
1848
1849                 },
1850
1851                 toArray: function ( array, offset ) {
1852
1853                         if ( array === undefined ) array = [];
1854                         if ( offset === undefined ) offset = 0;
1855
1856                         array[ offset ] = this.x;
1857                         array[ offset + 1 ] = this.y;
1858                         array[ offset + 2 ] = this.z;
1859                         array[ offset + 3 ] = this.w;
1860
1861                         return array;
1862
1863                 },
1864
1865                 fromBufferAttribute: function ( attribute, index, offset ) {
1866
1867                         if ( offset !== undefined ) {
1868
1869                                 console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
1870
1871                         }
1872
1873                         this.x = attribute.getX( index );
1874                         this.y = attribute.getY( index );
1875                         this.z = attribute.getZ( index );
1876                         this.w = attribute.getW( index );
1877
1878                         return this;
1879
1880                 }
1881
1882         } );
1883
1884         /**
1885          * @author szimek / https://github.com/szimek/
1886          * @author alteredq / http://alteredqualia.com/
1887          * @author Marius Kintel / https://github.com/kintel
1888          */
1889
1890         /*
1891          In options, we can specify:
1892          * Texture parameters for an auto-generated target texture
1893          * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
1894         */
1895         function WebGLRenderTarget( width, height, options ) {
1896
1897                 this.uuid = _Math.generateUUID();
1898
1899                 this.width = width;
1900                 this.height = height;
1901
1902                 this.scissor = new Vector4( 0, 0, width, height );
1903                 this.scissorTest = false;
1904
1905                 this.viewport = new Vector4( 0, 0, width, height );
1906
1907                 options = options || {};
1908
1909                 if ( options.minFilter === undefined ) options.minFilter = LinearFilter;
1910
1911                 this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
1912
1913                 this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
1914                 this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
1915                 this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
1916
1917         }
1918
1919         Object.assign( WebGLRenderTarget.prototype, EventDispatcher.prototype, {
1920
1921                 isWebGLRenderTarget: true,
1922
1923                 setSize: function ( width, height ) {
1924
1925                         if ( this.width !== width || this.height !== height ) {
1926
1927                                 this.width = width;
1928                                 this.height = height;
1929
1930                                 this.dispose();
1931
1932                         }
1933
1934                         this.viewport.set( 0, 0, width, height );
1935                         this.scissor.set( 0, 0, width, height );
1936
1937                 },
1938
1939                 clone: function () {
1940
1941                         return new this.constructor().copy( this );
1942
1943                 },
1944
1945                 copy: function ( source ) {
1946
1947                         this.width = source.width;
1948                         this.height = source.height;
1949
1950                         this.viewport.copy( source.viewport );
1951
1952                         this.texture = source.texture.clone();
1953
1954                         this.depthBuffer = source.depthBuffer;
1955                         this.stencilBuffer = source.stencilBuffer;
1956                         this.depthTexture = source.depthTexture;
1957
1958                         return this;
1959
1960                 },
1961
1962                 dispose: function () {
1963
1964                         this.dispatchEvent( { type: 'dispose' } );
1965
1966                 }
1967
1968         } );
1969
1970         /**
1971          * @author alteredq / http://alteredqualia.com
1972          */
1973
1974         function WebGLRenderTargetCube( width, height, options ) {
1975
1976                 WebGLRenderTarget.call( this, width, height, options );
1977
1978                 this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
1979                 this.activeMipMapLevel = 0;
1980
1981         }
1982
1983         WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype );
1984         WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;
1985
1986         WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;
1987
1988         /**
1989          * @author mikael emtinger / http://gomo.se/
1990          * @author alteredq / http://alteredqualia.com/
1991          * @author WestLangley / http://github.com/WestLangley
1992          * @author bhouston / http://clara.io
1993          */
1994
1995         function Quaternion( x, y, z, w ) {
1996
1997                 this._x = x || 0;
1998                 this._y = y || 0;
1999                 this._z = z || 0;
2000                 this._w = ( w !== undefined ) ? w : 1;
2001
2002         }
2003
2004         Object.assign( Quaternion, {
2005
2006                 slerp: function ( qa, qb, qm, t ) {
2007
2008                         return qm.copy( qa ).slerp( qb, t );
2009
2010                 },
2011
2012                 slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
2013
2014                         // fuzz-free, array-based Quaternion SLERP operation
2015
2016                         var x0 = src0[ srcOffset0 + 0 ],
2017                                 y0 = src0[ srcOffset0 + 1 ],
2018                                 z0 = src0[ srcOffset0 + 2 ],
2019                                 w0 = src0[ srcOffset0 + 3 ],
2020
2021                                 x1 = src1[ srcOffset1 + 0 ],
2022                                 y1 = src1[ srcOffset1 + 1 ],
2023                                 z1 = src1[ srcOffset1 + 2 ],
2024                                 w1 = src1[ srcOffset1 + 3 ];
2025
2026                         if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
2027
2028                                 var s = 1 - t,
2029
2030                                         cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
2031
2032                                         dir = ( cos >= 0 ? 1 : - 1 ),
2033                                         sqrSin = 1 - cos * cos;
2034
2035                                 // Skip the Slerp for tiny steps to avoid numeric problems:
2036                                 if ( sqrSin > Number.EPSILON ) {
2037
2038                                         var sin = Math.sqrt( sqrSin ),
2039                                                 len = Math.atan2( sin, cos * dir );
2040
2041                                         s = Math.sin( s * len ) / sin;
2042                                         t = Math.sin( t * len ) / sin;
2043
2044                                 }
2045
2046                                 var tDir = t * dir;
2047
2048                                 x0 = x0 * s + x1 * tDir;
2049                                 y0 = y0 * s + y1 * tDir;
2050                                 z0 = z0 * s + z1 * tDir;
2051                                 w0 = w0 * s + w1 * tDir;
2052
2053                                 // Normalize in case we just did a lerp:
2054                                 if ( s === 1 - t ) {
2055
2056                                         var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
2057
2058                                         x0 *= f;
2059                                         y0 *= f;
2060                                         z0 *= f;
2061                                         w0 *= f;
2062
2063                                 }
2064
2065                         }
2066
2067                         dst[ dstOffset ] = x0;
2068                         dst[ dstOffset + 1 ] = y0;
2069                         dst[ dstOffset + 2 ] = z0;
2070                         dst[ dstOffset + 3 ] = w0;
2071
2072                 }
2073
2074         } );
2075
2076         Object.defineProperties( Quaternion.prototype, {
2077
2078                 x: {
2079
2080                         get: function () {
2081
2082                                 return this._x;
2083
2084                         },
2085
2086                         set: function ( value ) {
2087
2088                                 this._x = value;
2089                                 this.onChangeCallback();
2090
2091                         }
2092
2093                 },
2094
2095                 y: {
2096
2097                         get: function () {
2098
2099                                 return this._y;
2100
2101                         },
2102
2103                         set: function ( value ) {
2104
2105                                 this._y = value;
2106                                 this.onChangeCallback();
2107
2108                         }
2109
2110                 },
2111
2112                 z: {
2113
2114                         get: function () {
2115
2116                                 return this._z;
2117
2118                         },
2119
2120                         set: function ( value ) {
2121
2122                                 this._z = value;
2123                                 this.onChangeCallback();
2124
2125                         }
2126
2127                 },
2128
2129                 w: {
2130
2131                         get: function () {
2132
2133                                 return this._w;
2134
2135                         },
2136
2137                         set: function ( value ) {
2138
2139                                 this._w = value;
2140                                 this.onChangeCallback();
2141
2142                         }
2143
2144                 }
2145
2146         } );
2147
2148         Object.assign( Quaternion.prototype, {
2149
2150                 set: function ( x, y, z, w ) {
2151
2152                         this._x = x;
2153                         this._y = y;
2154                         this._z = z;
2155                         this._w = w;
2156
2157                         this.onChangeCallback();
2158
2159                         return this;
2160
2161                 },
2162
2163                 clone: function () {
2164
2165                         return new this.constructor( this._x, this._y, this._z, this._w );
2166
2167                 },
2168
2169                 copy: function ( quaternion ) {
2170
2171                         this._x = quaternion.x;
2172                         this._y = quaternion.y;
2173                         this._z = quaternion.z;
2174                         this._w = quaternion.w;
2175
2176                         this.onChangeCallback();
2177
2178                         return this;
2179
2180                 },
2181
2182                 setFromEuler: function ( euler, update ) {
2183
2184                         if ( ! ( euler && euler.isEuler ) ) {
2185
2186                                 throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2187
2188                         }
2189
2190                         var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
2191
2192                         // http://www.mathworks.com/matlabcentral/fileexchange/
2193                         //      20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
2194                         //      content/SpinCalc.m
2195
2196                         var cos = Math.cos;
2197                         var sin = Math.sin;
2198
2199                         var c1 = cos( x / 2 );
2200                         var c2 = cos( y / 2 );
2201                         var c3 = cos( z / 2 );
2202
2203                         var s1 = sin( x / 2 );
2204                         var s2 = sin( y / 2 );
2205                         var s3 = sin( z / 2 );
2206
2207                         if ( order === 'XYZ' ) {
2208
2209                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2210                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2211                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2212                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2213
2214                         } else if ( order === 'YXZ' ) {
2215
2216                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2217                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2218                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2219                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2220
2221                         } else if ( order === 'ZXY' ) {
2222
2223                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2224                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2225                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2226                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2227
2228                         } else if ( order === 'ZYX' ) {
2229
2230                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2231                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2232                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2233                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2234
2235                         } else if ( order === 'YZX' ) {
2236
2237                                 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2238                                 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2239                                 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2240                                 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2241
2242                         } else if ( order === 'XZY' ) {
2243
2244                                 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2245                                 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2246                                 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2247                                 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2248
2249                         }
2250
2251                         if ( update !== false ) this.onChangeCallback();
2252
2253                         return this;
2254
2255                 },
2256
2257                 setFromAxisAngle: function ( axis, angle ) {
2258
2259                         // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
2260
2261                         // assumes axis is normalized
2262
2263                         var halfAngle = angle / 2, s = Math.sin( halfAngle );
2264
2265                         this._x = axis.x * s;
2266                         this._y = axis.y * s;
2267                         this._z = axis.z * s;
2268                         this._w = Math.cos( halfAngle );
2269
2270                         this.onChangeCallback();
2271
2272                         return this;
2273
2274                 },
2275
2276                 setFromRotationMatrix: function ( m ) {
2277
2278                         // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
2279
2280                         // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2281
2282                         var te = m.elements,
2283
2284                                 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2285                                 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2286                                 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
2287
2288                                 trace = m11 + m22 + m33,
2289                                 s;
2290
2291                         if ( trace > 0 ) {
2292
2293                                 s = 0.5 / Math.sqrt( trace + 1.0 );
2294
2295                                 this._w = 0.25 / s;
2296                                 this._x = ( m32 - m23 ) * s;
2297                                 this._y = ( m13 - m31 ) * s;
2298                                 this._z = ( m21 - m12 ) * s;
2299
2300                         } else if ( m11 > m22 && m11 > m33 ) {
2301
2302                                 s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
2303
2304                                 this._w = ( m32 - m23 ) / s;
2305                                 this._x = 0.25 * s;
2306                                 this._y = ( m12 + m21 ) / s;
2307                                 this._z = ( m13 + m31 ) / s;
2308
2309                         } else if ( m22 > m33 ) {
2310
2311                                 s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
2312
2313                                 this._w = ( m13 - m31 ) / s;
2314                                 this._x = ( m12 + m21 ) / s;
2315                                 this._y = 0.25 * s;
2316                                 this._z = ( m23 + m32 ) / s;
2317
2318                         } else {
2319
2320                                 s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
2321
2322                                 this._w = ( m21 - m12 ) / s;
2323                                 this._x = ( m13 + m31 ) / s;
2324                                 this._y = ( m23 + m32 ) / s;
2325                                 this._z = 0.25 * s;
2326
2327                         }
2328
2329                         this.onChangeCallback();
2330
2331                         return this;
2332
2333                 },
2334
2335                 setFromUnitVectors: function () {
2336
2337                         // assumes direction vectors vFrom and vTo are normalized
2338
2339                         var v1 = new Vector3();
2340                         var r;
2341
2342                         var EPS = 0.000001;
2343
2344                         return function setFromUnitVectors( vFrom, vTo ) {
2345
2346                                 if ( v1 === undefined ) v1 = new Vector3();
2347
2348                                 r = vFrom.dot( vTo ) + 1;
2349
2350                                 if ( r < EPS ) {
2351
2352                                         r = 0;
2353
2354                                         if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
2355
2356                                                 v1.set( - vFrom.y, vFrom.x, 0 );
2357
2358                                         } else {
2359
2360                                                 v1.set( 0, - vFrom.z, vFrom.y );
2361
2362                                         }
2363
2364                                 } else {
2365
2366                                         v1.crossVectors( vFrom, vTo );
2367
2368                                 }
2369
2370                                 this._x = v1.x;
2371                                 this._y = v1.y;
2372                                 this._z = v1.z;
2373                                 this._w = r;
2374
2375                                 return this.normalize();
2376
2377                         };
2378
2379                 }(),
2380
2381                 inverse: function () {
2382
2383                         return this.conjugate().normalize();
2384
2385                 },
2386
2387                 conjugate: function () {
2388
2389                         this._x *= - 1;
2390                         this._y *= - 1;
2391                         this._z *= - 1;
2392
2393                         this.onChangeCallback();
2394
2395                         return this;
2396
2397                 },
2398
2399                 dot: function ( v ) {
2400
2401                         return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
2402
2403                 },
2404
2405                 lengthSq: function () {
2406
2407                         return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
2408
2409                 },
2410
2411                 length: function () {
2412
2413                         return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
2414
2415                 },
2416
2417                 normalize: function () {
2418
2419                         var l = this.length();
2420
2421                         if ( l === 0 ) {
2422
2423                                 this._x = 0;
2424                                 this._y = 0;
2425                                 this._z = 0;
2426                                 this._w = 1;
2427
2428                         } else {
2429
2430                                 l = 1 / l;
2431
2432                                 this._x = this._x * l;
2433                                 this._y = this._y * l;
2434                                 this._z = this._z * l;
2435                                 this._w = this._w * l;
2436
2437                         }
2438
2439                         this.onChangeCallback();
2440
2441                         return this;
2442
2443                 },
2444
2445                 multiply: function ( q, p ) {
2446
2447                         if ( p !== undefined ) {
2448
2449                                 console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
2450                                 return this.multiplyQuaternions( q, p );
2451
2452                         }
2453
2454                         return this.multiplyQuaternions( this, q );
2455
2456                 },
2457
2458                 premultiply: function ( q ) {
2459
2460                         return this.multiplyQuaternions( q, this );
2461
2462                 },
2463
2464                 multiplyQuaternions: function ( a, b ) {
2465
2466                         // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
2467
2468                         var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
2469                         var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
2470
2471                         this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
2472                         this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
2473                         this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
2474                         this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
2475
2476                         this.onChangeCallback();
2477
2478                         return this;
2479
2480                 },
2481
2482                 slerp: function ( qb, t ) {
2483
2484                         if ( t === 0 ) return this;
2485                         if ( t === 1 ) return this.copy( qb );
2486
2487                         var x = this._x, y = this._y, z = this._z, w = this._w;
2488
2489                         // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
2490
2491                         var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
2492
2493                         if ( cosHalfTheta < 0 ) {
2494
2495                                 this._w = - qb._w;
2496                                 this._x = - qb._x;
2497                                 this._y = - qb._y;
2498                                 this._z = - qb._z;
2499
2500                                 cosHalfTheta = - cosHalfTheta;
2501
2502                         } else {
2503
2504                                 this.copy( qb );
2505
2506                         }
2507
2508                         if ( cosHalfTheta >= 1.0 ) {
2509
2510                                 this._w = w;
2511                                 this._x = x;
2512                                 this._y = y;
2513                                 this._z = z;
2514
2515                                 return this;
2516
2517                         }
2518
2519                         var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
2520
2521                         if ( Math.abs( sinHalfTheta ) < 0.001 ) {
2522
2523                                 this._w = 0.5 * ( w + this._w );
2524                                 this._x = 0.5 * ( x + this._x );
2525                                 this._y = 0.5 * ( y + this._y );
2526                                 this._z = 0.5 * ( z + this._z );
2527
2528                                 return this;
2529
2530                         }
2531
2532                         var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
2533                         var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
2534                                 ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
2535
2536                         this._w = ( w * ratioA + this._w * ratioB );
2537                         this._x = ( x * ratioA + this._x * ratioB );
2538                         this._y = ( y * ratioA + this._y * ratioB );
2539                         this._z = ( z * ratioA + this._z * ratioB );
2540
2541                         this.onChangeCallback();
2542
2543                         return this;
2544
2545                 },
2546
2547                 equals: function ( quaternion ) {
2548
2549                         return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
2550
2551                 },
2552
2553                 fromArray: function ( array, offset ) {
2554
2555                         if ( offset === undefined ) offset = 0;
2556
2557                         this._x = array[ offset ];
2558                         this._y = array[ offset + 1 ];
2559                         this._z = array[ offset + 2 ];
2560                         this._w = array[ offset + 3 ];
2561
2562                         this.onChangeCallback();
2563
2564                         return this;
2565
2566                 },
2567
2568                 toArray: function ( array, offset ) {
2569
2570                         if ( array === undefined ) array = [];
2571                         if ( offset === undefined ) offset = 0;
2572
2573                         array[ offset ] = this._x;
2574                         array[ offset + 1 ] = this._y;
2575                         array[ offset + 2 ] = this._z;
2576                         array[ offset + 3 ] = this._w;
2577
2578                         return array;
2579
2580                 },
2581
2582                 onChange: function ( callback ) {
2583
2584                         this.onChangeCallback = callback;
2585
2586                         return this;
2587
2588                 },
2589
2590                 onChangeCallback: function () {}
2591
2592         } );
2593
2594         /**
2595          * @author mrdoob / http://mrdoob.com/
2596          * @author kile / http://kile.stravaganza.org/
2597          * @author philogb / http://blog.thejit.org/
2598          * @author mikael emtinger / http://gomo.se/
2599          * @author egraether / http://egraether.com/
2600          * @author WestLangley / http://github.com/WestLangley
2601          */
2602
2603         function Vector3( x, y, z ) {
2604
2605                 this.x = x || 0;
2606                 this.y = y || 0;
2607                 this.z = z || 0;
2608
2609         }
2610
2611         Object.assign( Vector3.prototype, {
2612
2613                 isVector3: true,
2614
2615                 set: function ( x, y, z ) {
2616
2617                         this.x = x;
2618                         this.y = y;
2619                         this.z = z;
2620
2621                         return this;
2622
2623                 },
2624
2625                 setScalar: function ( scalar ) {
2626
2627                         this.x = scalar;
2628                         this.y = scalar;
2629                         this.z = scalar;
2630
2631                         return this;
2632
2633                 },
2634
2635                 setX: function ( x ) {
2636
2637                         this.x = x;
2638
2639                         return this;
2640
2641                 },
2642
2643                 setY: function ( y ) {
2644
2645                         this.y = y;
2646
2647                         return this;
2648
2649                 },
2650
2651                 setZ: function ( z ) {
2652
2653                         this.z = z;
2654
2655                         return this;
2656
2657                 },
2658
2659                 setComponent: function ( index, value ) {
2660
2661                         switch ( index ) {
2662
2663                                 case 0: this.x = value; break;
2664                                 case 1: this.y = value; break;
2665                                 case 2: this.z = value; break;
2666                                 default: throw new Error( 'index is out of range: ' + index );
2667
2668                         }
2669
2670                         return this;
2671
2672                 },
2673
2674                 getComponent: function ( index ) {
2675
2676                         switch ( index ) {
2677
2678                                 case 0: return this.x;
2679                                 case 1: return this.y;
2680                                 case 2: return this.z;
2681                                 default: throw new Error( 'index is out of range: ' + index );
2682
2683                         }
2684
2685                 },
2686
2687                 clone: function () {
2688
2689                         return new this.constructor( this.x, this.y, this.z );
2690
2691                 },
2692
2693                 copy: function ( v ) {
2694
2695                         this.x = v.x;
2696                         this.y = v.y;
2697                         this.z = v.z;
2698
2699                         return this;
2700
2701                 },
2702
2703                 add: function ( v, w ) {
2704
2705                         if ( w !== undefined ) {
2706
2707                                 console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
2708                                 return this.addVectors( v, w );
2709
2710                         }
2711
2712                         this.x += v.x;
2713                         this.y += v.y;
2714                         this.z += v.z;
2715
2716                         return this;
2717
2718                 },
2719
2720                 addScalar: function ( s ) {
2721
2722                         this.x += s;
2723                         this.y += s;
2724                         this.z += s;
2725
2726                         return this;
2727
2728                 },
2729
2730                 addVectors: function ( a, b ) {
2731
2732                         this.x = a.x + b.x;
2733                         this.y = a.y + b.y;
2734                         this.z = a.z + b.z;
2735
2736                         return this;
2737
2738                 },
2739
2740                 addScaledVector: function ( v, s ) {
2741
2742                         this.x += v.x * s;
2743                         this.y += v.y * s;
2744                         this.z += v.z * s;
2745
2746                         return this;
2747
2748                 },
2749
2750                 sub: function ( v, w ) {
2751
2752                         if ( w !== undefined ) {
2753
2754                                 console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
2755                                 return this.subVectors( v, w );
2756
2757                         }
2758
2759                         this.x -= v.x;
2760                         this.y -= v.y;
2761                         this.z -= v.z;
2762
2763                         return this;
2764
2765                 },
2766
2767                 subScalar: function ( s ) {
2768
2769                         this.x -= s;
2770                         this.y -= s;
2771                         this.z -= s;
2772
2773                         return this;
2774
2775                 },
2776
2777                 subVectors: function ( a, b ) {
2778
2779                         this.x = a.x - b.x;
2780                         this.y = a.y - b.y;
2781                         this.z = a.z - b.z;
2782
2783                         return this;
2784
2785                 },
2786
2787                 multiply: function ( v, w ) {
2788
2789                         if ( w !== undefined ) {
2790
2791                                 console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
2792                                 return this.multiplyVectors( v, w );
2793
2794                         }
2795
2796                         this.x *= v.x;
2797                         this.y *= v.y;
2798                         this.z *= v.z;
2799
2800                         return this;
2801
2802                 },
2803
2804                 multiplyScalar: function ( scalar ) {
2805
2806                         this.x *= scalar;
2807                         this.y *= scalar;
2808                         this.z *= scalar;
2809
2810                         return this;
2811
2812                 },
2813
2814                 multiplyVectors: function ( a, b ) {
2815
2816                         this.x = a.x * b.x;
2817                         this.y = a.y * b.y;
2818                         this.z = a.z * b.z;
2819
2820                         return this;
2821
2822                 },
2823
2824                 applyEuler: function () {
2825
2826                         var quaternion = new Quaternion();
2827
2828                         return function applyEuler( euler ) {
2829
2830                                 if ( ! ( euler && euler.isEuler ) ) {
2831
2832                                         console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2833
2834                                 }
2835
2836                                 return this.applyQuaternion( quaternion.setFromEuler( euler ) );
2837
2838                         };
2839
2840                 }(),
2841
2842                 applyAxisAngle: function () {
2843
2844                         var quaternion = new Quaternion();
2845
2846                         return function applyAxisAngle( axis, angle ) {
2847
2848                                 return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
2849
2850                         };
2851
2852                 }(),
2853
2854                 applyMatrix3: function ( m ) {
2855
2856                         var x = this.x, y = this.y, z = this.z;
2857                         var e = m.elements;
2858
2859                         this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
2860                         this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
2861                         this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
2862
2863                         return this;
2864
2865                 },
2866
2867                 applyMatrix4: function ( m ) {
2868
2869                         var x = this.x, y = this.y, z = this.z;
2870                         var e = m.elements;
2871
2872                         var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
2873
2874                         this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ]  * z + e[ 12 ] ) * w;
2875                         this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ]  * z + e[ 13 ] ) * w;
2876                         this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
2877
2878                         return this;
2879
2880                 },
2881
2882                 applyQuaternion: function ( q ) {
2883
2884                         var x = this.x, y = this.y, z = this.z;
2885                         var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
2886
2887                         // calculate quat * vector
2888
2889                         var ix =  qw * x + qy * z - qz * y;
2890                         var iy =  qw * y + qz * x - qx * z;
2891                         var iz =  qw * z + qx * y - qy * x;
2892                         var iw = - qx * x - qy * y - qz * z;
2893
2894                         // calculate result * inverse quat
2895
2896                         this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
2897                         this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
2898                         this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
2899
2900                         return this;
2901
2902                 },
2903
2904                 project: function () {
2905
2906                         var matrix = new Matrix4();
2907
2908                         return function project( camera ) {
2909
2910                                 matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
2911                                 return this.applyMatrix4( matrix );
2912
2913                         };
2914
2915                 }(),
2916
2917                 unproject: function () {
2918
2919                         var matrix = new Matrix4();
2920
2921                         return function unproject( camera ) {
2922
2923                                 matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
2924                                 return this.applyMatrix4( matrix );
2925
2926                         };
2927
2928                 }(),
2929
2930                 transformDirection: function ( m ) {
2931
2932                         // input: THREE.Matrix4 affine matrix
2933                         // vector interpreted as a direction
2934
2935                         var x = this.x, y = this.y, z = this.z;
2936                         var e = m.elements;
2937
2938                         this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ]  * z;
2939                         this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ]  * z;
2940                         this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
2941
2942                         return this.normalize();
2943
2944                 },
2945
2946                 divide: function ( v ) {
2947
2948                         this.x /= v.x;
2949                         this.y /= v.y;
2950                         this.z /= v.z;
2951
2952                         return this;
2953
2954                 },
2955
2956                 divideScalar: function ( scalar ) {
2957
2958                         return this.multiplyScalar( 1 / scalar );
2959
2960                 },
2961
2962                 min: function ( v ) {
2963
2964                         this.x = Math.min( this.x, v.x );
2965                         this.y = Math.min( this.y, v.y );
2966                         this.z = Math.min( this.z, v.z );
2967
2968                         return this;
2969
2970                 },
2971
2972                 max: function ( v ) {
2973
2974                         this.x = Math.max( this.x, v.x );
2975                         this.y = Math.max( this.y, v.y );
2976                         this.z = Math.max( this.z, v.z );
2977
2978                         return this;
2979
2980                 },
2981
2982                 clamp: function ( min, max ) {
2983
2984                         // assumes min < max, componentwise
2985
2986                         this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2987                         this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2988                         this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2989
2990                         return this;
2991
2992                 },
2993
2994                 clampScalar: function () {
2995
2996                         var min = new Vector3();
2997                         var max = new Vector3();
2998
2999                         return function clampScalar( minVal, maxVal ) {
3000
3001                                 min.set( minVal, minVal, minVal );
3002                                 max.set( maxVal, maxVal, maxVal );
3003
3004                                 return this.clamp( min, max );
3005
3006                         };
3007
3008                 }(),
3009
3010                 clampLength: function ( min, max ) {
3011
3012                         var length = this.length();
3013
3014                         return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
3015
3016                 },
3017
3018                 floor: function () {
3019
3020                         this.x = Math.floor( this.x );
3021                         this.y = Math.floor( this.y );
3022                         this.z = Math.floor( this.z );
3023
3024                         return this;
3025
3026                 },
3027
3028                 ceil: function () {
3029
3030                         this.x = Math.ceil( this.x );
3031                         this.y = Math.ceil( this.y );
3032                         this.z = Math.ceil( this.z );
3033
3034                         return this;
3035
3036                 },
3037
3038                 round: function () {
3039
3040                         this.x = Math.round( this.x );
3041                         this.y = Math.round( this.y );
3042                         this.z = Math.round( this.z );
3043
3044                         return this;
3045
3046                 },
3047
3048                 roundToZero: function () {
3049
3050                         this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
3051                         this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
3052                         this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
3053
3054                         return this;
3055
3056                 },
3057
3058                 negate: function () {
3059
3060                         this.x = - this.x;
3061                         this.y = - this.y;
3062                         this.z = - this.z;
3063
3064                         return this;
3065
3066                 },
3067
3068                 dot: function ( v ) {
3069
3070                         return this.x * v.x + this.y * v.y + this.z * v.z;
3071
3072                 },
3073
3074                 // TODO lengthSquared?
3075
3076                 lengthSq: function () {
3077
3078                         return this.x * this.x + this.y * this.y + this.z * this.z;
3079
3080                 },
3081
3082                 length: function () {
3083
3084                         return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
3085
3086                 },
3087
3088                 lengthManhattan: function () {
3089
3090                         return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
3091
3092                 },
3093
3094                 normalize: function () {
3095
3096                         return this.divideScalar( this.length() || 1 );
3097
3098                 },
3099
3100                 setLength: function ( length ) {
3101
3102                         return this.normalize().multiplyScalar( length );
3103
3104                 },
3105
3106                 lerp: function ( v, alpha ) {
3107
3108                         this.x += ( v.x - this.x ) * alpha;
3109                         this.y += ( v.y - this.y ) * alpha;
3110                         this.z += ( v.z - this.z ) * alpha;
3111
3112                         return this;
3113
3114                 },
3115
3116                 lerpVectors: function ( v1, v2, alpha ) {
3117
3118                         return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
3119
3120                 },
3121
3122                 cross: function ( v, w ) {
3123
3124                         if ( w !== undefined ) {
3125
3126                                 console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
3127                                 return this.crossVectors( v, w );
3128
3129                         }
3130
3131                         var x = this.x, y = this.y, z = this.z;
3132
3133                         this.x = y * v.z - z * v.y;
3134                         this.y = z * v.x - x * v.z;
3135                         this.z = x * v.y - y * v.x;
3136
3137                         return this;
3138
3139                 },
3140
3141                 crossVectors: function ( a, b ) {
3142
3143                         var ax = a.x, ay = a.y, az = a.z;
3144                         var bx = b.x, by = b.y, bz = b.z;
3145
3146                         this.x = ay * bz - az * by;
3147                         this.y = az * bx - ax * bz;
3148                         this.z = ax * by - ay * bx;
3149
3150                         return this;
3151
3152                 },
3153
3154                 projectOnVector: function ( vector ) {
3155
3156                         var scalar = vector.dot( this ) / vector.lengthSq();
3157
3158                         return this.copy( vector ).multiplyScalar( scalar );
3159
3160                 },
3161
3162                 projectOnPlane: function () {
3163
3164                         var v1 = new Vector3();
3165
3166                         return function projectOnPlane( planeNormal ) {
3167
3168                                 v1.copy( this ).projectOnVector( planeNormal );
3169
3170                                 return this.sub( v1 );
3171
3172                         };
3173
3174                 }(),
3175
3176                 reflect: function () {
3177
3178                         // reflect incident vector off plane orthogonal to normal
3179                         // normal is assumed to have unit length
3180
3181                         var v1 = new Vector3();
3182
3183                         return function reflect( normal ) {
3184
3185                                 return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
3186
3187                         };
3188
3189                 }(),
3190
3191                 angleTo: function ( v ) {
3192
3193                         var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
3194
3195                         // clamp, to handle numerical problems
3196
3197                         return Math.acos( _Math.clamp( theta, - 1, 1 ) );
3198
3199                 },
3200
3201                 distanceTo: function ( v ) {
3202
3203                         return Math.sqrt( this.distanceToSquared( v ) );
3204
3205                 },
3206
3207                 distanceToSquared: function ( v ) {
3208
3209                         var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
3210
3211                         return dx * dx + dy * dy + dz * dz;
3212
3213                 },
3214
3215                 distanceToManhattan: function ( v ) {
3216
3217                         return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
3218
3219                 },
3220
3221                 setFromSpherical: function ( s ) {
3222
3223                         var sinPhiRadius = Math.sin( s.phi ) * s.radius;
3224
3225                         this.x = sinPhiRadius * Math.sin( s.theta );
3226                         this.y = Math.cos( s.phi ) * s.radius;
3227                         this.z = sinPhiRadius * Math.cos( s.theta );
3228
3229                         return this;
3230
3231                 },
3232
3233                 setFromCylindrical: function ( c ) {
3234
3235                         this.x = c.radius * Math.sin( c.theta );
3236                         this.y = c.y;
3237                         this.z = c.radius * Math.cos( c.theta );
3238
3239                         return this;
3240
3241                 },
3242
3243                 setFromMatrixPosition: function ( m ) {
3244
3245                         var e = m.elements;
3246
3247                         this.x = e[ 12 ];
3248                         this.y = e[ 13 ];
3249                         this.z = e[ 14 ];
3250
3251                         return this;
3252
3253                 },
3254
3255                 setFromMatrixScale: function ( m ) {
3256
3257                         var sx = this.setFromMatrixColumn( m, 0 ).length();
3258                         var sy = this.setFromMatrixColumn( m, 1 ).length();
3259                         var sz = this.setFromMatrixColumn( m, 2 ).length();
3260
3261                         this.x = sx;
3262                         this.y = sy;
3263                         this.z = sz;
3264
3265                         return this;
3266
3267                 },
3268
3269                 setFromMatrixColumn: function ( m, index ) {
3270
3271                         return this.fromArray( m.elements, index * 4 );
3272
3273                 },
3274
3275                 equals: function ( v ) {
3276
3277                         return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
3278
3279                 },
3280
3281                 fromArray: function ( array, offset ) {
3282
3283                         if ( offset === undefined ) offset = 0;
3284
3285                         this.x = array[ offset ];
3286                         this.y = array[ offset + 1 ];
3287                         this.z = array[ offset + 2 ];
3288
3289                         return this;
3290
3291                 },
3292
3293                 toArray: function ( array, offset ) {
3294
3295                         if ( array === undefined ) array = [];
3296                         if ( offset === undefined ) offset = 0;
3297
3298                         array[ offset ] = this.x;
3299                         array[ offset + 1 ] = this.y;
3300                         array[ offset + 2 ] = this.z;
3301
3302                         return array;
3303
3304                 },
3305
3306                 fromBufferAttribute: function ( attribute, index, offset ) {
3307
3308                         if ( offset !== undefined ) {
3309
3310                                 console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
3311
3312                         }
3313
3314                         this.x = attribute.getX( index );
3315                         this.y = attribute.getY( index );
3316                         this.z = attribute.getZ( index );
3317
3318                         return this;
3319
3320                 }
3321
3322         } );
3323
3324         /**
3325          * @author mrdoob / http://mrdoob.com/
3326          * @author supereggbert / http://www.paulbrunt.co.uk/
3327          * @author philogb / http://blog.thejit.org/
3328          * @author jordi_ros / http://plattsoft.com
3329          * @author D1plo1d / http://github.com/D1plo1d
3330          * @author alteredq / http://alteredqualia.com/
3331          * @author mikael emtinger / http://gomo.se/
3332          * @author timknip / http://www.floorplanner.com/
3333          * @author bhouston / http://clara.io
3334          * @author WestLangley / http://github.com/WestLangley
3335          */
3336
3337         function Matrix4() {
3338
3339                 this.elements = [
3340
3341                         1, 0, 0, 0,
3342                         0, 1, 0, 0,
3343                         0, 0, 1, 0,
3344                         0, 0, 0, 1
3345
3346                 ];
3347
3348                 if ( arguments.length > 0 ) {
3349
3350                         console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
3351
3352                 }
3353
3354         }
3355
3356         Object.assign( Matrix4.prototype, {
3357
3358                 isMatrix4: true,
3359
3360                 set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
3361
3362                         var te = this.elements;
3363
3364                         te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
3365                         te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
3366                         te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
3367                         te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
3368
3369                         return this;
3370
3371                 },
3372
3373                 identity: function () {
3374
3375                         this.set(
3376
3377                                 1, 0, 0, 0,
3378                                 0, 1, 0, 0,
3379                                 0, 0, 1, 0,
3380                                 0, 0, 0, 1
3381
3382                         );
3383
3384                         return this;
3385
3386                 },
3387
3388                 clone: function () {
3389
3390                         return new Matrix4().fromArray( this.elements );
3391
3392                 },
3393
3394                 copy: function ( m ) {
3395
3396                         var te = this.elements;
3397                         var me = m.elements;
3398
3399                         te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
3400                         te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
3401                         te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
3402                         te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
3403
3404                         return this;
3405
3406                 },
3407
3408                 copyPosition: function ( m ) {
3409
3410                         var te = this.elements, me = m.elements;
3411
3412                         te[ 12 ] = me[ 12 ];
3413                         te[ 13 ] = me[ 13 ];
3414                         te[ 14 ] = me[ 14 ];
3415
3416                         return this;
3417
3418                 },
3419
3420                 extractBasis: function ( xAxis, yAxis, zAxis ) {
3421
3422                         xAxis.setFromMatrixColumn( this, 0 );
3423                         yAxis.setFromMatrixColumn( this, 1 );
3424                         zAxis.setFromMatrixColumn( this, 2 );
3425
3426                         return this;
3427
3428                 },
3429
3430                 makeBasis: function ( xAxis, yAxis, zAxis ) {
3431
3432                         this.set(
3433                                 xAxis.x, yAxis.x, zAxis.x, 0,
3434                                 xAxis.y, yAxis.y, zAxis.y, 0,
3435                                 xAxis.z, yAxis.z, zAxis.z, 0,
3436                                 0,       0,       0,       1
3437                         );
3438
3439                         return this;
3440
3441                 },
3442
3443                 extractRotation: function () {
3444
3445                         var v1 = new Vector3();
3446
3447                         return function extractRotation( m ) {
3448
3449                                 var te = this.elements;
3450                                 var me = m.elements;
3451
3452                                 var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
3453                                 var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
3454                                 var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
3455
3456                                 te[ 0 ] = me[ 0 ] * scaleX;
3457                                 te[ 1 ] = me[ 1 ] * scaleX;
3458                                 te[ 2 ] = me[ 2 ] * scaleX;
3459
3460                                 te[ 4 ] = me[ 4 ] * scaleY;
3461                                 te[ 5 ] = me[ 5 ] * scaleY;
3462                                 te[ 6 ] = me[ 6 ] * scaleY;
3463
3464                                 te[ 8 ] = me[ 8 ] * scaleZ;
3465                                 te[ 9 ] = me[ 9 ] * scaleZ;
3466                                 te[ 10 ] = me[ 10 ] * scaleZ;
3467
3468                                 return this;
3469
3470                         };
3471
3472                 }(),
3473
3474                 makeRotationFromEuler: function ( euler ) {
3475
3476                         if ( ! ( euler && euler.isEuler ) ) {
3477
3478                                 console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
3479
3480                         }
3481
3482                         var te = this.elements;
3483
3484                         var x = euler.x, y = euler.y, z = euler.z;
3485                         var a = Math.cos( x ), b = Math.sin( x );
3486                         var c = Math.cos( y ), d = Math.sin( y );
3487                         var e = Math.cos( z ), f = Math.sin( z );
3488
3489                         if ( euler.order === 'XYZ' ) {
3490
3491                                 var ae = a * e, af = a * f, be = b * e, bf = b * f;
3492
3493                                 te[ 0 ] = c * e;
3494                                 te[ 4 ] = - c * f;
3495                                 te[ 8 ] = d;
3496
3497                                 te[ 1 ] = af + be * d;
3498                                 te[ 5 ] = ae - bf * d;
3499                                 te[ 9 ] = - b * c;
3500
3501                                 te[ 2 ] = bf - ae * d;
3502                                 te[ 6 ] = be + af * d;
3503                                 te[ 10 ] = a * c;
3504
3505                         } else if ( euler.order === 'YXZ' ) {
3506
3507                                 var ce = c * e, cf = c * f, de = d * e, df = d * f;
3508
3509                                 te[ 0 ] = ce + df * b;
3510                                 te[ 4 ] = de * b - cf;
3511                                 te[ 8 ] = a * d;
3512
3513                                 te[ 1 ] = a * f;
3514                                 te[ 5 ] = a * e;
3515                                 te[ 9 ] = - b;
3516
3517                                 te[ 2 ] = cf * b - de;
3518                                 te[ 6 ] = df + ce * b;
3519                                 te[ 10 ] = a * c;
3520
3521                         } else if ( euler.order === 'ZXY' ) {
3522
3523                                 var ce = c * e, cf = c * f, de = d * e, df = d * f;
3524
3525                                 te[ 0 ] = ce - df * b;
3526                                 te[ 4 ] = - a * f;
3527                                 te[ 8 ] = de + cf * b;
3528
3529                                 te[ 1 ] = cf + de * b;
3530                                 te[ 5 ] = a * e;
3531                                 te[ 9 ] = df - ce * b;
3532
3533                                 te[ 2 ] = - a * d;
3534                                 te[ 6 ] = b;
3535                                 te[ 10 ] = a * c;
3536
3537                         } else if ( euler.order === 'ZYX' ) {
3538
3539                                 var ae = a * e, af = a * f, be = b * e, bf = b * f;
3540
3541                                 te[ 0 ] = c * e;
3542                                 te[ 4 ] = be * d - af;
3543                                 te[ 8 ] = ae * d + bf;
3544
3545                                 te[ 1 ] = c * f;
3546                                 te[ 5 ] = bf * d + ae;
3547                                 te[ 9 ] = af * d - be;
3548
3549                                 te[ 2 ] = - d;
3550                                 te[ 6 ] = b * c;
3551                                 te[ 10 ] = a * c;
3552
3553                         } else if ( euler.order === 'YZX' ) {
3554
3555                                 var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
3556
3557                                 te[ 0 ] = c * e;
3558                                 te[ 4 ] = bd - ac * f;
3559                                 te[ 8 ] = bc * f + ad;
3560
3561                                 te[ 1 ] = f;
3562                                 te[ 5 ] = a * e;
3563                                 te[ 9 ] = - b * e;
3564
3565                                 te[ 2 ] = - d * e;
3566                                 te[ 6 ] = ad * f + bc;
3567                                 te[ 10 ] = ac - bd * f;
3568
3569                         } else if ( euler.order === 'XZY' ) {
3570
3571                                 var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
3572
3573                                 te[ 0 ] = c * e;
3574                                 te[ 4 ] = - f;
3575                                 te[ 8 ] = d * e;
3576
3577                                 te[ 1 ] = ac * f + bd;
3578                                 te[ 5 ] = a * e;
3579                                 te[ 9 ] = ad * f - bc;
3580
3581                                 te[ 2 ] = bc * f - ad;
3582                                 te[ 6 ] = b * e;
3583                                 te[ 10 ] = bd * f + ac;
3584
3585                         }
3586
3587                         // last column
3588                         te[ 3 ] = 0;
3589                         te[ 7 ] = 0;
3590                         te[ 11 ] = 0;
3591
3592                         // bottom row
3593                         te[ 12 ] = 0;
3594                         te[ 13 ] = 0;
3595                         te[ 14 ] = 0;
3596                         te[ 15 ] = 1;
3597
3598                         return this;
3599
3600                 },
3601
3602                 makeRotationFromQuaternion: function ( q ) {
3603
3604                         var te = this.elements;
3605
3606                         var x = q._x, y = q._y, z = q._z, w = q._w;
3607                         var x2 = x + x, y2 = y + y, z2 = z + z;
3608                         var xx = x * x2, xy = x * y2, xz = x * z2;
3609                         var yy = y * y2, yz = y * z2, zz = z * z2;
3610                         var wx = w * x2, wy = w * y2, wz = w * z2;
3611
3612                         te[ 0 ] = 1 - ( yy + zz );
3613                         te[ 4 ] = xy - wz;
3614                         te[ 8 ] = xz + wy;
3615
3616                         te[ 1 ] = xy + wz;
3617                         te[ 5 ] = 1 - ( xx + zz );
3618                         te[ 9 ] = yz - wx;
3619
3620                         te[ 2 ] = xz - wy;
3621                         te[ 6 ] = yz + wx;
3622                         te[ 10 ] = 1 - ( xx + yy );
3623
3624                         // last column
3625                         te[ 3 ] = 0;
3626                         te[ 7 ] = 0;
3627                         te[ 11 ] = 0;
3628
3629                         // bottom row
3630                         te[ 12 ] = 0;
3631                         te[ 13 ] = 0;
3632                         te[ 14 ] = 0;
3633                         te[ 15 ] = 1;
3634
3635                         return this;
3636
3637                 },
3638
3639                 lookAt: function () {
3640
3641                         var x = new Vector3();
3642                         var y = new Vector3();
3643                         var z = new Vector3();
3644
3645                         return function lookAt( eye, target, up ) {
3646
3647                                 var te = this.elements;
3648
3649                                 z.subVectors( eye, target );
3650
3651                                 if ( z.lengthSq() === 0 ) {
3652
3653                                         // eye and target are in the same position
3654
3655                                         z.z = 1;
3656
3657                                 }
3658
3659                                 z.normalize();
3660                                 x.crossVectors( up, z );
3661
3662                                 if ( x.lengthSq() === 0 ) {
3663
3664                                         // up and z are parallel
3665
3666                                         if ( Math.abs( up.z ) === 1 ) {
3667
3668                                                 z.x += 0.0001;
3669
3670                                         } else {
3671
3672                                                 z.z += 0.0001;
3673
3674                                         }
3675
3676                                         z.normalize();
3677                                         x.crossVectors( up, z );
3678
3679                                 }
3680
3681                                 x.normalize();
3682                                 y.crossVectors( z, x );
3683
3684                                 te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
3685                                 te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
3686                                 te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
3687
3688                                 return this;
3689
3690                         };
3691
3692                 }(),
3693
3694                 multiply: function ( m, n ) {
3695
3696                         if ( n !== undefined ) {
3697
3698                                 console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
3699                                 return this.multiplyMatrices( m, n );
3700
3701                         }
3702
3703                         return this.multiplyMatrices( this, m );
3704
3705                 },
3706
3707                 premultiply: function ( m ) {
3708
3709                         return this.multiplyMatrices( m, this );
3710
3711                 },
3712
3713                 multiplyMatrices: function ( a, b ) {
3714
3715                         var ae = a.elements;
3716                         var be = b.elements;
3717                         var te = this.elements;
3718
3719                         var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
3720                         var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
3721                         var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
3722                         var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
3723
3724                         var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
3725                         var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
3726                         var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
3727                         var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
3728
3729                         te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
3730                         te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
3731                         te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
3732                         te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
3733
3734                         te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
3735                         te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
3736                         te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
3737                         te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
3738
3739                         te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
3740                         te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
3741                         te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
3742                         te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
3743
3744                         te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
3745                         te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
3746                         te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
3747                         te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
3748
3749                         return this;
3750
3751                 },
3752
3753                 multiplyScalar: function ( s ) {
3754
3755                         var te = this.elements;
3756
3757                         te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
3758                         te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
3759                         te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
3760                         te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
3761
3762                         return this;
3763
3764                 },
3765
3766                 applyToBufferAttribute: function () {
3767
3768                         var v1 = new Vector3();
3769
3770                         return function applyToBufferAttribute( attribute ) {
3771
3772                                 for ( var i = 0, l = attribute.count; i < l; i ++ ) {
3773
3774                                         v1.x = attribute.getX( i );
3775                                         v1.y = attribute.getY( i );
3776                                         v1.z = attribute.getZ( i );
3777
3778                                         v1.applyMatrix4( this );
3779
3780                                         attribute.setXYZ( i, v1.x, v1.y, v1.z );
3781
3782                                 }
3783
3784                                 return attribute;
3785
3786                         };
3787
3788                 }(),
3789
3790                 determinant: function () {
3791
3792                         var te = this.elements;
3793
3794                         var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
3795                         var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
3796                         var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
3797                         var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
3798
3799                         //TODO: make this more efficient
3800                         //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
3801
3802                         return (
3803                                 n41 * (
3804                                         + n14 * n23 * n32
3805                                          - n13 * n24 * n32
3806                                          - n14 * n22 * n33
3807                                          + n12 * n24 * n33
3808                                          + n13 * n22 * n34
3809                                          - n12 * n23 * n34
3810                                 ) +
3811                                 n42 * (
3812                                         + n11 * n23 * n34
3813                                          - n11 * n24 * n33
3814                                          + n14 * n21 * n33
3815                                          - n13 * n21 * n34
3816                                          + n13 * n24 * n31
3817                                          - n14 * n23 * n31
3818                                 ) +
3819                                 n43 * (
3820                                         + n11 * n24 * n32
3821                                          - n11 * n22 * n34
3822                                          - n14 * n21 * n32
3823                                          + n12 * n21 * n34
3824                                          + n14 * n22 * n31
3825                                          - n12 * n24 * n31
3826                                 ) +
3827                                 n44 * (
3828                                         - n13 * n22 * n31
3829                                          - n11 * n23 * n32
3830                                          + n11 * n22 * n33
3831                                          + n13 * n21 * n32
3832                                          - n12 * n21 * n33
3833                                          + n12 * n23 * n31
3834                                 )
3835
3836                         );
3837
3838                 },
3839
3840                 transpose: function () {
3841
3842                         var te = this.elements;
3843                         var tmp;
3844
3845                         tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
3846                         tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
3847                         tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
3848
3849                         tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
3850                         tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
3851                         tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
3852
3853                         return this;
3854
3855                 },
3856
3857                 setPosition: function ( v ) {
3858
3859                         var te = this.elements;
3860
3861                         te[ 12 ] = v.x;
3862                         te[ 13 ] = v.y;
3863                         te[ 14 ] = v.z;
3864
3865                         return this;
3866
3867                 },
3868
3869                 getInverse: function ( m, throwOnDegenerate ) {
3870
3871                         // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
3872                         var te = this.elements,
3873                                 me = m.elements,
3874
3875                                 n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
3876                                 n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
3877                                 n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
3878                                 n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
3879
3880                                 t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
3881                                 t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
3882                                 t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
3883                                 t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
3884
3885                         var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
3886
3887                         if ( det === 0 ) {
3888
3889                                 var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0";
3890
3891                                 if ( throwOnDegenerate === true ) {
3892
3893                                         throw new Error( msg );
3894
3895                                 } else {
3896
3897                                         console.warn( msg );
3898
3899                                 }
3900
3901                                 return this.identity();
3902
3903                         }
3904
3905                         var detInv = 1 / det;
3906
3907                         te[ 0 ] = t11 * detInv;
3908                         te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
3909                         te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
3910                         te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
3911
3912                         te[ 4 ] = t12 * detInv;
3913                         te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
3914                         te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
3915                         te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
3916
3917                         te[ 8 ] = t13 * detInv;
3918                         te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
3919                         te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
3920                         te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
3921
3922                         te[ 12 ] = t14 * detInv;
3923                         te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
3924                         te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
3925                         te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
3926
3927                         return this;
3928
3929                 },
3930
3931                 scale: function ( v ) {
3932
3933                         var te = this.elements;
3934                         var x = v.x, y = v.y, z = v.z;
3935
3936                         te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
3937                         te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
3938                         te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
3939                         te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
3940
3941                         return this;
3942
3943                 },
3944
3945                 getMaxScaleOnAxis: function () {
3946
3947                         var te = this.elements;
3948
3949                         var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
3950                         var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
3951                         var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
3952
3953                         return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
3954
3955                 },
3956
3957                 makeTranslation: function ( x, y, z ) {
3958
3959                         this.set(
3960
3961                                 1, 0, 0, x,
3962                                 0, 1, 0, y,
3963                                 0, 0, 1, z,
3964                                 0, 0, 0, 1
3965
3966                         );
3967
3968                         return this;
3969
3970                 },
3971
3972                 makeRotationX: function ( theta ) {
3973
3974                         var c = Math.cos( theta ), s = Math.sin( theta );
3975
3976                         this.set(
3977
3978                                 1, 0,  0, 0,
3979                                 0, c, - s, 0,
3980                                 0, s,  c, 0,
3981                                 0, 0,  0, 1
3982
3983                         );
3984
3985                         return this;
3986
3987                 },
3988
3989                 makeRotationY: function ( theta ) {
3990
3991                         var c = Math.cos( theta ), s = Math.sin( theta );
3992
3993                         this.set(
3994
3995                                  c, 0, s, 0,
3996                                  0, 1, 0, 0,
3997                                 - s, 0, c, 0,
3998                                  0, 0, 0, 1
3999
4000                         );
4001
4002                         return this;
4003
4004                 },
4005
4006                 makeRotationZ: function ( theta ) {
4007
4008                         var c = Math.cos( theta ), s = Math.sin( theta );
4009
4010                         this.set(
4011
4012                                 c, - s, 0, 0,
4013                                 s,  c, 0, 0,
4014                                 0,  0, 1, 0,
4015                                 0,  0, 0, 1
4016
4017                         );
4018
4019                         return this;
4020
4021                 },
4022
4023                 makeRotationAxis: function ( axis, angle ) {
4024
4025                         // Based on http://www.gamedev.net/reference/articles/article1199.asp
4026
4027                         var c = Math.cos( angle );
4028                         var s = Math.sin( angle );
4029                         var t = 1 - c;
4030                         var x = axis.x, y = axis.y, z = axis.z;
4031                         var tx = t * x, ty = t * y;
4032
4033                         this.set(
4034
4035                                 tx * x + c, tx * y - s * z, tx * z + s * y, 0,
4036                                 tx * y + s * z, ty * y + c, ty * z - s * x, 0,
4037                                 tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
4038                                 0, 0, 0, 1
4039
4040                         );
4041
4042                          return this;
4043
4044                 },
4045
4046                 makeScale: function ( x, y, z ) {
4047
4048                         this.set(
4049
4050                                 x, 0, 0, 0,
4051                                 0, y, 0, 0,
4052                                 0, 0, z, 0,
4053                                 0, 0, 0, 1
4054
4055                         );
4056
4057                         return this;
4058
4059                 },
4060
4061                 makeShear: function ( x, y, z ) {
4062
4063                         this.set(
4064
4065                                 1, y, z, 0,
4066                                 x, 1, z, 0,
4067                                 x, y, 1, 0,
4068                                 0, 0, 0, 1
4069
4070                         );
4071
4072                         return this;
4073
4074                 },
4075
4076                 compose: function ( position, quaternion, scale ) {
4077
4078                         this.makeRotationFromQuaternion( quaternion );
4079                         this.scale( scale );
4080                         this.setPosition( position );
4081
4082                         return this;
4083
4084                 },
4085
4086                 decompose: function () {
4087
4088                         var vector = new Vector3();
4089                         var matrix = new Matrix4();
4090
4091                         return function decompose( position, quaternion, scale ) {
4092
4093                                 var te = this.elements;
4094
4095                                 var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
4096                                 var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
4097                                 var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
4098
4099                                 // if determine is negative, we need to invert one scale
4100                                 var det = this.determinant();
4101                                 if ( det < 0 ) sx = - sx;
4102
4103                                 position.x = te[ 12 ];
4104                                 position.y = te[ 13 ];
4105                                 position.z = te[ 14 ];
4106
4107                                 // scale the rotation part
4108                                 matrix.copy( this );
4109
4110                                 var invSX = 1 / sx;
4111                                 var invSY = 1 / sy;
4112                                 var invSZ = 1 / sz;
4113
4114                                 matrix.elements[ 0 ] *= invSX;
4115                                 matrix.elements[ 1 ] *= invSX;
4116                                 matrix.elements[ 2 ] *= invSX;
4117
4118                                 matrix.elements[ 4 ] *= invSY;
4119                                 matrix.elements[ 5 ] *= invSY;
4120                                 matrix.elements[ 6 ] *= invSY;
4121
4122                                 matrix.elements[ 8 ] *= invSZ;
4123                                 matrix.elements[ 9 ] *= invSZ;
4124                                 matrix.elements[ 10 ] *= invSZ;
4125
4126                                 quaternion.setFromRotationMatrix( matrix );
4127
4128                                 scale.x = sx;
4129                                 scale.y = sy;
4130                                 scale.z = sz;
4131
4132                                 return this;
4133
4134                         };
4135
4136                 }(),
4137
4138                 makePerspective: function ( left, right, top, bottom, near, far ) {
4139
4140                         if ( far === undefined ) {
4141
4142                                 console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
4143
4144                         }
4145
4146                         var te = this.elements;
4147                         var x = 2 * near / ( right - left );
4148                         var y = 2 * near / ( top - bottom );
4149
4150                         var a = ( right + left ) / ( right - left );
4151                         var b = ( top + bottom ) / ( top - bottom );
4152                         var c = - ( far + near ) / ( far - near );
4153                         var d = - 2 * far * near / ( far - near );
4154
4155                         te[ 0 ] = x;    te[ 4 ] = 0;    te[ 8 ] = a;    te[ 12 ] = 0;
4156                         te[ 1 ] = 0;    te[ 5 ] = y;    te[ 9 ] = b;    te[ 13 ] = 0;
4157                         te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = c;   te[ 14 ] = d;
4158                         te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = - 1; te[ 15 ] = 0;
4159
4160                         return this;
4161
4162                 },
4163
4164                 makeOrthographic: function ( left, right, top, bottom, near, far ) {
4165
4166                         var te = this.elements;
4167                         var w = 1.0 / ( right - left );
4168                         var h = 1.0 / ( top - bottom );
4169                         var p = 1.0 / ( far - near );
4170
4171                         var x = ( right + left ) * w;
4172                         var y = ( top + bottom ) * h;
4173                         var z = ( far + near ) * p;
4174
4175                         te[ 0 ] = 2 * w;        te[ 4 ] = 0;    te[ 8 ] = 0;    te[ 12 ] = - x;
4176                         te[ 1 ] = 0;    te[ 5 ] = 2 * h;        te[ 9 ] = 0;    te[ 13 ] = - y;
4177                         te[ 2 ] = 0;    te[ 6 ] = 0;    te[ 10 ] = - 2 * p;     te[ 14 ] = - z;
4178                         te[ 3 ] = 0;    te[ 7 ] = 0;    te[ 11 ] = 0;   te[ 15 ] = 1;
4179
4180                         return this;
4181
4182                 },
4183
4184                 equals: function ( matrix ) {
4185
4186                         var te = this.elements;
4187                         var me = matrix.elements;
4188
4189                         for ( var i = 0; i < 16; i ++ ) {
4190
4191                                 if ( te[ i ] !== me[ i ] ) return false;
4192
4193                         }
4194
4195                         return true;
4196
4197                 },
4198
4199                 fromArray: function ( array, offset ) {
4200
4201                         if ( offset === undefined ) offset = 0;
4202
4203                         for ( var i = 0; i < 16; i ++ ) {
4204
4205                                 this.elements[ i ] = array[ i + offset ];
4206
4207                         }
4208
4209                         return this;
4210
4211                 },
4212
4213                 toArray: function ( array, offset ) {
4214
4215                         if ( array === undefined ) array = [];
4216                         if ( offset === undefined ) offset = 0;
4217
4218                         var te = this.elements;
4219
4220                         array[ offset ] = te[ 0 ];
4221                         array[ offset + 1 ] = te[ 1 ];
4222                         array[ offset + 2 ] = te[ 2 ];
4223                         array[ offset + 3 ] = te[ 3 ];
4224
4225                         array[ offset + 4 ] = te[ 4 ];
4226                         array[ offset + 5 ] = te[ 5 ];
4227                         array[ offset + 6 ] = te[ 6 ];
4228                         array[ offset + 7 ] = te[ 7 ];
4229
4230                         array[ offset + 8 ] = te[ 8 ];
4231                         array[ offset + 9 ] = te[ 9 ];
4232                         array[ offset + 10 ] = te[ 10 ];
4233                         array[ offset + 11 ] = te[ 11 ];
4234
4235                         array[ offset + 12 ] = te[ 12 ];
4236                         array[ offset + 13 ] = te[ 13 ];
4237                         array[ offset + 14 ] = te[ 14 ];
4238                         array[ offset + 15 ] = te[ 15 ];
4239
4240                         return array;
4241
4242                 }
4243
4244         } );
4245
4246         /**
4247          * @author alteredq / http://alteredqualia.com/
4248          */
4249
4250         function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
4251
4252                 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
4253
4254                 this.image = { data: data, width: width, height: height };
4255
4256                 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
4257                 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
4258
4259                 this.generateMipmaps = false;
4260                 this.flipY = false;
4261                 this.unpackAlignment = 1;
4262
4263         }
4264
4265         DataTexture.prototype = Object.create( Texture.prototype );
4266         DataTexture.prototype.constructor = DataTexture;
4267
4268         DataTexture.prototype.isDataTexture = true;
4269
4270         /**
4271          * @author mrdoob / http://mrdoob.com/
4272          */
4273
4274         function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
4275
4276                 images = images !== undefined ? images : [];
4277                 mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
4278
4279                 Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
4280
4281                 this.flipY = false;
4282
4283         }
4284
4285         CubeTexture.prototype = Object.create( Texture.prototype );
4286         CubeTexture.prototype.constructor = CubeTexture;
4287
4288         CubeTexture.prototype.isCubeTexture = true;
4289
4290         Object.defineProperty( CubeTexture.prototype, 'images', {
4291
4292                 get: function () {
4293
4294                         return this.image;
4295
4296                 },
4297
4298                 set: function ( value ) {
4299
4300                         this.image = value;
4301
4302                 }
4303
4304         } );
4305
4306         /**
4307          * @author tschw
4308          *
4309          * Uniforms of a program.
4310          * Those form a tree structure with a special top-level container for the root,
4311          * which you get by calling 'new WebGLUniforms( gl, program, renderer )'.
4312          *
4313          *
4314          * Properties of inner nodes including the top-level container:
4315          *
4316          * .seq - array of nested uniforms
4317          * .map - nested uniforms by name
4318          *
4319          *
4320          * Methods of all nodes except the top-level container:
4321          *
4322          * .setValue( gl, value, [renderer] )
4323          *
4324          *              uploads a uniform value(s)
4325          *      the 'renderer' parameter is needed for sampler uniforms
4326          *
4327          *
4328          * Static methods of the top-level container (renderer factorizations):
4329          *
4330          * .upload( gl, seq, values, renderer )
4331          *
4332          *              sets uniforms in 'seq' to 'values[id].value'
4333          *
4334          * .seqWithValue( seq, values ) : filteredSeq
4335          *
4336          *              filters 'seq' entries with corresponding entry in values
4337          *
4338          *
4339          * Methods of the top-level container (renderer factorizations):
4340          *
4341          * .setValue( gl, name, value )
4342          *
4343          *              sets uniform with  name 'name' to 'value'
4344          *
4345          * .set( gl, obj, prop )
4346          *
4347          *              sets uniform from object and property with same name than uniform
4348          *
4349          * .setOptional( gl, obj, prop )
4350          *
4351          *              like .set for an optional property of the object
4352          *
4353          */
4354
4355         var emptyTexture = new Texture();
4356         var emptyCubeTexture = new CubeTexture();
4357
4358         // --- Base for inner nodes (including the root) ---
4359
4360         function UniformContainer() {
4361
4362                 this.seq = [];
4363                 this.map = {};
4364
4365         }
4366
4367         // --- Utilities ---
4368
4369         // Array Caches (provide typed arrays for temporary by size)
4370
4371         var arrayCacheF32 = [];
4372         var arrayCacheI32 = [];
4373
4374         // Float32Array caches used for uploading Matrix uniforms
4375
4376         var mat4array = new Float32Array( 16 );
4377         var mat3array = new Float32Array( 9 );
4378
4379         // Flattening for arrays of vectors and matrices
4380
4381         function flatten( array, nBlocks, blockSize ) {
4382
4383                 var firstElem = array[ 0 ];
4384
4385                 if ( firstElem <= 0 || firstElem > 0 ) return array;
4386                 // unoptimized: ! isNaN( firstElem )
4387                 // see http://jacksondunstan.com/articles/983
4388
4389                 var n = nBlocks * blockSize,
4390                         r = arrayCacheF32[ n ];
4391
4392                 if ( r === undefined ) {
4393
4394                         r = new Float32Array( n );
4395                         arrayCacheF32[ n ] = r;
4396
4397                 }
4398
4399                 if ( nBlocks !== 0 ) {
4400
4401                         firstElem.toArray( r, 0 );
4402
4403                         for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {
4404
4405                                 offset += blockSize;
4406                                 array[ i ].toArray( r, offset );
4407
4408                         }
4409
4410                 }
4411
4412                 return r;
4413
4414         }
4415
4416         // Texture unit allocation
4417
4418         function allocTexUnits( renderer, n ) {
4419
4420                 var r = arrayCacheI32[ n ];
4421
4422                 if ( r === undefined ) {
4423
4424                         r = new Int32Array( n );
4425                         arrayCacheI32[ n ] = r;
4426
4427                 }
4428
4429                 for ( var i = 0; i !== n; ++ i )
4430                         r[ i ] = renderer.allocTextureUnit();
4431
4432                 return r;
4433
4434         }
4435
4436         // --- Setters ---
4437
4438         // Note: Defining these methods externally, because they come in a bunch
4439         // and this way their names minify.
4440
4441         // Single scalar
4442
4443         function setValue1f( gl, v ) { gl.uniform1f( this.addr, v ); }
4444         function setValue1i( gl, v ) { gl.uniform1i( this.addr, v ); }
4445
4446         // Single float vector (from flat array or THREE.VectorN)
4447
4448         function setValue2fv( gl, v ) {
4449
4450                 if ( v.x === undefined ) gl.uniform2fv( this.addr, v );
4451                 else gl.uniform2f( this.addr, v.x, v.y );
4452
4453         }
4454
4455         function setValue3fv( gl, v ) {
4456
4457                 if ( v.x !== undefined )
4458                         gl.uniform3f( this.addr, v.x, v.y, v.z );
4459                 else if ( v.r !== undefined )
4460                         gl.uniform3f( this.addr, v.r, v.g, v.b );
4461                 else
4462                         gl.uniform3fv( this.addr, v );
4463
4464         }
4465
4466         function setValue4fv( gl, v ) {
4467
4468                 if ( v.x === undefined ) gl.uniform4fv( this.addr, v );
4469                 else gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
4470
4471         }
4472
4473         // Single matrix (from flat array or MatrixN)
4474
4475         function setValue2fm( gl, v ) {
4476
4477                 gl.uniformMatrix2fv( this.addr, false, v.elements || v );
4478
4479         }
4480
4481         function setValue3fm( gl, v ) {
4482
4483                 if ( v.elements === undefined ) {
4484
4485                         gl.uniformMatrix3fv( this.addr, false, v );
4486
4487                 } else {
4488
4489                         mat3array.set( v.elements );
4490                         gl.uniformMatrix3fv( this.addr, false, mat3array );
4491
4492                 }
4493
4494         }
4495
4496         function setValue4fm( gl, v ) {
4497
4498                 if ( v.elements === undefined ) {
4499
4500                         gl.uniformMatrix4fv( this.addr, false, v );
4501
4502                 } else {
4503
4504                         mat4array.set( v.elements );
4505                         gl.uniformMatrix4fv( this.addr, false, mat4array );
4506
4507                 }
4508
4509         }
4510
4511         // Single texture (2D / Cube)
4512
4513         function setValueT1( gl, v, renderer ) {
4514
4515                 var unit = renderer.allocTextureUnit();
4516                 gl.uniform1i( this.addr, unit );
4517                 renderer.setTexture2D( v || emptyTexture, unit );
4518
4519         }
4520
4521         function setValueT6( gl, v, renderer ) {
4522
4523                 var unit = renderer.allocTextureUnit();
4524                 gl.uniform1i( this.addr, unit );
4525                 renderer.setTextureCube( v || emptyCubeTexture, unit );
4526
4527         }
4528
4529         // Integer / Boolean vectors or arrays thereof (always flat arrays)
4530
4531         function setValue2iv( gl, v ) { gl.uniform2iv( this.addr, v ); }
4532         function setValue3iv( gl, v ) { gl.uniform3iv( this.addr, v ); }
4533         function setValue4iv( gl, v ) { gl.uniform4iv( this.addr, v ); }
4534
4535         // Helper to pick the right setter for the singular case
4536
4537         function getSingularSetter( type ) {
4538
4539                 switch ( type ) {
4540
4541                         case 0x1406: return setValue1f; // FLOAT
4542                         case 0x8b50: return setValue2fv; // _VEC2
4543                         case 0x8b51: return setValue3fv; // _VEC3
4544                         case 0x8b52: return setValue4fv; // _VEC4
4545
4546                         case 0x8b5a: return setValue2fm; // _MAT2
4547                         case 0x8b5b: return setValue3fm; // _MAT3
4548                         case 0x8b5c: return setValue4fm; // _MAT4
4549
4550                         case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES
4551                         case 0x8b60: return setValueT6; // SAMPLER_CUBE
4552
4553                         case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL
4554                         case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
4555                         case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
4556                         case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
4557
4558                 }
4559
4560         }
4561
4562         // Array of scalars
4563
4564         function setValue1fv( gl, v ) { gl.uniform1fv( this.addr, v ); }
4565         function setValue1iv( gl, v ) { gl.uniform1iv( this.addr, v ); }
4566
4567         // Array of vectors (flat or from THREE classes)
4568
4569         function setValueV2a( gl, v ) {
4570
4571                 gl.uniform2fv( this.addr, flatten( v, this.size, 2 ) );
4572
4573         }
4574
4575         function setValueV3a( gl, v ) {
4576
4577                 gl.uniform3fv( this.addr, flatten( v, this.size, 3 ) );
4578
4579         }
4580
4581         function setValueV4a( gl, v ) {
4582
4583                 gl.uniform4fv( this.addr, flatten( v, this.size, 4 ) );
4584
4585         }
4586
4587         // Array of matrices (flat or from THREE clases)
4588
4589         function setValueM2a( gl, v ) {
4590
4591                 gl.uniformMatrix2fv( this.addr, false, flatten( v, this.size, 4 ) );
4592
4593         }
4594
4595         function setValueM3a( gl, v ) {
4596
4597                 gl.uniformMatrix3fv( this.addr, false, flatten( v, this.size, 9 ) );
4598
4599         }
4600
4601         function setValueM4a( gl, v ) {
4602
4603                 gl.uniformMatrix4fv( this.addr, false, flatten( v, this.size, 16 ) );
4604
4605         }
4606
4607         // Array of textures (2D / Cube)
4608
4609         function setValueT1a( gl, v, renderer ) {
4610
4611                 var n = v.length,
4612                         units = allocTexUnits( renderer, n );
4613
4614                 gl.uniform1iv( this.addr, units );
4615
4616                 for ( var i = 0; i !== n; ++ i ) {
4617
4618                         renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] );
4619
4620                 }
4621
4622         }
4623
4624         function setValueT6a( gl, v, renderer ) {
4625
4626                 var n = v.length,
4627                         units = allocTexUnits( renderer, n );
4628
4629                 gl.uniform1iv( this.addr, units );
4630
4631                 for ( var i = 0; i !== n; ++ i ) {
4632
4633                         renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
4634
4635                 }
4636
4637         }
4638
4639         // Helper to pick the right setter for a pure (bottom-level) array
4640
4641         function getPureArraySetter( type ) {
4642
4643                 switch ( type ) {
4644
4645                         case 0x1406: return setValue1fv; // FLOAT
4646                         case 0x8b50: return setValueV2a; // _VEC2
4647                         case 0x8b51: return setValueV3a; // _VEC3
4648                         case 0x8b52: return setValueV4a; // _VEC4
4649
4650                         case 0x8b5a: return setValueM2a; // _MAT2
4651                         case 0x8b5b: return setValueM3a; // _MAT3
4652                         case 0x8b5c: return setValueM4a; // _MAT4
4653
4654                         case 0x8b5e: return setValueT1a; // SAMPLER_2D
4655                         case 0x8b60: return setValueT6a; // SAMPLER_CUBE
4656
4657                         case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL
4658                         case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
4659                         case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
4660                         case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
4661
4662                 }
4663
4664         }
4665
4666         // --- Uniform Classes ---
4667
4668         function SingleUniform( id, activeInfo, addr ) {
4669
4670                 this.id = id;
4671                 this.addr = addr;
4672                 this.setValue = getSingularSetter( activeInfo.type );
4673
4674                 // this.path = activeInfo.name; // DEBUG
4675
4676         }
4677
4678         function PureArrayUniform( id, activeInfo, addr ) {
4679
4680                 this.id = id;
4681                 this.addr = addr;
4682                 this.size = activeInfo.size;
4683                 this.setValue = getPureArraySetter( activeInfo.type );
4684
4685                 // this.path = activeInfo.name; // DEBUG
4686
4687         }
4688
4689         function StructuredUniform( id ) {
4690
4691                 this.id = id;
4692
4693                 UniformContainer.call( this ); // mix-in
4694
4695         }
4696
4697         StructuredUniform.prototype.setValue = function ( gl, value ) {
4698
4699                 // Note: Don't need an extra 'renderer' parameter, since samplers
4700                 // are not allowed in structured uniforms.
4701
4702                 var seq = this.seq;
4703
4704                 for ( var i = 0, n = seq.length; i !== n; ++ i ) {
4705
4706                         var u = seq[ i ];
4707                         u.setValue( gl, value[ u.id ] );
4708
4709                 }
4710
4711         };
4712
4713         // --- Top-level ---
4714
4715         // Parser - builds up the property tree from the path strings
4716
4717         var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
4718
4719         // extracts
4720         //      - the identifier (member name or array index)
4721         //  - followed by an optional right bracket (found when array index)
4722         //  - followed by an optional left bracket or dot (type of subscript)
4723         //
4724         // Note: These portions can be read in a non-overlapping fashion and
4725         // allow straightforward parsing of the hierarchy that WebGL encodes
4726         // in the uniform names.
4727
4728         function addUniform( container, uniformObject ) {
4729
4730                 container.seq.push( uniformObject );
4731                 container.map[ uniformObject.id ] = uniformObject;
4732
4733         }
4734
4735         function parseUniform( activeInfo, addr, container ) {
4736
4737                 var path = activeInfo.name,
4738                         pathLength = path.length;
4739
4740                 // reset RegExp object, because of the early exit of a previous run
4741                 RePathPart.lastIndex = 0;
4742
4743                 for ( ; ; ) {
4744
4745                         var match = RePathPart.exec( path ),
4746                                 matchEnd = RePathPart.lastIndex,
4747
4748                                 id = match[ 1 ],
4749                                 idIsIndex = match[ 2 ] === ']',
4750                                 subscript = match[ 3 ];
4751
4752                         if ( idIsIndex ) id = id | 0; // convert to integer
4753
4754                         if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
4755
4756                                 // bare name or "pure" bottom-level array "[0]" suffix
4757
4758                                 addUniform( container, subscript === undefined ?
4759                                                 new SingleUniform( id, activeInfo, addr ) :
4760                                                 new PureArrayUniform( id, activeInfo, addr ) );
4761
4762                                 break;
4763
4764                         } else {
4765
4766                                 // step into inner node / create it in case it doesn't exist
4767
4768                                 var map = container.map, next = map[ id ];
4769
4770                                 if ( next === undefined ) {
4771
4772                                         next = new StructuredUniform( id );
4773                                         addUniform( container, next );
4774
4775                                 }
4776
4777                                 container = next;
4778
4779                         }
4780
4781                 }
4782
4783         }
4784
4785         // Root Container
4786
4787         function WebGLUniforms( gl, program, renderer ) {
4788
4789                 UniformContainer.call( this );
4790
4791                 this.renderer = renderer;
4792
4793                 var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
4794
4795                 for ( var i = 0; i < n; ++ i ) {
4796
4797                         var info = gl.getActiveUniform( program, i ),
4798                                 path = info.name,
4799                                 addr = gl.getUniformLocation( program, path );
4800
4801                         parseUniform( info, addr, this );
4802
4803                 }
4804
4805         }
4806
4807         WebGLUniforms.prototype.setValue = function ( gl, name, value ) {
4808
4809                 var u = this.map[ name ];
4810
4811                 if ( u !== undefined ) u.setValue( gl, value, this.renderer );
4812
4813         };
4814
4815         WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
4816
4817                 var v = object[ name ];
4818
4819                 if ( v !== undefined ) this.setValue( gl, name, v );
4820
4821         };
4822
4823
4824         // Static interface
4825
4826         WebGLUniforms.upload = function ( gl, seq, values, renderer ) {
4827
4828                 for ( var i = 0, n = seq.length; i !== n; ++ i ) {
4829
4830                         var u = seq[ i ],
4831                                 v = values[ u.id ];
4832
4833                         if ( v.needsUpdate !== false ) {
4834
4835                                 // note: always updating when .needsUpdate is undefined
4836                                 u.setValue( gl, v.value, renderer );
4837
4838                         }
4839
4840                 }
4841
4842         };
4843
4844         WebGLUniforms.seqWithValue = function ( seq, values ) {
4845
4846                 var r = [];
4847
4848                 for ( var i = 0, n = seq.length; i !== n; ++ i ) {
4849
4850                         var u = seq[ i ];
4851                         if ( u.id in values ) r.push( u );
4852
4853                 }
4854
4855                 return r;
4856
4857         };
4858
4859         /**
4860          * @author mrdoob / http://mrdoob.com/
4861          */
4862
4863         var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
4864                 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
4865                 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
4866                 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
4867                 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
4868                 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
4869                 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
4870                 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
4871                 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
4872                 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
4873                 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
4874                 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
4875                 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
4876                 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
4877                 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
4878                 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
4879                 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
4880                 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
4881                 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
4882                 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
4883                 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
4884                 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
4885                 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
4886                 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
4887
4888         function Color( r, g, b ) {
4889
4890                 if ( g === undefined && b === undefined ) {
4891
4892                         // r is THREE.Color, hex or string
4893                         return this.set( r );
4894
4895                 }
4896
4897                 return this.setRGB( r, g, b );
4898
4899         }
4900
4901         Object.assign( Color.prototype, {
4902
4903                 isColor: true,
4904
4905                 r: 1, g: 1, b: 1,
4906
4907                 set: function ( value ) {
4908
4909                         if ( value && value.isColor ) {
4910
4911                                 this.copy( value );
4912
4913                         } else if ( typeof value === 'number' ) {
4914
4915                                 this.setHex( value );
4916
4917                         } else if ( typeof value === 'string' ) {
4918
4919                                 this.setStyle( value );
4920
4921                         }
4922
4923                         return this;
4924
4925                 },
4926
4927                 setScalar: function ( scalar ) {
4928
4929                         this.r = scalar;
4930                         this.g = scalar;
4931                         this.b = scalar;
4932
4933                         return this;
4934
4935                 },
4936
4937                 setHex: function ( hex ) {
4938
4939                         hex = Math.floor( hex );
4940
4941                         this.r = ( hex >> 16 & 255 ) / 255;
4942                         this.g = ( hex >> 8 & 255 ) / 255;
4943                         this.b = ( hex & 255 ) / 255;
4944
4945                         return this;
4946
4947                 },
4948
4949                 setRGB: function ( r, g, b ) {
4950
4951                         this.r = r;
4952                         this.g = g;
4953                         this.b = b;
4954
4955                         return this;
4956
4957                 },
4958
4959                 setHSL: function () {
4960
4961                         function hue2rgb( p, q, t ) {
4962
4963                                 if ( t < 0 ) t += 1;
4964                                 if ( t > 1 ) t -= 1;
4965                                 if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
4966                                 if ( t < 1 / 2 ) return q;
4967                                 if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
4968                                 return p;
4969
4970                         }
4971
4972                         return function setHSL( h, s, l ) {
4973
4974                                 // h,s,l ranges are in 0.0 - 1.0
4975                                 h = _Math.euclideanModulo( h, 1 );
4976                                 s = _Math.clamp( s, 0, 1 );
4977                                 l = _Math.clamp( l, 0, 1 );
4978
4979                                 if ( s === 0 ) {
4980
4981                                         this.r = this.g = this.b = l;
4982
4983                                 } else {
4984
4985                                         var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
4986                                         var q = ( 2 * l ) - p;
4987
4988                                         this.r = hue2rgb( q, p, h + 1 / 3 );
4989                                         this.g = hue2rgb( q, p, h );
4990                                         this.b = hue2rgb( q, p, h - 1 / 3 );
4991
4992                                 }
4993
4994                                 return this;
4995
4996                         };
4997
4998                 }(),
4999
5000                 setStyle: function ( style ) {
5001
5002                         function handleAlpha( string ) {
5003
5004                                 if ( string === undefined ) return;
5005
5006                                 if ( parseFloat( string ) < 1 ) {
5007
5008                                         console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
5009
5010                                 }
5011
5012                         }
5013
5014
5015                         var m;
5016
5017                         if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
5018
5019                                 // rgb / hsl
5020
5021                                 var color;
5022                                 var name = m[ 1 ];
5023                                 var components = m[ 2 ];
5024
5025                                 switch ( name ) {
5026
5027                                         case 'rgb':
5028                                         case 'rgba':
5029
5030                                                 if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
5031
5032                                                         // rgb(255,0,0) rgba(255,0,0,0.5)
5033                                                         this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
5034                                                         this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
5035                                                         this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
5036
5037                                                         handleAlpha( color[ 5 ] );
5038
5039                                                         return this;
5040
5041                                                 }
5042
5043                                                 if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
5044
5045                                                         // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
5046                                                         this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
5047                                                         this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
5048                                                         this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
5049
5050                                                         handleAlpha( color[ 5 ] );
5051
5052                                                         return this;
5053
5054                                                 }
5055
5056                                                 break;
5057
5058                                         case 'hsl':
5059                                         case 'hsla':
5060
5061                                                 if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
5062
5063                                                         // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
5064                                                         var h = parseFloat( color[ 1 ] ) / 360;
5065                                                         var s = parseInt( color[ 2 ], 10 ) / 100;
5066                                                         var l = parseInt( color[ 3 ], 10 ) / 100;
5067
5068                                                         handleAlpha( color[ 5 ] );
5069
5070                                                         return this.setHSL( h, s, l );
5071
5072                                                 }
5073
5074                                                 break;
5075
5076                                 }
5077
5078                         } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
5079
5080                                 // hex color
5081
5082                                 var hex = m[ 1 ];
5083                                 var size = hex.length;
5084
5085                                 if ( size === 3 ) {
5086
5087                                         // #ff0
5088                                         this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
5089                                         this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
5090                                         this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
5091
5092                                         return this;
5093
5094                                 } else if ( size === 6 ) {
5095
5096                                         // #ff0000
5097                                         this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
5098                                         this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
5099                                         this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
5100
5101                                         return this;
5102
5103                                 }
5104
5105                         }
5106
5107                         if ( style && style.length > 0 ) {
5108
5109                                 // color keywords
5110                                 var hex = ColorKeywords[ style ];
5111
5112                                 if ( hex !== undefined ) {
5113
5114                                         // red
5115                                         this.setHex( hex );
5116
5117                                 } else {
5118
5119                                         // unknown color
5120                                         console.warn( 'THREE.Color: Unknown color ' + style );
5121
5122                                 }
5123
5124                         }
5125
5126                         return this;
5127
5128                 },
5129
5130                 clone: function () {
5131
5132                         return new this.constructor( this.r, this.g, this.b );
5133
5134                 },
5135
5136                 copy: function ( color ) {
5137
5138                         this.r = color.r;
5139                         this.g = color.g;
5140                         this.b = color.b;
5141
5142                         return this;
5143
5144                 },
5145
5146                 copyGammaToLinear: function ( color, gammaFactor ) {
5147
5148                         if ( gammaFactor === undefined ) gammaFactor = 2.0;
5149
5150                         this.r = Math.pow( color.r, gammaFactor );
5151                         this.g = Math.pow( color.g, gammaFactor );
5152                         this.b = Math.pow( color.b, gammaFactor );
5153
5154                         return this;
5155
5156                 },
5157
5158                 copyLinearToGamma: function ( color, gammaFactor ) {
5159
5160                         if ( gammaFactor === undefined ) gammaFactor = 2.0;
5161
5162                         var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
5163
5164                         this.r = Math.pow( color.r, safeInverse );
5165                         this.g = Math.pow( color.g, safeInverse );
5166                         this.b = Math.pow( color.b, safeInverse );
5167
5168                         return this;
5169
5170                 },
5171
5172                 convertGammaToLinear: function () {
5173
5174                         var r = this.r, g = this.g, b = this.b;
5175
5176                         this.r = r * r;
5177                         this.g = g * g;
5178                         this.b = b * b;
5179
5180                         return this;
5181
5182                 },
5183
5184                 convertLinearToGamma: function () {
5185
5186                         this.r = Math.sqrt( this.r );
5187                         this.g = Math.sqrt( this.g );
5188                         this.b = Math.sqrt( this.b );
5189
5190                         return this;
5191
5192                 },
5193
5194                 getHex: function () {
5195
5196                         return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
5197
5198                 },
5199
5200                 getHexString: function () {
5201
5202                         return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
5203
5204                 },
5205
5206                 getHSL: function ( optionalTarget ) {
5207
5208                         // h,s,l ranges are in 0.0 - 1.0
5209
5210                         var hsl = optionalTarget || { h: 0, s: 0, l: 0 };
5211
5212                         var r = this.r, g = this.g, b = this.b;
5213
5214                         var max = Math.max( r, g, b );
5215                         var min = Math.min( r, g, b );
5216
5217                         var hue, saturation;
5218                         var lightness = ( min + max ) / 2.0;
5219
5220                         if ( min === max ) {
5221
5222                                 hue = 0;
5223                                 saturation = 0;
5224
5225                         } else {
5226
5227                                 var delta = max - min;
5228
5229                                 saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
5230
5231                                 switch ( max ) {
5232
5233                                         case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
5234                                         case g: hue = ( b - r ) / delta + 2; break;
5235                                         case b: hue = ( r - g ) / delta + 4; break;
5236
5237                                 }
5238
5239                                 hue /= 6;
5240
5241                         }
5242
5243                         hsl.h = hue;
5244                         hsl.s = saturation;
5245                         hsl.l = lightness;
5246
5247                         return hsl;
5248
5249                 },
5250
5251                 getStyle: function () {
5252
5253                         return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
5254
5255                 },
5256
5257                 offsetHSL: function ( h, s, l ) {
5258
5259                         var hsl = this.getHSL();
5260
5261                         hsl.h += h; hsl.s += s; hsl.l += l;
5262
5263                         this.setHSL( hsl.h, hsl.s, hsl.l );
5264
5265                         return this;
5266
5267                 },
5268
5269                 add: function ( color ) {
5270
5271                         this.r += color.r;
5272                         this.g += color.g;
5273                         this.b += color.b;
5274
5275                         return this;
5276
5277                 },
5278
5279                 addColors: function ( color1, color2 ) {
5280
5281                         this.r = color1.r + color2.r;
5282                         this.g = color1.g + color2.g;
5283                         this.b = color1.b + color2.b;
5284
5285                         return this;
5286
5287                 },
5288
5289                 addScalar: function ( s ) {
5290
5291                         this.r += s;
5292                         this.g += s;
5293                         this.b += s;
5294
5295                         return this;
5296
5297                 },
5298
5299                 sub: function( color ) {
5300
5301                         this.r = Math.max( 0, this.r - color.r );
5302                         this.g = Math.max( 0, this.g - color.g );
5303                         this.b = Math.max( 0, this.b - color.b );
5304
5305                         return this;
5306
5307                 },
5308
5309                 multiply: function ( color ) {
5310
5311                         this.r *= color.r;
5312                         this.g *= color.g;
5313                         this.b *= color.b;
5314
5315                         return this;
5316
5317                 },
5318
5319                 multiplyScalar: function ( s ) {
5320
5321                         this.r *= s;
5322                         this.g *= s;
5323                         this.b *= s;
5324
5325                         return this;
5326
5327                 },
5328
5329                 lerp: function ( color, alpha ) {
5330
5331                         this.r += ( color.r - this.r ) * alpha;
5332                         this.g += ( color.g - this.g ) * alpha;
5333                         this.b += ( color.b - this.b ) * alpha;
5334
5335                         return this;
5336
5337                 },
5338
5339                 equals: function ( c ) {
5340
5341                         return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
5342
5343                 },
5344
5345                 fromArray: function ( array, offset ) {
5346
5347                         if ( offset === undefined ) offset = 0;
5348
5349                         this.r = array[ offset ];
5350                         this.g = array[ offset + 1 ];
5351                         this.b = array[ offset + 2 ];
5352
5353                         return this;
5354
5355                 },
5356
5357                 toArray: function ( array, offset ) {
5358
5359                         if ( array === undefined ) array = [];
5360                         if ( offset === undefined ) offset = 0;
5361
5362                         array[ offset ] = this.r;
5363                         array[ offset + 1 ] = this.g;
5364                         array[ offset + 2 ] = this.b;
5365
5366                         return array;
5367
5368                 },
5369
5370                 toJSON: function () {
5371
5372                         return this.getHex();
5373
5374                 }
5375
5376         } );
5377
5378         /**
5379          * Uniforms library for shared webgl shaders
5380          */
5381
5382         var UniformsLib = {
5383
5384                 common: {
5385
5386                         diffuse: { value: new Color( 0xeeeeee ) },
5387                         opacity: { value: 1.0 },
5388
5389                         map: { value: null },
5390                         offsetRepeat: { value: new Vector4( 0, 0, 1, 1 ) },
5391
5392                         alphaMap: { value: null },
5393
5394                 },
5395
5396                 specularmap: {
5397
5398                         specularMap: { value: null },
5399
5400                 },
5401
5402                 envmap: {
5403
5404                         envMap: { value: null },
5405                         flipEnvMap: { value: - 1 },
5406                         reflectivity: { value: 1.0 },
5407                         refractionRatio: { value: 0.98 }
5408
5409                 },
5410
5411                 aomap: {
5412
5413                         aoMap: { value: null },
5414                         aoMapIntensity: { value: 1 }
5415
5416                 },
5417
5418                 lightmap: {
5419
5420                         lightMap: { value: null },
5421                         lightMapIntensity: { value: 1 }
5422
5423                 },
5424
5425                 emissivemap: {
5426
5427                         emissiveMap: { value: null }
5428
5429                 },
5430
5431                 bumpmap: {
5432
5433                         bumpMap: { value: null },
5434                         bumpScale: { value: 1 }
5435
5436                 },
5437
5438                 normalmap: {
5439
5440                         normalMap: { value: null },
5441                         normalScale: { value: new Vector2( 1, 1 ) }
5442
5443                 },
5444
5445                 displacementmap: {
5446
5447                         displacementMap: { value: null },
5448                         displacementScale: { value: 1 },
5449                         displacementBias: { value: 0 }
5450
5451                 },
5452
5453                 roughnessmap: {
5454
5455                         roughnessMap: { value: null }
5456
5457                 },
5458
5459                 metalnessmap: {
5460
5461                         metalnessMap: { value: null }
5462
5463                 },
5464
5465                 gradientmap: {
5466
5467                         gradientMap: { value: null }
5468
5469                 },
5470
5471                 fog: {
5472
5473                         fogDensity: { value: 0.00025 },
5474                         fogNear: { value: 1 },
5475                         fogFar: { value: 2000 },
5476                         fogColor: { value: new Color( 0xffffff ) }
5477
5478                 },
5479
5480                 lights: {
5481
5482                         ambientLightColor: { value: [] },
5483
5484                         directionalLights: { value: [], properties: {
5485                                 direction: {},
5486                                 color: {},
5487
5488                                 shadow: {},
5489                                 shadowBias: {},
5490                                 shadowRadius: {},
5491                                 shadowMapSize: {}
5492                         } },
5493
5494                         directionalShadowMap: { value: [] },
5495                         directionalShadowMatrix: { value: [] },
5496
5497                         spotLights: { value: [], properties: {
5498                                 color: {},
5499                                 position: {},
5500                                 direction: {},
5501                                 distance: {},
5502                                 coneCos: {},
5503                                 penumbraCos: {},
5504                                 decay: {},
5505
5506                                 shadow: {},
5507                                 shadowBias: {},
5508                                 shadowRadius: {},
5509                                 shadowMapSize: {}
5510                         } },
5511
5512                         spotShadowMap: { value: [] },
5513                         spotShadowMatrix: { value: [] },
5514
5515                         pointLights: { value: [], properties: {
5516                                 color: {},
5517                                 position: {},
5518                                 decay: {},
5519                                 distance: {},
5520
5521                                 shadow: {},
5522                                 shadowBias: {},
5523                                 shadowRadius: {},
5524                                 shadowMapSize: {},
5525                                 shadowCameraNear: {},
5526                                 shadowCameraFar: {}
5527                         } },
5528
5529                         pointShadowMap: { value: [] },
5530                         pointShadowMatrix: { value: [] },
5531
5532                         hemisphereLights: { value: [], properties: {
5533                                 direction: {},
5534                                 skyColor: {},
5535                                 groundColor: {}
5536                         } },
5537
5538                         // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
5539                         rectAreaLights: { value: [], properties: {
5540                                 color: {},
5541                                 position: {},
5542                                 width: {},
5543                                 height: {}
5544                         } }
5545
5546                 },
5547
5548                 points: {
5549
5550                         diffuse: { value: new Color( 0xeeeeee ) },
5551                         opacity: { value: 1.0 },
5552                         size: { value: 1.0 },
5553                         scale: { value: 1.0 },
5554                         map: { value: null },
5555                         offsetRepeat: { value: new Vector4( 0, 0, 1, 1 ) }
5556
5557                 }
5558
5559         };
5560
5561         /**
5562          * Uniform Utilities
5563          */
5564
5565         var UniformsUtils = {
5566
5567                 merge: function ( uniforms ) {
5568
5569                         var merged = {};
5570
5571                         for ( var u = 0; u < uniforms.length; u ++ ) {
5572
5573                                 var tmp = this.clone( uniforms[ u ] );
5574
5575                                 for ( var p in tmp ) {
5576
5577                                         merged[ p ] = tmp[ p ];
5578
5579                                 }
5580
5581                         }
5582
5583                         return merged;
5584
5585                 },
5586
5587                 clone: function ( uniforms_src ) {
5588
5589                         var uniforms_dst = {};
5590
5591                         for ( var u in uniforms_src ) {
5592
5593                                 uniforms_dst[ u ] = {};
5594
5595                                 for ( var p in uniforms_src[ u ] ) {
5596
5597                                         var parameter_src = uniforms_src[ u ][ p ];
5598
5599                                         if ( parameter_src && ( parameter_src.isColor ||
5600                                                 parameter_src.isMatrix3 || parameter_src.isMatrix4 ||
5601                                                 parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 ||
5602                                                 parameter_src.isTexture ) ) {
5603
5604                                                 uniforms_dst[ u ][ p ] = parameter_src.clone();
5605
5606                                         } else if ( Array.isArray( parameter_src ) ) {
5607
5608                                                 uniforms_dst[ u ][ p ] = parameter_src.slice();
5609
5610                                         } else {
5611
5612                                                 uniforms_dst[ u ][ p ] = parameter_src;
5613
5614                                         }
5615
5616                                 }
5617
5618                         }
5619
5620                         return uniforms_dst;
5621
5622                 }
5623
5624         };
5625
5626         var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n";
5627
5628         var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n";
5629
5630         var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n";
5631
5632         var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n";
5633
5634         var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
5635
5636         var begin_vertex = "\nvec3 transformed = vec3( position );\n";
5637
5638         var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n";
5639
5640         var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\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 theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\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.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - 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 * transpose( 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\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";
5641
5642         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\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n";
5643
5644         var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n";
5645
5646         var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n";
5647
5648         var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n";
5649
5650         var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n";
5651
5652         var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
5653
5654         var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n";
5655
5656         var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
5657
5658         var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif";
5659
5660         var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transpose( const in mat3 v ) {\n\tmat3 tmp;\n\ttmp[0] = vec3(v[0].x, v[1].x, v[2].x);\n\ttmp[1] = vec3(v[0].y, v[1].y, v[2].y);\n\ttmp[2] = vec3(v[0].z, v[1].z, v[2].z);\n\treturn tmp;\n}\n";
5661
5662         var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1  (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale =  bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n";
5663
5664         var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n";
5665
5666         var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n";
5667
5668         var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n";
5669
5670         var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n";
5671
5672         var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n";
5673
5674         var encodings_fragment = "  gl_FragColor = linearToOutputTexel( gl_FragColor );\n";
5675
5676         var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M      = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM            = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D      = max( maxRange / maxRGB, 1.0 );\n\tD            = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value )  {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n";
5677
5678         var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n";
5679
5680         var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n";
5681
5682         var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n";
5683
5684         var envmap_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n";
5685
5686         var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif";
5687
5688         var fog_pars_vertex = "#ifdef USE_FOG\n  varying float fogDepth;\n#endif\n";
5689
5690         var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n";
5691
5692         var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n";
5693
5694         var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n";
5695
5696         var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n";
5697
5698         var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
5699
5700         var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n";
5701
5702         var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltcMat;\tuniform sampler2D ltcMag;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n";
5703
5704         var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n";
5705
5706         var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n";
5707
5708         var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n";
5709
5710         var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\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\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3(   1,   0, t.y ),\n\t\t\tvec3(   0, t.z,   0 ),\n\t\t\tvec3( t.w,   0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";
5711
5712         var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n";
5713
5714         var logdepthbuf_fragment = "#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)\n\tgl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;\n#endif";
5715
5716         var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n";
5717
5718         var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif";
5719
5720         var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tgl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n\t#endif\n#endif\n";
5721
5722         var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n";
5723
5724         var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n";
5725
5726         var map_particle_fragment = "#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n";
5727
5728         var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform vec4 offsetRepeat;\n\tuniform sampler2D map;\n#endif\n";
5729
5730         var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n";
5731
5732         var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
5733
5734         var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n";
5735
5736         var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
5737
5738         var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n";
5739
5740         var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n";
5741
5742         var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n";
5743
5744         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 1.0 - 2.0 * rgb.xyz;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256.,  256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n";
5745
5746         var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n";
5747
5748         var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n";
5749
5750         var dithering_fragment = "#if defined( DITHERING )\n  gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n";
5751
5752         var dithering_pars_fragment = "#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n";
5753
5754         var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n";
5755
5756         var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
5757
5758         var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n";
5759
5760         var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n";
5761
5762         var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n";
5763
5764         var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n";
5765
5766         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";
5767
5768         var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n";
5769
5770         var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n";
5771
5772         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#endif\n";
5773
5774         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";
5775
5776         var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
5777
5778         var tonemapping_fragment = "#if defined( TONE_MAPPING )\n  gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n";
5779
5780         var tonemapping_pars_fragment = "#define saturate(a) clamp( a, 0.0, 1.0 )\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n";
5781
5782         var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif";
5783
5784         var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform vec4 offsetRepeat;\n#endif\n";
5785
5786         var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif";
5787
5788         var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
5789
5790         var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif";
5791
5792         var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif";
5793
5794         var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n";
5795
5796         var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n";
5797
5798         var cube_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}\n";
5799
5800         var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n";
5801
5802         var depth_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n}\n";
5803
5804         var distanceRGBA_frag = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n";
5805
5806         var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}\n";
5807
5808         var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n";
5809
5810         var equirect_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}\n";
5811
5812         var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
5813
5814         var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}\n";
5815
5816         var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
5817
5818         var meshbasic_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_ENVMAP\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}\n";
5819
5820         var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <emissivemap_fragment>\n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include <lightmap_fragment>\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
5821
5822         var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <lights_lambert_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
5823
5824         var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\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>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_template>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
5825
5826         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}\n";
5827
5828         var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <lights_pars>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_template>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
5829
5830         var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
5831
5832         var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\nvoid main() {\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n";
5833
5834         var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n";
5835
5836         var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
5837
5838         var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <shadowmap_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 <project_vertex>\n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
5839
5840         var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <bsdfs>\n#include <lights_pars>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n}\n";
5841
5842         var shadow_vert = "#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n}\n";
5843
5844         var ShaderChunk = {
5845                 alphamap_fragment: alphamap_fragment,
5846                 alphamap_pars_fragment: alphamap_pars_fragment,
5847                 alphatest_fragment: alphatest_fragment,
5848                 aomap_fragment: aomap_fragment,
5849                 aomap_pars_fragment: aomap_pars_fragment,
5850                 begin_vertex: begin_vertex,
5851                 beginnormal_vertex: beginnormal_vertex,
5852                 bsdfs: bsdfs,
5853                 bumpmap_pars_fragment: bumpmap_pars_fragment,
5854                 clipping_planes_fragment: clipping_planes_fragment,
5855                 clipping_planes_pars_fragment: clipping_planes_pars_fragment,
5856                 clipping_planes_pars_vertex: clipping_planes_pars_vertex,
5857                 clipping_planes_vertex: clipping_planes_vertex,
5858                 color_fragment: color_fragment,
5859                 color_pars_fragment: color_pars_fragment,
5860                 color_pars_vertex: color_pars_vertex,
5861                 color_vertex: color_vertex,
5862                 common: common,
5863                 cube_uv_reflection_fragment: cube_uv_reflection_fragment,
5864                 defaultnormal_vertex: defaultnormal_vertex,
5865                 displacementmap_pars_vertex: displacementmap_pars_vertex,
5866                 displacementmap_vertex: displacementmap_vertex,
5867                 emissivemap_fragment: emissivemap_fragment,
5868                 emissivemap_pars_fragment: emissivemap_pars_fragment,
5869                 encodings_fragment: encodings_fragment,
5870                 encodings_pars_fragment: encodings_pars_fragment,
5871                 envmap_fragment: envmap_fragment,
5872                 envmap_pars_fragment: envmap_pars_fragment,
5873                 envmap_pars_vertex: envmap_pars_vertex,
5874                 envmap_vertex: envmap_vertex,
5875                 fog_vertex: fog_vertex,
5876                 fog_pars_vertex: fog_pars_vertex,
5877                 fog_fragment: fog_fragment,
5878                 fog_pars_fragment: fog_pars_fragment,
5879                 gradientmap_pars_fragment: gradientmap_pars_fragment,
5880                 lightmap_fragment: lightmap_fragment,
5881                 lightmap_pars_fragment: lightmap_pars_fragment,
5882                 lights_lambert_vertex: lights_lambert_vertex,
5883                 lights_pars: lights_pars,
5884                 lights_phong_fragment: lights_phong_fragment,
5885                 lights_phong_pars_fragment: lights_phong_pars_fragment,
5886                 lights_physical_fragment: lights_physical_fragment,
5887                 lights_physical_pars_fragment: lights_physical_pars_fragment,
5888                 lights_template: lights_template,
5889                 logdepthbuf_fragment: logdepthbuf_fragment,
5890                 logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
5891                 logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
5892                 logdepthbuf_vertex: logdepthbuf_vertex,
5893                 map_fragment: map_fragment,
5894                 map_pars_fragment: map_pars_fragment,
5895                 map_particle_fragment: map_particle_fragment,
5896                 map_particle_pars_fragment: map_particle_pars_fragment,
5897                 metalnessmap_fragment: metalnessmap_fragment,
5898                 metalnessmap_pars_fragment: metalnessmap_pars_fragment,
5899                 morphnormal_vertex: morphnormal_vertex,
5900                 morphtarget_pars_vertex: morphtarget_pars_vertex,
5901                 morphtarget_vertex: morphtarget_vertex,
5902                 normal_fragment: normal_fragment,
5903                 normalmap_pars_fragment: normalmap_pars_fragment,
5904                 packing: packing,
5905                 premultiplied_alpha_fragment: premultiplied_alpha_fragment,
5906                 project_vertex: project_vertex,
5907                 dithering_fragment: dithering_fragment,
5908                 dithering_pars_fragment: dithering_pars_fragment,
5909                 roughnessmap_fragment: roughnessmap_fragment,
5910                 roughnessmap_pars_fragment: roughnessmap_pars_fragment,
5911                 shadowmap_pars_fragment: shadowmap_pars_fragment,
5912                 shadowmap_pars_vertex: shadowmap_pars_vertex,
5913                 shadowmap_vertex: shadowmap_vertex,
5914                 shadowmask_pars_fragment: shadowmask_pars_fragment,
5915                 skinbase_vertex: skinbase_vertex,
5916                 skinning_pars_vertex: skinning_pars_vertex,
5917                 skinning_vertex: skinning_vertex,
5918                 skinnormal_vertex: skinnormal_vertex,
5919                 specularmap_fragment: specularmap_fragment,
5920                 specularmap_pars_fragment: specularmap_pars_fragment,
5921                 tonemapping_fragment: tonemapping_fragment,
5922                 tonemapping_pars_fragment: tonemapping_pars_fragment,
5923                 uv_pars_fragment: uv_pars_fragment,
5924                 uv_pars_vertex: uv_pars_vertex,
5925                 uv_vertex: uv_vertex,
5926                 uv2_pars_fragment: uv2_pars_fragment,
5927                 uv2_pars_vertex: uv2_pars_vertex,
5928                 uv2_vertex: uv2_vertex,
5929                 worldpos_vertex: worldpos_vertex,
5930
5931                 cube_frag: cube_frag,
5932                 cube_vert: cube_vert,
5933                 depth_frag: depth_frag,
5934                 depth_vert: depth_vert,
5935                 distanceRGBA_frag: distanceRGBA_frag,
5936                 distanceRGBA_vert: distanceRGBA_vert,
5937                 equirect_frag: equirect_frag,
5938                 equirect_vert: equirect_vert,
5939                 linedashed_frag: linedashed_frag,
5940                 linedashed_vert: linedashed_vert,
5941                 meshbasic_frag: meshbasic_frag,
5942                 meshbasic_vert: meshbasic_vert,
5943                 meshlambert_frag: meshlambert_frag,
5944                 meshlambert_vert: meshlambert_vert,
5945                 meshphong_frag: meshphong_frag,
5946                 meshphong_vert: meshphong_vert,
5947                 meshphysical_frag: meshphysical_frag,
5948                 meshphysical_vert: meshphysical_vert,
5949                 normal_frag: normal_frag,
5950                 normal_vert: normal_vert,
5951                 points_frag: points_frag,
5952                 points_vert: points_vert,
5953                 shadow_frag: shadow_frag,
5954                 shadow_vert: shadow_vert
5955         };
5956
5957         /**
5958          * @author alteredq / http://alteredqualia.com/
5959          * @author mrdoob / http://mrdoob.com/
5960          * @author mikael emtinger / http://gomo.se/
5961          */
5962
5963         var ShaderLib = {
5964
5965                 basic: {
5966
5967                         uniforms: UniformsUtils.merge( [
5968                                 UniformsLib.common,
5969                                 UniformsLib.specularmap,
5970                                 UniformsLib.envmap,
5971                                 UniformsLib.aomap,
5972                                 UniformsLib.lightmap,
5973                                 UniformsLib.fog
5974                         ] ),
5975
5976                         vertexShader: ShaderChunk.meshbasic_vert,
5977                         fragmentShader: ShaderChunk.meshbasic_frag
5978
5979                 },
5980
5981                 lambert: {
5982
5983                         uniforms: UniformsUtils.merge( [
5984                                 UniformsLib.common,
5985                                 UniformsLib.specularmap,
5986                                 UniformsLib.envmap,
5987                                 UniformsLib.aomap,
5988                                 UniformsLib.lightmap,
5989                                 UniformsLib.emissivemap,
5990                                 UniformsLib.fog,
5991                                 UniformsLib.lights,
5992                                 {
5993                                         emissive: { value: new Color( 0x000000 ) }
5994                                 }
5995                         ] ),
5996
5997                         vertexShader: ShaderChunk.meshlambert_vert,
5998                         fragmentShader: ShaderChunk.meshlambert_frag
5999
6000                 },
6001
6002                 phong: {
6003
6004                         uniforms: UniformsUtils.merge( [
6005                                 UniformsLib.common,
6006                                 UniformsLib.specularmap,
6007                                 UniformsLib.envmap,
6008                                 UniformsLib.aomap,
6009                                 UniformsLib.lightmap,
6010                                 UniformsLib.emissivemap,
6011                                 UniformsLib.bumpmap,
6012                                 UniformsLib.normalmap,
6013                                 UniformsLib.displacementmap,
6014                                 UniformsLib.gradientmap,
6015                                 UniformsLib.fog,
6016                                 UniformsLib.lights,
6017                                 {
6018                                         emissive: { value: new Color( 0x000000 ) },
6019                                         specular: { value: new Color( 0x111111 ) },
6020                                         shininess: { value: 30 }
6021                                 }
6022                         ] ),
6023
6024                         vertexShader: ShaderChunk.meshphong_vert,
6025                         fragmentShader: ShaderChunk.meshphong_frag
6026
6027                 },
6028
6029                 standard: {
6030
6031                         uniforms: UniformsUtils.merge( [
6032                                 UniformsLib.common,
6033                                 UniformsLib.envmap,
6034                                 UniformsLib.aomap,
6035                                 UniformsLib.lightmap,
6036                                 UniformsLib.emissivemap,
6037                                 UniformsLib.bumpmap,
6038                                 UniformsLib.normalmap,
6039                                 UniformsLib.displacementmap,
6040                                 UniformsLib.roughnessmap,
6041                                 UniformsLib.metalnessmap,
6042                                 UniformsLib.fog,
6043                                 UniformsLib.lights,
6044                                 {
6045                                         emissive: { value: new Color( 0x000000 ) },
6046                                         roughness: { value: 0.5 },
6047                                         metalness: { value: 0.5 },
6048                                         envMapIntensity: { value: 1 } // temporary
6049                                 }
6050                         ] ),
6051
6052                         vertexShader: ShaderChunk.meshphysical_vert,
6053                         fragmentShader: ShaderChunk.meshphysical_frag
6054
6055                 },
6056
6057                 points: {
6058
6059                         uniforms: UniformsUtils.merge( [
6060                                 UniformsLib.points,
6061                                 UniformsLib.fog
6062                         ] ),
6063
6064                         vertexShader: ShaderChunk.points_vert,
6065                         fragmentShader: ShaderChunk.points_frag
6066
6067                 },
6068
6069                 dashed: {
6070
6071                         uniforms: UniformsUtils.merge( [
6072                                 UniformsLib.common,
6073                                 UniformsLib.fog,
6074                                 {
6075                                         scale: { value: 1 },
6076                                         dashSize: { value: 1 },
6077                                         totalSize: { value: 2 }
6078                                 }
6079                         ] ),
6080
6081                         vertexShader: ShaderChunk.linedashed_vert,
6082                         fragmentShader: ShaderChunk.linedashed_frag
6083
6084                 },
6085
6086                 depth: {
6087
6088                         uniforms: UniformsUtils.merge( [
6089                                 UniformsLib.common,
6090                                 UniformsLib.displacementmap
6091                         ] ),
6092
6093                         vertexShader: ShaderChunk.depth_vert,
6094                         fragmentShader: ShaderChunk.depth_frag
6095
6096                 },
6097
6098                 normal: {
6099
6100                         uniforms: UniformsUtils.merge( [
6101                                 UniformsLib.common,
6102                                 UniformsLib.bumpmap,
6103                                 UniformsLib.normalmap,
6104                                 UniformsLib.displacementmap,
6105                                 {
6106                                         opacity: { value: 1.0 }
6107                                 }
6108                         ] ),
6109
6110                         vertexShader: ShaderChunk.normal_vert,
6111                         fragmentShader: ShaderChunk.normal_frag
6112
6113                 },
6114
6115                 /* -------------------------------------------------------------------------
6116                 //      Cube map shader
6117                  ------------------------------------------------------------------------- */
6118
6119                 cube: {
6120
6121                         uniforms: {
6122                                 tCube: { value: null },
6123                                 tFlip: { value: - 1 },
6124                                 opacity: { value: 1.0 }
6125                         },
6126
6127                         vertexShader: ShaderChunk.cube_vert,
6128                         fragmentShader: ShaderChunk.cube_frag
6129
6130                 },
6131
6132                 equirect: {
6133
6134                         uniforms: {
6135                                 tEquirect: { value: null },
6136                         },
6137
6138                         vertexShader: ShaderChunk.equirect_vert,
6139                         fragmentShader: ShaderChunk.equirect_frag
6140
6141                 },
6142
6143                 distanceRGBA: {
6144
6145                         uniforms: UniformsUtils.merge( [
6146                                 UniformsLib.common,
6147                                 UniformsLib.displacementmap,
6148                                 {
6149                                         referencePosition: { value: new Vector3() },
6150                                         nearDistance: { value: 1 },
6151                                         farDistance: { value: 1000 }
6152                                 }
6153                         ] ),
6154
6155                         vertexShader: ShaderChunk.distanceRGBA_vert,
6156                         fragmentShader: ShaderChunk.distanceRGBA_frag
6157
6158                 },
6159
6160                 shadow: {
6161
6162                         uniforms: UniformsUtils.merge( [
6163                                 UniformsLib.lights,
6164                                 {
6165                                         color: { value: new Color( 0x00000 ) },
6166                                         opacity: { value: 1.0 }
6167                                 },
6168                         ] ),
6169
6170                         vertexShader: ShaderChunk.shadow_vert,
6171                         fragmentShader: ShaderChunk.shadow_frag
6172
6173                 }
6174
6175         };
6176
6177         ShaderLib.physical = {
6178
6179                 uniforms: UniformsUtils.merge( [
6180                         ShaderLib.standard.uniforms,
6181                         {
6182                                 clearCoat: { value: 0 },
6183                                 clearCoatRoughness: { value: 0 }
6184                         }
6185                 ] ),
6186
6187                 vertexShader: ShaderChunk.meshphysical_vert,
6188                 fragmentShader: ShaderChunk.meshphysical_frag
6189
6190         };
6191
6192         /**
6193          * @author bhouston / http://clara.io
6194          */
6195
6196         function Box2( min, max ) {
6197
6198                 this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
6199                 this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
6200
6201         }
6202
6203         Object.assign( Box2.prototype, {
6204
6205                 set: function ( min, max ) {
6206
6207                         this.min.copy( min );
6208                         this.max.copy( max );
6209
6210                         return this;
6211
6212                 },
6213
6214                 setFromPoints: function ( points ) {
6215
6216                         this.makeEmpty();
6217
6218                         for ( var i = 0, il = points.length; i < il; i ++ ) {
6219
6220                                 this.expandByPoint( points[ i ] );
6221
6222                         }
6223
6224                         return this;
6225
6226                 },
6227
6228                 setFromCenterAndSize: function () {
6229
6230                         var v1 = new Vector2();
6231
6232                         return function setFromCenterAndSize( center, size ) {
6233
6234                                 var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
6235                                 this.min.copy( center ).sub( halfSize );
6236                                 this.max.copy( center ).add( halfSize );
6237
6238                                 return this;
6239
6240                         };
6241
6242                 }(),
6243
6244                 clone: function () {
6245
6246                         return new this.constructor().copy( this );
6247
6248                 },
6249
6250                 copy: function ( box ) {
6251
6252                         this.min.copy( box.min );
6253                         this.max.copy( box.max );
6254
6255                         return this;
6256
6257                 },
6258
6259                 makeEmpty: function () {
6260
6261                         this.min.x = this.min.y = + Infinity;
6262                         this.max.x = this.max.y = - Infinity;
6263
6264                         return this;
6265
6266                 },
6267
6268                 isEmpty: function () {
6269
6270                         // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
6271
6272                         return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
6273
6274                 },
6275
6276                 getCenter: function ( optionalTarget ) {
6277
6278                         var result = optionalTarget || new Vector2();
6279                         return this.isEmpty() ? result.set( 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
6280
6281                 },
6282
6283                 getSize: function ( optionalTarget ) {
6284
6285                         var result = optionalTarget || new Vector2();
6286                         return this.isEmpty() ? result.set( 0, 0 ) : result.subVectors( this.max, this.min );
6287
6288                 },
6289
6290                 expandByPoint: function ( point ) {
6291
6292                         this.min.min( point );
6293                         this.max.max( point );
6294
6295                         return this;
6296
6297                 },
6298
6299                 expandByVector: function ( vector ) {
6300
6301                         this.min.sub( vector );
6302                         this.max.add( vector );
6303
6304                         return this;
6305
6306                 },
6307
6308                 expandByScalar: function ( scalar ) {
6309
6310                         this.min.addScalar( - scalar );
6311                         this.max.addScalar( scalar );
6312
6313                         return this;
6314
6315                 },
6316
6317                 containsPoint: function ( point ) {
6318
6319                         return point.x < this.min.x || point.x > this.max.x ||
6320                                 point.y < this.min.y || point.y > this.max.y ? false : true;
6321
6322                 },
6323
6324                 containsBox: function ( box ) {
6325
6326                         return this.min.x <= box.min.x && box.max.x <= this.max.x &&
6327                                 this.min.y <= box.min.y && box.max.y <= this.max.y;
6328
6329                 },
6330
6331                 getParameter: function ( point, optionalTarget ) {
6332
6333                         // This can potentially have a divide by zero if the box
6334                         // has a size dimension of 0.
6335
6336                         var result = optionalTarget || new Vector2();
6337
6338                         return result.set(
6339                                 ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
6340                                 ( point.y - this.min.y ) / ( this.max.y - this.min.y )
6341                         );
6342
6343                 },
6344
6345                 intersectsBox: function ( box ) {
6346
6347                         // using 4 splitting planes to rule out intersections
6348
6349                         return box.max.x < this.min.x || box.min.x > this.max.x ||
6350                                 box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
6351
6352                 },
6353
6354                 clampPoint: function ( point, optionalTarget ) {
6355
6356                         var result = optionalTarget || new Vector2();
6357                         return result.copy( point ).clamp( this.min, this.max );
6358
6359                 },
6360
6361                 distanceToPoint: function () {
6362
6363                         var v1 = new Vector2();
6364
6365                         return function distanceToPoint( point ) {
6366
6367                                 var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
6368                                 return clampedPoint.sub( point ).length();
6369
6370                         };
6371
6372                 }(),
6373
6374                 intersect: function ( box ) {
6375
6376                         this.min.max( box.min );
6377                         this.max.min( box.max );
6378
6379                         return this;
6380
6381                 },
6382
6383                 union: function ( box ) {
6384
6385                         this.min.min( box.min );
6386                         this.max.max( box.max );
6387
6388                         return this;
6389
6390                 },
6391
6392                 translate: function ( offset ) {
6393
6394                         this.min.add( offset );
6395                         this.max.add( offset );
6396
6397                         return this;
6398
6399                 },
6400
6401                 equals: function ( box ) {
6402
6403                         return box.min.equals( this.min ) && box.max.equals( this.max );
6404
6405                 }
6406
6407         } );
6408
6409         /**
6410          * @author mikael emtinger / http://gomo.se/
6411          * @author alteredq / http://alteredqualia.com/
6412          */
6413
6414         function WebGLFlareRenderer( renderer, gl, state, textures, capabilities ) {
6415
6416                 var vertexBuffer, elementBuffer;
6417                 var shader, program, attributes, uniforms;
6418
6419                 var tempTexture, occlusionTexture;
6420
6421                 function init() {
6422
6423                         var vertices = new Float32Array( [
6424                                 - 1, - 1,  0, 0,
6425                                  1, - 1,  1, 0,
6426                                  1,  1,  1, 1,
6427                                 - 1,  1,  0, 1
6428                         ] );
6429
6430                         var faces = new Uint16Array( [
6431                                 0, 1, 2,
6432                                 0, 2, 3
6433                         ] );
6434
6435                         // buffers
6436
6437                         vertexBuffer     = gl.createBuffer();
6438                         elementBuffer    = gl.createBuffer();
6439
6440                         gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
6441                         gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
6442
6443                         gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
6444                         gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
6445
6446                         // textures
6447
6448                         tempTexture      = gl.createTexture();
6449                         occlusionTexture = gl.createTexture();
6450
6451                         state.bindTexture( gl.TEXTURE_2D, tempTexture );
6452                         gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null );
6453                         gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
6454                         gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
6455                         gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
6456                         gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
6457
6458                         state.bindTexture( gl.TEXTURE_2D, occlusionTexture );
6459                         gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null );
6460                         gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
6461                         gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
6462                         gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
6463                         gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
6464
6465                         shader = {
6466
6467                                 vertexShader: [
6468
6469                                         "uniform lowp int renderType;",
6470
6471                                         "uniform vec3 screenPosition;",
6472                                         "uniform vec2 scale;",
6473                                         "uniform float rotation;",
6474
6475                                         "uniform sampler2D occlusionMap;",
6476
6477                                         "attribute vec2 position;",
6478                                         "attribute vec2 uv;",
6479
6480                                         "varying vec2 vUV;",
6481                                         "varying float vVisibility;",
6482
6483                                         "void main() {",
6484
6485                                                 "vUV = uv;",
6486
6487                                                 "vec2 pos = position;",
6488
6489                                                 "if ( renderType == 2 ) {",
6490
6491                                                         "vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );",
6492                                                         "visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );",
6493                                                         "visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );",
6494                                                         "visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );",
6495                                                         "visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );",
6496                                                         "visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );",
6497                                                         "visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );",
6498                                                         "visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );",
6499                                                         "visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );",
6500
6501                                                         "vVisibility =        visibility.r / 9.0;",
6502                                                         "vVisibility *= 1.0 - visibility.g / 9.0;",
6503                                                         "vVisibility *=       visibility.b / 9.0;",
6504                                                         "vVisibility *= 1.0 - visibility.a / 9.0;",
6505
6506                                                         "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;",
6507                                                         "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;",
6508
6509                                                 "}",
6510
6511                                                 "gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );",
6512
6513                                         "}"
6514
6515                                 ].join( "\n" ),
6516
6517                                 fragmentShader: [
6518
6519                                         "uniform lowp int renderType;",
6520
6521                                         "uniform sampler2D map;",
6522                                         "uniform float opacity;",
6523                                         "uniform vec3 color;",
6524
6525                                         "varying vec2 vUV;",
6526                                         "varying float vVisibility;",
6527
6528                                         "void main() {",
6529
6530                                                 // pink square
6531
6532                                                 "if ( renderType == 0 ) {",
6533
6534                                                         "gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );",
6535
6536                                                 // restore
6537
6538                                                 "} else if ( renderType == 1 ) {",
6539
6540                                                         "gl_FragColor = texture2D( map, vUV );",
6541
6542                                                 // flare
6543
6544                                                 "} else {",
6545
6546                                                         "vec4 texture = texture2D( map, vUV );",
6547                                                         "texture.a *= opacity * vVisibility;",
6548                                                         "gl_FragColor = texture;",
6549                                                         "gl_FragColor.rgb *= color;",
6550
6551                                                 "}",
6552
6553                                         "}"
6554
6555                                 ].join( "\n" )
6556
6557                         };
6558
6559                         program = createProgram( shader );
6560
6561                         attributes = {
6562                                 vertex: gl.getAttribLocation ( program, "position" ),
6563                                 uv:     gl.getAttribLocation ( program, "uv" )
6564                         };
6565
6566                         uniforms = {
6567                                 renderType:     gl.getUniformLocation( program, "renderType" ),
6568                                 map:            gl.getUniformLocation( program, "map" ),
6569                                 occlusionMap:   gl.getUniformLocation( program, "occlusionMap" ),
6570                                 opacity:        gl.getUniformLocation( program, "opacity" ),
6571                                 color:          gl.getUniformLocation( program, "color" ),
6572                                 scale:          gl.getUniformLocation( program, "scale" ),
6573                                 rotation:       gl.getUniformLocation( program, "rotation" ),
6574                                 screenPosition: gl.getUniformLocation( program, "screenPosition" )
6575                         };
6576
6577                 }
6578
6579                 /*
6580                  * Render lens flares
6581                  * Method: renders 16x16 0xff00ff-colored points scattered over the light source area,
6582                  *         reads these back and calculates occlusion.
6583                  */
6584
6585                 this.render = function ( flares, scene, camera, viewport ) {
6586
6587                         if ( flares.length === 0 ) return;
6588
6589                         var tempPosition = new Vector3();
6590
6591                         var invAspect = viewport.w / viewport.z,
6592                                 halfViewportWidth = viewport.z * 0.5,
6593                                 halfViewportHeight = viewport.w * 0.5;
6594
6595                         var size = 16 / viewport.w,
6596                                 scale = new Vector2( size * invAspect, size );
6597
6598                         var screenPosition = new Vector3( 1, 1, 0 ),
6599                                 screenPositionPixels = new Vector2( 1, 1 );
6600
6601                         var validArea = new Box2();
6602
6603                         validArea.min.set( viewport.x, viewport.y );
6604                         validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) );
6605
6606                         if ( program === undefined ) {
6607
6608                                 init();
6609
6610                         }
6611
6612                         state.useProgram( program );
6613
6614                         state.initAttributes();
6615                         state.enableAttribute( attributes.vertex );
6616                         state.enableAttribute( attributes.uv );
6617                         state.disableUnusedAttributes();
6618
6619                         // loop through all lens flares to update their occlusion and positions
6620                         // setup gl and common used attribs/uniforms
6621
6622                         gl.uniform1i( uniforms.occlusionMap, 0 );
6623                         gl.uniform1i( uniforms.map, 1 );
6624
6625                         gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
6626                         gl.vertexAttribPointer( attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0 );
6627                         gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
6628
6629                         gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
6630
6631                         state.disable( gl.CULL_FACE );
6632                         state.buffers.depth.setMask( false );
6633
6634                         for ( var i = 0, l = flares.length; i < l; i ++ ) {
6635
6636                                 size = 16 / viewport.w;
6637                                 scale.set( size * invAspect, size );
6638
6639                                 // calc object screen position
6640
6641                                 var flare = flares[ i ];
6642
6643                                 tempPosition.set( flare.matrixWorld.elements[ 12 ], flare.matrixWorld.elements[ 13 ], flare.matrixWorld.elements[ 14 ] );
6644
6645                                 tempPosition.applyMatrix4( camera.matrixWorldInverse );
6646                                 tempPosition.applyMatrix4( camera.projectionMatrix );
6647
6648                                 // setup arrays for gl programs
6649
6650                                 screenPosition.copy( tempPosition );
6651
6652                                 // horizontal and vertical coordinate of the lower left corner of the pixels to copy
6653
6654                                 screenPositionPixels.x = viewport.x + ( screenPosition.x * halfViewportWidth ) + halfViewportWidth - 8;
6655                                 screenPositionPixels.y = viewport.y + ( screenPosition.y * halfViewportHeight ) + halfViewportHeight - 8;
6656
6657                                 // screen cull
6658
6659                                 if ( validArea.containsPoint( screenPositionPixels ) === true ) {
6660
6661                                         // save current RGB to temp texture
6662
6663                                         state.activeTexture( gl.TEXTURE0 );
6664                                         state.bindTexture( gl.TEXTURE_2D, null );
6665                                         state.activeTexture( gl.TEXTURE1 );
6666                                         state.bindTexture( gl.TEXTURE_2D, tempTexture );
6667                                         gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 );
6668
6669
6670                                         // render pink quad
6671
6672                                         gl.uniform1i( uniforms.renderType, 0 );
6673                                         gl.uniform2f( uniforms.scale, scale.x, scale.y );
6674                                         gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
6675
6676                                         state.disable( gl.BLEND );
6677                                         state.enable( gl.DEPTH_TEST );
6678
6679                                         gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
6680
6681
6682                                         // copy result to occlusionMap
6683
6684                                         state.activeTexture( gl.TEXTURE0 );
6685                                         state.bindTexture( gl.TEXTURE_2D, occlusionTexture );
6686                                         gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 );
6687
6688
6689                                         // restore graphics
6690
6691                                         gl.uniform1i( uniforms.renderType, 1 );
6692                                         state.disable( gl.DEPTH_TEST );
6693
6694                                         state.activeTexture( gl.TEXTURE1 );
6695                                         state.bindTexture( gl.TEXTURE_2D, tempTexture );
6696                                         gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
6697
6698
6699                                         // update object positions
6700
6701                                         flare.positionScreen.copy( screenPosition );
6702
6703                                         if ( flare.customUpdateCallback ) {
6704
6705                                                 flare.customUpdateCallback( flare );
6706
6707                                         } else {
6708
6709                                                 flare.updateLensFlares();
6710
6711                                         }
6712
6713                                         // render flares
6714
6715                                         gl.uniform1i( uniforms.renderType, 2 );
6716                                         state.enable( gl.BLEND );
6717
6718                                         for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
6719
6720                                                 var sprite = flare.lensFlares[ j ];
6721
6722                                                 if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
6723
6724                                                         screenPosition.x = sprite.x;
6725                                                         screenPosition.y = sprite.y;
6726                                                         screenPosition.z = sprite.z;
6727
6728                                                         size = sprite.size * sprite.scale / viewport.w;
6729
6730                                                         scale.x = size * invAspect;
6731                                                         scale.y = size;
6732
6733                                                         gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
6734                                                         gl.uniform2f( uniforms.scale, scale.x, scale.y );
6735                                                         gl.uniform1f( uniforms.rotation, sprite.rotation );
6736
6737                                                         gl.uniform1f( uniforms.opacity, sprite.opacity );
6738                                                         gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
6739
6740                                                         state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
6741
6742                                                         textures.setTexture2D( sprite.texture, 1 );
6743
6744                                                         gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
6745
6746                                                 }
6747
6748                                         }
6749
6750                                 }
6751
6752                         }
6753
6754                         // restore gl
6755
6756                         state.enable( gl.CULL_FACE );
6757                         state.enable( gl.DEPTH_TEST );
6758                         state.buffers.depth.setMask( true );
6759
6760                         state.reset();
6761
6762                 };
6763
6764                 function createProgram( shader ) {
6765
6766                         var program = gl.createProgram();
6767
6768                         var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
6769                         var vertexShader = gl.createShader( gl.VERTEX_SHADER );
6770
6771                         var prefix = "precision " + capabilities.precision + " float;\n";
6772
6773                         gl.shaderSource( fragmentShader, prefix + shader.fragmentShader );
6774                         gl.shaderSource( vertexShader, prefix + shader.vertexShader );
6775
6776                         gl.compileShader( fragmentShader );
6777                         gl.compileShader( vertexShader );
6778
6779                         gl.attachShader( program, fragmentShader );
6780                         gl.attachShader( program, vertexShader );
6781
6782                         gl.linkProgram( program );
6783
6784                         return program;
6785
6786                 }
6787
6788         }
6789
6790         /**
6791          * @author mrdoob / http://mrdoob.com/
6792          */
6793
6794         function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
6795
6796                 Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
6797
6798                 this.needsUpdate = true;
6799
6800         }
6801
6802         CanvasTexture.prototype = Object.create( Texture.prototype );
6803         CanvasTexture.prototype.constructor = CanvasTexture;
6804
6805         /**
6806          * @author mikael emtinger / http://gomo.se/
6807          * @author alteredq / http://alteredqualia.com/
6808          */
6809
6810         function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) {
6811
6812                 var vertexBuffer, elementBuffer;
6813                 var program, attributes, uniforms;
6814
6815                 var texture;
6816
6817                 // decompose matrixWorld
6818
6819                 var spritePosition = new Vector3();
6820                 var spriteRotation = new Quaternion();
6821                 var spriteScale = new Vector3();
6822
6823                 function init() {
6824
6825                         var vertices = new Float32Array( [
6826                                 - 0.5, - 0.5,  0, 0,
6827                                   0.5, - 0.5,  1, 0,
6828                                   0.5,   0.5,  1, 1,
6829                                 - 0.5,   0.5,  0, 1
6830                         ] );
6831
6832                         var faces = new Uint16Array( [
6833                                 0, 1, 2,
6834                                 0, 2, 3
6835                         ] );
6836
6837                         vertexBuffer  = gl.createBuffer();
6838                         elementBuffer = gl.createBuffer();
6839
6840                         gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
6841                         gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
6842
6843                         gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
6844                         gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
6845
6846                         program = createProgram();
6847
6848                         attributes = {
6849                                 position:                       gl.getAttribLocation ( program, 'position' ),
6850                                 uv:                                     gl.getAttribLocation ( program, 'uv' )
6851                         };
6852
6853                         uniforms = {
6854                                 uvOffset:                       gl.getUniformLocation( program, 'uvOffset' ),
6855                                 uvScale:                        gl.getUniformLocation( program, 'uvScale' ),
6856
6857                                 rotation:                       gl.getUniformLocation( program, 'rotation' ),
6858                                 scale:                          gl.getUniformLocation( program, 'scale' ),
6859
6860                                 color:                          gl.getUniformLocation( program, 'color' ),
6861                                 map:                            gl.getUniformLocation( program, 'map' ),
6862                                 opacity:                        gl.getUniformLocation( program, 'opacity' ),
6863
6864                                 modelViewMatrix:        gl.getUniformLocation( program, 'modelViewMatrix' ),
6865                                 projectionMatrix:       gl.getUniformLocation( program, 'projectionMatrix' ),
6866
6867                                 fogType:                        gl.getUniformLocation( program, 'fogType' ),
6868                                 fogDensity:                     gl.getUniformLocation( program, 'fogDensity' ),
6869                                 fogNear:                        gl.getUniformLocation( program, 'fogNear' ),
6870                                 fogFar:                         gl.getUniformLocation( program, 'fogFar' ),
6871                                 fogColor:                       gl.getUniformLocation( program, 'fogColor' ),
6872
6873                                 alphaTest:                      gl.getUniformLocation( program, 'alphaTest' )
6874                         };
6875
6876                         var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
6877                         canvas.width = 8;
6878                         canvas.height = 8;
6879
6880                         var context = canvas.getContext( '2d' );
6881                         context.fillStyle = 'white';
6882                         context.fillRect( 0, 0, 8, 8 );
6883
6884                         texture = new CanvasTexture( canvas );
6885
6886                 }
6887
6888                 this.render = function ( sprites, scene, camera ) {
6889
6890                         if ( sprites.length === 0 ) return;
6891
6892                         // setup gl
6893
6894                         if ( program === undefined ) {
6895
6896                                 init();
6897
6898                         }
6899
6900                         state.useProgram( program );
6901
6902                         state.initAttributes();
6903                         state.enableAttribute( attributes.position );
6904                         state.enableAttribute( attributes.uv );
6905                         state.disableUnusedAttributes();
6906
6907                         state.disable( gl.CULL_FACE );
6908                         state.enable( gl.BLEND );
6909
6910                         gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
6911                         gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 );
6912                         gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
6913
6914                         gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
6915
6916                         gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
6917
6918                         state.activeTexture( gl.TEXTURE0 );
6919                         gl.uniform1i( uniforms.map, 0 );
6920
6921                         var oldFogType = 0;
6922                         var sceneFogType = 0;
6923                         var fog = scene.fog;
6924
6925                         if ( fog ) {
6926
6927                                 gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
6928
6929                                 if ( fog.isFog ) {
6930
6931                                         gl.uniform1f( uniforms.fogNear, fog.near );
6932                                         gl.uniform1f( uniforms.fogFar, fog.far );
6933
6934                                         gl.uniform1i( uniforms.fogType, 1 );
6935                                         oldFogType = 1;
6936                                         sceneFogType = 1;
6937
6938                                 } else if ( fog.isFogExp2 ) {
6939
6940                                         gl.uniform1f( uniforms.fogDensity, fog.density );
6941
6942                                         gl.uniform1i( uniforms.fogType, 2 );
6943                                         oldFogType = 2;
6944                                         sceneFogType = 2;
6945
6946                                 }
6947
6948                         } else {
6949
6950                                 gl.uniform1i( uniforms.fogType, 0 );
6951                                 oldFogType = 0;
6952                                 sceneFogType = 0;
6953
6954                         }
6955
6956
6957                         // update positions and sort
6958
6959                         for ( var i = 0, l = sprites.length; i < l; i ++ ) {
6960
6961                                 var sprite = sprites[ i ];
6962
6963                                 sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
6964                                 sprite.z = - sprite.modelViewMatrix.elements[ 14 ];
6965
6966                         }
6967
6968                         sprites.sort( painterSortStable );
6969
6970                         // render all sprites
6971
6972                         var scale = [];
6973
6974                         for ( var i = 0, l = sprites.length; i < l; i ++ ) {
6975
6976                                 var sprite = sprites[ i ];
6977                                 var material = sprite.material;
6978
6979                                 if ( material.visible === false ) continue;
6980
6981                                 sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined );
6982
6983                                 gl.uniform1f( uniforms.alphaTest, material.alphaTest );
6984                                 gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements );
6985
6986                                 sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale );
6987
6988                                 scale[ 0 ] = spriteScale.x;
6989                                 scale[ 1 ] = spriteScale.y;
6990
6991                                 var fogType = 0;
6992
6993                                 if ( scene.fog && material.fog ) {
6994
6995                                         fogType = sceneFogType;
6996
6997                                 }
6998
6999                                 if ( oldFogType !== fogType ) {
7000
7001                                         gl.uniform1i( uniforms.fogType, fogType );
7002                                         oldFogType = fogType;
7003
7004                                 }
7005
7006                                 if ( material.map !== null ) {
7007
7008                                         gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
7009                                         gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
7010
7011                                 } else {
7012
7013                                         gl.uniform2f( uniforms.uvOffset, 0, 0 );
7014                                         gl.uniform2f( uniforms.uvScale, 1, 1 );
7015
7016                                 }
7017
7018                                 gl.uniform1f( uniforms.opacity, material.opacity );
7019                                 gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
7020
7021                                 gl.uniform1f( uniforms.rotation, material.rotation );
7022                                 gl.uniform2fv( uniforms.scale, scale );
7023
7024                                 state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
7025                                 state.buffers.depth.setTest( material.depthTest );
7026                                 state.buffers.depth.setMask( material.depthWrite );
7027
7028                                 textures.setTexture2D( material.map || texture, 0 );
7029
7030                                 gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
7031
7032                                 sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined );
7033
7034                         }
7035
7036                         // restore gl
7037
7038                         state.enable( gl.CULL_FACE );
7039
7040                         state.reset();
7041
7042                 };
7043
7044                 function createProgram() {
7045
7046                         var program = gl.createProgram();
7047
7048                         var vertexShader = gl.createShader( gl.VERTEX_SHADER );
7049                         var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
7050
7051                         gl.shaderSource( vertexShader, [
7052
7053                                 'precision ' + capabilities.precision + ' float;',
7054
7055                                 '#define SHADER_NAME ' + 'SpriteMaterial',
7056
7057                                 'uniform mat4 modelViewMatrix;',
7058                                 'uniform mat4 projectionMatrix;',
7059                                 'uniform float rotation;',
7060                                 'uniform vec2 scale;',
7061                                 'uniform vec2 uvOffset;',
7062                                 'uniform vec2 uvScale;',
7063
7064                                 'attribute vec2 position;',
7065                                 'attribute vec2 uv;',
7066
7067                                 'varying vec2 vUV;',
7068
7069                                 'void main() {',
7070
7071                                         'vUV = uvOffset + uv * uvScale;',
7072
7073                                         'vec2 alignedPosition = position * scale;',
7074
7075                                         'vec2 rotatedPosition;',
7076                                         'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
7077                                         'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
7078
7079                                         'vec4 finalPosition;',
7080
7081                                         'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
7082                                         'finalPosition.xy += rotatedPosition;',
7083                                         'finalPosition = projectionMatrix * finalPosition;',
7084
7085                                         'gl_Position = finalPosition;',
7086
7087                                 '}'
7088
7089                         ].join( '\n' ) );
7090
7091                         gl.shaderSource( fragmentShader, [
7092
7093                                 'precision ' + capabilities.precision + ' float;',
7094
7095                                 '#define SHADER_NAME ' + 'SpriteMaterial',
7096
7097                                 'uniform vec3 color;',
7098                                 'uniform sampler2D map;',
7099                                 'uniform float opacity;',
7100
7101                                 'uniform int fogType;',
7102                                 'uniform vec3 fogColor;',
7103                                 'uniform float fogDensity;',
7104                                 'uniform float fogNear;',
7105                                 'uniform float fogFar;',
7106                                 'uniform float alphaTest;',
7107
7108                                 'varying vec2 vUV;',
7109
7110                                 'void main() {',
7111
7112                                         'vec4 texture = texture2D( map, vUV );',
7113
7114                                         'if ( texture.a < alphaTest ) discard;',
7115
7116                                         'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
7117
7118                                         'if ( fogType > 0 ) {',
7119
7120                                                 'float depth = gl_FragCoord.z / gl_FragCoord.w;',
7121                                                 'float fogFactor = 0.0;',
7122
7123                                                 'if ( fogType == 1 ) {',
7124
7125                                                         'fogFactor = smoothstep( fogNear, fogFar, depth );',
7126
7127                                                 '} else {',
7128
7129                                                         'const float LOG2 = 1.442695;',
7130                                                         'fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );',
7131                                                         'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
7132
7133                                                 '}',
7134
7135                                                 'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );',
7136
7137                                         '}',
7138
7139                                 '}'
7140
7141                         ].join( '\n' ) );
7142
7143                         gl.compileShader( vertexShader );
7144                         gl.compileShader( fragmentShader );
7145
7146                         gl.attachShader( program, vertexShader );
7147                         gl.attachShader( program, fragmentShader );
7148
7149                         gl.linkProgram( program );
7150
7151                         return program;
7152
7153                 }
7154
7155                 function painterSortStable( a, b ) {
7156
7157                         if ( a.renderOrder !== b.renderOrder ) {
7158
7159                                 return a.renderOrder - b.renderOrder;
7160
7161                         } else if ( a.z !== b.z ) {
7162
7163                                 return b.z - a.z;
7164
7165                         } else {
7166
7167                                 return b.id - a.id;
7168
7169                         }
7170
7171                 }
7172
7173         }
7174
7175         /**
7176          * @author mrdoob / http://mrdoob.com/
7177          * @author alteredq / http://alteredqualia.com/
7178          */
7179
7180         var materialId = 0;
7181
7182         function Material() {
7183
7184                 Object.defineProperty( this, 'id', { value: materialId ++ } );
7185
7186                 this.uuid = _Math.generateUUID();
7187
7188                 this.name = '';
7189                 this.type = 'Material';
7190
7191                 this.fog = true;
7192                 this.lights = true;
7193
7194                 this.blending = NormalBlending;
7195                 this.side = FrontSide;
7196                 this.flatShading = false;
7197                 this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
7198
7199                 this.opacity = 1;
7200                 this.transparent = false;
7201
7202                 this.blendSrc = SrcAlphaFactor;
7203                 this.blendDst = OneMinusSrcAlphaFactor;
7204                 this.blendEquation = AddEquation;
7205                 this.blendSrcAlpha = null;
7206                 this.blendDstAlpha = null;
7207                 this.blendEquationAlpha = null;
7208
7209                 this.depthFunc = LessEqualDepth;
7210                 this.depthTest = true;
7211                 this.depthWrite = true;
7212
7213                 this.clippingPlanes = null;
7214                 this.clipIntersection = false;
7215                 this.clipShadows = false;
7216
7217                 this.colorWrite = true;
7218
7219                 this.precision = null; // override the renderer's default precision for this material
7220
7221                 this.polygonOffset = false;
7222                 this.polygonOffsetFactor = 0;
7223                 this.polygonOffsetUnits = 0;
7224
7225                 this.dithering = false;
7226
7227                 this.alphaTest = 0;
7228                 this.premultipliedAlpha = false;
7229
7230                 this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer
7231
7232                 this.visible = true;
7233
7234                 this.userData = {};
7235
7236                 this.needsUpdate = true;
7237
7238         }
7239
7240         Object.assign( Material.prototype, EventDispatcher.prototype, {
7241
7242                 isMaterial: true,
7243
7244                 onBeforeCompile: function () {},
7245
7246                 setValues: function ( values ) {
7247
7248                         if ( values === undefined ) return;
7249
7250                         for ( var key in values ) {
7251
7252                                 var newValue = values[ key ];
7253
7254                                 if ( newValue === undefined ) {
7255
7256                                         console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
7257                                         continue;
7258
7259                                 }
7260
7261                                 // for backward compatability if shading is set in the constructor
7262                                 if ( key === 'shading' ) {
7263
7264                                         console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
7265                                         this.flatShading = ( newValue === FlatShading ) ? true : false;
7266                                         continue;
7267
7268                                 }
7269
7270                                 var currentValue = this[ key ];
7271
7272                                 if ( currentValue === undefined ) {
7273
7274                                         console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
7275                                         continue;
7276
7277                                 }
7278
7279                                 if ( currentValue && currentValue.isColor ) {
7280
7281                                         currentValue.set( newValue );
7282
7283                                 } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
7284
7285                                         currentValue.copy( newValue );
7286
7287                                 } else if ( key === 'overdraw' ) {
7288
7289                                         // ensure overdraw is backwards-compatible with legacy boolean type
7290                                         this[ key ] = Number( newValue );
7291
7292                                 } else {
7293
7294                                         this[ key ] = newValue;
7295
7296                                 }
7297
7298                         }
7299
7300                 },
7301
7302                 toJSON: function ( meta ) {
7303
7304                         var isRoot = meta === undefined;
7305
7306                         if ( isRoot ) {
7307
7308                                 meta = {
7309                                         textures: {},
7310                                         images: {}
7311                                 };
7312
7313                         }
7314
7315                         var data = {
7316                                 metadata: {
7317                                         version: 4.5,
7318                                         type: 'Material',
7319                                         generator: 'Material.toJSON'
7320                                 }
7321                         };
7322
7323                         // standard Material serialization
7324                         data.uuid = this.uuid;
7325                         data.type = this.type;
7326
7327                         if ( this.name !== '' ) data.name = this.name;
7328
7329                         if ( this.color && this.color.isColor ) data.color = this.color.getHex();
7330
7331                         if ( this.roughness !== undefined ) data.roughness = this.roughness;
7332                         if ( this.metalness !== undefined ) data.metalness = this.metalness;
7333
7334                         if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
7335                         if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
7336                         if ( this.shininess !== undefined ) data.shininess = this.shininess;
7337                         if ( this.clearCoat !== undefined ) data.clearCoat = this.clearCoat;
7338                         if ( this.clearCoatRoughness !== undefined ) data.clearCoatRoughness = this.clearCoatRoughness;
7339
7340                         if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
7341                         if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
7342                         if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
7343                         if ( this.bumpMap && this.bumpMap.isTexture ) {
7344
7345                                 data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
7346                                 data.bumpScale = this.bumpScale;
7347
7348                         }
7349                         if ( this.normalMap && this.normalMap.isTexture ) {
7350
7351                                 data.normalMap = this.normalMap.toJSON( meta ).uuid;
7352                                 data.normalScale = this.normalScale.toArray();
7353
7354                         }
7355                         if ( this.displacementMap && this.displacementMap.isTexture ) {
7356
7357                                 data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
7358                                 data.displacementScale = this.displacementScale;
7359                                 data.displacementBias = this.displacementBias;
7360
7361                         }
7362                         if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
7363                         if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
7364
7365                         if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
7366                         if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
7367
7368                         if ( this.envMap && this.envMap.isTexture ) {
7369
7370                                 data.envMap = this.envMap.toJSON( meta ).uuid;
7371                                 data.reflectivity = this.reflectivity; // Scale behind envMap
7372
7373                         }
7374
7375                         if ( this.gradientMap && this.gradientMap.isTexture ) {
7376
7377                                 data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
7378
7379                         }
7380
7381                         if ( this.size !== undefined ) data.size = this.size;
7382                         if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
7383
7384                         if ( this.blending !== NormalBlending ) data.blending = this.blending;
7385                         if ( this.flatShading === true ) data.flatShading = this.flatShading;
7386                         if ( this.side !== FrontSide ) data.side = this.side;
7387                         if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors;
7388
7389                         if ( this.opacity < 1 ) data.opacity = this.opacity;
7390                         if ( this.transparent === true ) data.transparent = this.transparent;
7391
7392                         data.depthFunc = this.depthFunc;
7393                         data.depthTest = this.depthTest;
7394                         data.depthWrite = this.depthWrite;
7395
7396                         if ( this.dithering === true ) data.dithering = true;
7397
7398                         if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
7399                         if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
7400
7401                         if ( this.wireframe === true ) data.wireframe = this.wireframe;
7402                         if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
7403                         if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
7404                         if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
7405
7406                         if ( this.morphTargets === true ) data.morphTargets = true;
7407                         if ( this.skinning === true ) data.skinning = true;
7408
7409                         if ( this.visible === false ) data.visible = false;
7410                         if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
7411
7412                         // TODO: Copied from Object3D.toJSON
7413
7414                         function extractFromCache( cache ) {
7415
7416                                 var values = [];
7417
7418                                 for ( var key in cache ) {
7419
7420                                         var data = cache[ key ];
7421                                         delete data.metadata;
7422                                         values.push( data );
7423
7424                                 }
7425
7426                                 return values;
7427
7428                         }
7429
7430                         if ( isRoot ) {
7431
7432                                 var textures = extractFromCache( meta.textures );
7433                                 var images = extractFromCache( meta.images );
7434
7435                                 if ( textures.length > 0 ) data.textures = textures;
7436                                 if ( images.length > 0 ) data.images = images;
7437
7438                         }
7439
7440                         return data;
7441
7442                 },
7443
7444                 clone: function () {
7445
7446                         return new this.constructor().copy( this );
7447
7448                 },
7449
7450                 copy: function ( source ) {
7451
7452                         this.name = source.name;
7453
7454                         this.fog = source.fog;
7455                         this.lights = source.lights;
7456
7457                         this.blending = source.blending;
7458                         this.side = source.side;
7459                         this.flatShading = source.flatShading;
7460                         this.vertexColors = source.vertexColors;
7461
7462                         this.opacity = source.opacity;
7463                         this.transparent = source.transparent;
7464
7465                         this.blendSrc = source.blendSrc;
7466                         this.blendDst = source.blendDst;
7467                         this.blendEquation = source.blendEquation;
7468                         this.blendSrcAlpha = source.blendSrcAlpha;
7469                         this.blendDstAlpha = source.blendDstAlpha;
7470                         this.blendEquationAlpha = source.blendEquationAlpha;
7471
7472                         this.depthFunc = source.depthFunc;
7473                         this.depthTest = source.depthTest;
7474                         this.depthWrite = source.depthWrite;
7475
7476                         this.colorWrite = source.colorWrite;
7477
7478                         this.precision = source.precision;
7479
7480                         this.polygonOffset = source.polygonOffset;
7481                         this.polygonOffsetFactor = source.polygonOffsetFactor;
7482                         this.polygonOffsetUnits = source.polygonOffsetUnits;
7483
7484                         this.dithering = source.dithering;
7485
7486                         this.alphaTest = source.alphaTest;
7487                         this.premultipliedAlpha = source.premultipliedAlpha;
7488
7489                         this.overdraw = source.overdraw;
7490
7491                         this.visible = source.visible;
7492                         this.userData = JSON.parse( JSON.stringify( source.userData ) );
7493
7494                         this.clipShadows = source.clipShadows;
7495                         this.clipIntersection = source.clipIntersection;
7496
7497                         var srcPlanes = source.clippingPlanes,
7498                                 dstPlanes = null;
7499
7500                         if ( srcPlanes !== null ) {
7501
7502                                 var n = srcPlanes.length;
7503                                 dstPlanes = new Array( n );
7504
7505                                 for ( var i = 0; i !== n; ++ i )
7506                                         dstPlanes[ i ] = srcPlanes[ i ].clone();
7507
7508                         }
7509
7510                         this.clippingPlanes = dstPlanes;
7511
7512                         return this;
7513
7514                 },
7515
7516                 dispose: function () {
7517
7518                         this.dispatchEvent( { type: 'dispose' } );
7519
7520                 }
7521
7522         } );
7523
7524         /**
7525          * @author alteredq / http://alteredqualia.com/
7526          *
7527          * parameters = {
7528          *  defines: { "label" : "value" },
7529          *  uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
7530          *
7531          *  fragmentShader: <string>,
7532          *  vertexShader: <string>,
7533          *
7534          *  wireframe: <boolean>,
7535          *  wireframeLinewidth: <float>,
7536          *
7537          *  lights: <bool>,
7538          *
7539          *  skinning: <bool>,
7540          *  morphTargets: <bool>,
7541          *  morphNormals: <bool>
7542          * }
7543          */
7544
7545         function ShaderMaterial( parameters ) {
7546
7547                 Material.call( this );
7548
7549                 this.type = 'ShaderMaterial';
7550
7551                 this.defines = {};
7552                 this.uniforms = {};
7553
7554                 this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
7555                 this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
7556
7557                 this.linewidth = 1;
7558
7559                 this.wireframe = false;
7560                 this.wireframeLinewidth = 1;
7561
7562                 this.fog = false; // set to use scene fog
7563                 this.lights = false; // set to use scene lights
7564                 this.clipping = false; // set to use user-defined clipping planes
7565
7566                 this.skinning = false; // set to use skinning attribute streams
7567                 this.morphTargets = false; // set to use morph targets
7568                 this.morphNormals = false; // set to use morph normals
7569
7570                 this.extensions = {
7571                         derivatives: false, // set to use derivatives
7572                         fragDepth: false, // set to use fragment depth values
7573                         drawBuffers: false, // set to use draw buffers
7574                         shaderTextureLOD: false // set to use shader texture LOD
7575                 };
7576
7577                 // When rendered geometry doesn't include these attributes but the material does,
7578                 // use these default values in WebGL. This avoids errors when buffer data is missing.
7579                 this.defaultAttributeValues = {
7580                         'color': [ 1, 1, 1 ],
7581                         'uv': [ 0, 0 ],
7582                         'uv2': [ 0, 0 ]
7583                 };
7584
7585                 this.index0AttributeName = undefined;
7586
7587                 if ( parameters !== undefined ) {
7588
7589                         if ( parameters.attributes !== undefined ) {
7590
7591                                 console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
7592
7593                         }
7594
7595                         this.setValues( parameters );
7596
7597                 }
7598
7599         }
7600
7601         ShaderMaterial.prototype = Object.create( Material.prototype );
7602         ShaderMaterial.prototype.constructor = ShaderMaterial;
7603
7604         ShaderMaterial.prototype.isShaderMaterial = true;
7605
7606         ShaderMaterial.prototype.copy = function ( source ) {
7607
7608                 Material.prototype.copy.call( this, source );
7609
7610                 this.fragmentShader = source.fragmentShader;
7611                 this.vertexShader = source.vertexShader;
7612
7613                 this.uniforms = UniformsUtils.clone( source.uniforms );
7614
7615                 this.defines = source.defines;
7616
7617                 this.wireframe = source.wireframe;
7618                 this.wireframeLinewidth = source.wireframeLinewidth;
7619
7620                 this.lights = source.lights;
7621                 this.clipping = source.clipping;
7622
7623                 this.skinning = source.skinning;
7624
7625                 this.morphTargets = source.morphTargets;
7626                 this.morphNormals = source.morphNormals;
7627
7628                 this.extensions = source.extensions;
7629
7630                 return this;
7631
7632         };
7633
7634         ShaderMaterial.prototype.toJSON = function ( meta ) {
7635
7636                 var data = Material.prototype.toJSON.call( this, meta );
7637
7638                 data.uniforms = this.uniforms;
7639                 data.vertexShader = this.vertexShader;
7640                 data.fragmentShader = this.fragmentShader;
7641
7642                 return data;
7643
7644         };
7645
7646         /**
7647          * @author mrdoob / http://mrdoob.com/
7648          * @author alteredq / http://alteredqualia.com/
7649          * @author bhouston / https://clara.io
7650          * @author WestLangley / http://github.com/WestLangley
7651          *
7652          * parameters = {
7653          *
7654          *  opacity: <float>,
7655          *
7656          *  map: new THREE.Texture( <Image> ),
7657          *
7658          *  alphaMap: new THREE.Texture( <Image> ),
7659          *
7660          *  displacementMap: new THREE.Texture( <Image> ),
7661          *  displacementScale: <float>,
7662          *  displacementBias: <float>,
7663          *
7664          *  wireframe: <boolean>,
7665          *  wireframeLinewidth: <float>
7666          * }
7667          */
7668
7669         function MeshDepthMaterial( parameters ) {
7670
7671                 Material.call( this );
7672
7673                 this.type = 'MeshDepthMaterial';
7674
7675                 this.depthPacking = BasicDepthPacking;
7676
7677                 this.skinning = false;
7678                 this.morphTargets = false;
7679
7680                 this.map = null;
7681
7682                 this.alphaMap = null;
7683
7684                 this.displacementMap = null;
7685                 this.displacementScale = 1;
7686                 this.displacementBias = 0;
7687
7688                 this.wireframe = false;
7689                 this.wireframeLinewidth = 1;
7690
7691                 this.fog = false;
7692                 this.lights = false;
7693
7694                 this.setValues( parameters );
7695
7696         }
7697
7698         MeshDepthMaterial.prototype = Object.create( Material.prototype );
7699         MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
7700
7701         MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
7702
7703         MeshDepthMaterial.prototype.copy = function ( source ) {
7704
7705                 Material.prototype.copy.call( this, source );
7706
7707                 this.depthPacking = source.depthPacking;
7708
7709                 this.skinning = source.skinning;
7710                 this.morphTargets = source.morphTargets;
7711
7712                 this.map = source.map;
7713
7714                 this.alphaMap = source.alphaMap;
7715
7716                 this.displacementMap = source.displacementMap;
7717                 this.displacementScale = source.displacementScale;
7718                 this.displacementBias = source.displacementBias;
7719
7720                 this.wireframe = source.wireframe;
7721                 this.wireframeLinewidth = source.wireframeLinewidth;
7722
7723                 return this;
7724
7725         };
7726
7727         /**
7728          * @author WestLangley / http://github.com/WestLangley
7729          *
7730          * parameters = {
7731          *
7732          *  referencePosition: <float>,
7733          *  nearDistance: <float>,
7734          *  farDistance: <float>,
7735          *
7736          *  skinning: <bool>,
7737          *  morphTargets: <bool>,
7738          *
7739          *  map: new THREE.Texture( <Image> ),
7740          *
7741          *  alphaMap: new THREE.Texture( <Image> ),
7742          *
7743          *  displacementMap: new THREE.Texture( <Image> ),
7744          *  displacementScale: <float>,
7745          *  displacementBias: <float>
7746          *
7747          * }
7748          */
7749
7750         function MeshDistanceMaterial( parameters ) {
7751
7752                 Material.call( this );
7753
7754                 this.type = 'MeshDistanceMaterial';
7755
7756                 this.referencePosition = new Vector3();
7757                 this.nearDistance = 1;
7758                 this.farDistance = 1000;
7759
7760                 this.skinning = false;
7761                 this.morphTargets = false;
7762
7763                 this.map = null;
7764
7765                 this.alphaMap = null;
7766
7767                 this.displacementMap = null;
7768                 this.displacementScale = 1;
7769                 this.displacementBias = 0;
7770
7771                 this.fog = false;
7772                 this.lights = false;
7773
7774                 this.setValues( parameters );
7775
7776         }
7777
7778         MeshDistanceMaterial.prototype = Object.create( Material.prototype );
7779         MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
7780
7781         MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
7782
7783         MeshDistanceMaterial.prototype.copy = function ( source ) {
7784
7785                 Material.prototype.copy.call( this, source );
7786
7787                 this.referencePosition.copy( source.referencePosition );
7788                 this.nearDistance = source.nearDistance;
7789                 this.farDistance = source.farDistance;
7790
7791                 this.skinning = source.skinning;
7792                 this.morphTargets = source.morphTargets;
7793
7794                 this.map = source.map;
7795
7796                 this.alphaMap = source.alphaMap;
7797
7798                 this.displacementMap = source.displacementMap;
7799                 this.displacementScale = source.displacementScale;
7800                 this.displacementBias = source.displacementBias;
7801
7802                 return this;
7803
7804         };
7805
7806         /**
7807          * @author bhouston / http://clara.io
7808          * @author WestLangley / http://github.com/WestLangley
7809          */
7810
7811         function Box3( min, max ) {
7812
7813                 this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
7814                 this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
7815
7816         }
7817
7818         Object.assign( Box3.prototype, {
7819
7820                 isBox3: true,
7821
7822                 set: function ( min, max ) {
7823
7824                         this.min.copy( min );
7825                         this.max.copy( max );
7826
7827                         return this;
7828
7829                 },
7830
7831                 setFromArray: function ( array ) {
7832
7833                         var minX = + Infinity;
7834                         var minY = + Infinity;
7835                         var minZ = + Infinity;
7836
7837                         var maxX = - Infinity;
7838                         var maxY = - Infinity;
7839                         var maxZ = - Infinity;
7840
7841                         for ( var i = 0, l = array.length; i < l; i += 3 ) {
7842
7843                                 var x = array[ i ];
7844                                 var y = array[ i + 1 ];
7845                                 var z = array[ i + 2 ];
7846
7847                                 if ( x < minX ) minX = x;
7848                                 if ( y < minY ) minY = y;
7849                                 if ( z < minZ ) minZ = z;
7850
7851                                 if ( x > maxX ) maxX = x;
7852                                 if ( y > maxY ) maxY = y;
7853                                 if ( z > maxZ ) maxZ = z;
7854
7855                         }
7856
7857                         this.min.set( minX, minY, minZ );
7858                         this.max.set( maxX, maxY, maxZ );
7859
7860                         return this;
7861
7862                 },
7863
7864                 setFromBufferAttribute: function ( attribute ) {
7865
7866                         var minX = + Infinity;
7867                         var minY = + Infinity;
7868                         var minZ = + Infinity;
7869
7870                         var maxX = - Infinity;
7871                         var maxY = - Infinity;
7872                         var maxZ = - Infinity;
7873
7874                         for ( var i = 0, l = attribute.count; i < l; i ++ ) {
7875
7876                                 var x = attribute.getX( i );
7877                                 var y = attribute.getY( i );
7878                                 var z = attribute.getZ( i );
7879
7880                                 if ( x < minX ) minX = x;
7881                                 if ( y < minY ) minY = y;
7882                                 if ( z < minZ ) minZ = z;
7883
7884                                 if ( x > maxX ) maxX = x;
7885                                 if ( y > maxY ) maxY = y;
7886                                 if ( z > maxZ ) maxZ = z;
7887
7888                         }
7889
7890                         this.min.set( minX, minY, minZ );
7891                         this.max.set( maxX, maxY, maxZ );
7892
7893                         return this;
7894
7895                 },
7896
7897                 setFromPoints: function ( points ) {
7898
7899                         this.makeEmpty();
7900
7901                         for ( var i = 0, il = points.length; i < il; i ++ ) {
7902
7903                                 this.expandByPoint( points[ i ] );
7904
7905                         }
7906
7907                         return this;
7908
7909                 },
7910
7911                 setFromCenterAndSize: function () {
7912
7913                         var v1 = new Vector3();
7914
7915                         return function setFromCenterAndSize( center, size ) {
7916
7917                                 var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
7918
7919                                 this.min.copy( center ).sub( halfSize );
7920                                 this.max.copy( center ).add( halfSize );
7921
7922                                 return this;
7923
7924                         };
7925
7926                 }(),
7927
7928                 setFromObject: function ( object ) {
7929
7930                         this.makeEmpty();
7931
7932                         return this.expandByObject( object );
7933
7934                 },
7935
7936                 clone: function () {
7937
7938                         return new this.constructor().copy( this );
7939
7940                 },
7941
7942                 copy: function ( box ) {
7943
7944                         this.min.copy( box.min );
7945                         this.max.copy( box.max );
7946
7947                         return this;
7948
7949                 },
7950
7951                 makeEmpty: function () {
7952
7953                         this.min.x = this.min.y = this.min.z = + Infinity;
7954                         this.max.x = this.max.y = this.max.z = - Infinity;
7955
7956                         return this;
7957
7958                 },
7959
7960                 isEmpty: function () {
7961
7962                         // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
7963
7964                         return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
7965
7966                 },
7967
7968                 getCenter: function ( optionalTarget ) {
7969
7970                         var result = optionalTarget || new Vector3();
7971                         return this.isEmpty() ? result.set( 0, 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
7972
7973                 },
7974
7975                 getSize: function ( optionalTarget ) {
7976
7977                         var result = optionalTarget || new Vector3();
7978                         return this.isEmpty() ? result.set( 0, 0, 0 ) : result.subVectors( this.max, this.min );
7979
7980                 },
7981
7982                 expandByPoint: function ( point ) {
7983
7984                         this.min.min( point );
7985                         this.max.max( point );
7986
7987                         return this;
7988
7989                 },
7990
7991                 expandByVector: function ( vector ) {
7992
7993                         this.min.sub( vector );
7994                         this.max.add( vector );
7995
7996                         return this;
7997
7998                 },
7999
8000                 expandByScalar: function ( scalar ) {
8001
8002                         this.min.addScalar( - scalar );
8003                         this.max.addScalar( scalar );
8004
8005                         return this;
8006
8007                 },
8008
8009                 expandByObject: function () {
8010
8011                         // Computes the world-axis-aligned bounding box of an object (including its children),
8012                         // accounting for both the object's, and children's, world transforms
8013
8014                         var v1 = new Vector3();
8015
8016                         return function expandByObject( object ) {
8017
8018                                 var scope = this;
8019
8020                                 object.updateMatrixWorld( true );
8021
8022                                 object.traverse( function ( node ) {
8023
8024                                         var i, l;
8025
8026                                         var geometry = node.geometry;
8027
8028                                         if ( geometry !== undefined ) {
8029
8030                                                 if ( geometry.isGeometry ) {
8031
8032                                                         var vertices = geometry.vertices;
8033
8034                                                         for ( i = 0, l = vertices.length; i < l; i ++ ) {
8035
8036                                                                 v1.copy( vertices[ i ] );
8037                                                                 v1.applyMatrix4( node.matrixWorld );
8038
8039                                                                 scope.expandByPoint( v1 );
8040
8041                                                         }
8042
8043                                                 } else if ( geometry.isBufferGeometry ) {
8044
8045                                                         var attribute = geometry.attributes.position;
8046
8047                                                         if ( attribute !== undefined ) {
8048
8049                                                                 for ( i = 0, l = attribute.count; i < l; i ++ ) {
8050
8051                                                                         v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld );
8052
8053                                                                         scope.expandByPoint( v1 );
8054
8055                                                                 }
8056
8057                                                         }
8058
8059                                                 }
8060
8061                                         }
8062
8063                                 } );
8064
8065                                 return this;
8066
8067                         };
8068
8069                 }(),
8070
8071                 containsPoint: function ( point ) {
8072
8073                         return point.x < this.min.x || point.x > this.max.x ||
8074                                 point.y < this.min.y || point.y > this.max.y ||
8075                                 point.z < this.min.z || point.z > this.max.z ? false : true;
8076
8077                 },
8078
8079                 containsBox: function ( box ) {
8080
8081                         return this.min.x <= box.min.x && box.max.x <= this.max.x &&
8082                                 this.min.y <= box.min.y && box.max.y <= this.max.y &&
8083                                 this.min.z <= box.min.z && box.max.z <= this.max.z;
8084
8085                 },
8086
8087                 getParameter: function ( point, optionalTarget ) {
8088
8089                         // This can potentially have a divide by zero if the box
8090                         // has a size dimension of 0.
8091
8092                         var result = optionalTarget || new Vector3();
8093
8094                         return result.set(
8095                                 ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
8096                                 ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
8097                                 ( point.z - this.min.z ) / ( this.max.z - this.min.z )
8098                         );
8099
8100                 },
8101
8102                 intersectsBox: function ( box ) {
8103
8104                         // using 6 splitting planes to rule out intersections.
8105                         return box.max.x < this.min.x || box.min.x > this.max.x ||
8106                                 box.max.y < this.min.y || box.min.y > this.max.y ||
8107                                 box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
8108
8109                 },
8110
8111                 intersectsSphere: ( function () {
8112
8113                         var closestPoint = new Vector3();
8114
8115                         return function intersectsSphere( sphere ) {
8116
8117                                 // Find the point on the AABB closest to the sphere center.
8118                                 this.clampPoint( sphere.center, closestPoint );
8119
8120                                 // If that point is inside the sphere, the AABB and sphere intersect.
8121                                 return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
8122
8123                         };
8124
8125                 } )(),
8126
8127                 intersectsPlane: function ( plane ) {
8128
8129                         // We compute the minimum and maximum dot product values. If those values
8130                         // are on the same side (back or front) of the plane, then there is no intersection.
8131
8132                         var min, max;
8133
8134                         if ( plane.normal.x > 0 ) {
8135
8136                                 min = plane.normal.x * this.min.x;
8137                                 max = plane.normal.x * this.max.x;
8138
8139                         } else {
8140
8141                                 min = plane.normal.x * this.max.x;
8142                                 max = plane.normal.x * this.min.x;
8143
8144                         }
8145
8146                         if ( plane.normal.y > 0 ) {
8147
8148                                 min += plane.normal.y * this.min.y;
8149                                 max += plane.normal.y * this.max.y;
8150
8151                         } else {
8152
8153                                 min += plane.normal.y * this.max.y;
8154                                 max += plane.normal.y * this.min.y;
8155
8156                         }
8157
8158                         if ( plane.normal.z > 0 ) {
8159
8160                                 min += plane.normal.z * this.min.z;
8161                                 max += plane.normal.z * this.max.z;
8162
8163                         } else {
8164
8165                                 min += plane.normal.z * this.max.z;
8166                                 max += plane.normal.z * this.min.z;
8167
8168                         }
8169
8170                         return ( min <= plane.constant && max >= plane.constant );
8171
8172                 },
8173
8174                 clampPoint: function ( point, optionalTarget ) {
8175
8176                         var result = optionalTarget || new Vector3();
8177                         return result.copy( point ).clamp( this.min, this.max );
8178
8179                 },
8180
8181                 distanceToPoint: function () {
8182
8183                         var v1 = new Vector3();
8184
8185                         return function distanceToPoint( point ) {
8186
8187                                 var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
8188                                 return clampedPoint.sub( point ).length();
8189
8190                         };
8191
8192                 }(),
8193
8194                 getBoundingSphere: function () {
8195
8196                         var v1 = new Vector3();
8197
8198                         return function getBoundingSphere( optionalTarget ) {
8199
8200                                 var result = optionalTarget || new Sphere();
8201
8202                                 this.getCenter( result.center );
8203
8204                                 result.radius = this.getSize( v1 ).length() * 0.5;
8205
8206                                 return result;
8207
8208                         };
8209
8210                 }(),
8211
8212                 intersect: function ( box ) {
8213
8214                         this.min.max( box.min );
8215                         this.max.min( box.max );
8216
8217                         // 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.
8218                         if( this.isEmpty() ) this.makeEmpty();
8219
8220                         return this;
8221
8222                 },
8223
8224                 union: function ( box ) {
8225
8226                         this.min.min( box.min );
8227                         this.max.max( box.max );
8228
8229                         return this;
8230
8231                 },
8232
8233                 applyMatrix4: function () {
8234
8235                         var points = [
8236                                 new Vector3(),
8237                                 new Vector3(),
8238                                 new Vector3(),
8239                                 new Vector3(),
8240                                 new Vector3(),
8241                                 new Vector3(),
8242                                 new Vector3(),
8243                                 new Vector3()
8244                         ];
8245
8246                         return function applyMatrix4( matrix ) {
8247
8248                                 // transform of empty box is an empty box.
8249                                 if( this.isEmpty() ) return this;
8250
8251                                 // NOTE: I am using a binary pattern to specify all 2^3 combinations below
8252                                 points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
8253                                 points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
8254                                 points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
8255                                 points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
8256                                 points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
8257                                 points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
8258                                 points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
8259                                 points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix );   // 111
8260
8261                                 this.setFromPoints( points );
8262
8263                                 return this;
8264
8265                         };
8266
8267                 }(),
8268
8269                 translate: function ( offset ) {
8270
8271                         this.min.add( offset );
8272                         this.max.add( offset );
8273
8274                         return this;
8275
8276                 },
8277
8278                 equals: function ( box ) {
8279
8280                         return box.min.equals( this.min ) && box.max.equals( this.max );
8281
8282                 }
8283
8284         } );
8285
8286         /**
8287          * @author bhouston / http://clara.io
8288          * @author mrdoob / http://mrdoob.com/
8289          */
8290
8291         function Sphere( center, radius ) {
8292
8293                 this.center = ( center !== undefined ) ? center : new Vector3();
8294                 this.radius = ( radius !== undefined ) ? radius : 0;
8295
8296         }
8297
8298         Object.assign( Sphere.prototype, {
8299
8300                 set: function ( center, radius ) {
8301
8302                         this.center.copy( center );
8303                         this.radius = radius;
8304
8305                         return this;
8306
8307                 },
8308
8309                 setFromPoints: function () {
8310
8311                         var box = new Box3();
8312
8313                         return function setFromPoints( points, optionalCenter ) {
8314
8315                                 var center = this.center;
8316
8317                                 if ( optionalCenter !== undefined ) {
8318
8319                                         center.copy( optionalCenter );
8320
8321                                 } else {
8322
8323                                         box.setFromPoints( points ).getCenter( center );
8324
8325                                 }
8326
8327                                 var maxRadiusSq = 0;
8328
8329                                 for ( var i = 0, il = points.length; i < il; i ++ ) {
8330
8331                                         maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
8332
8333                                 }
8334
8335                                 this.radius = Math.sqrt( maxRadiusSq );
8336
8337                                 return this;
8338
8339                         };
8340
8341                 }(),
8342
8343                 clone: function () {
8344
8345                         return new this.constructor().copy( this );
8346
8347                 },
8348
8349                 copy: function ( sphere ) {
8350
8351                         this.center.copy( sphere.center );
8352                         this.radius = sphere.radius;
8353
8354                         return this;
8355
8356                 },
8357
8358                 empty: function () {
8359
8360                         return ( this.radius <= 0 );
8361
8362                 },
8363
8364                 containsPoint: function ( point ) {
8365
8366                         return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
8367
8368                 },
8369
8370                 distanceToPoint: function ( point ) {
8371
8372                         return ( point.distanceTo( this.center ) - this.radius );
8373
8374                 },
8375
8376                 intersectsSphere: function ( sphere ) {
8377
8378                         var radiusSum = this.radius + sphere.radius;
8379
8380                         return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
8381
8382                 },
8383
8384                 intersectsBox: function ( box ) {
8385
8386                         return box.intersectsSphere( this );
8387
8388                 },
8389
8390                 intersectsPlane: function ( plane ) {
8391
8392                         return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
8393
8394                 },
8395
8396                 clampPoint: function ( point, optionalTarget ) {
8397
8398                         var deltaLengthSq = this.center.distanceToSquared( point );
8399
8400                         var result = optionalTarget || new Vector3();
8401
8402                         result.copy( point );
8403
8404                         if ( deltaLengthSq > ( this.radius * this.radius ) ) {
8405
8406                                 result.sub( this.center ).normalize();
8407                                 result.multiplyScalar( this.radius ).add( this.center );
8408
8409                         }
8410
8411                         return result;
8412
8413                 },
8414
8415                 getBoundingBox: function ( optionalTarget ) {
8416
8417                         var box = optionalTarget || new Box3();
8418
8419                         box.set( this.center, this.center );
8420                         box.expandByScalar( this.radius );
8421
8422                         return box;
8423
8424                 },
8425
8426                 applyMatrix4: function ( matrix ) {
8427
8428                         this.center.applyMatrix4( matrix );
8429                         this.radius = this.radius * matrix.getMaxScaleOnAxis();
8430
8431                         return this;
8432
8433                 },
8434
8435                 translate: function ( offset ) {
8436
8437                         this.center.add( offset );
8438
8439                         return this;
8440
8441                 },
8442
8443                 equals: function ( sphere ) {
8444
8445                         return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
8446
8447                 }
8448
8449         } );
8450
8451         /**
8452          * @author alteredq / http://alteredqualia.com/
8453          * @author WestLangley / http://github.com/WestLangley
8454          * @author bhouston / http://clara.io
8455          * @author tschw
8456          */
8457
8458         function Matrix3() {
8459
8460                 this.elements = [
8461
8462                         1, 0, 0,
8463                         0, 1, 0,
8464                         0, 0, 1
8465
8466                 ];
8467
8468                 if ( arguments.length > 0 ) {
8469
8470                         console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
8471
8472                 }
8473
8474         }
8475
8476         Object.assign( Matrix3.prototype, {
8477
8478                 isMatrix3: true,
8479
8480                 set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
8481
8482                         var te = this.elements;
8483
8484                         te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
8485                         te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
8486                         te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
8487
8488                         return this;
8489
8490                 },
8491
8492                 identity: function () {
8493
8494                         this.set(
8495
8496                                 1, 0, 0,
8497                                 0, 1, 0,
8498                                 0, 0, 1
8499
8500                         );
8501
8502                         return this;
8503
8504                 },
8505
8506                 clone: function () {
8507
8508                         return new this.constructor().fromArray( this.elements );
8509
8510                 },
8511
8512                 copy: function ( m ) {
8513
8514                         var te = this.elements;
8515                         var me = m.elements;
8516
8517                         te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
8518                         te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
8519                         te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
8520
8521                         return this;
8522
8523                 },
8524
8525                 setFromMatrix4: function ( m ) {
8526
8527                         var me = m.elements;
8528
8529                         this.set(
8530
8531                                 me[ 0 ], me[ 4 ], me[  8 ],
8532                                 me[ 1 ], me[ 5 ], me[  9 ],
8533                                 me[ 2 ], me[ 6 ], me[ 10 ]
8534
8535                         );
8536
8537                         return this;
8538
8539                 },
8540
8541                 applyToBufferAttribute: function () {
8542
8543                         var v1 = new Vector3();
8544
8545                         return function applyToBufferAttribute( attribute ) {
8546
8547                                 for ( var i = 0, l = attribute.count; i < l; i ++ ) {
8548
8549                                         v1.x = attribute.getX( i );
8550                                         v1.y = attribute.getY( i );
8551                                         v1.z = attribute.getZ( i );
8552
8553                                         v1.applyMatrix3( this );
8554
8555                                         attribute.setXYZ( i, v1.x, v1.y, v1.z );
8556
8557                                 }
8558
8559                                 return attribute;
8560
8561                         };
8562
8563                 }(),
8564
8565                 multiply: function ( m ) {
8566
8567                         return this.multiplyMatrices( this, m );
8568
8569                 },
8570
8571                 premultiply: function ( m ) {
8572
8573                         return this.multiplyMatrices( m, this );
8574
8575                 },
8576
8577                 multiplyMatrices: function ( a, b ) {
8578
8579                         var ae = a.elements;
8580                         var be = b.elements;
8581                         var te = this.elements;
8582
8583                         var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
8584                         var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
8585                         var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
8586
8587                         var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
8588                         var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
8589                         var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
8590
8591                         te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
8592                         te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
8593                         te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
8594
8595                         te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
8596                         te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
8597                         te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
8598
8599                         te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
8600                         te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
8601                         te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
8602
8603                         return this;
8604
8605                 },
8606
8607                 multiplyScalar: function ( s ) {
8608
8609                         var te = this.elements;
8610
8611                         te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
8612                         te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
8613                         te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
8614
8615                         return this;
8616
8617                 },
8618
8619                 determinant: function () {
8620
8621                         var te = this.elements;
8622
8623                         var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
8624                                 d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
8625                                 g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
8626
8627                         return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
8628
8629                 },
8630
8631                 getInverse: function ( matrix, throwOnDegenerate ) {
8632
8633                         if ( matrix && matrix.isMatrix4 ) {
8634
8635                                 console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." );
8636
8637                         }
8638
8639                         var me = matrix.elements,
8640                                 te = this.elements,
8641
8642                                 n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
8643                                 n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
8644                                 n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
8645
8646                                 t11 = n33 * n22 - n32 * n23,
8647                                 t12 = n32 * n13 - n33 * n12,
8648                                 t13 = n23 * n12 - n22 * n13,
8649
8650                                 det = n11 * t11 + n21 * t12 + n31 * t13;
8651
8652                         if ( det === 0 ) {
8653
8654                                 var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0";
8655
8656                                 if ( throwOnDegenerate === true ) {
8657
8658                                         throw new Error( msg );
8659
8660                                 } else {
8661
8662                                         console.warn( msg );
8663
8664                                 }
8665
8666                                 return this.identity();
8667
8668                         }
8669
8670                         var detInv = 1 / det;
8671
8672                         te[ 0 ] = t11 * detInv;
8673                         te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
8674                         te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
8675
8676                         te[ 3 ] = t12 * detInv;
8677                         te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
8678                         te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
8679
8680                         te[ 6 ] = t13 * detInv;
8681                         te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
8682                         te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
8683
8684                         return this;
8685
8686                 },
8687
8688                 transpose: function () {
8689
8690                         var tmp, m = this.elements;
8691
8692                         tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
8693                         tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
8694                         tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
8695
8696                         return this;
8697
8698                 },
8699
8700                 getNormalMatrix: function ( matrix4 ) {
8701
8702                         return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
8703
8704                 },
8705
8706                 transposeIntoArray: function ( r ) {
8707
8708                         var m = this.elements;
8709
8710                         r[ 0 ] = m[ 0 ];
8711                         r[ 1 ] = m[ 3 ];
8712                         r[ 2 ] = m[ 6 ];
8713                         r[ 3 ] = m[ 1 ];
8714                         r[ 4 ] = m[ 4 ];
8715                         r[ 5 ] = m[ 7 ];
8716                         r[ 6 ] = m[ 2 ];
8717                         r[ 7 ] = m[ 5 ];
8718                         r[ 8 ] = m[ 8 ];
8719
8720                         return this;
8721
8722                 },
8723
8724                 equals: function ( matrix ) {
8725
8726                         var te = this.elements;
8727                         var me = matrix.elements;
8728
8729                         for ( var i = 0; i < 9; i ++ ) {
8730
8731                                 if ( te[ i ] !== me[ i ] ) return false;
8732
8733                         }
8734
8735                         return true;
8736
8737                 },
8738
8739                 fromArray: function ( array, offset ) {
8740
8741                         if ( offset === undefined ) offset = 0;
8742
8743                         for ( var i = 0; i < 9; i ++ ) {
8744
8745                                 this.elements[ i ] = array[ i + offset ];
8746
8747                         }
8748
8749                         return this;
8750
8751                 },
8752
8753                 toArray: function ( array, offset ) {
8754
8755                         if ( array === undefined ) array = [];
8756                         if ( offset === undefined ) offset = 0;
8757
8758                         var te = this.elements;
8759
8760                         array[ offset ] = te[ 0 ];
8761                         array[ offset + 1 ] = te[ 1 ];
8762                         array[ offset + 2 ] = te[ 2 ];
8763
8764                         array[ offset + 3 ] = te[ 3 ];
8765                         array[ offset + 4 ] = te[ 4 ];
8766                         array[ offset + 5 ] = te[ 5 ];
8767
8768                         array[ offset + 6 ] = te[ 6 ];
8769                         array[ offset + 7 ] = te[ 7 ];
8770                         array[ offset + 8 ] = te[ 8 ];
8771
8772                         return array;
8773
8774                 }
8775
8776         } );
8777
8778         /**
8779          * @author bhouston / http://clara.io
8780          */
8781
8782         function Plane( normal, constant ) {
8783
8784                 // normal is assumed to be normalized
8785
8786                 this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
8787                 this.constant = ( constant !== undefined ) ? constant : 0;
8788
8789         }
8790
8791         Object.assign( Plane.prototype, {
8792
8793                 set: function ( normal, constant ) {
8794
8795                         this.normal.copy( normal );
8796                         this.constant = constant;
8797
8798                         return this;
8799
8800                 },
8801
8802                 setComponents: function ( x, y, z, w ) {
8803
8804                         this.normal.set( x, y, z );
8805                         this.constant = w;
8806
8807                         return this;
8808
8809                 },
8810
8811                 setFromNormalAndCoplanarPoint: function ( normal, point ) {
8812
8813                         this.normal.copy( normal );
8814                         this.constant = - point.dot( this.normal );
8815
8816                         return this;
8817
8818                 },
8819
8820                 setFromCoplanarPoints: function () {
8821
8822                         var v1 = new Vector3();
8823                         var v2 = new Vector3();
8824
8825                         return function setFromCoplanarPoints( a, b, c ) {
8826
8827                                 var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
8828
8829                                 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
8830
8831                                 this.setFromNormalAndCoplanarPoint( normal, a );
8832
8833                                 return this;
8834
8835                         };
8836
8837                 }(),
8838
8839                 clone: function () {
8840
8841                         return new this.constructor().copy( this );
8842
8843                 },
8844
8845                 copy: function ( plane ) {
8846
8847                         this.normal.copy( plane.normal );
8848                         this.constant = plane.constant;
8849
8850                         return this;
8851
8852                 },
8853
8854                 normalize: function () {
8855
8856                         // Note: will lead to a divide by zero if the plane is invalid.
8857
8858                         var inverseNormalLength = 1.0 / this.normal.length();
8859                         this.normal.multiplyScalar( inverseNormalLength );
8860                         this.constant *= inverseNormalLength;
8861
8862                         return this;
8863
8864                 },
8865
8866                 negate: function () {
8867
8868                         this.constant *= - 1;
8869                         this.normal.negate();
8870
8871                         return this;
8872
8873                 },
8874
8875                 distanceToPoint: function ( point ) {
8876
8877                         return this.normal.dot( point ) + this.constant;
8878
8879                 },
8880
8881                 distanceToSphere: function ( sphere ) {
8882
8883                         return this.distanceToPoint( sphere.center ) - sphere.radius;
8884
8885                 },
8886
8887                 projectPoint: function ( point, optionalTarget ) {
8888
8889                         var result = optionalTarget || new Vector3();
8890
8891                         return result.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
8892
8893                 },
8894
8895                 intersectLine: function () {
8896
8897                         var v1 = new Vector3();
8898
8899                         return function intersectLine( line, optionalTarget ) {
8900
8901                                 var result = optionalTarget || new Vector3();
8902
8903                                 var direction = line.delta( v1 );
8904
8905                                 var denominator = this.normal.dot( direction );
8906
8907                                 if ( denominator === 0 ) {
8908
8909                                         // line is coplanar, return origin
8910                                         if ( this.distanceToPoint( line.start ) === 0 ) {
8911
8912                                                 return result.copy( line.start );
8913
8914                                         }
8915
8916                                         // Unsure if this is the correct method to handle this case.
8917                                         return undefined;
8918
8919                                 }
8920
8921                                 var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
8922
8923                                 if ( t < 0 || t > 1 ) {
8924
8925                                         return undefined;
8926
8927                                 }
8928
8929                                 return result.copy( direction ).multiplyScalar( t ).add( line.start );
8930
8931                         };
8932
8933                 }(),
8934
8935                 intersectsLine: function ( line ) {
8936
8937                         // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
8938
8939                         var startSign = this.distanceToPoint( line.start );
8940                         var endSign = this.distanceToPoint( line.end );
8941
8942                         return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
8943
8944                 },
8945
8946                 intersectsBox: function ( box ) {
8947
8948                         return box.intersectsPlane( this );
8949
8950                 },
8951
8952                 intersectsSphere: function ( sphere ) {
8953
8954                         return sphere.intersectsPlane( this );
8955
8956                 },
8957
8958                 coplanarPoint: function ( optionalTarget ) {
8959
8960                         var result = optionalTarget || new Vector3();
8961
8962                         return result.copy( this.normal ).multiplyScalar( - this.constant );
8963
8964                 },
8965
8966                 applyMatrix4: function () {
8967
8968                         var v1 = new Vector3();
8969                         var m1 = new Matrix3();
8970
8971                         return function applyMatrix4( matrix, optionalNormalMatrix ) {
8972
8973                                 var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
8974
8975                                 var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix );
8976
8977                                 var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
8978
8979                                 this.constant = - referencePoint.dot( normal );
8980
8981                                 return this;
8982
8983                         };
8984
8985                 }(),
8986
8987                 translate: function ( offset ) {
8988
8989                         this.constant -= offset.dot( this.normal );
8990
8991                         return this;
8992
8993                 },
8994
8995                 equals: function ( plane ) {
8996
8997                         return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
8998
8999                 }
9000
9001         } );
9002
9003         /**
9004          * @author mrdoob / http://mrdoob.com/
9005          * @author alteredq / http://alteredqualia.com/
9006          * @author bhouston / http://clara.io
9007          */
9008
9009         function Frustum( p0, p1, p2, p3, p4, p5 ) {
9010
9011                 this.planes = [
9012
9013                         ( p0 !== undefined ) ? p0 : new Plane(),
9014                         ( p1 !== undefined ) ? p1 : new Plane(),
9015                         ( p2 !== undefined ) ? p2 : new Plane(),
9016                         ( p3 !== undefined ) ? p3 : new Plane(),
9017                         ( p4 !== undefined ) ? p4 : new Plane(),
9018                         ( p5 !== undefined ) ? p5 : new Plane()
9019
9020                 ];
9021
9022         }
9023
9024         Object.assign( Frustum.prototype, {
9025
9026                 set: function ( p0, p1, p2, p3, p4, p5 ) {
9027
9028                         var planes = this.planes;
9029
9030                         planes[ 0 ].copy( p0 );
9031                         planes[ 1 ].copy( p1 );
9032                         planes[ 2 ].copy( p2 );
9033                         planes[ 3 ].copy( p3 );
9034                         planes[ 4 ].copy( p4 );
9035                         planes[ 5 ].copy( p5 );
9036
9037                         return this;
9038
9039                 },
9040
9041                 clone: function () {
9042
9043                         return new this.constructor().copy( this );
9044
9045                 },
9046
9047                 copy: function ( frustum ) {
9048
9049                         var planes = this.planes;
9050
9051                         for ( var i = 0; i < 6; i ++ ) {
9052
9053                                 planes[ i ].copy( frustum.planes[ i ] );
9054
9055                         }
9056
9057                         return this;
9058
9059                 },
9060
9061                 setFromMatrix: function ( m ) {
9062
9063                         var planes = this.planes;
9064                         var me = m.elements;
9065                         var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
9066                         var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
9067                         var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
9068                         var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
9069
9070                         planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
9071                         planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
9072                         planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
9073                         planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
9074                         planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
9075                         planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
9076
9077                         return this;
9078
9079                 },
9080
9081                 intersectsObject: function () {
9082
9083                         var sphere = new Sphere();
9084
9085                         return function intersectsObject( object ) {
9086
9087                                 var geometry = object.geometry;
9088
9089                                 if ( geometry.boundingSphere === null )
9090                                         geometry.computeBoundingSphere();
9091
9092                                 sphere.copy( geometry.boundingSphere )
9093                                         .applyMatrix4( object.matrixWorld );
9094
9095                                 return this.intersectsSphere( sphere );
9096
9097                         };
9098
9099                 }(),
9100
9101                 intersectsSprite: function () {
9102
9103                         var sphere = new Sphere();
9104
9105                         return function intersectsSprite( sprite ) {
9106
9107                                 sphere.center.set( 0, 0, 0 );
9108                                 sphere.radius = 0.7071067811865476;
9109                                 sphere.applyMatrix4( sprite.matrixWorld );
9110
9111                                 return this.intersectsSphere( sphere );
9112
9113                         };
9114
9115                 }(),
9116
9117                 intersectsSphere: function ( sphere ) {
9118
9119                         var planes = this.planes;
9120                         var center = sphere.center;
9121                         var negRadius = - sphere.radius;
9122
9123                         for ( var i = 0; i < 6; i ++ ) {
9124
9125                                 var distance = planes[ i ].distanceToPoint( center );
9126
9127                                 if ( distance < negRadius ) {
9128
9129                                         return false;
9130
9131                                 }
9132
9133                         }
9134
9135                         return true;
9136
9137                 },
9138
9139                 intersectsBox: function () {
9140
9141                         var p1 = new Vector3(),
9142                                 p2 = new Vector3();
9143
9144                         return function intersectsBox( box ) {
9145
9146                                 var planes = this.planes;
9147
9148                                 for ( var i = 0; i < 6; i ++ ) {
9149
9150                                         var plane = planes[ i ];
9151
9152                                         p1.x = plane.normal.x > 0 ? box.min.x : box.max.x;
9153                                         p2.x = plane.normal.x > 0 ? box.max.x : box.min.x;
9154                                         p1.y = plane.normal.y > 0 ? box.min.y : box.max.y;
9155                                         p2.y = plane.normal.y > 0 ? box.max.y : box.min.y;
9156                                         p1.z = plane.normal.z > 0 ? box.min.z : box.max.z;
9157                                         p2.z = plane.normal.z > 0 ? box.max.z : box.min.z;
9158
9159                                         var d1 = plane.distanceToPoint( p1 );
9160                                         var d2 = plane.distanceToPoint( p2 );
9161
9162                                         // if both outside plane, no intersection
9163
9164                                         if ( d1 < 0 && d2 < 0 ) {
9165
9166                                                 return false;
9167
9168                                         }
9169
9170                                 }
9171
9172                                 return true;
9173
9174                         };
9175
9176                 }(),
9177
9178                 containsPoint: function ( point ) {
9179
9180                         var planes = this.planes;
9181
9182                         for ( var i = 0; i < 6; i ++ ) {
9183
9184                                 if ( planes[ i ].distanceToPoint( point ) < 0 ) {
9185
9186                                         return false;
9187
9188                                 }
9189
9190                         }
9191
9192                         return true;
9193
9194                 }
9195
9196         } );
9197
9198         /**
9199          * @author alteredq / http://alteredqualia.com/
9200          * @author mrdoob / http://mrdoob.com/
9201          */
9202
9203         function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
9204
9205                 var _frustum = new Frustum(),
9206                         _projScreenMatrix = new Matrix4(),
9207
9208                         _shadowMapSize = new Vector2(),
9209                         _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ),
9210
9211                         _lookTarget = new Vector3(),
9212                         _lightPositionWorld = new Vector3(),
9213
9214                         _MorphingFlag = 1,
9215                         _SkinningFlag = 2,
9216
9217                         _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
9218
9219                         _depthMaterials = new Array( _NumberOfMaterialVariants ),
9220                         _distanceMaterials = new Array( _NumberOfMaterialVariants ),
9221
9222                         _materialCache = {};
9223
9224                 var cubeDirections = [
9225                         new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
9226                         new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
9227                 ];
9228
9229                 var cubeUps = [
9230                         new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
9231                         new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
9232                 ];
9233
9234                 var cube2DViewPorts = [
9235                         new Vector4(), new Vector4(), new Vector4(),
9236                         new Vector4(), new Vector4(), new Vector4()
9237                 ];
9238
9239                 // init
9240
9241                 for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
9242
9243                         var useMorphing = ( i & _MorphingFlag ) !== 0;
9244                         var useSkinning = ( i & _SkinningFlag ) !== 0;
9245
9246                         var depthMaterial = new MeshDepthMaterial( {
9247
9248                                 depthPacking: RGBADepthPacking,
9249
9250                                 morphTargets: useMorphing,
9251                                 skinning: useSkinning
9252
9253                         } );
9254
9255                         _depthMaterials[ i ] = depthMaterial;
9256
9257                         //
9258
9259                         var distanceMaterial = new MeshDistanceMaterial( {
9260
9261                                 morphTargets: useMorphing,
9262                                 skinning: useSkinning
9263
9264                         } );
9265
9266                         _distanceMaterials[ i ] = distanceMaterial;
9267
9268                 }
9269
9270                 //
9271
9272                 var scope = this;
9273
9274                 this.enabled = false;
9275
9276                 this.autoUpdate = true;
9277                 this.needsUpdate = false;
9278
9279                 this.type = PCFShadowMap;
9280
9281                 this.renderReverseSided = true;
9282                 this.renderSingleSided = true;
9283
9284                 this.render = function ( lights, scene, camera ) {
9285
9286                         if ( scope.enabled === false ) return;
9287                         if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
9288
9289                         if ( lights.length === 0 ) return;
9290
9291                         // TODO Clean up (needed in case of contextlost)
9292                         var _gl = _renderer.context;
9293                         var _state = _renderer.state;
9294
9295                         // Set GL state for depth map.
9296                         _state.disable( _gl.BLEND );
9297                         _state.buffers.color.setClear( 1, 1, 1, 1 );
9298                         _state.buffers.depth.setTest( true );
9299                         _state.setScissorTest( false );
9300
9301                         // render depth map
9302
9303                         var faceCount;
9304
9305                         for ( var i = 0, il = lights.length; i < il; i ++ ) {
9306
9307                                 var light = lights[ i ];
9308                                 var shadow = light.shadow;
9309                                 var isPointLight = light && light.isPointLight;
9310
9311                                 if ( shadow === undefined ) {
9312
9313                                         console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
9314                                         continue;
9315
9316                                 }
9317
9318                                 var shadowCamera = shadow.camera;
9319
9320                                 _shadowMapSize.copy( shadow.mapSize );
9321                                 _shadowMapSize.min( _maxShadowMapSize );
9322
9323                                 if ( isPointLight ) {
9324
9325                                         var vpWidth = _shadowMapSize.x;
9326                                         var vpHeight = _shadowMapSize.y;
9327
9328                                         // These viewports map a cube-map onto a 2D texture with the
9329                                         // following orientation:
9330                                         //
9331                                         //  xzXZ
9332                                         //   y Y
9333                                         //
9334                                         // X - Positive x direction
9335                                         // x - Negative x direction
9336                                         // Y - Positive y direction
9337                                         // y - Negative y direction
9338                                         // Z - Positive z direction
9339                                         // z - Negative z direction
9340
9341                                         // positive X
9342                                         cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
9343                                         // negative X
9344                                         cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
9345                                         // positive Z
9346                                         cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
9347                                         // negative Z
9348                                         cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
9349                                         // positive Y
9350                                         cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
9351                                         // negative Y
9352                                         cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
9353
9354                                         _shadowMapSize.x *= 4.0;
9355                                         _shadowMapSize.y *= 2.0;
9356
9357                                 }
9358
9359                                 if ( shadow.map === null ) {
9360
9361                                         var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
9362
9363                                         shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
9364                                         shadow.map.texture.name = light.name + ".shadowMap";
9365
9366                                         shadowCamera.updateProjectionMatrix();
9367
9368                                 }
9369
9370                                 if ( shadow.isSpotLightShadow ) {
9371
9372                                         shadow.update( light );
9373
9374                                 }
9375
9376                                 var shadowMap = shadow.map;
9377                                 var shadowMatrix = shadow.matrix;
9378
9379                                 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
9380                                 shadowCamera.position.copy( _lightPositionWorld );
9381
9382                                 if ( isPointLight ) {
9383
9384                                         faceCount = 6;
9385
9386                                         // for point lights we set the shadow matrix to be a translation-only matrix
9387                                         // equal to inverse of the light's position
9388
9389                                         shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
9390
9391                                 } else {
9392
9393                                         faceCount = 1;
9394
9395                                         _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
9396                                         shadowCamera.lookAt( _lookTarget );
9397                                         shadowCamera.updateMatrixWorld();
9398
9399                                         // compute shadow matrix
9400
9401                                         shadowMatrix.set(
9402                                                 0.5, 0.0, 0.0, 0.5,
9403                                                 0.0, 0.5, 0.0, 0.5,
9404                                                 0.0, 0.0, 0.5, 0.5,
9405                                                 0.0, 0.0, 0.0, 1.0
9406                                         );
9407
9408                                         shadowMatrix.multiply( shadowCamera.projectionMatrix );
9409                                         shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
9410
9411                                 }
9412
9413                                 _renderer.setRenderTarget( shadowMap );
9414                                 _renderer.clear();
9415
9416                                 // render shadow map for each cube face (if omni-directional) or
9417                                 // run a single pass if not
9418
9419                                 for ( var face = 0; face < faceCount; face ++ ) {
9420
9421                                         if ( isPointLight ) {
9422
9423                                                 _lookTarget.copy( shadowCamera.position );
9424                                                 _lookTarget.add( cubeDirections[ face ] );
9425                                                 shadowCamera.up.copy( cubeUps[ face ] );
9426                                                 shadowCamera.lookAt( _lookTarget );
9427                                                 shadowCamera.updateMatrixWorld();
9428
9429                                                 var vpDimensions = cube2DViewPorts[ face ];
9430                                                 _state.viewport( vpDimensions );
9431
9432                                         }
9433
9434                                         // update camera matrices and frustum
9435
9436                                         _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
9437                                         _frustum.setFromMatrix( _projScreenMatrix );
9438
9439                                         // set object matrices & frustum culling
9440
9441                                         renderObject( scene, camera, shadowCamera, isPointLight );
9442
9443                                 }
9444
9445                         }
9446
9447                         scope.needsUpdate = false;
9448
9449                 };
9450
9451                 function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) {
9452
9453                         var geometry = object.geometry;
9454
9455                         var result = null;
9456
9457                         var materialVariants = _depthMaterials;
9458                         var customMaterial = object.customDepthMaterial;
9459
9460                         if ( isPointLight ) {
9461
9462                                 materialVariants = _distanceMaterials;
9463                                 customMaterial = object.customDistanceMaterial;
9464
9465                         }
9466
9467                         if ( ! customMaterial ) {
9468
9469                                 var useMorphing = false;
9470
9471                                 if ( material.morphTargets ) {
9472
9473                                         if ( geometry && geometry.isBufferGeometry ) {
9474
9475                                                 useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
9476
9477                                         } else if ( geometry && geometry.isGeometry ) {
9478
9479                                                 useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;
9480
9481                                         }
9482
9483                                 }
9484
9485                                 if ( object.isSkinnedMesh && material.skinning === false ) {
9486
9487                                         console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
9488
9489                                 }
9490
9491                                 var useSkinning = object.isSkinnedMesh && material.skinning;
9492
9493                                 var variantIndex = 0;
9494
9495                                 if ( useMorphing ) variantIndex |= _MorphingFlag;
9496                                 if ( useSkinning ) variantIndex |= _SkinningFlag;
9497
9498                                 result = materialVariants[ variantIndex ];
9499
9500                         } else {
9501
9502                                 result = customMaterial;
9503
9504                         }
9505
9506                         if ( _renderer.localClippingEnabled &&
9507                                         material.clipShadows === true &&
9508                                         material.clippingPlanes.length !== 0 ) {
9509
9510                                 // in this case we need a unique material instance reflecting the
9511                                 // appropriate state
9512
9513                                 var keyA = result.uuid, keyB = material.uuid;
9514
9515                                 var materialsForVariant = _materialCache[ keyA ];
9516
9517                                 if ( materialsForVariant === undefined ) {
9518
9519                                         materialsForVariant = {};
9520                                         _materialCache[ keyA ] = materialsForVariant;
9521
9522                                 }
9523
9524                                 var cachedMaterial = materialsForVariant[ keyB ];
9525
9526                                 if ( cachedMaterial === undefined ) {
9527
9528                                         cachedMaterial = result.clone();
9529                                         materialsForVariant[ keyB ] = cachedMaterial;
9530
9531                                 }
9532
9533                                 result = cachedMaterial;
9534
9535                         }
9536
9537                         result.visible = material.visible;
9538                         result.wireframe = material.wireframe;
9539
9540                         var side = material.side;
9541
9542                         if ( scope.renderSingleSided && side == DoubleSide ) {
9543
9544                                 side = FrontSide;
9545
9546                         }
9547
9548                         if ( scope.renderReverseSided ) {
9549
9550                                 if ( side === FrontSide ) side = BackSide;
9551                                 else if ( side === BackSide ) side = FrontSide;
9552
9553                         }
9554
9555                         result.side = side;
9556
9557                         result.clipShadows = material.clipShadows;
9558                         result.clippingPlanes = material.clippingPlanes;
9559                         result.clipIntersection = material.clipIntersection;
9560
9561                         result.wireframeLinewidth = material.wireframeLinewidth;
9562                         result.linewidth = material.linewidth;
9563
9564                         if ( isPointLight && result.isMeshDistanceMaterial ) {
9565
9566                                 result.referencePosition.copy( lightPositionWorld );
9567                                 result.nearDistance = shadowCameraNear;
9568                                 result.farDistance = shadowCameraFar;
9569
9570                         }
9571
9572                         return result;
9573
9574                 }
9575
9576                 function renderObject( object, camera, shadowCamera, isPointLight ) {
9577
9578                         if ( object.visible === false ) return;
9579
9580                         var visible = object.layers.test( camera.layers );
9581
9582                         if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
9583
9584                                 if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
9585
9586                                         object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
9587
9588                                         var geometry = _objects.update( object );
9589                                         var material = object.material;
9590
9591                                         if ( Array.isArray( material ) ) {
9592
9593                                                 var groups = geometry.groups;
9594
9595                                                 for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
9596
9597                                                         var group = groups[ k ];
9598                                                         var groupMaterial = material[ group.materialIndex ];
9599
9600                                                         if ( groupMaterial && groupMaterial.visible ) {
9601
9602                                                                 var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
9603                                                                 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
9604
9605                                                         }
9606
9607                                                 }
9608
9609                                         } else if ( material.visible ) {
9610
9611                                                 var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
9612                                                 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
9613
9614                                         }
9615
9616                                 }
9617
9618                         }
9619
9620                         var children = object.children;
9621
9622                         for ( var i = 0, l = children.length; i < l; i ++ ) {
9623
9624                                 renderObject( children[ i ], camera, shadowCamera, isPointLight );
9625
9626                         }
9627
9628                 }
9629
9630         }
9631
9632         /**
9633          * @author mrdoob / http://mrdoob.com/
9634          */
9635
9636         function WebGLAttributes( gl ) {
9637
9638                 var buffers = {};
9639
9640                 function createBuffer( attribute, bufferType ) {
9641
9642                         var array = attribute.array;
9643                         var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
9644
9645                         var buffer = gl.createBuffer();
9646
9647                         gl.bindBuffer( bufferType, buffer );
9648                         gl.bufferData( bufferType, array, usage );
9649
9650                         attribute.onUploadCallback();
9651
9652                         var type = gl.FLOAT;
9653
9654                         if ( array instanceof Float32Array ) {
9655
9656                                 type = gl.FLOAT;
9657
9658                         } else if ( array instanceof Float64Array ) {
9659
9660                                 console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
9661
9662                         } else if ( array instanceof Uint16Array ) {
9663
9664                                 type = gl.UNSIGNED_SHORT;
9665
9666                         } else if ( array instanceof Int16Array ) {
9667
9668                                 type = gl.SHORT;
9669
9670                         } else if ( array instanceof Uint32Array ) {
9671
9672                                 type = gl.UNSIGNED_INT;
9673
9674                         } else if ( array instanceof Int32Array ) {
9675
9676                                 type = gl.INT;
9677
9678                         } else if ( array instanceof Int8Array ) {
9679
9680                                 type = gl.BYTE;
9681
9682                         } else if ( array instanceof Uint8Array ) {
9683
9684                                 type = gl.UNSIGNED_BYTE;
9685
9686                         }
9687
9688                         return {
9689                                 buffer: buffer,
9690                                 type: type,
9691                                 bytesPerElement: array.BYTES_PER_ELEMENT,
9692                                 version: attribute.version
9693                         };
9694
9695                 }
9696
9697                 function updateBuffer( buffer, attribute, bufferType ) {
9698
9699                         var array = attribute.array;
9700                         var updateRange = attribute.updateRange;
9701
9702                         gl.bindBuffer( bufferType, buffer );
9703
9704                         if ( attribute.dynamic === false ) {
9705
9706                                 gl.bufferData( bufferType, array, gl.STATIC_DRAW );
9707
9708                         } else if ( updateRange.count === - 1 ) {
9709
9710                                 // Not using update ranges
9711
9712                                 gl.bufferSubData( bufferType, 0, array );
9713
9714                         } else if ( updateRange.count === 0 ) {
9715
9716                                 console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' );
9717
9718                         } else {
9719
9720                                 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
9721                                         array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
9722
9723                                 updateRange.count = -1; // reset range
9724
9725                         }
9726
9727                 }
9728
9729                 //
9730
9731                 function get( attribute ) {
9732
9733                         if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
9734
9735                         return buffers[ attribute.uuid ];
9736
9737                 }
9738
9739                 function remove( attribute ) {
9740
9741                         if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
9742                         
9743                         var data = buffers[ attribute.uuid ];
9744
9745                         if ( data ) {
9746
9747                                 gl.deleteBuffer( data.buffer );
9748
9749                                 delete buffers[ attribute.uuid ];
9750
9751                         }
9752
9753                 }
9754
9755                 function update( attribute, bufferType ) {
9756
9757                         if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
9758
9759                         var data = buffers[ attribute.uuid ];
9760
9761                         if ( data === undefined ) {
9762
9763                                 buffers[ attribute.uuid ] = createBuffer( attribute, bufferType );
9764
9765                         } else if ( data.version < attribute.version ) {
9766
9767                                 updateBuffer( data.buffer, attribute, bufferType );
9768
9769                                 data.version = attribute.version;
9770
9771                         }
9772
9773                 }
9774
9775                 return {
9776
9777                         get: get,
9778                         remove: remove,
9779                         update: update
9780
9781                 };
9782
9783         }
9784
9785         /**
9786          * @author mrdoob / http://mrdoob.com/
9787          * @author WestLangley / http://github.com/WestLangley
9788          * @author bhouston / http://clara.io
9789          */
9790
9791         function Euler( x, y, z, order ) {
9792
9793                 this._x = x || 0;
9794                 this._y = y || 0;
9795                 this._z = z || 0;
9796                 this._order = order || Euler.DefaultOrder;
9797
9798         }
9799
9800         Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
9801
9802         Euler.DefaultOrder = 'XYZ';
9803
9804         Object.defineProperties( Euler.prototype, {
9805
9806                 x: {
9807
9808                         get: function () {
9809
9810                                 return this._x;
9811
9812                         },
9813
9814                         set: function ( value ) {
9815
9816                                 this._x = value;
9817                                 this.onChangeCallback();
9818
9819                         }
9820
9821                 },
9822
9823                 y: {
9824
9825                         get: function () {
9826
9827                                 return this._y;
9828
9829                         },
9830
9831                         set: function ( value ) {
9832
9833                                 this._y = value;
9834                                 this.onChangeCallback();
9835
9836                         }
9837
9838                 },
9839
9840                 z: {
9841
9842                         get: function () {
9843
9844                                 return this._z;
9845
9846                         },
9847
9848                         set: function ( value ) {
9849
9850                                 this._z = value;
9851                                 this.onChangeCallback();
9852
9853                         }
9854
9855                 },
9856
9857                 order: {
9858
9859                         get: function () {
9860
9861                                 return this._order;
9862
9863                         },
9864
9865                         set: function ( value ) {
9866
9867                                 this._order = value;
9868                                 this.onChangeCallback();
9869
9870                         }
9871
9872                 }
9873
9874         } );
9875
9876         Object.assign( Euler.prototype, {
9877
9878                 isEuler: true,
9879
9880                 set: function ( x, y, z, order ) {
9881
9882                         this._x = x;
9883                         this._y = y;
9884                         this._z = z;
9885                         this._order = order || this._order;
9886
9887                         this.onChangeCallback();
9888
9889                         return this;
9890
9891                 },
9892
9893                 clone: function () {
9894
9895                         return new this.constructor( this._x, this._y, this._z, this._order );
9896
9897                 },
9898
9899                 copy: function ( euler ) {
9900
9901                         this._x = euler._x;
9902                         this._y = euler._y;
9903                         this._z = euler._z;
9904                         this._order = euler._order;
9905
9906                         this.onChangeCallback();
9907
9908                         return this;
9909
9910                 },
9911
9912                 setFromRotationMatrix: function ( m, order, update ) {
9913
9914                         var clamp = _Math.clamp;
9915
9916                         // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
9917
9918                         var te = m.elements;
9919                         var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
9920                         var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
9921                         var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
9922
9923                         order = order || this._order;
9924
9925                         if ( order === 'XYZ' ) {
9926
9927                                 this._y = Math.asin( clamp( m13, - 1, 1 ) );
9928
9929                                 if ( Math.abs( m13 ) < 0.99999 ) {
9930
9931                                         this._x = Math.atan2( - m23, m33 );
9932                                         this._z = Math.atan2( - m12, m11 );
9933
9934                                 } else {
9935
9936                                         this._x = Math.atan2( m32, m22 );
9937                                         this._z = 0;
9938
9939                                 }
9940
9941                         } else if ( order === 'YXZ' ) {
9942
9943                                 this._x = Math.asin( - clamp( m23, - 1, 1 ) );
9944
9945                                 if ( Math.abs( m23 ) < 0.99999 ) {
9946
9947                                         this._y = Math.atan2( m13, m33 );
9948                                         this._z = Math.atan2( m21, m22 );
9949
9950                                 } else {
9951
9952                                         this._y = Math.atan2( - m31, m11 );
9953                                         this._z = 0;
9954
9955                                 }
9956
9957                         } else if ( order === 'ZXY' ) {
9958
9959                                 this._x = Math.asin( clamp( m32, - 1, 1 ) );
9960
9961                                 if ( Math.abs( m32 ) < 0.99999 ) {
9962
9963                                         this._y = Math.atan2( - m31, m33 );
9964                                         this._z = Math.atan2( - m12, m22 );
9965
9966                                 } else {
9967
9968                                         this._y = 0;
9969                                         this._z = Math.atan2( m21, m11 );
9970
9971                                 }
9972
9973                         } else if ( order === 'ZYX' ) {
9974
9975                                 this._y = Math.asin( - clamp( m31, - 1, 1 ) );
9976
9977                                 if ( Math.abs( m31 ) < 0.99999 ) {
9978
9979                                         this._x = Math.atan2( m32, m33 );
9980                                         this._z = Math.atan2( m21, m11 );
9981
9982                                 } else {
9983
9984                                         this._x = 0;
9985                                         this._z = Math.atan2( - m12, m22 );
9986
9987                                 }
9988
9989                         } else if ( order === 'YZX' ) {
9990
9991                                 this._z = Math.asin( clamp( m21, - 1, 1 ) );
9992
9993                                 if ( Math.abs( m21 ) < 0.99999 ) {
9994
9995                                         this._x = Math.atan2( - m23, m22 );
9996                                         this._y = Math.atan2( - m31, m11 );
9997
9998                                 } else {
9999
10000                                         this._x = 0;
10001                                         this._y = Math.atan2( m13, m33 );
10002
10003                                 }
10004
10005                         } else if ( order === 'XZY' ) {
10006
10007                                 this._z = Math.asin( - clamp( m12, - 1, 1 ) );
10008
10009                                 if ( Math.abs( m12 ) < 0.99999 ) {
10010
10011                                         this._x = Math.atan2( m32, m22 );
10012                                         this._y = Math.atan2( m13, m11 );
10013
10014                                 } else {
10015
10016                                         this._x = Math.atan2( - m23, m33 );
10017                                         this._y = 0;
10018
10019                                 }
10020
10021                         } else {
10022
10023                                 console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );
10024
10025                         }
10026
10027                         this._order = order;
10028
10029                         if ( update !== false ) this.onChangeCallback();
10030
10031                         return this;
10032
10033                 },
10034
10035                 setFromQuaternion: function () {
10036
10037                         var matrix = new Matrix4();
10038
10039                         return function setFromQuaternion( q, order, update ) {
10040
10041                                 matrix.makeRotationFromQuaternion( q );
10042
10043                                 return this.setFromRotationMatrix( matrix, order, update );
10044
10045                         };
10046
10047                 }(),
10048
10049                 setFromVector3: function ( v, order ) {
10050
10051                         return this.set( v.x, v.y, v.z, order || this._order );
10052
10053                 },
10054
10055                 reorder: function () {
10056
10057                         // WARNING: this discards revolution information -bhouston
10058
10059                         var q = new Quaternion();
10060
10061                         return function reorder( newOrder ) {
10062
10063                                 q.setFromEuler( this );
10064
10065                                 return this.setFromQuaternion( q, newOrder );
10066
10067                         };
10068
10069                 }(),
10070
10071                 equals: function ( euler ) {
10072
10073                         return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
10074
10075                 },
10076
10077                 fromArray: function ( array ) {
10078
10079                         this._x = array[ 0 ];
10080                         this._y = array[ 1 ];
10081                         this._z = array[ 2 ];
10082                         if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
10083
10084                         this.onChangeCallback();
10085
10086                         return this;
10087
10088                 },
10089
10090                 toArray: function ( array, offset ) {
10091
10092                         if ( array === undefined ) array = [];
10093                         if ( offset === undefined ) offset = 0;
10094
10095                         array[ offset ] = this._x;
10096                         array[ offset + 1 ] = this._y;
10097                         array[ offset + 2 ] = this._z;
10098                         array[ offset + 3 ] = this._order;
10099
10100                         return array;
10101
10102                 },
10103
10104                 toVector3: function ( optionalResult ) {
10105
10106                         if ( optionalResult ) {
10107
10108                                 return optionalResult.set( this._x, this._y, this._z );
10109
10110                         } else {
10111
10112                                 return new Vector3( this._x, this._y, this._z );
10113
10114                         }
10115
10116                 },
10117
10118                 onChange: function ( callback ) {
10119
10120                         this.onChangeCallback = callback;
10121
10122                         return this;
10123
10124                 },
10125
10126                 onChangeCallback: function () {}
10127
10128         } );
10129
10130         /**
10131          * @author mrdoob / http://mrdoob.com/
10132          */
10133
10134         function Layers() {
10135
10136                 this.mask = 1 | 0;
10137
10138         }
10139
10140         Object.assign( Layers.prototype, {
10141
10142                 set: function ( channel ) {
10143
10144                         this.mask = 1 << channel | 0;
10145
10146                 },
10147
10148                 enable: function ( channel ) {
10149
10150                         this.mask |= 1 << channel | 0;
10151
10152                 },
10153
10154                 toggle: function ( channel ) {
10155
10156                         this.mask ^= 1 << channel | 0;
10157
10158                 },
10159
10160                 disable: function ( channel ) {
10161
10162                         this.mask &= ~ ( 1 << channel | 0 );
10163
10164                 },
10165
10166                 test: function ( layers ) {
10167
10168                         return ( this.mask & layers.mask ) !== 0;
10169
10170                 }
10171
10172         } );
10173
10174         /**
10175          * @author mrdoob / http://mrdoob.com/
10176          * @author mikael emtinger / http://gomo.se/
10177          * @author alteredq / http://alteredqualia.com/
10178          * @author WestLangley / http://github.com/WestLangley
10179          * @author elephantatwork / www.elephantatwork.ch
10180          */
10181
10182         var object3DId = 0;
10183
10184         function Object3D() {
10185
10186                 Object.defineProperty( this, 'id', { value: object3DId ++ } );
10187
10188                 this.uuid = _Math.generateUUID();
10189
10190                 this.name = '';
10191                 this.type = 'Object3D';
10192
10193                 this.parent = null;
10194                 this.children = [];
10195
10196                 this.up = Object3D.DefaultUp.clone();
10197
10198                 var position = new Vector3();
10199                 var rotation = new Euler();
10200                 var quaternion = new Quaternion();
10201                 var scale = new Vector3( 1, 1, 1 );
10202
10203                 function onRotationChange() {
10204
10205                         quaternion.setFromEuler( rotation, false );
10206
10207                 }
10208
10209                 function onQuaternionChange() {
10210
10211                         rotation.setFromQuaternion( quaternion, undefined, false );
10212
10213                 }
10214
10215                 rotation.onChange( onRotationChange );
10216                 quaternion.onChange( onQuaternionChange );
10217
10218                 Object.defineProperties( this, {
10219                         position: {
10220                                 enumerable: true,
10221                                 value: position
10222                         },
10223                         rotation: {
10224                                 enumerable: true,
10225                                 value: rotation
10226                         },
10227                         quaternion: {
10228                                 enumerable: true,
10229                                 value: quaternion
10230                         },
10231                         scale: {
10232                                 enumerable: true,
10233                                 value: scale
10234                         },
10235                         modelViewMatrix: {
10236                                 value: new Matrix4()
10237                         },
10238                         normalMatrix: {
10239                                 value: new Matrix3()
10240                         }
10241                 } );
10242
10243                 this.matrix = new Matrix4();
10244                 this.matrixWorld = new Matrix4();
10245
10246                 this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
10247                 this.matrixWorldNeedsUpdate = false;
10248
10249                 this.layers = new Layers();
10250                 this.visible = true;
10251
10252                 this.castShadow = false;
10253                 this.receiveShadow = false;
10254
10255                 this.frustumCulled = true;
10256                 this.renderOrder = 0;
10257
10258                 this.userData = {};
10259         }
10260
10261         Object3D.DefaultUp = new Vector3( 0, 1, 0 );
10262         Object3D.DefaultMatrixAutoUpdate = true;
10263
10264         Object.assign( Object3D.prototype, EventDispatcher.prototype, {
10265
10266                 isObject3D: true,
10267
10268                 onBeforeRender: function () {},
10269                 onAfterRender: function () {},
10270
10271                 applyMatrix: function ( matrix ) {
10272
10273                         this.matrix.multiplyMatrices( matrix, this.matrix );
10274
10275                         this.matrix.decompose( this.position, this.quaternion, this.scale );
10276
10277                 },
10278
10279                 applyQuaternion: function ( q ) {
10280
10281                         this.quaternion.premultiply( q );
10282
10283                         return this;
10284
10285                 },
10286
10287                 setRotationFromAxisAngle: function ( axis, angle ) {
10288
10289                         // assumes axis is normalized
10290
10291                         this.quaternion.setFromAxisAngle( axis, angle );
10292
10293                 },
10294
10295                 setRotationFromEuler: function ( euler ) {
10296
10297                         this.quaternion.setFromEuler( euler, true );
10298
10299                 },
10300
10301                 setRotationFromMatrix: function ( m ) {
10302
10303                         // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
10304
10305                         this.quaternion.setFromRotationMatrix( m );
10306
10307                 },
10308
10309                 setRotationFromQuaternion: function ( q ) {
10310
10311                         // assumes q is normalized
10312
10313                         this.quaternion.copy( q );
10314
10315                 },
10316
10317                 rotateOnAxis: function () {
10318
10319                         // rotate object on axis in object space
10320                         // axis is assumed to be normalized
10321
10322                         var q1 = new Quaternion();
10323
10324                         return function rotateOnAxis( axis, angle ) {
10325
10326                                 q1.setFromAxisAngle( axis, angle );
10327
10328                                 this.quaternion.multiply( q1 );
10329
10330                                 return this;
10331
10332                         };
10333
10334                 }(),
10335
10336                 rotateX: function () {
10337
10338                         var v1 = new Vector3( 1, 0, 0 );
10339
10340                         return function rotateX( angle ) {
10341
10342                                 return this.rotateOnAxis( v1, angle );
10343
10344                         };
10345
10346                 }(),
10347
10348                 rotateY: function () {
10349
10350                         var v1 = new Vector3( 0, 1, 0 );
10351
10352                         return function rotateY( angle ) {
10353
10354                                 return this.rotateOnAxis( v1, angle );
10355
10356                         };
10357
10358                 }(),
10359
10360                 rotateZ: function () {
10361
10362                         var v1 = new Vector3( 0, 0, 1 );
10363
10364                         return function rotateZ( angle ) {
10365
10366                                 return this.rotateOnAxis( v1, angle );
10367
10368                         };
10369
10370                 }(),
10371
10372                 translateOnAxis: function () {
10373
10374                         // translate object by distance along axis in object space
10375                         // axis is assumed to be normalized
10376
10377                         var v1 = new Vector3();
10378
10379                         return function translateOnAxis( axis, distance ) {
10380
10381                                 v1.copy( axis ).applyQuaternion( this.quaternion );
10382
10383                                 this.position.add( v1.multiplyScalar( distance ) );
10384
10385                                 return this;
10386
10387                         };
10388
10389                 }(),
10390
10391                 translateX: function () {
10392
10393                         var v1 = new Vector3( 1, 0, 0 );
10394
10395                         return function translateX( distance ) {
10396
10397                                 return this.translateOnAxis( v1, distance );
10398
10399                         };
10400
10401                 }(),
10402
10403                 translateY: function () {
10404
10405                         var v1 = new Vector3( 0, 1, 0 );
10406
10407                         return function translateY( distance ) {
10408
10409                                 return this.translateOnAxis( v1, distance );
10410
10411                         };
10412
10413                 }(),
10414
10415                 translateZ: function () {
10416
10417                         var v1 = new Vector3( 0, 0, 1 );
10418
10419                         return function translateZ( distance ) {
10420
10421                                 return this.translateOnAxis( v1, distance );
10422
10423                         };
10424
10425                 }(),
10426
10427                 localToWorld: function ( vector ) {
10428
10429                         return vector.applyMatrix4( this.matrixWorld );
10430
10431                 },
10432
10433                 worldToLocal: function () {
10434
10435                         var m1 = new Matrix4();
10436
10437                         return function worldToLocal( vector ) {
10438
10439                                 return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
10440
10441                         };
10442
10443                 }(),
10444
10445                 lookAt: function () {
10446
10447                         // This method does not support objects with rotated and/or translated parent(s)
10448
10449                         var m1 = new Matrix4();
10450
10451                         return function lookAt( vector ) {
10452
10453                                 if ( this.isCamera ) {
10454
10455                                         m1.lookAt( this.position, vector, this.up );
10456
10457                                 } else {
10458
10459                                         m1.lookAt( vector, this.position, this.up );
10460
10461                                 }
10462
10463                                 this.quaternion.setFromRotationMatrix( m1 );
10464
10465                         };
10466
10467                 }(),
10468
10469                 add: function ( object ) {
10470
10471                         if ( arguments.length > 1 ) {
10472
10473                                 for ( var i = 0; i < arguments.length; i ++ ) {
10474
10475                                         this.add( arguments[ i ] );
10476
10477                                 }
10478
10479                                 return this;
10480
10481                         }
10482
10483                         if ( object === this ) {
10484
10485                                 console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
10486                                 return this;
10487
10488                         }
10489
10490                         if ( ( object && object.isObject3D ) ) {
10491
10492                                 if ( object.parent !== null ) {
10493
10494                                         object.parent.remove( object );
10495
10496                                 }
10497
10498                                 object.parent = this;
10499                                 object.dispatchEvent( { type: 'added' } );
10500
10501                                 this.children.push( object );
10502
10503                         } else {
10504
10505                                 console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
10506
10507                         }
10508
10509                         return this;
10510
10511                 },
10512
10513                 remove: function ( object ) {
10514
10515                         if ( arguments.length > 1 ) {
10516
10517                                 for ( var i = 0; i < arguments.length; i ++ ) {
10518
10519                                         this.remove( arguments[ i ] );
10520
10521                                 }
10522
10523                                 return this;
10524
10525                         }
10526
10527                         var index = this.children.indexOf( object );
10528
10529                         if ( index !== - 1 ) {
10530
10531                                 object.parent = null;
10532
10533                                 object.dispatchEvent( { type: 'removed' } );
10534
10535                                 this.children.splice( index, 1 );
10536
10537                         }
10538
10539                         return this;
10540
10541                 },
10542
10543                 getObjectById: function ( id ) {
10544
10545                         return this.getObjectByProperty( 'id', id );
10546
10547                 },
10548
10549                 getObjectByName: function ( name ) {
10550
10551                         return this.getObjectByProperty( 'name', name );
10552
10553                 },
10554
10555                 getObjectByProperty: function ( name, value ) {
10556
10557                         if ( this[ name ] === value ) return this;
10558
10559                         for ( var i = 0, l = this.children.length; i < l; i ++ ) {
10560
10561                                 var child = this.children[ i ];
10562                                 var object = child.getObjectByProperty( name, value );
10563
10564                                 if ( object !== undefined ) {
10565
10566                                         return object;
10567
10568                                 }
10569
10570                         }
10571
10572                         return undefined;
10573
10574                 },
10575
10576                 getWorldPosition: function ( optionalTarget ) {
10577
10578                         var result = optionalTarget || new Vector3();
10579
10580                         this.updateMatrixWorld( true );
10581
10582                         return result.setFromMatrixPosition( this.matrixWorld );
10583
10584                 },
10585
10586                 getWorldQuaternion: function () {
10587
10588                         var position = new Vector3();
10589                         var scale = new Vector3();
10590
10591                         return function getWorldQuaternion( optionalTarget ) {
10592
10593                                 var result = optionalTarget || new Quaternion();
10594
10595                                 this.updateMatrixWorld( true );
10596
10597                                 this.matrixWorld.decompose( position, result, scale );
10598
10599                                 return result;
10600
10601                         };
10602
10603                 }(),
10604
10605                 getWorldRotation: function () {
10606
10607                         var quaternion = new Quaternion();
10608
10609                         return function getWorldRotation( optionalTarget ) {
10610
10611                                 var result = optionalTarget || new Euler();
10612
10613                                 this.getWorldQuaternion( quaternion );
10614
10615                                 return result.setFromQuaternion( quaternion, this.rotation.order, false );
10616
10617                         };
10618
10619                 }(),
10620
10621                 getWorldScale: function () {
10622
10623                         var position = new Vector3();
10624                         var quaternion = new Quaternion();
10625
10626                         return function getWorldScale( optionalTarget ) {
10627
10628                                 var result = optionalTarget || new Vector3();
10629
10630                                 this.updateMatrixWorld( true );
10631
10632                                 this.matrixWorld.decompose( position, quaternion, result );
10633
10634                                 return result;
10635
10636                         };
10637
10638                 }(),
10639
10640                 getWorldDirection: function () {
10641
10642                         var quaternion = new Quaternion();
10643
10644                         return function getWorldDirection( optionalTarget ) {
10645
10646                                 var result = optionalTarget || new Vector3();
10647
10648                                 this.getWorldQuaternion( quaternion );
10649
10650                                 return result.set( 0, 0, 1 ).applyQuaternion( quaternion );
10651
10652                         };
10653
10654                 }(),
10655
10656                 raycast: function () {},
10657
10658                 traverse: function ( callback ) {
10659
10660                         callback( this );
10661
10662                         var children = this.children;
10663
10664                         for ( var i = 0, l = children.length; i < l; i ++ ) {
10665
10666                                 children[ i ].traverse( callback );
10667
10668                         }
10669
10670                 },
10671
10672                 traverseVisible: function ( callback ) {
10673
10674                         if ( this.visible === false ) return;
10675
10676                         callback( this );
10677
10678                         var children = this.children;
10679
10680                         for ( var i = 0, l = children.length; i < l; i ++ ) {
10681
10682                                 children[ i ].traverseVisible( callback );
10683
10684                         }
10685
10686                 },
10687
10688                 traverseAncestors: function ( callback ) {
10689
10690                         var parent = this.parent;
10691
10692                         if ( parent !== null ) {
10693
10694                                 callback( parent );
10695
10696                                 parent.traverseAncestors( callback );
10697
10698                         }
10699
10700                 },
10701
10702                 updateMatrix: function () {
10703
10704                         this.matrix.compose( this.position, this.quaternion, this.scale );
10705
10706                         this.matrixWorldNeedsUpdate = true;
10707
10708                 },
10709
10710                 updateMatrixWorld: function ( force ) {
10711
10712                         if ( this.matrixAutoUpdate ) this.updateMatrix();
10713
10714                         if ( this.matrixWorldNeedsUpdate || force ) {
10715
10716                                 if ( this.parent === null ) {
10717
10718                                         this.matrixWorld.copy( this.matrix );
10719
10720                                 } else {
10721
10722                                         this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
10723
10724                                 }
10725
10726                                 this.matrixWorldNeedsUpdate = false;
10727
10728                                 force = true;
10729
10730                         }
10731
10732                         // update children
10733
10734                         var children = this.children;
10735
10736                         for ( var i = 0, l = children.length; i < l; i ++ ) {
10737
10738                                 children[ i ].updateMatrixWorld( force );
10739
10740                         }
10741
10742                 },
10743
10744                 toJSON: function ( meta ) {
10745
10746                         // meta is '' when called from JSON.stringify
10747                         var isRootObject = ( meta === undefined || meta === '' );
10748
10749                         var output = {};
10750
10751                         // meta is a hash used to collect geometries, materials.
10752                         // not providing it implies that this is the root object
10753                         // being serialized.
10754                         if ( isRootObject ) {
10755
10756                                 // initialize meta obj
10757                                 meta = {
10758                                         geometries: {},
10759                                         materials: {},
10760                                         textures: {},
10761                                         images: {}
10762                                 };
10763
10764                                 output.metadata = {
10765                                         version: 4.5,
10766                                         type: 'Object',
10767                                         generator: 'Object3D.toJSON'
10768                                 };
10769
10770                         }
10771
10772                         // standard Object3D serialization
10773
10774                         var object = {};
10775
10776                         object.uuid = this.uuid;
10777                         object.type = this.type;
10778
10779                         if ( this.name !== '' ) object.name = this.name;
10780                         if ( this.castShadow === true ) object.castShadow = true;
10781                         if ( this.receiveShadow === true ) object.receiveShadow = true;
10782                         if ( this.visible === false ) object.visible = false;
10783                         if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
10784
10785                         object.matrix = this.matrix.toArray();
10786
10787                         //
10788
10789                         function serialize( library, element ) {
10790
10791                                 if ( library[ element.uuid ] === undefined ) {
10792
10793                                         library[ element.uuid ] = element.toJSON( meta );
10794
10795                                 }
10796
10797                                 return element.uuid;
10798
10799                         }
10800
10801                         if ( this.geometry !== undefined ) {
10802
10803                                 object.geometry = serialize( meta.geometries, this.geometry );
10804
10805                         }
10806
10807                         if ( this.material !== undefined ) {
10808
10809                                 if ( Array.isArray( this.material ) ) {
10810
10811                                         var uuids = [];
10812
10813                                         for ( var i = 0, l = this.material.length; i < l; i ++ ) {
10814
10815                                                 uuids.push( serialize( meta.materials, this.material[ i ] ) );
10816
10817                                         }
10818
10819                                         object.material = uuids;
10820
10821                                 } else {
10822
10823                                         object.material = serialize( meta.materials, this.material );
10824
10825                                 }
10826
10827                         }
10828
10829                         //
10830
10831                         if ( this.children.length > 0 ) {
10832
10833                                 object.children = [];
10834
10835                                 for ( var i = 0; i < this.children.length; i ++ ) {
10836
10837                                         object.children.push( this.children[ i ].toJSON( meta ).object );
10838
10839                                 }
10840
10841                         }
10842
10843                         if ( isRootObject ) {
10844
10845                                 var geometries = extractFromCache( meta.geometries );
10846                                 var materials = extractFromCache( meta.materials );
10847                                 var textures = extractFromCache( meta.textures );
10848                                 var images = extractFromCache( meta.images );
10849
10850                                 if ( geometries.length > 0 ) output.geometries = geometries;
10851                                 if ( materials.length > 0 ) output.materials = materials;
10852                                 if ( textures.length > 0 ) output.textures = textures;
10853                                 if ( images.length > 0 ) output.images = images;
10854
10855                         }
10856
10857                         output.object = object;
10858
10859                         return output;
10860
10861                         // extract data from the cache hash
10862                         // remove metadata on each item
10863                         // and return as array
10864                         function extractFromCache( cache ) {
10865
10866                                 var values = [];
10867                                 for ( var key in cache ) {
10868
10869                                         var data = cache[ key ];
10870                                         delete data.metadata;
10871                                         values.push( data );
10872
10873                                 }
10874                                 return values;
10875
10876                         }
10877
10878                 },
10879
10880                 clone: function ( recursive ) {
10881
10882                         return new this.constructor().copy( this, recursive );
10883
10884                 },
10885
10886                 copy: function ( source, recursive ) {
10887
10888                         if ( recursive === undefined ) recursive = true;
10889
10890                         this.name = source.name;
10891
10892                         this.up.copy( source.up );
10893
10894                         this.position.copy( source.position );
10895                         this.quaternion.copy( source.quaternion );
10896                         this.scale.copy( source.scale );
10897
10898                         this.matrix.copy( source.matrix );
10899                         this.matrixWorld.copy( source.matrixWorld );
10900
10901                         this.matrixAutoUpdate = source.matrixAutoUpdate;
10902                         this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
10903
10904                         this.layers.mask = source.layers.mask;
10905                         this.visible = source.visible;
10906
10907                         this.castShadow = source.castShadow;
10908                         this.receiveShadow = source.receiveShadow;
10909
10910                         this.frustumCulled = source.frustumCulled;
10911                         this.renderOrder = source.renderOrder;
10912
10913                         this.userData = JSON.parse( JSON.stringify( source.userData ) );
10914
10915                         if ( recursive === true ) {
10916
10917                                 for ( var i = 0; i < source.children.length; i ++ ) {
10918
10919                                         var child = source.children[ i ];
10920                                         this.add( child.clone() );
10921
10922                                 }
10923
10924                         }
10925
10926                         return this;
10927
10928                 }
10929
10930         } );
10931
10932         /**
10933          * @author mrdoob / http://mrdoob.com/
10934          * @author mikael emtinger / http://gomo.se/
10935          * @author WestLangley / http://github.com/WestLangley
10936         */
10937
10938         function Camera() {
10939
10940                 Object3D.call( this );
10941
10942                 this.type = 'Camera';
10943
10944                 this.matrixWorldInverse = new Matrix4();
10945                 this.projectionMatrix = new Matrix4();
10946
10947         }
10948
10949         Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
10950
10951                 constructor: Camera,
10952
10953                 isCamera: true,
10954
10955                 copy: function ( source, recursive ) {
10956
10957                         Object3D.prototype.copy.call( this, source, recursive );
10958
10959                         this.matrixWorldInverse.copy( source.matrixWorldInverse );
10960                         this.projectionMatrix.copy( source.projectionMatrix );
10961
10962                         return this;
10963
10964                 },
10965
10966                 getWorldDirection: function () {
10967
10968                         var quaternion = new Quaternion();
10969
10970                         return function getWorldDirection( optionalTarget ) {
10971
10972                                 var result = optionalTarget || new Vector3();
10973
10974                                 this.getWorldQuaternion( quaternion );
10975
10976                                 return result.set( 0, 0, - 1 ).applyQuaternion( quaternion );
10977
10978                         };
10979
10980                 }(),
10981
10982                 updateMatrixWorld: function ( force ) {
10983
10984                         Object3D.prototype.updateMatrixWorld.call( this, force );
10985
10986                         this.matrixWorldInverse.getInverse( this.matrixWorld );
10987
10988                 },
10989
10990                 clone: function () {
10991
10992                         return new this.constructor().copy( this );
10993
10994                 }
10995
10996         } );
10997
10998         /**
10999          * @author alteredq / http://alteredqualia.com/
11000          * @author arose / http://github.com/arose
11001          */
11002
11003         function OrthographicCamera( left, right, top, bottom, near, far ) {
11004
11005                 Camera.call( this );
11006
11007                 this.type = 'OrthographicCamera';
11008
11009                 this.zoom = 1;
11010                 this.view = null;
11011
11012                 this.left = left;
11013                 this.right = right;
11014                 this.top = top;
11015                 this.bottom = bottom;
11016
11017                 this.near = ( near !== undefined ) ? near : 0.1;
11018                 this.far = ( far !== undefined ) ? far : 2000;
11019
11020                 this.updateProjectionMatrix();
11021
11022         }
11023
11024         OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
11025
11026                 constructor: OrthographicCamera,
11027
11028                 isOrthographicCamera: true,
11029
11030                 copy: function ( source, recursive ) {
11031
11032                         Camera.prototype.copy.call( this, source, recursive );
11033
11034                         this.left = source.left;
11035                         this.right = source.right;
11036                         this.top = source.top;
11037                         this.bottom = source.bottom;
11038                         this.near = source.near;
11039                         this.far = source.far;
11040
11041                         this.zoom = source.zoom;
11042                         this.view = source.view === null ? null : Object.assign( {}, source.view );
11043
11044                         return this;
11045
11046                 },
11047
11048                 setViewOffset: function( fullWidth, fullHeight, x, y, width, height ) {
11049
11050                         this.view = {
11051                                 fullWidth: fullWidth,
11052                                 fullHeight: fullHeight,
11053                                 offsetX: x,
11054                                 offsetY: y,
11055                                 width: width,
11056                                 height: height
11057                         };
11058
11059                         this.updateProjectionMatrix();
11060
11061                 },
11062
11063                 clearViewOffset: function() {
11064
11065                         this.view = null;
11066                         this.updateProjectionMatrix();
11067
11068                 },
11069
11070                 updateProjectionMatrix: function () {
11071
11072                         var dx = ( this.right - this.left ) / ( 2 * this.zoom );
11073                         var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
11074                         var cx = ( this.right + this.left ) / 2;
11075                         var cy = ( this.top + this.bottom ) / 2;
11076
11077                         var left = cx - dx;
11078                         var right = cx + dx;
11079                         var top = cy + dy;
11080                         var bottom = cy - dy;
11081
11082                         if ( this.view !== null ) {
11083
11084                                 var zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
11085                                 var zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
11086                                 var scaleW = ( this.right - this.left ) / this.view.width;
11087                                 var scaleH = ( this.top - this.bottom ) / this.view.height;
11088
11089                                 left += scaleW * ( this.view.offsetX / zoomW );
11090                                 right = left + scaleW * ( this.view.width / zoomW );
11091                                 top -= scaleH * ( this.view.offsetY / zoomH );
11092                                 bottom = top - scaleH * ( this.view.height / zoomH );
11093
11094                         }
11095
11096                         this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
11097
11098                 },
11099
11100                 toJSON: function ( meta ) {
11101
11102                         var data = Object3D.prototype.toJSON.call( this, meta );
11103
11104                         data.object.zoom = this.zoom;
11105                         data.object.left = this.left;
11106                         data.object.right = this.right;
11107                         data.object.top = this.top;
11108                         data.object.bottom = this.bottom;
11109                         data.object.near = this.near;
11110                         data.object.far = this.far;
11111
11112                         if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
11113
11114                         return data;
11115
11116                 }
11117
11118         } );
11119
11120         /**
11121          * @author mrdoob / http://mrdoob.com/
11122          * @author greggman / http://games.greggman.com/
11123          * @author zz85 / http://www.lab4games.net/zz85/blog
11124          * @author tschw
11125          */
11126
11127         function PerspectiveCamera( fov, aspect, near, far ) {
11128
11129                 Camera.call( this );
11130
11131                 this.type = 'PerspectiveCamera';
11132
11133                 this.fov = fov !== undefined ? fov : 50;
11134                 this.zoom = 1;
11135
11136                 this.near = near !== undefined ? near : 0.1;
11137                 this.far = far !== undefined ? far : 2000;
11138                 this.focus = 10;
11139
11140                 this.aspect = aspect !== undefined ? aspect : 1;
11141                 this.view = null;
11142
11143                 this.filmGauge = 35;    // width of the film (default in millimeters)
11144                 this.filmOffset = 0;    // horizontal film offset (same unit as gauge)
11145
11146                 this.updateProjectionMatrix();
11147
11148         }
11149
11150         PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
11151
11152                 constructor: PerspectiveCamera,
11153
11154                 isPerspectiveCamera: true,
11155
11156                 copy: function ( source, recursive ) {
11157
11158                         Camera.prototype.copy.call( this, source, recursive );
11159
11160                         this.fov = source.fov;
11161                         this.zoom = source.zoom;
11162
11163                         this.near = source.near;
11164                         this.far = source.far;
11165                         this.focus = source.focus;
11166
11167                         this.aspect = source.aspect;
11168                         this.view = source.view === null ? null : Object.assign( {}, source.view );
11169
11170                         this.filmGauge = source.filmGauge;
11171                         this.filmOffset = source.filmOffset;
11172
11173                         return this;
11174
11175                 },
11176
11177                 /**
11178                  * Sets the FOV by focal length in respect to the current .filmGauge.
11179                  *
11180                  * The default film gauge is 35, so that the focal length can be specified for
11181                  * a 35mm (full frame) camera.
11182                  *
11183                  * Values for focal length and film gauge must have the same unit.
11184                  */
11185                 setFocalLength: function ( focalLength ) {
11186
11187                         // see http://www.bobatkins.com/photography/technical/field_of_view.html
11188                         var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
11189
11190                         this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
11191                         this.updateProjectionMatrix();
11192
11193                 },
11194
11195                 /**
11196                  * Calculates the focal length from the current .fov and .filmGauge.
11197                  */
11198                 getFocalLength: function () {
11199
11200                         var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov );
11201
11202                         return 0.5 * this.getFilmHeight() / vExtentSlope;
11203
11204                 },
11205
11206                 getEffectiveFOV: function () {
11207
11208                         return _Math.RAD2DEG * 2 * Math.atan(
11209                                         Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );
11210
11211                 },
11212
11213                 getFilmWidth: function () {
11214
11215                         // film not completely covered in portrait format (aspect < 1)
11216                         return this.filmGauge * Math.min( this.aspect, 1 );
11217
11218                 },
11219
11220                 getFilmHeight: function () {
11221
11222                         // film not completely covered in landscape format (aspect > 1)
11223                         return this.filmGauge / Math.max( this.aspect, 1 );
11224
11225                 },
11226
11227                 /**
11228                  * Sets an offset in a larger frustum. This is useful for multi-window or
11229                  * multi-monitor/multi-machine setups.
11230                  *
11231                  * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
11232                  * the monitors are in grid like this
11233                  *
11234                  *   +---+---+---+
11235                  *   | A | B | C |
11236                  *   +---+---+---+
11237                  *   | D | E | F |
11238                  *   +---+---+---+
11239                  *
11240                  * then for each monitor you would call it like this
11241                  *
11242                  *   var w = 1920;
11243                  *   var h = 1080;
11244                  *   var fullWidth = w * 3;
11245                  *   var fullHeight = h * 2;
11246                  *
11247                  *   --A--
11248                  *   camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
11249                  *   --B--
11250                  *   camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
11251                  *   --C--
11252                  *   camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
11253                  *   --D--
11254                  *   camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
11255                  *   --E--
11256                  *   camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
11257                  *   --F--
11258                  *   camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
11259                  *
11260                  *   Note there is no reason monitors have to be the same size or in a grid.
11261                  */
11262                 setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
11263
11264                         this.aspect = fullWidth / fullHeight;
11265
11266                         this.view = {
11267                                 fullWidth: fullWidth,
11268                                 fullHeight: fullHeight,
11269                                 offsetX: x,
11270                                 offsetY: y,
11271                                 width: width,
11272                                 height: height
11273                         };
11274
11275                         this.updateProjectionMatrix();
11276
11277                 },
11278
11279                 clearViewOffset: function () {
11280
11281                         this.view = null;
11282                         this.updateProjectionMatrix();
11283
11284                 },
11285
11286                 updateProjectionMatrix: function () {
11287
11288                         var near = this.near,
11289                                 top = near * Math.tan(
11290                                                 _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,
11291                                 height = 2 * top,
11292                                 width = this.aspect * height,
11293                                 left = - 0.5 * width,
11294                                 view = this.view;
11295
11296                         if ( view !== null ) {
11297
11298                                 var fullWidth = view.fullWidth,
11299                                         fullHeight = view.fullHeight;
11300
11301                                 left += view.offsetX * width / fullWidth;
11302                                 top -= view.offsetY * height / fullHeight;
11303                                 width *= view.width / fullWidth;
11304                                 height *= view.height / fullHeight;
11305
11306                         }
11307
11308                         var skew = this.filmOffset;
11309                         if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
11310
11311                         this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
11312
11313                 },
11314
11315                 toJSON: function ( meta ) {
11316
11317                         var data = Object3D.prototype.toJSON.call( this, meta );
11318
11319                         data.object.fov = this.fov;
11320                         data.object.zoom = this.zoom;
11321
11322                         data.object.near = this.near;
11323                         data.object.far = this.far;
11324                         data.object.focus = this.focus;
11325
11326                         data.object.aspect = this.aspect;
11327
11328                         if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
11329
11330                         data.object.filmGauge = this.filmGauge;
11331                         data.object.filmOffset = this.filmOffset;
11332
11333                         return data;
11334
11335                 }
11336
11337         } );
11338
11339         /**
11340          * @author mrdoob / http://mrdoob.com/
11341          * @author alteredq / http://alteredqualia.com/
11342          */
11343
11344         function Face3( a, b, c, normal, color, materialIndex ) {
11345
11346                 this.a = a;
11347                 this.b = b;
11348                 this.c = c;
11349
11350                 this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
11351                 this.vertexNormals = Array.isArray( normal ) ? normal : [];
11352
11353                 this.color = ( color && color.isColor ) ? color : new Color();
11354                 this.vertexColors = Array.isArray( color ) ? color : [];
11355
11356                 this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
11357
11358         }
11359
11360         Object.assign( Face3.prototype, {
11361
11362                 clone: function () {
11363
11364                         return new this.constructor().copy( this );
11365
11366                 },
11367
11368                 copy: function ( source ) {
11369
11370                         this.a = source.a;
11371                         this.b = source.b;
11372                         this.c = source.c;
11373
11374                         this.normal.copy( source.normal );
11375                         this.color.copy( source.color );
11376
11377                         this.materialIndex = source.materialIndex;
11378
11379                         for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
11380
11381                                 this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
11382
11383                         }
11384
11385                         for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
11386
11387                                 this.vertexColors[ i ] = source.vertexColors[ i ].clone();
11388
11389                         }
11390
11391                         return this;
11392
11393                 }
11394
11395         } );
11396
11397         /**
11398          * @author mrdoob / http://mrdoob.com/
11399          * @author kile / http://kile.stravaganza.org/
11400          * @author alteredq / http://alteredqualia.com/
11401          * @author mikael emtinger / http://gomo.se/
11402          * @author zz85 / http://www.lab4games.net/zz85/blog
11403          * @author bhouston / http://clara.io
11404          */
11405
11406         var count = 0;
11407         function GeometryIdCount() { return count++; }
11408
11409         function Geometry() {
11410
11411                 Object.defineProperty( this, 'id', { value: GeometryIdCount() } );
11412
11413                 this.uuid = _Math.generateUUID();
11414
11415                 this.name = '';
11416                 this.type = 'Geometry';
11417
11418                 this.vertices = [];
11419                 this.colors = [];
11420                 this.faces = [];
11421                 this.faceVertexUvs = [[]];
11422
11423                 this.morphTargets = [];
11424                 this.morphNormals = [];
11425
11426                 this.skinWeights = [];
11427                 this.skinIndices = [];
11428
11429                 this.lineDistances = [];
11430
11431                 this.boundingBox = null;
11432                 this.boundingSphere = null;
11433
11434                 // update flags
11435
11436                 this.elementsNeedUpdate = false;
11437                 this.verticesNeedUpdate = false;
11438                 this.uvsNeedUpdate = false;
11439                 this.normalsNeedUpdate = false;
11440                 this.colorsNeedUpdate = false;
11441                 this.lineDistancesNeedUpdate = false;
11442                 this.groupsNeedUpdate = false;
11443
11444         }
11445
11446         Object.assign( Geometry.prototype, EventDispatcher.prototype, {
11447
11448                 isGeometry: true,
11449
11450                 applyMatrix: function ( matrix ) {
11451
11452                         var normalMatrix = new Matrix3().getNormalMatrix( matrix );
11453
11454                         for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
11455
11456                                 var vertex = this.vertices[ i ];
11457                                 vertex.applyMatrix4( matrix );
11458
11459                         }
11460
11461                         for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
11462
11463                                 var face = this.faces[ i ];
11464                                 face.normal.applyMatrix3( normalMatrix ).normalize();
11465
11466                                 for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
11467
11468                                         face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
11469
11470                                 }
11471
11472                         }
11473
11474                         if ( this.boundingBox !== null ) {
11475
11476                                 this.computeBoundingBox();
11477
11478                         }
11479
11480                         if ( this.boundingSphere !== null ) {
11481
11482                                 this.computeBoundingSphere();
11483
11484                         }
11485
11486                         this.verticesNeedUpdate = true;
11487                         this.normalsNeedUpdate = true;
11488
11489                         return this;
11490
11491                 },
11492
11493                 rotateX: function () {
11494
11495                         // rotate geometry around world x-axis
11496
11497                         var m1 = new Matrix4();
11498
11499                         return function rotateX( angle ) {
11500
11501                                 m1.makeRotationX( angle );
11502
11503                                 this.applyMatrix( m1 );
11504
11505                                 return this;
11506
11507                         };
11508
11509                 }(),
11510
11511                 rotateY: function () {
11512
11513                         // rotate geometry around world y-axis
11514
11515                         var m1 = new Matrix4();
11516
11517                         return function rotateY( angle ) {
11518
11519                                 m1.makeRotationY( angle );
11520
11521                                 this.applyMatrix( m1 );
11522
11523                                 return this;
11524
11525                         };
11526
11527                 }(),
11528
11529                 rotateZ: function () {
11530
11531                         // rotate geometry around world z-axis
11532
11533                         var m1 = new Matrix4();
11534
11535                         return function rotateZ( angle ) {
11536
11537                                 m1.makeRotationZ( angle );
11538
11539                                 this.applyMatrix( m1 );
11540
11541                                 return this;
11542
11543                         };
11544
11545                 }(),
11546
11547                 translate: function () {
11548
11549                         // translate geometry
11550
11551                         var m1 = new Matrix4();
11552
11553                         return function translate( x, y, z ) {
11554
11555                                 m1.makeTranslation( x, y, z );
11556
11557                                 this.applyMatrix( m1 );
11558
11559                                 return this;
11560
11561                         };
11562
11563                 }(),
11564
11565                 scale: function () {
11566
11567                         // scale geometry
11568
11569                         var m1 = new Matrix4();
11570
11571                         return function scale( x, y, z ) {
11572
11573                                 m1.makeScale( x, y, z );
11574
11575                                 this.applyMatrix( m1 );
11576
11577                                 return this;
11578
11579                         };
11580
11581                 }(),
11582
11583                 lookAt: function () {
11584
11585                         var obj = new Object3D();
11586
11587                         return function lookAt( vector ) {
11588
11589                                 obj.lookAt( vector );
11590
11591                                 obj.updateMatrix();
11592
11593                                 this.applyMatrix( obj.matrix );
11594
11595                         };
11596
11597                 }(),
11598
11599                 fromBufferGeometry: function ( geometry ) {
11600
11601                         var scope = this;
11602
11603                         var indices = geometry.index !== null ? geometry.index.array : undefined;
11604                         var attributes = geometry.attributes;
11605
11606                         var positions = attributes.position.array;
11607                         var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
11608                         var colors = attributes.color !== undefined ? attributes.color.array : undefined;
11609                         var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
11610                         var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
11611
11612                         if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
11613
11614                         var tempNormals = [];
11615                         var tempUVs = [];
11616                         var tempUVs2 = [];
11617
11618                         for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) {
11619
11620                                 scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) );
11621
11622                                 if ( normals !== undefined ) {
11623
11624                                         tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) );
11625
11626                                 }
11627
11628                                 if ( colors !== undefined ) {
11629
11630                                         scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) );
11631
11632                                 }
11633
11634                                 if ( uvs !== undefined ) {
11635
11636                                         tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) );
11637
11638                                 }
11639
11640                                 if ( uvs2 !== undefined ) {
11641
11642                                         tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) );
11643
11644                                 }
11645
11646                         }
11647
11648                         function addFace( a, b, c, materialIndex ) {
11649
11650                                 var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : [];
11651                                 var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
11652
11653                                 var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
11654
11655                                 scope.faces.push( face );
11656
11657                                 if ( uvs !== undefined ) {
11658
11659                                         scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] );
11660
11661                                 }
11662
11663                                 if ( uvs2 !== undefined ) {
11664
11665                                         scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] );
11666
11667                                 }
11668
11669                         }
11670
11671                         var groups = geometry.groups;
11672
11673                         if ( groups.length > 0 ) {
11674
11675                                 for ( var i = 0; i < groups.length; i ++ ) {
11676
11677                                         var group = groups[ i ];
11678
11679                                         var start = group.start;
11680                                         var count = group.count;
11681
11682                                         for ( var j = start, jl = start + count; j < jl; j += 3 ) {
11683
11684                                                 if ( indices !== undefined ) {
11685
11686                                                         addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );
11687
11688                                                 } else {
11689
11690                                                         addFace( j, j + 1, j + 2, group.materialIndex );
11691
11692                                                 }
11693
11694                                         }
11695
11696                                 }
11697
11698                         } else {
11699
11700                                 if ( indices !== undefined ) {
11701
11702                                         for ( var i = 0; i < indices.length; i += 3 ) {
11703
11704                                                 addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
11705
11706                                         }
11707
11708                                 } else {
11709
11710                                         for ( var i = 0; i < positions.length / 3; i += 3 ) {
11711
11712                                                 addFace( i, i + 1, i + 2 );
11713
11714                                         }
11715
11716                                 }
11717
11718                         }
11719
11720                         this.computeFaceNormals();
11721
11722                         if ( geometry.boundingBox !== null ) {
11723
11724                                 this.boundingBox = geometry.boundingBox.clone();
11725
11726                         }
11727
11728                         if ( geometry.boundingSphere !== null ) {
11729
11730                                 this.boundingSphere = geometry.boundingSphere.clone();
11731
11732                         }
11733
11734                         return this;
11735
11736                 },
11737
11738                 center: function () {
11739
11740                         this.computeBoundingBox();
11741
11742                         var offset = this.boundingBox.getCenter().negate();
11743
11744                         this.translate( offset.x, offset.y, offset.z );
11745
11746                         return offset;
11747
11748                 },
11749
11750                 normalize: function () {
11751
11752                         this.computeBoundingSphere();
11753
11754                         var center = this.boundingSphere.center;
11755                         var radius = this.boundingSphere.radius;
11756
11757                         var s = radius === 0 ? 1 : 1.0 / radius;
11758
11759                         var matrix = new Matrix4();
11760                         matrix.set(
11761                                 s, 0, 0, - s * center.x,
11762                                 0, s, 0, - s * center.y,
11763                                 0, 0, s, - s * center.z,
11764                                 0, 0, 0, 1
11765                         );
11766
11767                         this.applyMatrix( matrix );
11768
11769                         return this;
11770
11771                 },
11772
11773                 computeFaceNormals: function () {
11774
11775                         var cb = new Vector3(), ab = new Vector3();
11776
11777                         for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
11778
11779                                 var face = this.faces[ f ];
11780
11781                                 var vA = this.vertices[ face.a ];
11782                                 var vB = this.vertices[ face.b ];
11783                                 var vC = this.vertices[ face.c ];
11784
11785                                 cb.subVectors( vC, vB );
11786                                 ab.subVectors( vA, vB );
11787                                 cb.cross( ab );
11788
11789                                 cb.normalize();
11790
11791                                 face.normal.copy( cb );
11792
11793                         }
11794
11795                 },
11796
11797                 computeVertexNormals: function ( areaWeighted ) {
11798
11799                         if ( areaWeighted === undefined ) areaWeighted = true;
11800
11801                         var v, vl, f, fl, face, vertices;
11802
11803                         vertices = new Array( this.vertices.length );
11804
11805                         for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
11806
11807                                 vertices[ v ] = new Vector3();
11808
11809                         }
11810
11811                         if ( areaWeighted ) {
11812
11813                                 // vertex normals weighted by triangle areas
11814                                 // http://www.iquilezles.org/www/articles/normals/normals.htm
11815
11816                                 var vA, vB, vC;
11817                                 var cb = new Vector3(), ab = new Vector3();
11818
11819                                 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
11820
11821                                         face = this.faces[ f ];
11822
11823                                         vA = this.vertices[ face.a ];
11824                                         vB = this.vertices[ face.b ];
11825                                         vC = this.vertices[ face.c ];
11826
11827                                         cb.subVectors( vC, vB );
11828                                         ab.subVectors( vA, vB );
11829                                         cb.cross( ab );
11830
11831                                         vertices[ face.a ].add( cb );
11832                                         vertices[ face.b ].add( cb );
11833                                         vertices[ face.c ].add( cb );
11834
11835                                 }
11836
11837                         } else {
11838
11839                                 this.computeFaceNormals();
11840
11841                                 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
11842
11843                                         face = this.faces[ f ];
11844
11845                                         vertices[ face.a ].add( face.normal );
11846                                         vertices[ face.b ].add( face.normal );
11847                                         vertices[ face.c ].add( face.normal );
11848
11849                                 }
11850
11851                         }
11852
11853                         for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
11854
11855                                 vertices[ v ].normalize();
11856
11857                         }
11858
11859                         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
11860
11861                                 face = this.faces[ f ];
11862
11863                                 var vertexNormals = face.vertexNormals;
11864
11865                                 if ( vertexNormals.length === 3 ) {
11866
11867                                         vertexNormals[ 0 ].copy( vertices[ face.a ] );
11868                                         vertexNormals[ 1 ].copy( vertices[ face.b ] );
11869                                         vertexNormals[ 2 ].copy( vertices[ face.c ] );
11870
11871                                 } else {
11872
11873                                         vertexNormals[ 0 ] = vertices[ face.a ].clone();
11874                                         vertexNormals[ 1 ] = vertices[ face.b ].clone();
11875                                         vertexNormals[ 2 ] = vertices[ face.c ].clone();
11876
11877                                 }
11878
11879                         }
11880
11881                         if ( this.faces.length > 0 ) {
11882
11883                                 this.normalsNeedUpdate = true;
11884
11885                         }
11886
11887                 },
11888
11889                 computeFlatVertexNormals: function () {
11890
11891                         var f, fl, face;
11892
11893                         this.computeFaceNormals();
11894
11895                         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
11896
11897                                 face = this.faces[ f ];
11898
11899                                 var vertexNormals = face.vertexNormals;
11900
11901                                 if ( vertexNormals.length === 3 ) {
11902
11903                                         vertexNormals[ 0 ].copy( face.normal );
11904                                         vertexNormals[ 1 ].copy( face.normal );
11905                                         vertexNormals[ 2 ].copy( face.normal );
11906
11907                                 } else {
11908
11909                                         vertexNormals[ 0 ] = face.normal.clone();
11910                                         vertexNormals[ 1 ] = face.normal.clone();
11911                                         vertexNormals[ 2 ] = face.normal.clone();
11912
11913                                 }
11914
11915                         }
11916
11917                         if ( this.faces.length > 0 ) {
11918
11919                                 this.normalsNeedUpdate = true;
11920
11921                         }
11922
11923                 },
11924
11925                 computeMorphNormals: function () {
11926
11927                         var i, il, f, fl, face;
11928
11929                         // save original normals
11930                         // - create temp variables on first access
11931                         //   otherwise just copy (for faster repeated calls)
11932
11933                         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
11934
11935                                 face = this.faces[ f ];
11936
11937                                 if ( ! face.__originalFaceNormal ) {
11938
11939                                         face.__originalFaceNormal = face.normal.clone();
11940
11941                                 } else {
11942
11943                                         face.__originalFaceNormal.copy( face.normal );
11944
11945                                 }
11946
11947                                 if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
11948
11949                                 for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
11950
11951                                         if ( ! face.__originalVertexNormals[ i ] ) {
11952
11953                                                 face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
11954
11955                                         } else {
11956
11957                                                 face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
11958
11959                                         }
11960
11961                                 }
11962
11963                         }
11964
11965                         // use temp geometry to compute face and vertex normals for each morph
11966
11967                         var tmpGeo = new Geometry();
11968                         tmpGeo.faces = this.faces;
11969
11970                         for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
11971
11972                                 // create on first access
11973
11974                                 if ( ! this.morphNormals[ i ] ) {
11975
11976                                         this.morphNormals[ i ] = {};
11977                                         this.morphNormals[ i ].faceNormals = [];
11978                                         this.morphNormals[ i ].vertexNormals = [];
11979
11980                                         var dstNormalsFace = this.morphNormals[ i ].faceNormals;
11981                                         var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
11982
11983                                         var faceNormal, vertexNormals;
11984
11985                                         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
11986
11987                                                 faceNormal = new Vector3();
11988                                                 vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
11989
11990                                                 dstNormalsFace.push( faceNormal );
11991                                                 dstNormalsVertex.push( vertexNormals );
11992
11993                                         }
11994
11995                                 }
11996
11997                                 var morphNormals = this.morphNormals[ i ];
11998
11999                                 // set vertices to morph target
12000
12001                                 tmpGeo.vertices = this.morphTargets[ i ].vertices;
12002
12003                                 // compute morph normals
12004
12005                                 tmpGeo.computeFaceNormals();
12006                                 tmpGeo.computeVertexNormals();
12007
12008                                 // store morph normals
12009
12010                                 var faceNormal, vertexNormals;
12011
12012                                 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12013
12014                                         face = this.faces[ f ];
12015
12016                                         faceNormal = morphNormals.faceNormals[ f ];
12017                                         vertexNormals = morphNormals.vertexNormals[ f ];
12018
12019                                         faceNormal.copy( face.normal );
12020
12021                                         vertexNormals.a.copy( face.vertexNormals[ 0 ] );
12022                                         vertexNormals.b.copy( face.vertexNormals[ 1 ] );
12023                                         vertexNormals.c.copy( face.vertexNormals[ 2 ] );
12024
12025                                 }
12026
12027                         }
12028
12029                         // restore original normals
12030
12031                         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12032
12033                                 face = this.faces[ f ];
12034
12035                                 face.normal = face.__originalFaceNormal;
12036                                 face.vertexNormals = face.__originalVertexNormals;
12037
12038                         }
12039
12040                 },
12041
12042                 computeLineDistances: function () {
12043
12044                         var d = 0;
12045                         var vertices = this.vertices;
12046
12047                         for ( var i = 0, il = vertices.length; i < il; i ++ ) {
12048
12049                                 if ( i > 0 ) {
12050
12051                                         d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
12052
12053                                 }
12054
12055                                 this.lineDistances[ i ] = d;
12056
12057                         }
12058
12059                 },
12060
12061                 computeBoundingBox: function () {
12062
12063                         if ( this.boundingBox === null ) {
12064
12065                                 this.boundingBox = new Box3();
12066
12067                         }
12068
12069                         this.boundingBox.setFromPoints( this.vertices );
12070
12071                 },
12072
12073                 computeBoundingSphere: function () {
12074
12075                         if ( this.boundingSphere === null ) {
12076
12077                                 this.boundingSphere = new Sphere();
12078
12079                         }
12080
12081                         this.boundingSphere.setFromPoints( this.vertices );
12082
12083                 },
12084
12085                 merge: function ( geometry, matrix, materialIndexOffset ) {
12086
12087                         if ( ! ( geometry && geometry.isGeometry ) ) {
12088
12089                                 console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
12090                                 return;
12091
12092                         }
12093
12094                         var normalMatrix,
12095                                 vertexOffset = this.vertices.length,
12096                                 vertices1 = this.vertices,
12097                                 vertices2 = geometry.vertices,
12098                                 faces1 = this.faces,
12099                                 faces2 = geometry.faces,
12100                                 uvs1 = this.faceVertexUvs[ 0 ],
12101                                 uvs2 = geometry.faceVertexUvs[ 0 ],
12102                                 colors1 = this.colors,
12103                                 colors2 = geometry.colors;
12104
12105                         if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
12106
12107                         if ( matrix !== undefined ) {
12108
12109                                 normalMatrix = new Matrix3().getNormalMatrix( matrix );
12110
12111                         }
12112
12113                         // vertices
12114
12115                         for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
12116
12117                                 var vertex = vertices2[ i ];
12118
12119                                 var vertexCopy = vertex.clone();
12120
12121                                 if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
12122
12123                                 vertices1.push( vertexCopy );
12124
12125                         }
12126
12127                         // colors
12128
12129                         for ( var i = 0, il = colors2.length; i < il; i ++ ) {
12130
12131                                 colors1.push( colors2[ i ].clone() );
12132
12133                         }
12134
12135                         // faces
12136
12137                         for ( i = 0, il = faces2.length; i < il; i ++ ) {
12138
12139                                 var face = faces2[ i ], faceCopy, normal, color,
12140                                         faceVertexNormals = face.vertexNormals,
12141                                         faceVertexColors = face.vertexColors;
12142
12143                                 faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
12144                                 faceCopy.normal.copy( face.normal );
12145
12146                                 if ( normalMatrix !== undefined ) {
12147
12148                                         faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
12149
12150                                 }
12151
12152                                 for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
12153
12154                                         normal = faceVertexNormals[ j ].clone();
12155
12156                                         if ( normalMatrix !== undefined ) {
12157
12158                                                 normal.applyMatrix3( normalMatrix ).normalize();
12159
12160                                         }
12161
12162                                         faceCopy.vertexNormals.push( normal );
12163
12164                                 }
12165
12166                                 faceCopy.color.copy( face.color );
12167
12168                                 for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
12169
12170                                         color = faceVertexColors[ j ];
12171                                         faceCopy.vertexColors.push( color.clone() );
12172
12173                                 }
12174
12175                                 faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
12176
12177                                 faces1.push( faceCopy );
12178
12179                         }
12180
12181                         // uvs
12182
12183                         for ( i = 0, il = uvs2.length; i < il; i ++ ) {
12184
12185                                 var uv = uvs2[ i ], uvCopy = [];
12186
12187                                 if ( uv === undefined ) {
12188
12189                                         continue;
12190
12191                                 }
12192
12193                                 for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
12194
12195                                         uvCopy.push( uv[ j ].clone() );
12196
12197                                 }
12198
12199                                 uvs1.push( uvCopy );
12200
12201                         }
12202
12203                 },
12204
12205                 mergeMesh: function ( mesh ) {
12206
12207                         if ( ! ( mesh && mesh.isMesh ) ) {
12208
12209                                 console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
12210                                 return;
12211
12212                         }
12213
12214                         mesh.matrixAutoUpdate && mesh.updateMatrix();
12215
12216                         this.merge( mesh.geometry, mesh.matrix );
12217
12218                 },
12219
12220                 /*
12221                  * Checks for duplicate vertices with hashmap.
12222                  * Duplicated vertices are removed
12223                  * and faces' vertices are updated.
12224                  */
12225
12226                 mergeVertices: function () {
12227
12228                         var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
12229                         var unique = [], changes = [];
12230
12231                         var v, key;
12232                         var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
12233                         var precision = Math.pow( 10, precisionPoints );
12234                         var i, il, face;
12235                         var indices, j, jl;
12236
12237                         for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
12238
12239                                 v = this.vertices[ i ];
12240                                 key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
12241
12242                                 if ( verticesMap[ key ] === undefined ) {
12243
12244                                         verticesMap[ key ] = i;
12245                                         unique.push( this.vertices[ i ] );
12246                                         changes[ i ] = unique.length - 1;
12247
12248                                 } else {
12249
12250                                         //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
12251                                         changes[ i ] = changes[ verticesMap[ key ] ];
12252
12253                                 }
12254
12255                         }
12256
12257
12258                         // if faces are completely degenerate after merging vertices, we
12259                         // have to remove them from the geometry.
12260                         var faceIndicesToRemove = [];
12261
12262                         for ( i = 0, il = this.faces.length; i < il; i ++ ) {
12263
12264                                 face = this.faces[ i ];
12265
12266                                 face.a = changes[ face.a ];
12267                                 face.b = changes[ face.b ];
12268                                 face.c = changes[ face.c ];
12269
12270                                 indices = [ face.a, face.b, face.c ];
12271
12272                                 // if any duplicate vertices are found in a Face3
12273                                 // we have to remove the face as nothing can be saved
12274                                 for ( var n = 0; n < 3; n ++ ) {
12275
12276                                         if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
12277
12278                                                 faceIndicesToRemove.push( i );
12279                                                 break;
12280
12281                                         }
12282
12283                                 }
12284
12285                         }
12286
12287                         for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
12288
12289                                 var idx = faceIndicesToRemove[ i ];
12290
12291                                 this.faces.splice( idx, 1 );
12292
12293                                 for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
12294
12295                                         this.faceVertexUvs[ j ].splice( idx, 1 );
12296
12297                                 }
12298
12299                         }
12300
12301                         // Use unique set of vertices
12302
12303                         var diff = this.vertices.length - unique.length;
12304                         this.vertices = unique;
12305                         return diff;
12306
12307                 },
12308
12309                 sortFacesByMaterialIndex: function () {
12310
12311                         var faces = this.faces;
12312                         var length = faces.length;
12313
12314                         // tag faces
12315
12316                         for ( var i = 0; i < length; i ++ ) {
12317
12318                                 faces[ i ]._id = i;
12319
12320                         }
12321
12322                         // sort faces
12323
12324                         function materialIndexSort( a, b ) {
12325
12326                                 return a.materialIndex - b.materialIndex;
12327
12328                         }
12329
12330                         faces.sort( materialIndexSort );
12331
12332                         // sort uvs
12333
12334                         var uvs1 = this.faceVertexUvs[ 0 ];
12335                         var uvs2 = this.faceVertexUvs[ 1 ];
12336
12337                         var newUvs1, newUvs2;
12338
12339                         if ( uvs1 && uvs1.length === length ) newUvs1 = [];
12340                         if ( uvs2 && uvs2.length === length ) newUvs2 = [];
12341
12342                         for ( var i = 0; i < length; i ++ ) {
12343
12344                                 var id = faces[ i ]._id;
12345
12346                                 if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
12347                                 if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
12348
12349                         }
12350
12351                         if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
12352                         if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
12353
12354                 },
12355
12356                 toJSON: function () {
12357
12358                         var data = {
12359                                 metadata: {
12360                                         version: 4.5,
12361                                         type: 'Geometry',
12362                                         generator: 'Geometry.toJSON'
12363                                 }
12364                         };
12365
12366                         // standard Geometry serialization
12367
12368                         data.uuid = this.uuid;
12369                         data.type = this.type;
12370                         if ( this.name !== '' ) data.name = this.name;
12371
12372                         if ( this.parameters !== undefined ) {
12373
12374                                 var parameters = this.parameters;
12375
12376                                 for ( var key in parameters ) {
12377
12378                                         if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
12379
12380                                 }
12381
12382                                 return data;
12383
12384                         }
12385
12386                         var vertices = [];
12387
12388                         for ( var i = 0; i < this.vertices.length; i ++ ) {
12389
12390                                 var vertex = this.vertices[ i ];
12391                                 vertices.push( vertex.x, vertex.y, vertex.z );
12392
12393                         }
12394
12395                         var faces = [];
12396                         var normals = [];
12397                         var normalsHash = {};
12398                         var colors = [];
12399                         var colorsHash = {};
12400                         var uvs = [];
12401                         var uvsHash = {};
12402
12403                         for ( var i = 0; i < this.faces.length; i ++ ) {
12404
12405                                 var face = this.faces[ i ];
12406
12407                                 var hasMaterial = true;
12408                                 var hasFaceUv = false; // deprecated
12409                                 var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
12410                                 var hasFaceNormal = face.normal.length() > 0;
12411                                 var hasFaceVertexNormal = face.vertexNormals.length > 0;
12412                                 var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
12413                                 var hasFaceVertexColor = face.vertexColors.length > 0;
12414
12415                                 var faceType = 0;
12416
12417                                 faceType = setBit( faceType, 0, 0 ); // isQuad
12418                                 faceType = setBit( faceType, 1, hasMaterial );
12419                                 faceType = setBit( faceType, 2, hasFaceUv );
12420                                 faceType = setBit( faceType, 3, hasFaceVertexUv );
12421                                 faceType = setBit( faceType, 4, hasFaceNormal );
12422                                 faceType = setBit( faceType, 5, hasFaceVertexNormal );
12423                                 faceType = setBit( faceType, 6, hasFaceColor );
12424                                 faceType = setBit( faceType, 7, hasFaceVertexColor );
12425
12426                                 faces.push( faceType );
12427                                 faces.push( face.a, face.b, face.c );
12428                                 faces.push( face.materialIndex );
12429
12430                                 if ( hasFaceVertexUv ) {
12431
12432                                         var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
12433
12434                                         faces.push(
12435                                                 getUvIndex( faceVertexUvs[ 0 ] ),
12436                                                 getUvIndex( faceVertexUvs[ 1 ] ),
12437                                                 getUvIndex( faceVertexUvs[ 2 ] )
12438                                         );
12439
12440                                 }
12441
12442                                 if ( hasFaceNormal ) {
12443
12444                                         faces.push( getNormalIndex( face.normal ) );
12445
12446                                 }
12447
12448                                 if ( hasFaceVertexNormal ) {
12449
12450                                         var vertexNormals = face.vertexNormals;
12451
12452                                         faces.push(
12453                                                 getNormalIndex( vertexNormals[ 0 ] ),
12454                                                 getNormalIndex( vertexNormals[ 1 ] ),
12455                                                 getNormalIndex( vertexNormals[ 2 ] )
12456                                         );
12457
12458                                 }
12459
12460                                 if ( hasFaceColor ) {
12461
12462                                         faces.push( getColorIndex( face.color ) );
12463
12464                                 }
12465
12466                                 if ( hasFaceVertexColor ) {
12467
12468                                         var vertexColors = face.vertexColors;
12469
12470                                         faces.push(
12471                                                 getColorIndex( vertexColors[ 0 ] ),
12472                                                 getColorIndex( vertexColors[ 1 ] ),
12473                                                 getColorIndex( vertexColors[ 2 ] )
12474                                         );
12475
12476                                 }
12477
12478                         }
12479
12480                         function setBit( value, position, enabled ) {
12481
12482                                 return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
12483
12484                         }
12485
12486                         function getNormalIndex( normal ) {
12487
12488                                 var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
12489
12490                                 if ( normalsHash[ hash ] !== undefined ) {
12491
12492                                         return normalsHash[ hash ];
12493
12494                                 }
12495
12496                                 normalsHash[ hash ] = normals.length / 3;
12497                                 normals.push( normal.x, normal.y, normal.z );
12498
12499                                 return normalsHash[ hash ];
12500
12501                         }
12502
12503                         function getColorIndex( color ) {
12504
12505                                 var hash = color.r.toString() + color.g.toString() + color.b.toString();
12506
12507                                 if ( colorsHash[ hash ] !== undefined ) {
12508
12509                                         return colorsHash[ hash ];
12510
12511                                 }
12512
12513                                 colorsHash[ hash ] = colors.length;
12514                                 colors.push( color.getHex() );
12515
12516                                 return colorsHash[ hash ];
12517
12518                         }
12519
12520                         function getUvIndex( uv ) {
12521
12522                                 var hash = uv.x.toString() + uv.y.toString();
12523
12524                                 if ( uvsHash[ hash ] !== undefined ) {
12525
12526                                         return uvsHash[ hash ];
12527
12528                                 }
12529
12530                                 uvsHash[ hash ] = uvs.length / 2;
12531                                 uvs.push( uv.x, uv.y );
12532
12533                                 return uvsHash[ hash ];
12534
12535                         }
12536
12537                         data.data = {};
12538
12539                         data.data.vertices = vertices;
12540                         data.data.normals = normals;
12541                         if ( colors.length > 0 ) data.data.colors = colors;
12542                         if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
12543                         data.data.faces = faces;
12544
12545                         return data;
12546
12547                 },
12548
12549                 clone: function () {
12550
12551                         /*
12552                          // Handle primitives
12553
12554                          var parameters = this.parameters;
12555
12556                          if ( parameters !== undefined ) {
12557
12558                          var values = [];
12559
12560                          for ( var key in parameters ) {
12561
12562                          values.push( parameters[ key ] );
12563
12564                          }
12565
12566                          var geometry = Object.create( this.constructor.prototype );
12567                          this.constructor.apply( geometry, values );
12568                          return geometry;
12569
12570                          }
12571
12572                          return new this.constructor().copy( this );
12573                          */
12574
12575                         return new Geometry().copy( this );
12576
12577                 },
12578
12579                 copy: function ( source ) {
12580
12581                         var i, il, j, jl, k, kl;
12582
12583                         // reset
12584
12585                         this.vertices = [];
12586                         this.colors = [];
12587                         this.faces = [];
12588                         this.faceVertexUvs = [[]];
12589                         this.morphTargets = [];
12590                         this.morphNormals = [];
12591                         this.skinWeights = [];
12592                         this.skinIndices = [];
12593                         this.lineDistances = [];
12594                         this.boundingBox = null;
12595                         this.boundingSphere = null;
12596
12597                         // name
12598
12599                         this.name = source.name;
12600
12601                         // vertices
12602
12603                         var vertices = source.vertices;
12604
12605                         for ( i = 0, il = vertices.length; i < il; i ++ ) {
12606
12607                                 this.vertices.push( vertices[ i ].clone() );
12608
12609                         }
12610
12611                         // colors
12612
12613                         var colors = source.colors;
12614
12615                         for ( i = 0, il = colors.length; i < il; i ++ ) {
12616
12617                                 this.colors.push( colors[ i ].clone() );
12618
12619                         }
12620
12621                         // faces
12622
12623                         var faces = source.faces;
12624
12625                         for ( i = 0, il = faces.length; i < il; i ++ ) {
12626
12627                                 this.faces.push( faces[ i ].clone() );
12628
12629                         }
12630
12631                         // face vertex uvs
12632
12633                         for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
12634
12635                                 var faceVertexUvs = source.faceVertexUvs[ i ];
12636
12637                                 if ( this.faceVertexUvs[ i ] === undefined ) {
12638
12639                                         this.faceVertexUvs[ i ] = [];
12640
12641                                 }
12642
12643                                 for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
12644
12645                                         var uvs = faceVertexUvs[ j ], uvsCopy = [];
12646
12647                                         for ( k = 0, kl = uvs.length; k < kl; k ++ ) {
12648
12649                                                 var uv = uvs[ k ];
12650
12651                                                 uvsCopy.push( uv.clone() );
12652
12653                                         }
12654
12655                                         this.faceVertexUvs[ i ].push( uvsCopy );
12656
12657                                 }
12658
12659                         }
12660
12661                         // morph targets
12662
12663                         var morphTargets = source.morphTargets;
12664
12665                         for ( i = 0, il = morphTargets.length; i < il; i ++ ) {
12666
12667                                 var morphTarget = {};
12668                                 morphTarget.name = morphTargets[ i ].name;
12669
12670                                 // vertices
12671
12672                                 if ( morphTargets[ i ].vertices !== undefined ) {
12673
12674                                         morphTarget.vertices = [];
12675
12676                                         for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
12677
12678                                                 morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
12679
12680                                         }
12681
12682                                 }
12683
12684                                 // normals
12685
12686                                 if ( morphTargets[ i ].normals !== undefined ) {
12687
12688                                         morphTarget.normals = [];
12689
12690                                         for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
12691
12692                                                 morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
12693
12694                                         }
12695
12696                                 }
12697
12698                                 this.morphTargets.push( morphTarget );
12699
12700                         }
12701
12702                         // morph normals
12703
12704                         var morphNormals = source.morphNormals;
12705
12706                         for ( i = 0, il = morphNormals.length; i < il; i ++ ) {
12707
12708                                 var morphNormal = {};
12709
12710                                 // vertex normals
12711
12712                                 if ( morphNormals[ i ].vertexNormals !== undefined ) {
12713
12714                                         morphNormal.vertexNormals = [];
12715
12716                                         for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
12717
12718                                                 var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
12719                                                 var destVertexNormal = {};
12720
12721                                                 destVertexNormal.a = srcVertexNormal.a.clone();
12722                                                 destVertexNormal.b = srcVertexNormal.b.clone();
12723                                                 destVertexNormal.c = srcVertexNormal.c.clone();
12724
12725                                                 morphNormal.vertexNormals.push( destVertexNormal );
12726
12727                                         }
12728
12729                                 }
12730
12731                                 // face normals
12732
12733                                 if ( morphNormals[ i ].faceNormals !== undefined ) {
12734
12735                                         morphNormal.faceNormals = [];
12736
12737                                         for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
12738
12739                                                 morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
12740
12741                                         }
12742
12743                                 }
12744
12745                                 this.morphNormals.push( morphNormal );
12746
12747                         }
12748
12749                         // skin weights
12750
12751                         var skinWeights = source.skinWeights;
12752
12753                         for ( i = 0, il = skinWeights.length; i < il; i ++ ) {
12754
12755                                 this.skinWeights.push( skinWeights[ i ].clone() );
12756
12757                         }
12758
12759                         // skin indices
12760
12761                         var skinIndices = source.skinIndices;
12762
12763                         for ( i = 0, il = skinIndices.length; i < il; i ++ ) {
12764
12765                                 this.skinIndices.push( skinIndices[ i ].clone() );
12766
12767                         }
12768
12769                         // line distances
12770
12771                         var lineDistances = source.lineDistances;
12772
12773                         for ( i = 0, il = lineDistances.length; i < il; i ++ ) {
12774
12775                                 this.lineDistances.push( lineDistances[ i ] );
12776
12777                         }
12778
12779                         // bounding box
12780
12781                         var boundingBox = source.boundingBox;
12782
12783                         if ( boundingBox !== null ) {
12784
12785                                 this.boundingBox = boundingBox.clone();
12786
12787                         }
12788
12789                         // bounding sphere
12790
12791                         var boundingSphere = source.boundingSphere;
12792
12793                         if ( boundingSphere !== null ) {
12794
12795                                 this.boundingSphere = boundingSphere.clone();
12796
12797                         }
12798
12799                         // update flags
12800
12801                         this.elementsNeedUpdate = source.elementsNeedUpdate;
12802                         this.verticesNeedUpdate = source.verticesNeedUpdate;
12803                         this.uvsNeedUpdate = source.uvsNeedUpdate;
12804                         this.normalsNeedUpdate = source.normalsNeedUpdate;
12805                         this.colorsNeedUpdate = source.colorsNeedUpdate;
12806                         this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
12807                         this.groupsNeedUpdate = source.groupsNeedUpdate;
12808
12809                         return this;
12810
12811                 },
12812
12813                 dispose: function () {
12814
12815                         this.dispatchEvent( { type: 'dispose' } );
12816
12817                 }
12818
12819         } );
12820
12821         /**
12822          * @author mrdoob / http://mrdoob.com/
12823          */
12824
12825         function BufferAttribute( array, itemSize, normalized ) {
12826
12827                 if ( Array.isArray( array ) ) {
12828
12829                         throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
12830
12831                 }
12832
12833                 this.uuid = _Math.generateUUID();
12834                 this.name = '';
12835
12836                 this.array = array;
12837                 this.itemSize = itemSize;
12838                 this.count = array !== undefined ? array.length / itemSize : 0;
12839                 this.normalized = normalized === true;
12840
12841                 this.dynamic = false;
12842                 this.updateRange = { offset: 0, count: - 1 };
12843
12844                 this.onUploadCallback = function () {};
12845
12846                 this.version = 0;
12847
12848         }
12849
12850         Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
12851
12852                 set: function ( value ) {
12853
12854                         if ( value === true ) this.version ++;
12855
12856                 }
12857
12858         } );
12859
12860         Object.assign( BufferAttribute.prototype, {
12861
12862                 isBufferAttribute: true,
12863
12864                 setArray: function ( array ) {
12865
12866                         if ( Array.isArray( array ) ) {
12867
12868                                 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
12869
12870                         }
12871
12872                         this.count = array !== undefined ? array.length / this.itemSize : 0;
12873                         this.array = array;
12874
12875                 },
12876
12877                 setDynamic: function ( value ) {
12878
12879                         this.dynamic = value;
12880
12881                         return this;
12882
12883                 },
12884
12885                 copy: function ( source ) {
12886
12887                         this.array = new source.array.constructor( source.array );
12888                         this.itemSize = source.itemSize;
12889                         this.count = source.count;
12890                         this.normalized = source.normalized;
12891
12892                         this.dynamic = source.dynamic;
12893
12894                         return this;
12895
12896                 },
12897
12898                 copyAt: function ( index1, attribute, index2 ) {
12899
12900                         index1 *= this.itemSize;
12901                         index2 *= attribute.itemSize;
12902
12903                         for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
12904
12905                                 this.array[ index1 + i ] = attribute.array[ index2 + i ];
12906
12907                         }
12908
12909                         return this;
12910
12911                 },
12912
12913                 copyArray: function ( array ) {
12914
12915                         this.array.set( array );
12916
12917                         return this;
12918
12919                 },
12920
12921                 copyColorsArray: function ( colors ) {
12922
12923                         var array = this.array, offset = 0;
12924
12925                         for ( var i = 0, l = colors.length; i < l; i ++ ) {
12926
12927                                 var color = colors[ i ];
12928
12929                                 if ( color === undefined ) {
12930
12931                                         console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
12932                                         color = new Color();
12933
12934                                 }
12935
12936                                 array[ offset ++ ] = color.r;
12937                                 array[ offset ++ ] = color.g;
12938                                 array[ offset ++ ] = color.b;
12939
12940                         }
12941
12942                         return this;
12943
12944                 },
12945
12946                 copyIndicesArray: function ( indices ) {
12947
12948                         var array = this.array, offset = 0;
12949
12950                         for ( var i = 0, l = indices.length; i < l; i ++ ) {
12951
12952                                 var index = indices[ i ];
12953
12954                                 array[ offset ++ ] = index.a;
12955                                 array[ offset ++ ] = index.b;
12956                                 array[ offset ++ ] = index.c;
12957
12958                         }
12959
12960                         return this;
12961
12962                 },
12963
12964                 copyVector2sArray: function ( vectors ) {
12965
12966                         var array = this.array, offset = 0;
12967
12968                         for ( var i = 0, l = vectors.length; i < l; i ++ ) {
12969
12970                                 var vector = vectors[ i ];
12971
12972                                 if ( vector === undefined ) {
12973
12974                                         console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
12975                                         vector = new Vector2();
12976
12977                                 }
12978
12979                                 array[ offset ++ ] = vector.x;
12980                                 array[ offset ++ ] = vector.y;
12981
12982                         }
12983
12984                         return this;
12985
12986                 },
12987
12988                 copyVector3sArray: function ( vectors ) {
12989
12990                         var array = this.array, offset = 0;
12991
12992                         for ( var i = 0, l = vectors.length; i < l; i ++ ) {
12993
12994                                 var vector = vectors[ i ];
12995
12996                                 if ( vector === undefined ) {
12997
12998                                         console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
12999                                         vector = new Vector3();
13000
13001                                 }
13002
13003                                 array[ offset ++ ] = vector.x;
13004                                 array[ offset ++ ] = vector.y;
13005                                 array[ offset ++ ] = vector.z;
13006
13007                         }
13008
13009                         return this;
13010
13011                 },
13012
13013                 copyVector4sArray: function ( vectors ) {
13014
13015                         var array = this.array, offset = 0;
13016
13017                         for ( var i = 0, l = vectors.length; i < l; i ++ ) {
13018
13019                                 var vector = vectors[ i ];
13020
13021                                 if ( vector === undefined ) {
13022
13023                                         console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
13024                                         vector = new Vector4();
13025
13026                                 }
13027
13028                                 array[ offset ++ ] = vector.x;
13029                                 array[ offset ++ ] = vector.y;
13030                                 array[ offset ++ ] = vector.z;
13031                                 array[ offset ++ ] = vector.w;
13032
13033                         }
13034
13035                         return this;
13036
13037                 },
13038
13039                 set: function ( value, offset ) {
13040
13041                         if ( offset === undefined ) offset = 0;
13042
13043                         this.array.set( value, offset );
13044
13045                         return this;
13046
13047                 },
13048
13049                 getX: function ( index ) {
13050
13051                         return this.array[ index * this.itemSize ];
13052
13053                 },
13054
13055                 setX: function ( index, x ) {
13056
13057                         this.array[ index * this.itemSize ] = x;
13058
13059                         return this;
13060
13061                 },
13062
13063                 getY: function ( index ) {
13064
13065                         return this.array[ index * this.itemSize + 1 ];
13066
13067                 },
13068
13069                 setY: function ( index, y ) {
13070
13071                         this.array[ index * this.itemSize + 1 ] = y;
13072
13073                         return this;
13074
13075                 },
13076
13077                 getZ: function ( index ) {
13078
13079                         return this.array[ index * this.itemSize + 2 ];
13080
13081                 },
13082
13083                 setZ: function ( index, z ) {
13084
13085                         this.array[ index * this.itemSize + 2 ] = z;
13086
13087                         return this;
13088
13089                 },
13090
13091                 getW: function ( index ) {
13092
13093                         return this.array[ index * this.itemSize + 3 ];
13094
13095                 },
13096
13097                 setW: function ( index, w ) {
13098
13099                         this.array[ index * this.itemSize + 3 ] = w;
13100
13101                         return this;
13102
13103                 },
13104
13105                 setXY: function ( index, x, y ) {
13106
13107                         index *= this.itemSize;
13108
13109                         this.array[ index + 0 ] = x;
13110                         this.array[ index + 1 ] = y;
13111
13112                         return this;
13113
13114                 },
13115
13116                 setXYZ: function ( index, x, y, z ) {
13117
13118                         index *= this.itemSize;
13119
13120                         this.array[ index + 0 ] = x;
13121                         this.array[ index + 1 ] = y;
13122                         this.array[ index + 2 ] = z;
13123
13124                         return this;
13125
13126                 },
13127
13128                 setXYZW: function ( index, x, y, z, w ) {
13129
13130                         index *= this.itemSize;
13131
13132                         this.array[ index + 0 ] = x;
13133                         this.array[ index + 1 ] = y;
13134                         this.array[ index + 2 ] = z;
13135                         this.array[ index + 3 ] = w;
13136
13137                         return this;
13138
13139                 },
13140
13141                 onUpload: function ( callback ) {
13142
13143                         this.onUploadCallback = callback;
13144
13145                         return this;
13146
13147                 },
13148
13149                 clone: function () {
13150
13151                         return new this.constructor( this.array, this.itemSize ).copy( this );
13152
13153                 }
13154
13155         } );
13156
13157         //
13158
13159         function Int8BufferAttribute( array, itemSize ) {
13160
13161                 BufferAttribute.call( this, new Int8Array( array ), itemSize );
13162
13163         }
13164
13165         Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13166         Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
13167
13168
13169         function Uint8BufferAttribute( array, itemSize ) {
13170
13171                 BufferAttribute.call( this, new Uint8Array( array ), itemSize );
13172
13173         }
13174
13175         Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13176         Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
13177
13178
13179         function Uint8ClampedBufferAttribute( array, itemSize ) {
13180
13181                 BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize );
13182
13183         }
13184
13185         Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13186         Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
13187
13188
13189         function Int16BufferAttribute( array, itemSize ) {
13190
13191                 BufferAttribute.call( this, new Int16Array( array ), itemSize );
13192
13193         }
13194
13195         Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13196         Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
13197
13198
13199         function Uint16BufferAttribute( array, itemSize ) {
13200
13201                 BufferAttribute.call( this, new Uint16Array( array ), itemSize );
13202
13203         }
13204
13205         Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13206         Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
13207
13208
13209         function Int32BufferAttribute( array, itemSize ) {
13210
13211                 BufferAttribute.call( this, new Int32Array( array ), itemSize );
13212
13213         }
13214
13215         Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13216         Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
13217
13218
13219         function Uint32BufferAttribute( array, itemSize ) {
13220
13221                 BufferAttribute.call( this, new Uint32Array( array ), itemSize );
13222
13223         }
13224
13225         Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13226         Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
13227
13228
13229         function Float32BufferAttribute( array, itemSize ) {
13230
13231                 BufferAttribute.call( this, new Float32Array( array ), itemSize );
13232
13233         }
13234
13235         Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13236         Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
13237
13238
13239         function Float64BufferAttribute( array, itemSize ) {
13240
13241                 BufferAttribute.call( this, new Float64Array( array ), itemSize );
13242
13243         }
13244
13245         Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
13246         Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
13247
13248         /**
13249          * @author mrdoob / http://mrdoob.com/
13250          */
13251
13252         function DirectGeometry() {
13253
13254                 this.indices = [];
13255                 this.vertices = [];
13256                 this.normals = [];
13257                 this.colors = [];
13258                 this.uvs = [];
13259                 this.uvs2 = [];
13260
13261                 this.groups = [];
13262
13263                 this.morphTargets = {};
13264
13265                 this.skinWeights = [];
13266                 this.skinIndices = [];
13267
13268                 // this.lineDistances = [];
13269
13270                 this.boundingBox = null;
13271                 this.boundingSphere = null;
13272
13273                 // update flags
13274
13275                 this.verticesNeedUpdate = false;
13276                 this.normalsNeedUpdate = false;
13277                 this.colorsNeedUpdate = false;
13278                 this.uvsNeedUpdate = false;
13279                 this.groupsNeedUpdate = false;
13280
13281         }
13282
13283         Object.assign( DirectGeometry.prototype, {
13284
13285                 computeGroups: function ( geometry ) {
13286
13287                         var group;
13288                         var groups = [];
13289                         var materialIndex = undefined;
13290
13291                         var faces = geometry.faces;
13292
13293                         for ( var i = 0; i < faces.length; i ++ ) {
13294
13295                                 var face = faces[ i ];
13296
13297                                 // materials
13298
13299                                 if ( face.materialIndex !== materialIndex ) {
13300
13301                                         materialIndex = face.materialIndex;
13302
13303                                         if ( group !== undefined ) {
13304
13305                                                 group.count = ( i * 3 ) - group.start;
13306                                                 groups.push( group );
13307
13308                                         }
13309
13310                                         group = {
13311                                                 start: i * 3,
13312                                                 materialIndex: materialIndex
13313                                         };
13314
13315                                 }
13316
13317                         }
13318
13319                         if ( group !== undefined ) {
13320
13321                                 group.count = ( i * 3 ) - group.start;
13322                                 groups.push( group );
13323
13324                         }
13325
13326                         this.groups = groups;
13327
13328                 },
13329
13330                 fromGeometry: function ( geometry ) {
13331
13332                         var faces = geometry.faces;
13333                         var vertices = geometry.vertices;
13334                         var faceVertexUvs = geometry.faceVertexUvs;
13335
13336                         var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
13337                         var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
13338
13339                         // morphs
13340
13341                         var morphTargets = geometry.morphTargets;
13342                         var morphTargetsLength = morphTargets.length;
13343
13344                         var morphTargetsPosition;
13345
13346                         if ( morphTargetsLength > 0 ) {
13347
13348                                 morphTargetsPosition = [];
13349
13350                                 for ( var i = 0; i < morphTargetsLength; i ++ ) {
13351
13352                                         morphTargetsPosition[ i ] = [];
13353
13354                                 }
13355
13356                                 this.morphTargets.position = morphTargetsPosition;
13357
13358                         }
13359
13360                         var morphNormals = geometry.morphNormals;
13361                         var morphNormalsLength = morphNormals.length;
13362
13363                         var morphTargetsNormal;
13364
13365                         if ( morphNormalsLength > 0 ) {
13366
13367                                 morphTargetsNormal = [];
13368
13369                                 for ( var i = 0; i < morphNormalsLength; i ++ ) {
13370
13371                                         morphTargetsNormal[ i ] = [];
13372
13373                                 }
13374
13375                                 this.morphTargets.normal = morphTargetsNormal;
13376
13377                         }
13378
13379                         // skins
13380
13381                         var skinIndices = geometry.skinIndices;
13382                         var skinWeights = geometry.skinWeights;
13383
13384                         var hasSkinIndices = skinIndices.length === vertices.length;
13385                         var hasSkinWeights = skinWeights.length === vertices.length;
13386
13387                         //
13388
13389                         for ( var i = 0; i < faces.length; i ++ ) {
13390
13391                                 var face = faces[ i ];
13392
13393                                 this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
13394
13395                                 var vertexNormals = face.vertexNormals;
13396
13397                                 if ( vertexNormals.length === 3 ) {
13398
13399                                         this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
13400
13401                                 } else {
13402
13403                                         var normal = face.normal;
13404
13405                                         this.normals.push( normal, normal, normal );
13406
13407                                 }
13408
13409                                 var vertexColors = face.vertexColors;
13410
13411                                 if ( vertexColors.length === 3 ) {
13412
13413                                         this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
13414
13415                                 } else {
13416
13417                                         var color = face.color;
13418
13419                                         this.colors.push( color, color, color );
13420
13421                                 }
13422
13423                                 if ( hasFaceVertexUv === true ) {
13424
13425                                         var vertexUvs = faceVertexUvs[ 0 ][ i ];
13426
13427                                         if ( vertexUvs !== undefined ) {
13428
13429                                                 this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
13430
13431                                         } else {
13432
13433                                                 console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
13434
13435                                                 this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
13436
13437                                         }
13438
13439                                 }
13440
13441                                 if ( hasFaceVertexUv2 === true ) {
13442
13443                                         var vertexUvs = faceVertexUvs[ 1 ][ i ];
13444
13445                                         if ( vertexUvs !== undefined ) {
13446
13447                                                 this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
13448
13449                                         } else {
13450
13451                                                 console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
13452
13453                                                 this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
13454
13455                                         }
13456
13457                                 }
13458
13459                                 // morphs
13460
13461                                 for ( var j = 0; j < morphTargetsLength; j ++ ) {
13462
13463                                         var morphTarget = morphTargets[ j ].vertices;
13464
13465                                         morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
13466
13467                                 }
13468
13469                                 for ( var j = 0; j < morphNormalsLength; j ++ ) {
13470
13471                                         var morphNormal = morphNormals[ j ].vertexNormals[ i ];
13472
13473                                         morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c );
13474
13475                                 }
13476
13477                                 // skins
13478
13479                                 if ( hasSkinIndices ) {
13480
13481                                         this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
13482
13483                                 }
13484
13485                                 if ( hasSkinWeights ) {
13486
13487                                         this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
13488
13489                                 }
13490
13491                         }
13492
13493                         this.computeGroups( geometry );
13494
13495                         this.verticesNeedUpdate = geometry.verticesNeedUpdate;
13496                         this.normalsNeedUpdate = geometry.normalsNeedUpdate;
13497                         this.colorsNeedUpdate = geometry.colorsNeedUpdate;
13498                         this.uvsNeedUpdate = geometry.uvsNeedUpdate;
13499                         this.groupsNeedUpdate = geometry.groupsNeedUpdate;
13500
13501                         return this;
13502
13503                 }
13504
13505         } );
13506
13507         /**
13508          * @author mrdoob / http://mrdoob.com/
13509          */
13510
13511         function arrayMax( array ) {
13512
13513                 if ( array.length === 0 ) return - Infinity;
13514
13515                 var max = array[ 0 ];
13516
13517                 for ( var i = 1, l = array.length; i < l; ++ i ) {
13518
13519                         if ( array[ i ] > max ) max = array[ i ];
13520
13521                 }
13522
13523                 return max;
13524
13525         }
13526
13527         /**
13528          * @author alteredq / http://alteredqualia.com/
13529          * @author mrdoob / http://mrdoob.com/
13530          */
13531
13532         function BufferGeometry() {
13533
13534                 Object.defineProperty( this, 'id', { value: GeometryIdCount() } );
13535
13536                 this.uuid = _Math.generateUUID();
13537
13538                 this.name = '';
13539                 this.type = 'BufferGeometry';
13540
13541                 this.index = null;
13542                 this.attributes = {};
13543
13544                 this.morphAttributes = {};
13545
13546                 this.groups = [];
13547
13548                 this.boundingBox = null;
13549                 this.boundingSphere = null;
13550
13551                 this.drawRange = { start: 0, count: Infinity };
13552
13553         }
13554
13555         BufferGeometry.MaxIndex = 65535;
13556
13557         Object.assign( BufferGeometry.prototype, EventDispatcher.prototype, {
13558
13559                 isBufferGeometry: true,
13560
13561                 getIndex: function () {
13562
13563                         return this.index;
13564
13565                 },
13566
13567                 setIndex: function ( index ) {
13568
13569                         if ( Array.isArray( index ) ) {
13570
13571                                 this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
13572
13573                         } else {
13574
13575                                 this.index = index;
13576
13577                         }
13578
13579                 },
13580
13581                 addAttribute: function ( name, attribute ) {
13582
13583                         if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
13584
13585                                 console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
13586
13587                                 this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
13588
13589                                 return;
13590
13591                         }
13592
13593                         if ( name === 'index' ) {
13594
13595                                 console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
13596                                 this.setIndex( attribute );
13597
13598                                 return;
13599
13600                         }
13601
13602                         this.attributes[ name ] = attribute;
13603
13604                         return this;
13605
13606                 },
13607
13608                 getAttribute: function ( name ) {
13609
13610                         return this.attributes[ name ];
13611
13612                 },
13613
13614                 removeAttribute: function ( name ) {
13615
13616                         delete this.attributes[ name ];
13617
13618                         return this;
13619
13620                 },
13621
13622                 addGroup: function ( start, count, materialIndex ) {
13623
13624                         this.groups.push( {
13625
13626                                 start: start,
13627                                 count: count,
13628                                 materialIndex: materialIndex !== undefined ? materialIndex : 0
13629
13630                         } );
13631
13632                 },
13633
13634                 clearGroups: function () {
13635
13636                         this.groups = [];
13637
13638                 },
13639
13640                 setDrawRange: function ( start, count ) {
13641
13642                         this.drawRange.start = start;
13643                         this.drawRange.count = count;
13644
13645                 },
13646
13647                 applyMatrix: function ( matrix ) {
13648
13649                         var position = this.attributes.position;
13650
13651                         if ( position !== undefined ) {
13652
13653                                 matrix.applyToBufferAttribute( position );
13654                                 position.needsUpdate = true;
13655
13656                         }
13657
13658                         var normal = this.attributes.normal;
13659
13660                         if ( normal !== undefined ) {
13661
13662                                 var normalMatrix = new Matrix3().getNormalMatrix( matrix );
13663
13664                                 normalMatrix.applyToBufferAttribute( normal );
13665                                 normal.needsUpdate = true;
13666
13667                         }
13668
13669                         if ( this.boundingBox !== null ) {
13670
13671                                 this.computeBoundingBox();
13672
13673                         }
13674
13675                         if ( this.boundingSphere !== null ) {
13676
13677                                 this.computeBoundingSphere();
13678
13679                         }
13680
13681                         return this;
13682
13683                 },
13684
13685                 rotateX: function () {
13686
13687                         // rotate geometry around world x-axis
13688
13689                         var m1 = new Matrix4();
13690
13691                         return function rotateX( angle ) {
13692
13693                                 m1.makeRotationX( angle );
13694
13695                                 this.applyMatrix( m1 );
13696
13697                                 return this;
13698
13699                         };
13700
13701                 }(),
13702
13703                 rotateY: function () {
13704
13705                         // rotate geometry around world y-axis
13706
13707                         var m1 = new Matrix4();
13708
13709                         return function rotateY( angle ) {
13710
13711                                 m1.makeRotationY( angle );
13712
13713                                 this.applyMatrix( m1 );
13714
13715                                 return this;
13716
13717                         };
13718
13719                 }(),
13720
13721                 rotateZ: function () {
13722
13723                         // rotate geometry around world z-axis
13724
13725                         var m1 = new Matrix4();
13726
13727                         return function rotateZ( angle ) {
13728
13729                                 m1.makeRotationZ( angle );
13730
13731                                 this.applyMatrix( m1 );
13732
13733                                 return this;
13734
13735                         };
13736
13737                 }(),
13738
13739                 translate: function () {
13740
13741                         // translate geometry
13742
13743                         var m1 = new Matrix4();
13744
13745                         return function translate( x, y, z ) {
13746
13747                                 m1.makeTranslation( x, y, z );
13748
13749                                 this.applyMatrix( m1 );
13750
13751                                 return this;
13752
13753                         };
13754
13755                 }(),
13756
13757                 scale: function () {
13758
13759                         // scale geometry
13760
13761                         var m1 = new Matrix4();
13762
13763                         return function scale( x, y, z ) {
13764
13765                                 m1.makeScale( x, y, z );
13766
13767                                 this.applyMatrix( m1 );
13768
13769                                 return this;
13770
13771                         };
13772
13773                 }(),
13774
13775                 lookAt: function () {
13776
13777                         var obj = new Object3D();
13778
13779                         return function lookAt( vector ) {
13780
13781                                 obj.lookAt( vector );
13782
13783                                 obj.updateMatrix();
13784
13785                                 this.applyMatrix( obj.matrix );
13786
13787                         };
13788
13789                 }(),
13790
13791                 center: function () {
13792
13793                         this.computeBoundingBox();
13794
13795                         var offset = this.boundingBox.getCenter().negate();
13796
13797                         this.translate( offset.x, offset.y, offset.z );
13798
13799                         return offset;
13800
13801                 },
13802
13803                 setFromObject: function ( object ) {
13804
13805                         // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
13806
13807                         var geometry = object.geometry;
13808
13809                         if ( object.isPoints || object.isLine ) {
13810
13811                                 var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
13812                                 var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
13813
13814                                 this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
13815                                 this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
13816
13817                                 if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
13818
13819                                         var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
13820
13821                                         this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
13822
13823                                 }
13824
13825                                 if ( geometry.boundingSphere !== null ) {
13826
13827                                         this.boundingSphere = geometry.boundingSphere.clone();
13828
13829                                 }
13830
13831                                 if ( geometry.boundingBox !== null ) {
13832
13833                                         this.boundingBox = geometry.boundingBox.clone();
13834
13835                                 }
13836
13837                         } else if ( object.isMesh ) {
13838
13839                                 if ( geometry && geometry.isGeometry ) {
13840
13841                                         this.fromGeometry( geometry );
13842
13843                                 }
13844
13845                         }
13846
13847                         return this;
13848
13849                 },
13850
13851                 updateFromObject: function ( object ) {
13852
13853                         var geometry = object.geometry;
13854
13855                         if ( object.isMesh ) {
13856
13857                                 var direct = geometry.__directGeometry;
13858
13859                                 if ( geometry.elementsNeedUpdate === true ) {
13860
13861                                         direct = undefined;
13862                                         geometry.elementsNeedUpdate = false;
13863
13864                                 }
13865
13866                                 if ( direct === undefined ) {
13867
13868                                         return this.fromGeometry( geometry );
13869
13870                                 }
13871
13872                                 direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
13873                                 direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
13874                                 direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
13875                                 direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
13876                                 direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
13877
13878                                 geometry.verticesNeedUpdate = false;
13879                                 geometry.normalsNeedUpdate = false;
13880                                 geometry.colorsNeedUpdate = false;
13881                                 geometry.uvsNeedUpdate = false;
13882                                 geometry.groupsNeedUpdate = false;
13883
13884                                 geometry = direct;
13885
13886                         }
13887
13888                         var attribute;
13889
13890                         if ( geometry.verticesNeedUpdate === true ) {
13891
13892                                 attribute = this.attributes.position;
13893
13894                                 if ( attribute !== undefined ) {
13895
13896                                         attribute.copyVector3sArray( geometry.vertices );
13897                                         attribute.needsUpdate = true;
13898
13899                                 }
13900
13901                                 geometry.verticesNeedUpdate = false;
13902
13903                         }
13904
13905                         if ( geometry.normalsNeedUpdate === true ) {
13906
13907                                 attribute = this.attributes.normal;
13908
13909                                 if ( attribute !== undefined ) {
13910
13911                                         attribute.copyVector3sArray( geometry.normals );
13912                                         attribute.needsUpdate = true;
13913
13914                                 }
13915
13916                                 geometry.normalsNeedUpdate = false;
13917
13918                         }
13919
13920                         if ( geometry.colorsNeedUpdate === true ) {
13921
13922                                 attribute = this.attributes.color;
13923
13924                                 if ( attribute !== undefined ) {
13925
13926                                         attribute.copyColorsArray( geometry.colors );
13927                                         attribute.needsUpdate = true;
13928
13929                                 }
13930
13931                                 geometry.colorsNeedUpdate = false;
13932
13933                         }
13934
13935                         if ( geometry.uvsNeedUpdate ) {
13936
13937                                 attribute = this.attributes.uv;
13938
13939                                 if ( attribute !== undefined ) {
13940
13941                                         attribute.copyVector2sArray( geometry.uvs );
13942                                         attribute.needsUpdate = true;
13943
13944                                 }
13945
13946                                 geometry.uvsNeedUpdate = false;
13947
13948                         }
13949
13950                         if ( geometry.lineDistancesNeedUpdate ) {
13951
13952                                 attribute = this.attributes.lineDistance;
13953
13954                                 if ( attribute !== undefined ) {
13955
13956                                         attribute.copyArray( geometry.lineDistances );
13957                                         attribute.needsUpdate = true;
13958
13959                                 }
13960
13961                                 geometry.lineDistancesNeedUpdate = false;
13962
13963                         }
13964
13965                         if ( geometry.groupsNeedUpdate ) {
13966
13967                                 geometry.computeGroups( object.geometry );
13968                                 this.groups = geometry.groups;
13969
13970                                 geometry.groupsNeedUpdate = false;
13971
13972                         }
13973
13974                         return this;
13975
13976                 },
13977
13978                 fromGeometry: function ( geometry ) {
13979
13980                         geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
13981
13982                         return this.fromDirectGeometry( geometry.__directGeometry );
13983
13984                 },
13985
13986                 fromDirectGeometry: function ( geometry ) {
13987
13988                         var positions = new Float32Array( geometry.vertices.length * 3 );
13989                         this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
13990
13991                         if ( geometry.normals.length > 0 ) {
13992
13993                                 var normals = new Float32Array( geometry.normals.length * 3 );
13994                                 this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
13995
13996                         }
13997
13998                         if ( geometry.colors.length > 0 ) {
13999
14000                                 var colors = new Float32Array( geometry.colors.length * 3 );
14001                                 this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
14002
14003                         }
14004
14005                         if ( geometry.uvs.length > 0 ) {
14006
14007                                 var uvs = new Float32Array( geometry.uvs.length * 2 );
14008                                 this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
14009
14010                         }
14011
14012                         if ( geometry.uvs2.length > 0 ) {
14013
14014                                 var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
14015                                 this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
14016
14017                         }
14018
14019                         if ( geometry.indices.length > 0 ) {
14020
14021                                 var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array;
14022                                 var indices = new TypeArray( geometry.indices.length * 3 );
14023                                 this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) );
14024
14025                         }
14026
14027                         // groups
14028
14029                         this.groups = geometry.groups;
14030
14031                         // morphs
14032
14033                         for ( var name in geometry.morphTargets ) {
14034
14035                                 var array = [];
14036                                 var morphTargets = geometry.morphTargets[ name ];
14037
14038                                 for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
14039
14040                                         var morphTarget = morphTargets[ i ];
14041
14042                                         var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 );
14043
14044                                         array.push( attribute.copyVector3sArray( morphTarget ) );
14045
14046                                 }
14047
14048                                 this.morphAttributes[ name ] = array;
14049
14050                         }
14051
14052                         // skinning
14053
14054                         if ( geometry.skinIndices.length > 0 ) {
14055
14056                                 var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
14057                                 this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
14058
14059                         }
14060
14061                         if ( geometry.skinWeights.length > 0 ) {
14062
14063                                 var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
14064                                 this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
14065
14066                         }
14067
14068                         //
14069
14070                         if ( geometry.boundingSphere !== null ) {
14071
14072                                 this.boundingSphere = geometry.boundingSphere.clone();
14073
14074                         }
14075
14076                         if ( geometry.boundingBox !== null ) {
14077
14078                                 this.boundingBox = geometry.boundingBox.clone();
14079
14080                         }
14081
14082                         return this;
14083
14084                 },
14085
14086                 computeBoundingBox: function () {
14087
14088                         if ( this.boundingBox === null ) {
14089
14090                                 this.boundingBox = new Box3();
14091
14092                         }
14093
14094                         var position = this.attributes.position;
14095
14096                         if ( position !== undefined ) {
14097
14098                                 this.boundingBox.setFromBufferAttribute( position );
14099
14100                         } else {
14101
14102                                 this.boundingBox.makeEmpty();
14103
14104                         }
14105
14106                         if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
14107
14108                                 console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
14109
14110                         }
14111
14112                 },
14113
14114                 computeBoundingSphere: function () {
14115
14116                         var box = new Box3();
14117                         var vector = new Vector3();
14118
14119                         return function computeBoundingSphere() {
14120
14121                                 if ( this.boundingSphere === null ) {
14122
14123                                         this.boundingSphere = new Sphere();
14124
14125                                 }
14126
14127                                 var position = this.attributes.position;
14128
14129                                 if ( position ) {
14130
14131                                         var center = this.boundingSphere.center;
14132
14133                                         box.setFromBufferAttribute( position );
14134                                         box.getCenter( center );
14135
14136                                         // hoping to find a boundingSphere with a radius smaller than the
14137                                         // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
14138
14139                                         var maxRadiusSq = 0;
14140
14141                                         for ( var i = 0, il = position.count; i < il; i ++ ) {
14142
14143                                                 vector.x = position.getX( i );
14144                                                 vector.y = position.getY( i );
14145                                                 vector.z = position.getZ( i );
14146                                                 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
14147
14148                                         }
14149
14150                                         this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
14151
14152                                         if ( isNaN( this.boundingSphere.radius ) ) {
14153
14154                                                 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
14155
14156                                         }
14157
14158                                 }
14159
14160                         };
14161
14162                 }(),
14163
14164                 computeFaceNormals: function () {
14165
14166                         // backwards compatibility
14167
14168                 },
14169
14170                 computeVertexNormals: function () {
14171
14172                         var index = this.index;
14173                         var attributes = this.attributes;
14174                         var groups = this.groups;
14175
14176                         if ( attributes.position ) {
14177
14178                                 var positions = attributes.position.array;
14179
14180                                 if ( attributes.normal === undefined ) {
14181
14182                                         this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );
14183
14184                                 } else {
14185
14186                                         // reset existing normals to zero
14187
14188                                         var array = attributes.normal.array;
14189
14190                                         for ( var i = 0, il = array.length; i < il; i ++ ) {
14191
14192                                                 array[ i ] = 0;
14193
14194                                         }
14195
14196                                 }
14197
14198                                 var normals = attributes.normal.array;
14199
14200                                 var vA, vB, vC;
14201                                 var pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
14202                                 var cb = new Vector3(), ab = new Vector3();
14203
14204                                 // indexed elements
14205
14206                                 if ( index ) {
14207
14208                                         var indices = index.array;
14209
14210                                         if ( groups.length === 0 ) {
14211
14212                                                 this.addGroup( 0, indices.length );
14213
14214                                         }
14215
14216                                         for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
14217
14218                                                 var group = groups[ j ];
14219
14220                                                 var start = group.start;
14221                                                 var count = group.count;
14222
14223                                                 for ( var i = start, il = start + count; i < il; i += 3 ) {
14224
14225                                                         vA = indices[ i + 0 ] * 3;
14226                                                         vB = indices[ i + 1 ] * 3;
14227                                                         vC = indices[ i + 2 ] * 3;
14228
14229                                                         pA.fromArray( positions, vA );
14230                                                         pB.fromArray( positions, vB );
14231                                                         pC.fromArray( positions, vC );
14232
14233                                                         cb.subVectors( pC, pB );
14234                                                         ab.subVectors( pA, pB );
14235                                                         cb.cross( ab );
14236
14237                                                         normals[ vA ] += cb.x;
14238                                                         normals[ vA + 1 ] += cb.y;
14239                                                         normals[ vA + 2 ] += cb.z;
14240
14241                                                         normals[ vB ] += cb.x;
14242                                                         normals[ vB + 1 ] += cb.y;
14243                                                         normals[ vB + 2 ] += cb.z;
14244
14245                                                         normals[ vC ] += cb.x;
14246                                                         normals[ vC + 1 ] += cb.y;
14247                                                         normals[ vC + 2 ] += cb.z;
14248
14249                                                 }
14250
14251                                         }
14252
14253                                 } else {
14254
14255                                         // non-indexed elements (unconnected triangle soup)
14256
14257                                         for ( var i = 0, il = positions.length; i < il; i += 9 ) {
14258
14259                                                 pA.fromArray( positions, i );
14260                                                 pB.fromArray( positions, i + 3 );
14261                                                 pC.fromArray( positions, i + 6 );
14262
14263                                                 cb.subVectors( pC, pB );
14264                                                 ab.subVectors( pA, pB );
14265                                                 cb.cross( ab );
14266
14267                                                 normals[ i ] = cb.x;
14268                                                 normals[ i + 1 ] = cb.y;
14269                                                 normals[ i + 2 ] = cb.z;
14270
14271                                                 normals[ i + 3 ] = cb.x;
14272                                                 normals[ i + 4 ] = cb.y;
14273                                                 normals[ i + 5 ] = cb.z;
14274
14275                                                 normals[ i + 6 ] = cb.x;
14276                                                 normals[ i + 7 ] = cb.y;
14277                                                 normals[ i + 8 ] = cb.z;
14278
14279                                         }
14280
14281                                 }
14282
14283                                 this.normalizeNormals();
14284
14285                                 attributes.normal.needsUpdate = true;
14286
14287                         }
14288
14289                 },
14290
14291                 merge: function ( geometry, offset ) {
14292
14293                         if ( ! ( geometry && geometry.isBufferGeometry ) ) {
14294
14295                                 console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
14296                                 return;
14297
14298                         }
14299
14300                         if ( offset === undefined ) offset = 0;
14301
14302                         var attributes = this.attributes;
14303
14304                         for ( var key in attributes ) {
14305
14306                                 if ( geometry.attributes[ key ] === undefined ) continue;
14307
14308                                 var attribute1 = attributes[ key ];
14309                                 var attributeArray1 = attribute1.array;
14310
14311                                 var attribute2 = geometry.attributes[ key ];
14312                                 var attributeArray2 = attribute2.array;
14313
14314                                 var attributeSize = attribute2.itemSize;
14315
14316                                 for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {
14317
14318                                         attributeArray1[ j ] = attributeArray2[ i ];
14319
14320                                 }
14321
14322                         }
14323
14324                         return this;
14325
14326                 },
14327
14328                 normalizeNormals: function () {
14329
14330                         var vector = new Vector3();
14331
14332                         return function normalizeNormals() {
14333
14334                                 var normals = this.attributes.normal;
14335
14336                                 for ( var i = 0, il = normals.count; i < il; i ++ ) {
14337
14338                                         vector.x = normals.getX( i );
14339                                         vector.y = normals.getY( i );
14340                                         vector.z = normals.getZ( i );
14341
14342                                         vector.normalize();
14343
14344                                         normals.setXYZ( i, vector.x, vector.y, vector.z );
14345
14346                                 }
14347
14348                         };
14349
14350                 }(),
14351
14352                 toNonIndexed: function () {
14353
14354                         if ( this.index === null ) {
14355
14356                                 console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
14357                                 return this;
14358
14359                         }
14360
14361                         var geometry2 = new BufferGeometry();
14362
14363                         var indices = this.index.array;
14364                         var attributes = this.attributes;
14365
14366                         for ( var name in attributes ) {
14367
14368                                 var attribute = attributes[ name ];
14369
14370                                 var array = attribute.array;
14371                                 var itemSize = attribute.itemSize;
14372
14373                                 var array2 = new array.constructor( indices.length * itemSize );
14374
14375                                 var index = 0, index2 = 0;
14376
14377                                 for ( var i = 0, l = indices.length; i < l; i ++ ) {
14378
14379                                         index = indices[ i ] * itemSize;
14380
14381                                         for ( var j = 0; j < itemSize; j ++ ) {
14382
14383                                                 array2[ index2 ++ ] = array[ index ++ ];
14384
14385                                         }
14386
14387                                 }
14388
14389                                 geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) );
14390
14391                         }
14392
14393                         return geometry2;
14394
14395                 },
14396
14397                 toJSON: function () {
14398
14399                         var data = {
14400                                 metadata: {
14401                                         version: 4.5,
14402                                         type: 'BufferGeometry',
14403                                         generator: 'BufferGeometry.toJSON'
14404                                 }
14405                         };
14406
14407                         // standard BufferGeometry serialization
14408
14409                         data.uuid = this.uuid;
14410                         data.type = this.type;
14411                         if ( this.name !== '' ) data.name = this.name;
14412
14413                         if ( this.parameters !== undefined ) {
14414
14415                                 var parameters = this.parameters;
14416
14417                                 for ( var key in parameters ) {
14418
14419                                         if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
14420
14421                                 }
14422
14423                                 return data;
14424
14425                         }
14426
14427                         data.data = { attributes: {} };
14428
14429                         var index = this.index;
14430
14431                         if ( index !== null ) {
14432
14433                                 var array = Array.prototype.slice.call( index.array );
14434
14435                                 data.data.index = {
14436                                         type: index.array.constructor.name,
14437                                         array: array
14438                                 };
14439
14440                         }
14441
14442                         var attributes = this.attributes;
14443
14444                         for ( var key in attributes ) {
14445
14446                                 var attribute = attributes[ key ];
14447
14448                                 var array = Array.prototype.slice.call( attribute.array );
14449
14450                                 data.data.attributes[ key ] = {
14451                                         itemSize: attribute.itemSize,
14452                                         type: attribute.array.constructor.name,
14453                                         array: array,
14454                                         normalized: attribute.normalized
14455                                 };
14456
14457                         }
14458
14459                         var groups = this.groups;
14460
14461                         if ( groups.length > 0 ) {
14462
14463                                 data.data.groups = JSON.parse( JSON.stringify( groups ) );
14464
14465                         }
14466
14467                         var boundingSphere = this.boundingSphere;
14468
14469                         if ( boundingSphere !== null ) {
14470
14471                                 data.data.boundingSphere = {
14472                                         center: boundingSphere.center.toArray(),
14473                                         radius: boundingSphere.radius
14474                                 };
14475
14476                         }
14477
14478                         return data;
14479
14480                 },
14481
14482                 clone: function () {
14483
14484                         /*
14485                          // Handle primitives
14486
14487                          var parameters = this.parameters;
14488
14489                          if ( parameters !== undefined ) {
14490
14491                          var values = [];
14492
14493                          for ( var key in parameters ) {
14494
14495                          values.push( parameters[ key ] );
14496
14497                          }
14498
14499                          var geometry = Object.create( this.constructor.prototype );
14500                          this.constructor.apply( geometry, values );
14501                          return geometry;
14502
14503                          }
14504
14505                          return new this.constructor().copy( this );
14506                          */
14507
14508                         return new BufferGeometry().copy( this );
14509
14510                 },
14511
14512                 copy: function ( source ) {
14513
14514                         var name, i, l;
14515
14516                         // reset
14517
14518                         this.index = null;
14519                         this.attributes = {};
14520                         this.morphAttributes = {};
14521                         this.groups = [];
14522                         this.boundingBox = null;
14523                         this.boundingSphere = null;
14524
14525                         // name
14526
14527                         this.name = source.name;
14528
14529                         // index
14530
14531                         var index = source.index;
14532
14533                         if ( index !== null ) {
14534
14535                                 this.setIndex( index.clone() );
14536
14537                         }
14538
14539                         // attributes
14540
14541                         var attributes = source.attributes;
14542
14543                         for ( name in attributes ) {
14544
14545                                 var attribute = attributes[ name ];
14546                                 this.addAttribute( name, attribute.clone() );
14547
14548                         }
14549
14550                         // morph attributes
14551
14552                         var morphAttributes = source.morphAttributes;
14553
14554                         for ( name in morphAttributes ) {
14555
14556                                 var array = [];
14557                                 var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
14558
14559                                 for ( i = 0, l = morphAttribute.length; i < l; i ++ ) {
14560
14561                                         array.push( morphAttribute[ i ].clone() );
14562
14563                                 }
14564
14565                                 this.morphAttributes[ name ] = array;
14566
14567                         }
14568
14569                         // groups
14570
14571                         var groups = source.groups;
14572
14573                         for ( i = 0, l = groups.length; i < l; i ++ ) {
14574
14575                                 var group = groups[ i ];
14576                                 this.addGroup( group.start, group.count, group.materialIndex );
14577
14578                         }
14579
14580                         // bounding box
14581
14582                         var boundingBox = source.boundingBox;
14583
14584                         if ( boundingBox !== null ) {
14585
14586                                 this.boundingBox = boundingBox.clone();
14587
14588                         }
14589
14590                         // bounding sphere
14591
14592                         var boundingSphere = source.boundingSphere;
14593
14594                         if ( boundingSphere !== null ) {
14595
14596                                 this.boundingSphere = boundingSphere.clone();
14597
14598                         }
14599
14600                         // draw range
14601
14602                         this.drawRange.start = source.drawRange.start;
14603                         this.drawRange.count = source.drawRange.count;
14604
14605                         return this;
14606
14607                 },
14608
14609                 dispose: function () {
14610
14611                         this.dispatchEvent( { type: 'dispose' } );
14612
14613                 }
14614
14615         } );
14616
14617         /**
14618          * @author mrdoob / http://mrdoob.com/
14619          * @author Mugen87 / https://github.com/Mugen87
14620          */
14621
14622         // BoxGeometry
14623
14624         function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
14625
14626                 Geometry.call( this );
14627
14628                 this.type = 'BoxGeometry';
14629
14630                 this.parameters = {
14631                         width: width,
14632                         height: height,
14633                         depth: depth,
14634                         widthSegments: widthSegments,
14635                         heightSegments: heightSegments,
14636                         depthSegments: depthSegments
14637                 };
14638
14639                 this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
14640                 this.mergeVertices();
14641
14642         }
14643
14644         BoxGeometry.prototype = Object.create( Geometry.prototype );
14645         BoxGeometry.prototype.constructor = BoxGeometry;
14646
14647         // BoxBufferGeometry
14648
14649         function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
14650
14651                 BufferGeometry.call( this );
14652
14653                 this.type = 'BoxBufferGeometry';
14654
14655                 this.parameters = {
14656                         width: width,
14657                         height: height,
14658                         depth: depth,
14659                         widthSegments: widthSegments,
14660                         heightSegments: heightSegments,
14661                         depthSegments: depthSegments
14662                 };
14663
14664                 var scope = this;
14665
14666                 // segments
14667
14668                 widthSegments = Math.floor( widthSegments ) || 1;
14669                 heightSegments = Math.floor( heightSegments ) || 1;
14670                 depthSegments = Math.floor( depthSegments ) || 1;
14671
14672                 // buffers
14673
14674                 var indices = [];
14675                 var vertices = [];
14676                 var normals = [];
14677                 var uvs = [];
14678
14679                 // helper variables
14680
14681                 var numberOfVertices = 0;
14682                 var groupStart = 0;
14683
14684                 // build each side of the box geometry
14685
14686                 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height,   width,  depthSegments, heightSegments, 0 ); // px
14687                 buildPlane( 'z', 'y', 'x',   1, - 1, depth, height, - width,  depthSegments, heightSegments, 1 ); // nx
14688                 buildPlane( 'x', 'z', 'y',   1,   1, width, depth,    height, widthSegments, depthSegments,  2 ); // py
14689                 buildPlane( 'x', 'z', 'y',   1, - 1, width, depth,  - height, widthSegments, depthSegments,  3 ); // ny
14690                 buildPlane( 'x', 'y', 'z',   1, - 1, width, height,   depth,  widthSegments, heightSegments, 4 ); // pz
14691                 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth,  widthSegments, heightSegments, 5 ); // nz
14692
14693                 // build geometry
14694
14695                 this.setIndex( indices );
14696                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
14697                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
14698                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
14699
14700                 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
14701
14702                         var segmentWidth = width / gridX;
14703                         var segmentHeight = height / gridY;
14704
14705                         var widthHalf = width / 2;
14706                         var heightHalf = height / 2;
14707                         var depthHalf = depth / 2;
14708
14709                         var gridX1 = gridX + 1;
14710                         var gridY1 = gridY + 1;
14711
14712                         var vertexCounter = 0;
14713                         var groupCount = 0;
14714
14715                         var ix, iy;
14716
14717                         var vector = new Vector3();
14718
14719                         // generate vertices, normals and uvs
14720
14721                         for ( iy = 0; iy < gridY1; iy ++ ) {
14722
14723                                 var y = iy * segmentHeight - heightHalf;
14724
14725                                 for ( ix = 0; ix < gridX1; ix ++ ) {
14726
14727                                         var x = ix * segmentWidth - widthHalf;
14728
14729                                         // set values to correct vector component
14730
14731                                         vector[ u ] = x * udir;
14732                                         vector[ v ] = y * vdir;
14733                                         vector[ w ] = depthHalf;
14734
14735                                         // now apply vector to vertex buffer
14736
14737                                         vertices.push( vector.x, vector.y, vector.z );
14738
14739                                         // set values to correct vector component
14740
14741                                         vector[ u ] = 0;
14742                                         vector[ v ] = 0;
14743                                         vector[ w ] = depth > 0 ? 1 : - 1;
14744
14745                                         // now apply vector to normal buffer
14746
14747                                         normals.push( vector.x, vector.y, vector.z );
14748
14749                                         // uvs
14750
14751                                         uvs.push( ix / gridX );
14752                                         uvs.push( 1 - ( iy / gridY ) );
14753
14754                                         // counters
14755
14756                                         vertexCounter += 1;
14757
14758                                 }
14759
14760                         }
14761
14762                         // indices
14763
14764                         // 1. you need three indices to draw a single face
14765                         // 2. a single segment consists of two faces
14766                         // 3. so we need to generate six (2*3) indices per segment
14767
14768                         for ( iy = 0; iy < gridY; iy ++ ) {
14769
14770                                 for ( ix = 0; ix < gridX; ix ++ ) {
14771
14772                                         var a = numberOfVertices + ix + gridX1 * iy;
14773                                         var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
14774                                         var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
14775                                         var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
14776
14777                                         // faces
14778
14779                                         indices.push( a, b, d );
14780                                         indices.push( b, c, d );
14781
14782                                         // increase counter
14783
14784                                         groupCount += 6;
14785
14786                                 }
14787
14788                         }
14789
14790                         // add a group to the geometry. this will ensure multi material support
14791
14792                         scope.addGroup( groupStart, groupCount, materialIndex );
14793
14794                         // calculate new start value for groups
14795
14796                         groupStart += groupCount;
14797
14798                         // update total number of vertices
14799
14800                         numberOfVertices += vertexCounter;
14801
14802                 }
14803
14804         }
14805
14806         BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
14807         BoxBufferGeometry.prototype.constructor = BoxBufferGeometry;
14808
14809         /**
14810          * @author mrdoob / http://mrdoob.com/
14811          * @author Mugen87 / https://github.com/Mugen87
14812          */
14813
14814         // PlaneGeometry
14815
14816         function PlaneGeometry( width, height, widthSegments, heightSegments ) {
14817
14818                 Geometry.call( this );
14819
14820                 this.type = 'PlaneGeometry';
14821
14822                 this.parameters = {
14823                         width: width,
14824                         height: height,
14825                         widthSegments: widthSegments,
14826                         heightSegments: heightSegments
14827                 };
14828
14829                 this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
14830                 this.mergeVertices();
14831
14832         }
14833
14834         PlaneGeometry.prototype = Object.create( Geometry.prototype );
14835         PlaneGeometry.prototype.constructor = PlaneGeometry;
14836
14837         // PlaneBufferGeometry
14838
14839         function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {
14840
14841                 BufferGeometry.call( this );
14842
14843                 this.type = 'PlaneBufferGeometry';
14844
14845                 this.parameters = {
14846                         width: width,
14847                         height: height,
14848                         widthSegments: widthSegments,
14849                         heightSegments: heightSegments
14850                 };
14851
14852                 var width_half = width / 2;
14853                 var height_half = height / 2;
14854
14855                 var gridX = Math.floor( widthSegments ) || 1;
14856                 var gridY = Math.floor( heightSegments ) || 1;
14857
14858                 var gridX1 = gridX + 1;
14859                 var gridY1 = gridY + 1;
14860
14861                 var segment_width = width / gridX;
14862                 var segment_height = height / gridY;
14863
14864                 var ix, iy;
14865
14866                 // buffers
14867
14868                 var indices = [];
14869                 var vertices = [];
14870                 var normals = [];
14871                 var uvs = [];
14872
14873                 // generate vertices, normals and uvs
14874
14875                 for ( iy = 0; iy < gridY1; iy ++ ) {
14876
14877                         var y = iy * segment_height - height_half;
14878
14879                         for ( ix = 0; ix < gridX1; ix ++ ) {
14880
14881                                 var x = ix * segment_width - width_half;
14882
14883                                 vertices.push( x, - y, 0 );
14884
14885                                 normals.push( 0, 0, 1 );
14886
14887                                 uvs.push( ix / gridX );
14888                                 uvs.push( 1 - ( iy / gridY ) );
14889
14890                         }
14891
14892                 }
14893
14894                 // indices
14895
14896                 for ( iy = 0; iy < gridY; iy ++ ) {
14897
14898                         for ( ix = 0; ix < gridX; ix ++ ) {
14899
14900                                 var a = ix + gridX1 * iy;
14901                                 var b = ix + gridX1 * ( iy + 1 );
14902                                 var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
14903                                 var d = ( ix + 1 ) + gridX1 * iy;
14904
14905                                 // faces
14906
14907                                 indices.push( a, b, d );
14908                                 indices.push( b, c, d );
14909
14910                         }
14911
14912                 }
14913
14914                 // build geometry
14915
14916                 this.setIndex( indices );
14917                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
14918                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
14919                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
14920
14921         }
14922
14923         PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
14924         PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;
14925
14926         /**
14927          * @author mrdoob / http://mrdoob.com/
14928          * @author alteredq / http://alteredqualia.com/
14929          *
14930          * parameters = {
14931          *  color: <hex>,
14932          *  opacity: <float>,
14933          *  map: new THREE.Texture( <Image> ),
14934          *
14935          *  lightMap: new THREE.Texture( <Image> ),
14936          *  lightMapIntensity: <float>
14937          *
14938          *  aoMap: new THREE.Texture( <Image> ),
14939          *  aoMapIntensity: <float>
14940          *
14941          *  specularMap: new THREE.Texture( <Image> ),
14942          *
14943          *  alphaMap: new THREE.Texture( <Image> ),
14944          *
14945          *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
14946          *  combine: THREE.Multiply,
14947          *  reflectivity: <float>,
14948          *  refractionRatio: <float>,
14949          *
14950          *  depthTest: <bool>,
14951          *  depthWrite: <bool>,
14952          *
14953          *  wireframe: <boolean>,
14954          *  wireframeLinewidth: <float>,
14955          *
14956          *  skinning: <bool>,
14957          *  morphTargets: <bool>
14958          * }
14959          */
14960
14961         function MeshBasicMaterial( parameters ) {
14962
14963                 Material.call( this );
14964
14965                 this.type = 'MeshBasicMaterial';
14966
14967                 this.color = new Color( 0xffffff ); // emissive
14968
14969                 this.map = null;
14970
14971                 this.lightMap = null;
14972                 this.lightMapIntensity = 1.0;
14973
14974                 this.aoMap = null;
14975                 this.aoMapIntensity = 1.0;
14976
14977                 this.specularMap = null;
14978
14979                 this.alphaMap = null;
14980
14981                 this.envMap = null;
14982                 this.combine = MultiplyOperation;
14983                 this.reflectivity = 1;
14984                 this.refractionRatio = 0.98;
14985
14986                 this.wireframe = false;
14987                 this.wireframeLinewidth = 1;
14988                 this.wireframeLinecap = 'round';
14989                 this.wireframeLinejoin = 'round';
14990
14991                 this.skinning = false;
14992                 this.morphTargets = false;
14993
14994                 this.lights = false;
14995
14996                 this.setValues( parameters );
14997
14998         }
14999
15000         MeshBasicMaterial.prototype = Object.create( Material.prototype );
15001         MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
15002
15003         MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
15004
15005         MeshBasicMaterial.prototype.copy = function ( source ) {
15006
15007                 Material.prototype.copy.call( this, source );
15008
15009                 this.color.copy( source.color );
15010
15011                 this.map = source.map;
15012
15013                 this.lightMap = source.lightMap;
15014                 this.lightMapIntensity = source.lightMapIntensity;
15015
15016                 this.aoMap = source.aoMap;
15017                 this.aoMapIntensity = source.aoMapIntensity;
15018
15019                 this.specularMap = source.specularMap;
15020
15021                 this.alphaMap = source.alphaMap;
15022
15023                 this.envMap = source.envMap;
15024                 this.combine = source.combine;
15025                 this.reflectivity = source.reflectivity;
15026                 this.refractionRatio = source.refractionRatio;
15027
15028                 this.wireframe = source.wireframe;
15029                 this.wireframeLinewidth = source.wireframeLinewidth;
15030                 this.wireframeLinecap = source.wireframeLinecap;
15031                 this.wireframeLinejoin = source.wireframeLinejoin;
15032
15033                 this.skinning = source.skinning;
15034                 this.morphTargets = source.morphTargets;
15035
15036                 return this;
15037
15038         };
15039
15040         /**
15041          * @author bhouston / http://clara.io
15042          */
15043
15044         function Ray( origin, direction ) {
15045
15046                 this.origin = ( origin !== undefined ) ? origin : new Vector3();
15047                 this.direction = ( direction !== undefined ) ? direction : new Vector3();
15048
15049         }
15050
15051         Object.assign( Ray.prototype, {
15052
15053                 set: function ( origin, direction ) {
15054
15055                         this.origin.copy( origin );
15056                         this.direction.copy( direction );
15057
15058                         return this;
15059
15060                 },
15061
15062                 clone: function () {
15063
15064                         return new this.constructor().copy( this );
15065
15066                 },
15067
15068                 copy: function ( ray ) {
15069
15070                         this.origin.copy( ray.origin );
15071                         this.direction.copy( ray.direction );
15072
15073                         return this;
15074
15075                 },
15076
15077                 at: function ( t, optionalTarget ) {
15078
15079                         var result = optionalTarget || new Vector3();
15080
15081                         return result.copy( this.direction ).multiplyScalar( t ).add( this.origin );
15082
15083                 },
15084
15085                 lookAt: function ( v ) {
15086
15087                         this.direction.copy( v ).sub( this.origin ).normalize();
15088
15089                         return this;
15090
15091                 },
15092
15093                 recast: function () {
15094
15095                         var v1 = new Vector3();
15096
15097                         return function recast( t ) {
15098
15099                                 this.origin.copy( this.at( t, v1 ) );
15100
15101                                 return this;
15102
15103                         };
15104
15105                 }(),
15106
15107                 closestPointToPoint: function ( point, optionalTarget ) {
15108
15109                         var result = optionalTarget || new Vector3();
15110                         result.subVectors( point, this.origin );
15111                         var directionDistance = result.dot( this.direction );
15112
15113                         if ( directionDistance < 0 ) {
15114
15115                                 return result.copy( this.origin );
15116
15117                         }
15118
15119                         return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
15120
15121                 },
15122
15123                 distanceToPoint: function ( point ) {
15124
15125                         return Math.sqrt( this.distanceSqToPoint( point ) );
15126
15127                 },
15128
15129                 distanceSqToPoint: function () {
15130
15131                         var v1 = new Vector3();
15132
15133                         return function distanceSqToPoint( point ) {
15134
15135                                 var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
15136
15137                                 // point behind the ray
15138
15139                                 if ( directionDistance < 0 ) {
15140
15141                                         return this.origin.distanceToSquared( point );
15142
15143                                 }
15144
15145                                 v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
15146
15147                                 return v1.distanceToSquared( point );
15148
15149                         };
15150
15151                 }(),
15152
15153                 distanceSqToSegment: function () {
15154
15155                         var segCenter = new Vector3();
15156                         var segDir = new Vector3();
15157                         var diff = new Vector3();
15158
15159                         return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
15160
15161                                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
15162                                 // It returns the min distance between the ray and the segment
15163                                 // defined by v0 and v1
15164                                 // It can also set two optional targets :
15165                                 // - The closest point on the ray
15166                                 // - The closest point on the segment
15167
15168                                 segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
15169                                 segDir.copy( v1 ).sub( v0 ).normalize();
15170                                 diff.copy( this.origin ).sub( segCenter );
15171
15172                                 var segExtent = v0.distanceTo( v1 ) * 0.5;
15173                                 var a01 = - this.direction.dot( segDir );
15174                                 var b0 = diff.dot( this.direction );
15175                                 var b1 = - diff.dot( segDir );
15176                                 var c = diff.lengthSq();
15177                                 var det = Math.abs( 1 - a01 * a01 );
15178                                 var s0, s1, sqrDist, extDet;
15179
15180                                 if ( det > 0 ) {
15181
15182                                         // The ray and segment are not parallel.
15183
15184                                         s0 = a01 * b1 - b0;
15185                                         s1 = a01 * b0 - b1;
15186                                         extDet = segExtent * det;
15187
15188                                         if ( s0 >= 0 ) {
15189
15190                                                 if ( s1 >= - extDet ) {
15191
15192                                                         if ( s1 <= extDet ) {
15193
15194                                                                 // region 0
15195                                                                 // Minimum at interior points of ray and segment.
15196
15197                                                                 var invDet = 1 / det;
15198                                                                 s0 *= invDet;
15199                                                                 s1 *= invDet;
15200                                                                 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
15201
15202                                                         } else {
15203
15204                                                                 // region 1
15205
15206                                                                 s1 = segExtent;
15207                                                                 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
15208                                                                 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
15209
15210                                                         }
15211
15212                                                 } else {
15213
15214                                                         // region 5
15215
15216                                                         s1 = - segExtent;
15217                                                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
15218                                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
15219
15220                                                 }
15221
15222                                         } else {
15223
15224                                                 if ( s1 <= - extDet ) {
15225
15226                                                         // region 4
15227
15228                                                         s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
15229                                                         s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
15230                                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
15231
15232                                                 } else if ( s1 <= extDet ) {
15233
15234                                                         // region 3
15235
15236                                                         s0 = 0;
15237                                                         s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
15238                                                         sqrDist = s1 * ( s1 + 2 * b1 ) + c;
15239
15240                                                 } else {
15241
15242                                                         // region 2
15243
15244                                                         s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
15245                                                         s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
15246                                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
15247
15248                                                 }
15249
15250                                         }
15251
15252                                 } else {
15253
15254                                         // Ray and segment are parallel.
15255
15256                                         s1 = ( a01 > 0 ) ? - segExtent : segExtent;
15257                                         s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
15258                                         sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
15259
15260                                 }
15261
15262                                 if ( optionalPointOnRay ) {
15263
15264                                         optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
15265
15266                                 }
15267
15268                                 if ( optionalPointOnSegment ) {
15269
15270                                         optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
15271
15272                                 }
15273
15274                                 return sqrDist;
15275
15276                         };
15277
15278                 }(),
15279
15280                 intersectSphere: function () {
15281
15282                         var v1 = new Vector3();
15283
15284                         return function intersectSphere( sphere, optionalTarget ) {
15285
15286                                 v1.subVectors( sphere.center, this.origin );
15287                                 var tca = v1.dot( this.direction );
15288                                 var d2 = v1.dot( v1 ) - tca * tca;
15289                                 var radius2 = sphere.radius * sphere.radius;
15290
15291                                 if ( d2 > radius2 ) return null;
15292
15293                                 var thc = Math.sqrt( radius2 - d2 );
15294
15295                                 // t0 = first intersect point - entrance on front of sphere
15296                                 var t0 = tca - thc;
15297
15298                                 // t1 = second intersect point - exit point on back of sphere
15299                                 var t1 = tca + thc;
15300
15301                                 // test to see if both t0 and t1 are behind the ray - if so, return null
15302                                 if ( t0 < 0 && t1 < 0 ) return null;
15303
15304                                 // test to see if t0 is behind the ray:
15305                                 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
15306                                 // in order to always return an intersect point that is in front of the ray.
15307                                 if ( t0 < 0 ) return this.at( t1, optionalTarget );
15308
15309                                 // else t0 is in front of the ray, so return the first collision point scaled by t0
15310                                 return this.at( t0, optionalTarget );
15311
15312                         };
15313
15314                 }(),
15315
15316                 intersectsSphere: function ( sphere ) {
15317
15318                         return this.distanceToPoint( sphere.center ) <= sphere.radius;
15319
15320                 },
15321
15322                 distanceToPlane: function ( plane ) {
15323
15324                         var denominator = plane.normal.dot( this.direction );
15325
15326                         if ( denominator === 0 ) {
15327
15328                                 // line is coplanar, return origin
15329                                 if ( plane.distanceToPoint( this.origin ) === 0 ) {
15330
15331                                         return 0;
15332
15333                                 }
15334
15335                                 // Null is preferable to undefined since undefined means.... it is undefined
15336
15337                                 return null;
15338
15339                         }
15340
15341                         var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
15342
15343                         // Return if the ray never intersects the plane
15344
15345                         return t >= 0 ? t :  null;
15346
15347                 },
15348
15349                 intersectPlane: function ( plane, optionalTarget ) {
15350
15351                         var t = this.distanceToPlane( plane );
15352
15353                         if ( t === null ) {
15354
15355                                 return null;
15356
15357                         }
15358
15359                         return this.at( t, optionalTarget );
15360
15361                 },
15362
15363                 intersectsPlane: function ( plane ) {
15364
15365                         // check if the ray lies on the plane first
15366
15367                         var distToPoint = plane.distanceToPoint( this.origin );
15368
15369                         if ( distToPoint === 0 ) {
15370
15371                                 return true;
15372
15373                         }
15374
15375                         var denominator = plane.normal.dot( this.direction );
15376
15377                         if ( denominator * distToPoint < 0 ) {
15378
15379                                 return true;
15380
15381                         }
15382
15383                         // ray origin is behind the plane (and is pointing behind it)
15384
15385                         return false;
15386
15387                 },
15388
15389                 intersectBox: function ( box, optionalTarget ) {
15390
15391                         var tmin, tmax, tymin, tymax, tzmin, tzmax;
15392
15393                         var invdirx = 1 / this.direction.x,
15394                                 invdiry = 1 / this.direction.y,
15395                                 invdirz = 1 / this.direction.z;
15396
15397                         var origin = this.origin;
15398
15399                         if ( invdirx >= 0 ) {
15400
15401                                 tmin = ( box.min.x - origin.x ) * invdirx;
15402                                 tmax = ( box.max.x - origin.x ) * invdirx;
15403
15404                         } else {
15405
15406                                 tmin = ( box.max.x - origin.x ) * invdirx;
15407                                 tmax = ( box.min.x - origin.x ) * invdirx;
15408
15409                         }
15410
15411                         if ( invdiry >= 0 ) {
15412
15413                                 tymin = ( box.min.y - origin.y ) * invdiry;
15414                                 tymax = ( box.max.y - origin.y ) * invdiry;
15415
15416                         } else {
15417
15418                                 tymin = ( box.max.y - origin.y ) * invdiry;
15419                                 tymax = ( box.min.y - origin.y ) * invdiry;
15420
15421                         }
15422
15423                         if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
15424
15425                         // These lines also handle the case where tmin or tmax is NaN
15426                         // (result of 0 * Infinity). x !== x returns true if x is NaN
15427
15428                         if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
15429
15430                         if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
15431
15432                         if ( invdirz >= 0 ) {
15433
15434                                 tzmin = ( box.min.z - origin.z ) * invdirz;
15435                                 tzmax = ( box.max.z - origin.z ) * invdirz;
15436
15437                         } else {
15438
15439                                 tzmin = ( box.max.z - origin.z ) * invdirz;
15440                                 tzmax = ( box.min.z - origin.z ) * invdirz;
15441
15442                         }
15443
15444                         if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
15445
15446                         if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
15447
15448                         if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
15449
15450                         //return point closest to the ray (positive side)
15451
15452                         if ( tmax < 0 ) return null;
15453
15454                         return this.at( tmin >= 0 ? tmin : tmax, optionalTarget );
15455
15456                 },
15457
15458                 intersectsBox: ( function () {
15459
15460                         var v = new Vector3();
15461
15462                         return function intersectsBox( box ) {
15463
15464                                 return this.intersectBox( box, v ) !== null;
15465
15466                         };
15467
15468                 } )(),
15469
15470                 intersectTriangle: function () {
15471
15472                         // Compute the offset origin, edges, and normal.
15473                         var diff = new Vector3();
15474                         var edge1 = new Vector3();
15475                         var edge2 = new Vector3();
15476                         var normal = new Vector3();
15477
15478                         return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) {
15479
15480                                 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
15481
15482                                 edge1.subVectors( b, a );
15483                                 edge2.subVectors( c, a );
15484                                 normal.crossVectors( edge1, edge2 );
15485
15486                                 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
15487                                 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
15488                                 //   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
15489                                 //   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
15490                                 //   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
15491                                 var DdN = this.direction.dot( normal );
15492                                 var sign;
15493
15494                                 if ( DdN > 0 ) {
15495
15496                                         if ( backfaceCulling ) return null;
15497                                         sign = 1;
15498
15499                                 } else if ( DdN < 0 ) {
15500
15501                                         sign = - 1;
15502                                         DdN = - DdN;
15503
15504                                 } else {
15505
15506                                         return null;
15507
15508                                 }
15509
15510                                 diff.subVectors( this.origin, a );
15511                                 var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
15512
15513                                 // b1 < 0, no intersection
15514                                 if ( DdQxE2 < 0 ) {
15515
15516                                         return null;
15517
15518                                 }
15519
15520                                 var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
15521
15522                                 // b2 < 0, no intersection
15523                                 if ( DdE1xQ < 0 ) {
15524
15525                                         return null;
15526
15527                                 }
15528
15529                                 // b1+b2 > 1, no intersection
15530                                 if ( DdQxE2 + DdE1xQ > DdN ) {
15531
15532                                         return null;
15533
15534                                 }
15535
15536                                 // Line intersects triangle, check if ray does.
15537                                 var QdN = - sign * diff.dot( normal );
15538
15539                                 // t < 0, no intersection
15540                                 if ( QdN < 0 ) {
15541
15542                                         return null;
15543
15544                                 }
15545
15546                                 // Ray intersects triangle.
15547                                 return this.at( QdN / DdN, optionalTarget );
15548
15549                         };
15550
15551                 }(),
15552
15553                 applyMatrix4: function ( matrix4 ) {
15554
15555                         this.origin.applyMatrix4( matrix4 );
15556                         this.direction.transformDirection( matrix4 );
15557
15558                         return this;
15559
15560                 },
15561
15562                 equals: function ( ray ) {
15563
15564                         return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
15565
15566                 }
15567
15568         } );
15569
15570         /**
15571          * @author bhouston / http://clara.io
15572          */
15573
15574         function Line3( start, end ) {
15575
15576                 this.start = ( start !== undefined ) ? start : new Vector3();
15577                 this.end = ( end !== undefined ) ? end : new Vector3();
15578
15579         }
15580
15581         Object.assign( Line3.prototype, {
15582
15583                 set: function ( start, end ) {
15584
15585                         this.start.copy( start );
15586                         this.end.copy( end );
15587
15588                         return this;
15589
15590                 },
15591
15592                 clone: function () {
15593
15594                         return new this.constructor().copy( this );
15595
15596                 },
15597
15598                 copy: function ( line ) {
15599
15600                         this.start.copy( line.start );
15601                         this.end.copy( line.end );
15602
15603                         return this;
15604
15605                 },
15606
15607                 getCenter: function ( optionalTarget ) {
15608
15609                         var result = optionalTarget || new Vector3();
15610                         return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
15611
15612                 },
15613
15614                 delta: function ( optionalTarget ) {
15615
15616                         var result = optionalTarget || new Vector3();
15617                         return result.subVectors( this.end, this.start );
15618
15619                 },
15620
15621                 distanceSq: function () {
15622
15623                         return this.start.distanceToSquared( this.end );
15624
15625                 },
15626
15627                 distance: function () {
15628
15629                         return this.start.distanceTo( this.end );
15630
15631                 },
15632
15633                 at: function ( t, optionalTarget ) {
15634
15635                         var result = optionalTarget || new Vector3();
15636
15637                         return this.delta( result ).multiplyScalar( t ).add( this.start );
15638
15639                 },
15640
15641                 closestPointToPointParameter: function () {
15642
15643                         var startP = new Vector3();
15644                         var startEnd = new Vector3();
15645
15646                         return function closestPointToPointParameter( point, clampToLine ) {
15647
15648                                 startP.subVectors( point, this.start );
15649                                 startEnd.subVectors( this.end, this.start );
15650
15651                                 var startEnd2 = startEnd.dot( startEnd );
15652                                 var startEnd_startP = startEnd.dot( startP );
15653
15654                                 var t = startEnd_startP / startEnd2;
15655
15656                                 if ( clampToLine ) {
15657
15658                                         t = _Math.clamp( t, 0, 1 );
15659
15660                                 }
15661
15662                                 return t;
15663
15664                         };
15665
15666                 }(),
15667
15668                 closestPointToPoint: function ( point, clampToLine, optionalTarget ) {
15669
15670                         var t = this.closestPointToPointParameter( point, clampToLine );
15671
15672                         var result = optionalTarget || new Vector3();
15673
15674                         return this.delta( result ).multiplyScalar( t ).add( this.start );
15675
15676                 },
15677
15678                 applyMatrix4: function ( matrix ) {
15679
15680                         this.start.applyMatrix4( matrix );
15681                         this.end.applyMatrix4( matrix );
15682
15683                         return this;
15684
15685                 },
15686
15687                 equals: function ( line ) {
15688
15689                         return line.start.equals( this.start ) && line.end.equals( this.end );
15690
15691                 }
15692
15693         } );
15694
15695         /**
15696          * @author bhouston / http://clara.io
15697          * @author mrdoob / http://mrdoob.com/
15698          */
15699
15700         function Triangle( a, b, c ) {
15701
15702                 this.a = ( a !== undefined ) ? a : new Vector3();
15703                 this.b = ( b !== undefined ) ? b : new Vector3();
15704                 this.c = ( c !== undefined ) ? c : new Vector3();
15705
15706         }
15707
15708         Object.assign( Triangle, {
15709
15710                 normal: function () {
15711
15712                         var v0 = new Vector3();
15713
15714                         return function normal( a, b, c, optionalTarget ) {
15715
15716                                 var result = optionalTarget || new Vector3();
15717
15718                                 result.subVectors( c, b );
15719                                 v0.subVectors( a, b );
15720                                 result.cross( v0 );
15721
15722                                 var resultLengthSq = result.lengthSq();
15723                                 if ( resultLengthSq > 0 ) {
15724
15725                                         return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) );
15726
15727                                 }
15728
15729                                 return result.set( 0, 0, 0 );
15730
15731                         };
15732
15733                 }(),
15734
15735                 // static/instance method to calculate barycentric coordinates
15736                 // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
15737                 barycoordFromPoint: function () {
15738
15739                         var v0 = new Vector3();
15740                         var v1 = new Vector3();
15741                         var v2 = new Vector3();
15742
15743                         return function barycoordFromPoint( point, a, b, c, optionalTarget ) {
15744
15745                                 v0.subVectors( c, a );
15746                                 v1.subVectors( b, a );
15747                                 v2.subVectors( point, a );
15748
15749                                 var dot00 = v0.dot( v0 );
15750                                 var dot01 = v0.dot( v1 );
15751                                 var dot02 = v0.dot( v2 );
15752                                 var dot11 = v1.dot( v1 );
15753                                 var dot12 = v1.dot( v2 );
15754
15755                                 var denom = ( dot00 * dot11 - dot01 * dot01 );
15756
15757                                 var result = optionalTarget || new Vector3();
15758
15759                                 // collinear or singular triangle
15760                                 if ( denom === 0 ) {
15761
15762                                         // arbitrary location outside of triangle?
15763                                         // not sure if this is the best idea, maybe should be returning undefined
15764                                         return result.set( - 2, - 1, - 1 );
15765
15766                                 }
15767
15768                                 var invDenom = 1 / denom;
15769                                 var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
15770                                 var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
15771
15772                                 // barycentric coordinates must always sum to 1
15773                                 return result.set( 1 - u - v, v, u );
15774
15775                         };
15776
15777                 }(),
15778
15779                 containsPoint: function () {
15780
15781                         var v1 = new Vector3();
15782
15783                         return function containsPoint( point, a, b, c ) {
15784
15785                                 var result = Triangle.barycoordFromPoint( point, a, b, c, v1 );
15786
15787                                 return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 );
15788
15789                         };
15790
15791                 }()
15792
15793         } );
15794
15795         Object.assign( Triangle.prototype, {
15796
15797                 set: function ( a, b, c ) {
15798
15799                         this.a.copy( a );
15800                         this.b.copy( b );
15801                         this.c.copy( c );
15802
15803                         return this;
15804
15805                 },
15806
15807                 setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
15808
15809                         this.a.copy( points[ i0 ] );
15810                         this.b.copy( points[ i1 ] );
15811                         this.c.copy( points[ i2 ] );
15812
15813                         return this;
15814
15815                 },
15816
15817                 clone: function () {
15818
15819                         return new this.constructor().copy( this );
15820
15821                 },
15822
15823                 copy: function ( triangle ) {
15824
15825                         this.a.copy( triangle.a );
15826                         this.b.copy( triangle.b );
15827                         this.c.copy( triangle.c );
15828
15829                         return this;
15830
15831                 },
15832
15833                 area: function () {
15834
15835                         var v0 = new Vector3();
15836                         var v1 = new Vector3();
15837
15838                         return function area() {
15839
15840                                 v0.subVectors( this.c, this.b );
15841                                 v1.subVectors( this.a, this.b );
15842
15843                                 return v0.cross( v1 ).length() * 0.5;
15844
15845                         };
15846
15847                 }(),
15848
15849                 midpoint: function ( optionalTarget ) {
15850
15851                         var result = optionalTarget || new Vector3();
15852                         return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
15853
15854                 },
15855
15856                 normal: function ( optionalTarget ) {
15857
15858                         return Triangle.normal( this.a, this.b, this.c, optionalTarget );
15859
15860                 },
15861
15862                 plane: function ( optionalTarget ) {
15863
15864                         var result = optionalTarget || new Plane();
15865
15866                         return result.setFromCoplanarPoints( this.a, this.b, this.c );
15867
15868                 },
15869
15870                 barycoordFromPoint: function ( point, optionalTarget ) {
15871
15872                         return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget );
15873
15874                 },
15875
15876                 containsPoint: function ( point ) {
15877
15878                         return Triangle.containsPoint( point, this.a, this.b, this.c );
15879
15880                 },
15881
15882                 closestPointToPoint: function () {
15883
15884                         var plane = new Plane();
15885                         var edgeList = [ new Line3(), new Line3(), new Line3() ];
15886                         var projectedPoint = new Vector3();
15887                         var closestPoint = new Vector3();
15888
15889                         return function closestPointToPoint( point, optionalTarget ) {
15890
15891                                 var result = optionalTarget || new Vector3();
15892                                 var minDistance = Infinity;
15893
15894                                 // project the point onto the plane of the triangle
15895
15896                                 plane.setFromCoplanarPoints( this.a, this.b, this.c );
15897                                 plane.projectPoint( point, projectedPoint );
15898
15899                                 // check if the projection lies within the triangle
15900
15901                                 if( this.containsPoint( projectedPoint ) === true ) {
15902
15903                                         // if so, this is the closest point
15904
15905                                         result.copy( projectedPoint );
15906
15907                                 } else {
15908
15909                                         // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices
15910
15911                                         edgeList[ 0 ].set( this.a, this.b );
15912                                         edgeList[ 1 ].set( this.b, this.c );
15913                                         edgeList[ 2 ].set( this.c, this.a );
15914
15915                                         for( var i = 0; i < edgeList.length; i ++ ) {
15916
15917                                                 edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint );
15918
15919                                                 var distance = projectedPoint.distanceToSquared( closestPoint );
15920
15921                                                 if( distance < minDistance ) {
15922
15923                                                         minDistance = distance;
15924
15925                                                         result.copy( closestPoint );
15926
15927                                                 }
15928
15929                                         }
15930
15931                                 }
15932
15933                                 return result;
15934
15935                         };
15936
15937                 }(),
15938
15939                 equals: function ( triangle ) {
15940
15941                         return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
15942
15943                 }
15944
15945         } );
15946
15947         /**
15948          * @author mrdoob / http://mrdoob.com/
15949          * @author alteredq / http://alteredqualia.com/
15950          * @author mikael emtinger / http://gomo.se/
15951          * @author jonobr1 / http://jonobr1.com/
15952          */
15953
15954         function Mesh( geometry, material ) {
15955
15956                 Object3D.call( this );
15957
15958                 this.type = 'Mesh';
15959
15960                 this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
15961                 this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );
15962
15963                 this.drawMode = TrianglesDrawMode;
15964
15965                 this.updateMorphTargets();
15966
15967         }
15968
15969         Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
15970
15971                 constructor: Mesh,
15972
15973                 isMesh: true,
15974
15975                 setDrawMode: function ( value ) {
15976
15977                         this.drawMode = value;
15978
15979                 },
15980
15981                 copy: function ( source ) {
15982
15983                         Object3D.prototype.copy.call( this, source );
15984
15985                         this.drawMode = source.drawMode;
15986
15987                         return this;
15988
15989                 },
15990
15991                 updateMorphTargets: function () {
15992
15993                         var geometry = this.geometry;
15994                         var m, ml, name;
15995
15996                         if ( geometry.isBufferGeometry ) {
15997
15998                                 var morphAttributes = geometry.morphAttributes;
15999                                 var keys = Object.keys( morphAttributes );
16000
16001                                 if ( keys.length > 0 ) {
16002
16003                                         var morphAttribute = morphAttributes[ keys[ 0 ] ];
16004
16005                                         if ( morphAttribute !== undefined ) {
16006
16007                                                 this.morphTargetInfluences = [];
16008                                                 this.morphTargetDictionary = {};
16009
16010                                                 for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
16011
16012                                                         name = morphAttribute[ m ].name || String( m );
16013
16014                                                         this.morphTargetInfluences.push( 0 );
16015                                                         this.morphTargetDictionary[ name ] = m;
16016
16017                                                 }
16018
16019                                         }
16020
16021                                 }
16022
16023                         } else {
16024
16025                                 var morphTargets = geometry.morphTargets;
16026
16027                                 if ( morphTargets !== undefined && morphTargets.length > 0 ) {
16028
16029                                         this.morphTargetInfluences = [];
16030                                         this.morphTargetDictionary = {};
16031
16032                                         for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) {
16033
16034                                                 name = morphTargets[ m ].name || String( m );
16035
16036                                                 this.morphTargetInfluences.push( 0 );
16037                                                 this.morphTargetDictionary[ name ] = m;
16038
16039                                         }
16040
16041                                 }
16042
16043                         }
16044
16045                 },
16046
16047                 raycast: ( function () {
16048
16049                         var inverseMatrix = new Matrix4();
16050                         var ray = new Ray();
16051                         var sphere = new Sphere();
16052
16053                         var vA = new Vector3();
16054                         var vB = new Vector3();
16055                         var vC = new Vector3();
16056
16057                         var tempA = new Vector3();
16058                         var tempB = new Vector3();
16059                         var tempC = new Vector3();
16060
16061                         var uvA = new Vector2();
16062                         var uvB = new Vector2();
16063                         var uvC = new Vector2();
16064
16065                         var barycoord = new Vector3();
16066
16067                         var intersectionPoint = new Vector3();
16068                         var intersectionPointWorld = new Vector3();
16069
16070                         function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) {
16071
16072                                 Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord );
16073
16074                                 uv1.multiplyScalar( barycoord.x );
16075                                 uv2.multiplyScalar( barycoord.y );
16076                                 uv3.multiplyScalar( barycoord.z );
16077
16078                                 uv1.add( uv2 ).add( uv3 );
16079
16080                                 return uv1.clone();
16081
16082                         }
16083
16084                         function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
16085
16086                                 var intersect;
16087
16088                                 if ( material.side === BackSide ) {
16089
16090                                         intersect = ray.intersectTriangle( pC, pB, pA, true, point );
16091
16092                                 } else {
16093
16094                                         intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
16095
16096                                 }
16097
16098                                 if ( intersect === null ) return null;
16099
16100                                 intersectionPointWorld.copy( point );
16101                                 intersectionPointWorld.applyMatrix4( object.matrixWorld );
16102
16103                                 var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
16104
16105                                 if ( distance < raycaster.near || distance > raycaster.far ) return null;
16106
16107                                 return {
16108                                         distance: distance,
16109                                         point: intersectionPointWorld.clone(),
16110                                         object: object
16111                                 };
16112
16113                         }
16114
16115                         function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) {
16116
16117                                 vA.fromBufferAttribute( position, a );
16118                                 vB.fromBufferAttribute( position, b );
16119                                 vC.fromBufferAttribute( position, c );
16120
16121                                 var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint );
16122
16123                                 if ( intersection ) {
16124
16125                                         if ( uv ) {
16126
16127                                                 uvA.fromBufferAttribute( uv, a );
16128                                                 uvB.fromBufferAttribute( uv, b );
16129                                                 uvC.fromBufferAttribute( uv, c );
16130
16131                                                 intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC );
16132
16133                                         }
16134
16135                                         intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) );
16136                                         intersection.faceIndex = a;
16137
16138                                 }
16139
16140                                 return intersection;
16141
16142                         }
16143
16144                         return function raycast( raycaster, intersects ) {
16145
16146                                 var geometry = this.geometry;
16147                                 var material = this.material;
16148                                 var matrixWorld = this.matrixWorld;
16149
16150                                 if ( material === undefined ) return;
16151
16152                                 // Checking boundingSphere distance to ray
16153
16154                                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
16155
16156                                 sphere.copy( geometry.boundingSphere );
16157                                 sphere.applyMatrix4( matrixWorld );
16158
16159                                 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
16160
16161                                 //
16162
16163                                 inverseMatrix.getInverse( matrixWorld );
16164                                 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
16165
16166                                 // Check boundingBox before continuing
16167
16168                                 if ( geometry.boundingBox !== null ) {
16169
16170                                         if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
16171
16172                                 }
16173
16174                                 var intersection;
16175
16176                                 if ( geometry.isBufferGeometry ) {
16177
16178                                         var a, b, c;
16179                                         var index = geometry.index;
16180                                         var position = geometry.attributes.position;
16181                                         var uv = geometry.attributes.uv;
16182                                         var i, l;
16183
16184                                         if ( index !== null ) {
16185
16186                                                 // indexed buffer geometry
16187
16188                                                 for ( i = 0, l = index.count; i < l; i += 3 ) {
16189
16190                                                         a = index.getX( i );
16191                                                         b = index.getX( i + 1 );
16192                                                         c = index.getX( i + 2 );
16193
16194                                                         intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c );
16195
16196                                                         if ( intersection ) {
16197
16198                                                                 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics
16199                                                                 intersects.push( intersection );
16200
16201                                                         }
16202
16203                                                 }
16204
16205                                         } else {
16206
16207                                                 // non-indexed buffer geometry
16208
16209                                                 for ( i = 0, l = position.count; i < l; i += 3 ) {
16210
16211                                                         a = i;
16212                                                         b = i + 1;
16213                                                         c = i + 2;
16214
16215                                                         intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c );
16216
16217                                                         if ( intersection ) {
16218
16219                                                                 intersection.index = a; // triangle number in positions buffer semantics
16220                                                                 intersects.push( intersection );
16221
16222                                                         }
16223
16224                                                 }
16225
16226                                         }
16227
16228                                 } else if ( geometry.isGeometry ) {
16229
16230                                         var fvA, fvB, fvC;
16231                                         var isMultiMaterial = Array.isArray( material );
16232
16233                                         var vertices = geometry.vertices;
16234                                         var faces = geometry.faces;
16235                                         var uvs;
16236
16237                                         var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
16238                                         if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
16239
16240                                         for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
16241
16242                                                 var face = faces[ f ];
16243                                                 var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
16244
16245                                                 if ( faceMaterial === undefined ) continue;
16246
16247                                                 fvA = vertices[ face.a ];
16248                                                 fvB = vertices[ face.b ];
16249                                                 fvC = vertices[ face.c ];
16250
16251                                                 if ( faceMaterial.morphTargets === true ) {
16252
16253                                                         var morphTargets = geometry.morphTargets;
16254                                                         var morphInfluences = this.morphTargetInfluences;
16255
16256                                                         vA.set( 0, 0, 0 );
16257                                                         vB.set( 0, 0, 0 );
16258                                                         vC.set( 0, 0, 0 );
16259
16260                                                         for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
16261
16262                                                                 var influence = morphInfluences[ t ];
16263
16264                                                                 if ( influence === 0 ) continue;
16265
16266                                                                 var targets = morphTargets[ t ].vertices;
16267
16268                                                                 vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
16269                                                                 vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
16270                                                                 vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
16271
16272                                                         }
16273
16274                                                         vA.add( fvA );
16275                                                         vB.add( fvB );
16276                                                         vC.add( fvC );
16277
16278                                                         fvA = vA;
16279                                                         fvB = vB;
16280                                                         fvC = vC;
16281
16282                                                 }
16283
16284                                                 intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
16285
16286                                                 if ( intersection ) {
16287
16288                                                         if ( uvs && uvs[ f ] ) {
16289
16290                                                                 var uvs_f = uvs[ f ];
16291                                                                 uvA.copy( uvs_f[ 0 ] );
16292                                                                 uvB.copy( uvs_f[ 1 ] );
16293                                                                 uvC.copy( uvs_f[ 2 ] );
16294
16295                                                                 intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC );
16296
16297                                                         }
16298
16299                                                         intersection.face = face;
16300                                                         intersection.faceIndex = f;
16301                                                         intersects.push( intersection );
16302
16303                                                 }
16304
16305                                         }
16306
16307                                 }
16308
16309                         };
16310
16311                 }() ),
16312
16313                 clone: function () {
16314
16315                         return new this.constructor( this.geometry, this.material ).copy( this );
16316
16317                 }
16318
16319         } );
16320
16321         /**
16322          * @author mrdoob / http://mrdoob.com/
16323          */
16324
16325         function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) {
16326
16327                 var clearColor = new Color( 0x000000 );
16328                 var clearAlpha = 0;
16329
16330                 var planeCamera, planeMesh;
16331                 var boxMesh;
16332
16333                 function render( renderList, scene, camera, forceClear ) {
16334
16335                         var background = scene.background;
16336
16337                         if ( background === null ) {
16338
16339                                 setClear( clearColor, clearAlpha );
16340
16341                         } else if ( background && background.isColor ) {
16342
16343                                 setClear( background, 1 );
16344                                 forceClear = true;
16345
16346                         }
16347
16348                         if ( renderer.autoClear || forceClear ) {
16349
16350                                 renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
16351
16352                         }
16353
16354                         if ( background && background.isCubeTexture ) {
16355
16356                                 if ( boxMesh === undefined ) {
16357
16358                                         boxMesh = new Mesh(
16359                                                 new BoxBufferGeometry( 1, 1, 1 ),
16360                                                 new ShaderMaterial( {
16361                                                         uniforms: ShaderLib.cube.uniforms,
16362                                                         vertexShader: ShaderLib.cube.vertexShader,
16363                                                         fragmentShader: ShaderLib.cube.fragmentShader,
16364                                                         side: BackSide,
16365                                                         depthTest: true,
16366                                                         depthWrite: false,
16367                                                         polygonOffset: true,
16368                                                         fog: false
16369                                                 } )
16370                                         );
16371
16372                                         boxMesh.geometry.removeAttribute( 'normal' );
16373                                         boxMesh.geometry.removeAttribute( 'uv' );
16374
16375                                         boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
16376
16377                                                 var scale = camera.far;
16378
16379                                                 this.matrixWorld.makeScale( scale, scale, scale );
16380                                                 this.matrixWorld.copyPosition( camera.matrixWorld );
16381
16382                                                 this.material.polygonOffsetUnits = scale * 10;
16383
16384                                         };
16385
16386                                         geometries.update( boxMesh.geometry );
16387
16388                                 }
16389
16390                                 boxMesh.material.uniforms.tCube.value = background;
16391
16392                                 renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null );
16393
16394                         } else if ( background && background.isTexture ) {
16395
16396                                 if ( planeCamera === undefined ) {
16397
16398                                         planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
16399
16400                                         planeMesh = new Mesh(
16401                                                 new PlaneBufferGeometry( 2, 2 ),
16402                                                 new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } )
16403                                         );
16404
16405                                         geometries.update( planeMesh.geometry );
16406
16407                                 }
16408
16409                                 planeMesh.material.map = background;
16410
16411                                 // TODO Push this to renderList
16412
16413                                 renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null );
16414
16415                         }
16416
16417                 }
16418
16419                 function setClear( color, alpha ) {
16420
16421                         state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
16422
16423                 }
16424
16425                 return {
16426
16427                         getClearColor: function () {
16428
16429                                 return clearColor;
16430
16431                         },
16432                         setClearColor: function ( color, alpha ) {
16433
16434                                 clearColor.set( color );
16435                                 clearAlpha = alpha !== undefined ? alpha : 1;
16436                                 setClear( clearColor, clearAlpha );
16437
16438                         },
16439                         getClearAlpha: function () {
16440
16441                                 return clearAlpha;
16442
16443                         },
16444                         setClearAlpha: function ( alpha ) {
16445
16446                                 clearAlpha = alpha;
16447                                 setClear( clearColor, clearAlpha );
16448
16449                         },
16450                         render: render
16451
16452                 };
16453
16454         }
16455
16456         /**
16457          * @author mrdoob / http://mrdoob.com/
16458          */
16459
16460         function painterSortStable( a, b ) {
16461
16462                 if ( a.renderOrder !== b.renderOrder ) {
16463
16464                         return a.renderOrder - b.renderOrder;
16465
16466                 } else if ( a.program && b.program && a.program !== b.program ) {
16467
16468                         return a.program.id - b.program.id;
16469
16470                 } else if ( a.material.id !== b.material.id ) {
16471
16472                         return a.material.id - b.material.id;
16473
16474                 } else if ( a.z !== b.z ) {
16475
16476                         return a.z - b.z;
16477
16478                 } else {
16479
16480                         return a.id - b.id;
16481
16482                 }
16483
16484         }
16485
16486         function reversePainterSortStable( a, b ) {
16487
16488                 if ( a.renderOrder !== b.renderOrder ) {
16489
16490                         return a.renderOrder - b.renderOrder;
16491
16492                 } if ( a.z !== b.z ) {
16493
16494                         return b.z - a.z;
16495
16496                 } else {
16497
16498                         return a.id - b.id;
16499
16500                 }
16501
16502         }
16503
16504         function WebGLRenderList() {
16505
16506                 var renderItems = [];
16507                 var renderItemsIndex = 0;
16508
16509                 var opaque = [];
16510                 var transparent = [];
16511
16512                 function init() {
16513
16514                         renderItemsIndex = 0;
16515
16516                         opaque.length = 0;
16517                         transparent.length = 0;
16518
16519                 }
16520
16521                 function push( object, geometry, material, z, group ) {
16522
16523                         var renderItem = renderItems[ renderItemsIndex ];
16524
16525                         if ( renderItem === undefined ) {
16526
16527                                 renderItem = {
16528                                         id: object.id,
16529                                         object: object,
16530                                         geometry: geometry,
16531                                         material: material,
16532                                         program: material.program,
16533                                         renderOrder: object.renderOrder,
16534                                         z: z,
16535                                         group: group
16536                                 };
16537
16538                                 renderItems[ renderItemsIndex ] = renderItem;
16539
16540                         } else {
16541
16542                                 renderItem.id = object.id;
16543                                 renderItem.object = object;
16544                                 renderItem.geometry = geometry;
16545                                 renderItem.material = material;
16546                                 renderItem.program = material.program;
16547                                 renderItem.renderOrder = object.renderOrder;
16548                                 renderItem.z = z;
16549                                 renderItem.group = group;
16550
16551                         }
16552
16553                         ( material.transparent === true ? transparent : opaque ).push( renderItem );
16554
16555                         renderItemsIndex ++;
16556
16557                 }
16558
16559                 function sort() {
16560
16561                         if ( opaque.length > 1 ) opaque.sort( painterSortStable );
16562                         if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable );
16563
16564                 }
16565
16566                 return {
16567                         opaque: opaque,
16568                         transparent: transparent,
16569
16570                         init: init,
16571                         push: push,
16572
16573                         sort: sort
16574                 };
16575
16576         }
16577
16578         function WebGLRenderLists() {
16579
16580                 var lists = {};
16581
16582                 function get( scene, camera ) {
16583
16584                         var hash = scene.id + ',' + camera.id;
16585                         var list = lists[ hash ];
16586
16587                         if ( list === undefined ) {
16588
16589                                 // console.log( 'THREE.WebGLRenderLists:', hash );
16590
16591                                 list = new WebGLRenderList();
16592                                 lists[ hash ] = list;
16593
16594                         }
16595
16596                         return list;
16597
16598                 }
16599
16600                 function dispose() {
16601
16602                         lists = {};
16603
16604                 }
16605
16606                 return {
16607                         get: get,
16608                         dispose: dispose
16609                 };
16610
16611         }
16612
16613         /**
16614          * @author mrdoob / http://mrdoob.com/
16615          */
16616
16617         function absNumericalSort( a, b ) {
16618
16619                 return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
16620
16621         }
16622
16623         function WebGLMorphtargets( gl ) {
16624
16625                 var influencesList = {};
16626                 var morphInfluences = new Float32Array( 8 );
16627
16628                 function update( object, geometry, material, program ) {
16629
16630                         var objectInfluences = object.morphTargetInfluences;
16631
16632                         var length = objectInfluences.length;
16633
16634                         var influences = influencesList[ geometry.id ];
16635
16636                         if ( influences === undefined ) {
16637
16638                                 // initialise list
16639
16640                                 influences = [];
16641
16642                                 for ( var i = 0; i < length; i ++ ) {
16643
16644                                         influences[ i ] = [ i, 0 ];
16645
16646                                 }
16647
16648                                 influencesList[ geometry.id ] = influences;
16649
16650                         }
16651
16652                         var morphTargets = material.morphTargets && geometry.morphAttributes.position;
16653                         var morphNormals = material.morphNormals && geometry.morphAttributes.normal;
16654
16655                         // Remove current morphAttributes
16656
16657                         for ( var i = 0; i < length; i ++ ) {
16658
16659                                 var influence = influences[ i ];
16660
16661                                 if ( influence[ 1 ] !== 0 ) {
16662
16663                                         if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i );
16664                                         if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i );
16665
16666                                 }
16667
16668                         }
16669
16670                         // Collect influences
16671
16672                         for ( var i = 0; i < length; i ++ ) {
16673
16674                                 var influence = influences[ i ];
16675
16676                                 influence[ 0 ] = i;
16677                                 influence[ 1 ] = objectInfluences[ i ];
16678
16679                         }
16680
16681                         influences.sort( absNumericalSort );
16682
16683                         // Add morphAttributes
16684
16685                         for ( var i = 0; i < 8; i ++ ) {
16686
16687                                 var influence = influences[ i ];
16688
16689                                 if ( influence ) {
16690
16691                                         var index = influence[ 0 ];
16692                                         var value = influence[ 1 ];
16693
16694                                         if ( value ) {
16695
16696                                                 if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] );
16697                                                 if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] );
16698
16699                                                 morphInfluences[ i ] = value;
16700                                                 continue;
16701
16702                                         }
16703
16704                                 }
16705
16706                                 morphInfluences[ i ] = 0;
16707
16708                         }
16709
16710                         program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
16711
16712                 }
16713
16714                 return {
16715
16716                         update: update
16717
16718                 }
16719
16720         }
16721
16722         /**
16723          * @author mrdoob / http://mrdoob.com/
16724          */
16725
16726         function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) {
16727
16728                 var mode;
16729
16730                 function setMode( value ) {
16731
16732                         mode = value;
16733
16734                 }
16735
16736                 var type, bytesPerElement;
16737
16738                 function setIndex( value ) {
16739
16740                         type = value.type;
16741                         bytesPerElement = value.bytesPerElement;
16742
16743                 }
16744
16745                 function render( start, count ) {
16746
16747                         gl.drawElements( mode, count, type, start * bytesPerElement );
16748
16749                         infoRender.calls ++;
16750                         infoRender.vertices += count;
16751
16752                         if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3;
16753                         else if ( mode === gl.POINTS ) infoRender.points += count;
16754
16755                 }
16756
16757                 function renderInstances( geometry, start, count ) {
16758
16759                         var extension = extensions.get( 'ANGLE_instanced_arrays' );
16760
16761                         if ( extension === null ) {
16762
16763                                 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
16764                                 return;
16765
16766                         }
16767
16768                         extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
16769
16770                         infoRender.calls ++;
16771                         infoRender.vertices += count * geometry.maxInstancedCount;
16772
16773                         if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3;
16774                         else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count;
16775
16776                 }
16777
16778                 //
16779
16780                 this.setMode = setMode;
16781                 this.setIndex = setIndex;
16782                 this.render = render;
16783                 this.renderInstances = renderInstances;
16784
16785         }
16786
16787         /**
16788          * @author mrdoob / http://mrdoob.com/
16789          */
16790
16791         function WebGLBufferRenderer( gl, extensions, infoRender ) {
16792
16793                 var mode;
16794
16795                 function setMode( value ) {
16796
16797                         mode = value;
16798
16799                 }
16800
16801                 function render( start, count ) {
16802
16803                         gl.drawArrays( mode, start, count );
16804
16805                         infoRender.calls ++;
16806                         infoRender.vertices += count;
16807
16808                         if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3;
16809                         else if ( mode === gl.POINTS ) infoRender.points += count;
16810
16811                 }
16812
16813                 function renderInstances( geometry, start, count ) {
16814
16815                         var extension = extensions.get( 'ANGLE_instanced_arrays' );
16816
16817                         if ( extension === null ) {
16818
16819                                 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
16820                                 return;
16821
16822                         }
16823
16824                         var position = geometry.attributes.position;
16825
16826                         if ( position.isInterleavedBufferAttribute ) {
16827
16828                                 count = position.data.count;
16829
16830                                 extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount );
16831
16832                         } else {
16833
16834                                 extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount );
16835
16836                         }
16837
16838                         infoRender.calls ++;
16839                         infoRender.vertices += count * geometry.maxInstancedCount;
16840
16841                         if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3;
16842                         else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count;
16843
16844                 }
16845
16846                 //
16847
16848                 this.setMode = setMode;
16849                 this.render = render;
16850                 this.renderInstances = renderInstances;
16851
16852         }
16853
16854         /**
16855          * @author mrdoob / http://mrdoob.com/
16856          */
16857
16858         function WebGLGeometries( gl, attributes, infoMemory ) {
16859
16860                 var geometries = {};
16861                 var wireframeAttributes = {};
16862
16863                 function onGeometryDispose( event ) {
16864
16865                         var geometry = event.target;
16866                         var buffergeometry = geometries[ geometry.id ];
16867
16868                         if ( buffergeometry.index !== null ) {
16869
16870                                 attributes.remove( buffergeometry.index );
16871
16872                         }
16873
16874                         for ( var name in buffergeometry.attributes ) {
16875
16876                                 attributes.remove( buffergeometry.attributes[ name ] );
16877
16878                         }
16879
16880                         geometry.removeEventListener( 'dispose', onGeometryDispose );
16881
16882                         delete geometries[ geometry.id ];
16883
16884                         // TODO Remove duplicate code
16885
16886                         var attribute = wireframeAttributes[ geometry.id ];
16887
16888                         if ( attribute ) {
16889
16890                                 attributes.remove( attribute );
16891                                 delete wireframeAttributes[ geometry.id ];
16892
16893                         }
16894
16895                         attribute = wireframeAttributes[ buffergeometry.id ];
16896
16897                         if ( attribute ) {
16898
16899                                 attributes.remove( attribute );
16900                                 delete wireframeAttributes[ buffergeometry.id ];
16901
16902                         }
16903
16904                         //
16905
16906                         infoMemory.geometries --;
16907
16908                 }
16909
16910                 function get( object, geometry ) {
16911
16912                         var buffergeometry = geometries[ geometry.id ];
16913
16914                         if ( buffergeometry ) return buffergeometry;
16915
16916                         geometry.addEventListener( 'dispose', onGeometryDispose );
16917
16918                         if ( geometry.isBufferGeometry ) {
16919
16920                                 buffergeometry = geometry;
16921
16922                         } else if ( geometry.isGeometry ) {
16923
16924                                 if ( geometry._bufferGeometry === undefined ) {
16925
16926                                         geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
16927
16928                                 }
16929
16930                                 buffergeometry = geometry._bufferGeometry;
16931
16932                         }
16933
16934                         geometries[ geometry.id ] = buffergeometry;
16935
16936                         infoMemory.geometries ++;
16937
16938                         return buffergeometry;
16939
16940                 }
16941
16942                 function update( geometry ) {
16943
16944                         var index = geometry.index;
16945                         var geometryAttributes = geometry.attributes;
16946
16947                         if ( index !== null ) {
16948
16949                                 attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
16950
16951                         }
16952
16953                         for ( var name in geometryAttributes ) {
16954
16955                                 attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
16956
16957                         }
16958
16959                         // morph targets
16960
16961                         var morphAttributes = geometry.morphAttributes;
16962
16963                         for ( var name in morphAttributes ) {
16964
16965                                 var array = morphAttributes[ name ];
16966
16967                                 for ( var i = 0, l = array.length; i < l; i ++ ) {
16968
16969                                         attributes.update( array[ i ], gl.ARRAY_BUFFER );
16970
16971                                 }
16972
16973                         }
16974
16975                 }
16976
16977                 function getWireframeAttribute( geometry ) {
16978
16979                         var attribute = wireframeAttributes[ geometry.id ];
16980
16981                         if ( attribute ) return attribute;
16982
16983                         var indices = [];
16984
16985                         var geometryIndex = geometry.index;
16986                         var geometryAttributes = geometry.attributes;
16987
16988                         // console.time( 'wireframe' );
16989
16990                         if ( geometryIndex !== null ) {
16991
16992                                 var array = geometryIndex.array;
16993
16994                                 for ( var i = 0, l = array.length; i < l; i += 3 ) {
16995
16996                                         var a = array[ i + 0 ];
16997                                         var b = array[ i + 1 ];
16998                                         var c = array[ i + 2 ];
16999
17000                                         indices.push( a, b, b, c, c, a );
17001
17002                                 }
17003
17004                         } else {
17005
17006                                 var array = geometryAttributes.position.array;
17007
17008                                 for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
17009
17010                                         var a = i + 0;
17011                                         var b = i + 1;
17012                                         var c = i + 2;
17013
17014                                         indices.push( a, b, b, c, c, a );
17015
17016                                 }
17017
17018                         }
17019
17020                         // console.timeEnd( 'wireframe' );
17021
17022                         attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
17023
17024                         attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER );
17025
17026                         wireframeAttributes[ geometry.id ] = attribute;
17027
17028                         return attribute;
17029
17030                 }
17031
17032                 return {
17033
17034                         get: get,
17035                         update: update,
17036
17037                         getWireframeAttribute: getWireframeAttribute
17038
17039                 };
17040
17041         }
17042
17043         /**
17044          * @author mrdoob / http://mrdoob.com/
17045          */
17046
17047         function UniformsCache() {
17048
17049                 var lights = {};
17050
17051                 return {
17052
17053                         get: function ( light ) {
17054
17055                                 if ( lights[ light.id ] !== undefined ) {
17056
17057                                         return lights[ light.id ];
17058
17059                                 }
17060
17061                                 var uniforms;
17062
17063                                 switch ( light.type ) {
17064
17065                                         case 'DirectionalLight':
17066                                                 uniforms = {
17067                                                         direction: new Vector3(),
17068                                                         color: new Color(),
17069
17070                                                         shadow: false,
17071                                                         shadowBias: 0,
17072                                                         shadowRadius: 1,
17073                                                         shadowMapSize: new Vector2()
17074                                                 };
17075                                                 break;
17076
17077                                         case 'SpotLight':
17078                                                 uniforms = {
17079                                                         position: new Vector3(),
17080                                                         direction: new Vector3(),
17081                                                         color: new Color(),
17082                                                         distance: 0,
17083                                                         coneCos: 0,
17084                                                         penumbraCos: 0,
17085                                                         decay: 0,
17086
17087                                                         shadow: false,
17088                                                         shadowBias: 0,
17089                                                         shadowRadius: 1,
17090                                                         shadowMapSize: new Vector2()
17091                                                 };
17092                                                 break;
17093
17094                                         case 'PointLight':
17095                                                 uniforms = {
17096                                                         position: new Vector3(),
17097                                                         color: new Color(),
17098                                                         distance: 0,
17099                                                         decay: 0,
17100
17101                                                         shadow: false,
17102                                                         shadowBias: 0,
17103                                                         shadowRadius: 1,
17104                                                         shadowMapSize: new Vector2(),
17105                                                         shadowCameraNear: 1,
17106                                                         shadowCameraFar: 1000
17107                                                 };
17108                                                 break;
17109
17110                                         case 'HemisphereLight':
17111                                                 uniforms = {
17112                                                         direction: new Vector3(),
17113                                                         skyColor: new Color(),
17114                                                         groundColor: new Color()
17115                                                 };
17116                                                 break;
17117
17118                                         case 'RectAreaLight':
17119                                                 uniforms = {
17120                                                         color: new Color(),
17121                                                         position: new Vector3(),
17122                                                         halfWidth: new Vector3(),
17123                                                         halfHeight: new Vector3()
17124                                                         // TODO (abelnation): set RectAreaLight shadow uniforms
17125                                                 };
17126                                                 break;
17127
17128                                 }
17129
17130                                 lights[ light.id ] = uniforms;
17131
17132                                 return uniforms;
17133
17134                         }
17135
17136                 };
17137
17138         }
17139
17140         function WebGLLights() {
17141
17142                 var cache = new UniformsCache();
17143
17144                 var state = {
17145
17146                         hash: '',
17147
17148                         ambient: [ 0, 0, 0 ],
17149                         directional: [],
17150                         directionalShadowMap: [],
17151                         directionalShadowMatrix: [],
17152                         spot: [],
17153                         spotShadowMap: [],
17154                         spotShadowMatrix: [],
17155                         rectArea: [],
17156                         point: [],
17157                         pointShadowMap: [],
17158                         pointShadowMatrix: [],
17159                         hemi: []
17160
17161                 };
17162
17163                 var vector3 = new Vector3();
17164                 var matrix4 = new Matrix4();
17165                 var matrix42 = new Matrix4();
17166
17167                 function setup( lights, shadows, camera ) {
17168
17169                         var r = 0, g = 0, b = 0;
17170
17171                         var directionalLength = 0;
17172                         var pointLength = 0;
17173                         var spotLength = 0;
17174                         var rectAreaLength = 0;
17175                         var hemiLength = 0;
17176
17177                         var viewMatrix = camera.matrixWorldInverse;
17178
17179                         for ( var i = 0, l = lights.length; i < l; i ++ ) {
17180
17181                                 var light = lights[ i ];
17182
17183                                 var color = light.color;
17184                                 var intensity = light.intensity;
17185                                 var distance = light.distance;
17186
17187                                 var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
17188
17189                                 if ( light.isAmbientLight ) {
17190
17191                                         r += color.r * intensity;
17192                                         g += color.g * intensity;
17193                                         b += color.b * intensity;
17194
17195                                 } else if ( light.isDirectionalLight ) {
17196
17197                                         var uniforms = cache.get( light );
17198
17199                                         uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
17200                                         uniforms.direction.setFromMatrixPosition( light.matrixWorld );
17201                                         vector3.setFromMatrixPosition( light.target.matrixWorld );
17202                                         uniforms.direction.sub( vector3 );
17203                                         uniforms.direction.transformDirection( viewMatrix );
17204
17205                                         uniforms.shadow = light.castShadow;
17206
17207                                         if ( light.castShadow ) {
17208
17209                                                 var shadow = light.shadow;
17210
17211                                                 uniforms.shadowBias = shadow.bias;
17212                                                 uniforms.shadowRadius = shadow.radius;
17213                                                 uniforms.shadowMapSize = shadow.mapSize;
17214
17215                                         }
17216
17217                                         state.directionalShadowMap[ directionalLength ] = shadowMap;
17218                                         state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
17219                                         state.directional[ directionalLength ] = uniforms;
17220
17221                                         directionalLength ++;
17222
17223                                 } else if ( light.isSpotLight ) {
17224
17225                                         var uniforms = cache.get( light );
17226
17227                                         uniforms.position.setFromMatrixPosition( light.matrixWorld );
17228                                         uniforms.position.applyMatrix4( viewMatrix );
17229
17230                                         uniforms.color.copy( color ).multiplyScalar( intensity );
17231                                         uniforms.distance = distance;
17232
17233                                         uniforms.direction.setFromMatrixPosition( light.matrixWorld );
17234                                         vector3.setFromMatrixPosition( light.target.matrixWorld );
17235                                         uniforms.direction.sub( vector3 );
17236                                         uniforms.direction.transformDirection( viewMatrix );
17237
17238                                         uniforms.coneCos = Math.cos( light.angle );
17239                                         uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
17240                                         uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
17241
17242                                         uniforms.shadow = light.castShadow;
17243
17244                                         if ( light.castShadow ) {
17245
17246                                                 var shadow = light.shadow;
17247
17248                                                 uniforms.shadowBias = shadow.bias;
17249                                                 uniforms.shadowRadius = shadow.radius;
17250                                                 uniforms.shadowMapSize = shadow.mapSize;
17251
17252                                         }
17253
17254                                         state.spotShadowMap[ spotLength ] = shadowMap;
17255                                         state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
17256                                         state.spot[ spotLength ] = uniforms;
17257
17258                                         spotLength ++;
17259
17260                                 } else if ( light.isRectAreaLight ) {
17261
17262                                         var uniforms = cache.get( light );
17263
17264                                         // (a) intensity controls irradiance of entire light
17265                                         uniforms.color
17266                                                 .copy( color )
17267                                                 .multiplyScalar( intensity / ( light.width * light.height ) );
17268
17269                                         // (b) intensity controls the radiance per light area
17270                                         // uniforms.color.copy( color ).multiplyScalar( intensity );
17271
17272                                         uniforms.position.setFromMatrixPosition( light.matrixWorld );
17273                                         uniforms.position.applyMatrix4( viewMatrix );
17274
17275                                         // extract local rotation of light to derive width/height half vectors
17276                                         matrix42.identity();
17277                                         matrix4.copy( light.matrixWorld );
17278                                         matrix4.premultiply( viewMatrix );
17279                                         matrix42.extractRotation( matrix4 );
17280
17281                                         uniforms.halfWidth.set( light.width * 0.5,                0.0, 0.0 );
17282                                         uniforms.halfHeight.set(              0.0, light.height * 0.5, 0.0 );
17283
17284                                         uniforms.halfWidth.applyMatrix4( matrix42 );
17285                                         uniforms.halfHeight.applyMatrix4( matrix42 );
17286
17287                                         // TODO (abelnation): RectAreaLight distance?
17288                                         // uniforms.distance = distance;
17289
17290                                         state.rectArea[ rectAreaLength ] = uniforms;
17291
17292                                         rectAreaLength ++;
17293
17294                                 } else if ( light.isPointLight ) {
17295
17296                                         var uniforms = cache.get( light );
17297
17298                                         uniforms.position.setFromMatrixPosition( light.matrixWorld );
17299                                         uniforms.position.applyMatrix4( viewMatrix );
17300
17301                                         uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
17302                                         uniforms.distance = light.distance;
17303                                         uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
17304
17305                                         uniforms.shadow = light.castShadow;
17306
17307                                         if ( light.castShadow ) {
17308
17309                                                 var shadow = light.shadow;
17310
17311                                                 uniforms.shadowBias = shadow.bias;
17312                                                 uniforms.shadowRadius = shadow.radius;
17313                                                 uniforms.shadowMapSize = shadow.mapSize;
17314                                                 uniforms.shadowCameraNear = shadow.camera.near;
17315                                                 uniforms.shadowCameraFar = shadow.camera.far;
17316
17317                                         }
17318
17319                                         state.pointShadowMap[ pointLength ] = shadowMap;
17320                                         state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
17321                                         state.point[ pointLength ] = uniforms;
17322
17323                                         pointLength ++;
17324
17325                                 } else if ( light.isHemisphereLight ) {
17326
17327                                         var uniforms = cache.get( light );
17328
17329                                         uniforms.direction.setFromMatrixPosition( light.matrixWorld );
17330                                         uniforms.direction.transformDirection( viewMatrix );
17331                                         uniforms.direction.normalize();
17332
17333                                         uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
17334                                         uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
17335
17336                                         state.hemi[ hemiLength ] = uniforms;
17337
17338                                         hemiLength ++;
17339
17340                                 }
17341
17342                         }
17343
17344                         state.ambient[ 0 ] = r;
17345                         state.ambient[ 1 ] = g;
17346                         state.ambient[ 2 ] = b;
17347
17348                         state.directional.length = directionalLength;
17349                         state.spot.length = spotLength;
17350                         state.rectArea.length = rectAreaLength;
17351                         state.point.length = pointLength;
17352                         state.hemi.length = hemiLength;
17353
17354                         // TODO (sam-g-steel) why aren't we using join
17355                         state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length;
17356
17357                 }
17358
17359                 return {
17360                         setup: setup,
17361                         state: state
17362                 }
17363
17364         }
17365
17366         /**
17367          * @author mrdoob / http://mrdoob.com/
17368          */
17369
17370         function WebGLObjects( geometries, infoRender ) {
17371
17372                 var updateList = {};
17373
17374                 function update( object ) {
17375
17376                         var frame = infoRender.frame;
17377
17378                         var geometry = object.geometry;
17379                         var buffergeometry = geometries.get( object, geometry );
17380
17381                         // Update once per frame
17382
17383                         if ( updateList[ buffergeometry.id ] !== frame ) {
17384
17385                                 if ( geometry.isGeometry ) {
17386
17387                                         buffergeometry.updateFromObject( object );
17388
17389                                 }
17390
17391                                 geometries.update( buffergeometry );
17392
17393                                 updateList[ buffergeometry.id ] = frame;
17394
17395                         }
17396
17397                         return buffergeometry;
17398
17399                 }
17400
17401                 function clear() {
17402
17403                         updateList = {};
17404
17405                 }
17406
17407                 return {
17408
17409                         update: update,
17410                         clear: clear
17411
17412                 };
17413
17414         }
17415
17416         /**
17417          * @author mrdoob / http://mrdoob.com/
17418          */
17419
17420         function addLineNumbers( string ) {
17421
17422                 var lines = string.split( '\n' );
17423
17424                 for ( var i = 0; i < lines.length; i ++ ) {
17425
17426                         lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
17427
17428                 }
17429
17430                 return lines.join( '\n' );
17431
17432         }
17433
17434         function WebGLShader( gl, type, string ) {
17435
17436                 var shader = gl.createShader( type );
17437
17438                 gl.shaderSource( shader, string );
17439                 gl.compileShader( shader );
17440
17441                 if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) {
17442
17443                         console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' );
17444
17445                 }
17446
17447                 if ( gl.getShaderInfoLog( shader ) !== '' ) {
17448
17449                         console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) );
17450
17451                 }
17452
17453                 // --enable-privileged-webgl-extension
17454                 // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
17455
17456                 return shader;
17457
17458         }
17459
17460         /**
17461          * @author mrdoob / http://mrdoob.com/
17462          */
17463
17464         var programIdCount = 0;
17465
17466         function getEncodingComponents( encoding ) {
17467
17468                 switch ( encoding ) {
17469
17470                         case LinearEncoding:
17471                                 return [ 'Linear','( value )' ];
17472                         case sRGBEncoding:
17473                                 return [ 'sRGB','( value )' ];
17474                         case RGBEEncoding:
17475                                 return [ 'RGBE','( value )' ];
17476                         case RGBM7Encoding:
17477                                 return [ 'RGBM','( value, 7.0 )' ];
17478                         case RGBM16Encoding:
17479                                 return [ 'RGBM','( value, 16.0 )' ];
17480                         case RGBDEncoding:
17481                                 return [ 'RGBD','( value, 256.0 )' ];
17482                         case GammaEncoding:
17483                                 return [ 'Gamma','( value, float( GAMMA_FACTOR ) )' ];
17484                         default:
17485                                 throw new Error( 'unsupported encoding: ' + encoding );
17486
17487                 }
17488
17489         }
17490
17491         function getTexelDecodingFunction( functionName, encoding ) {
17492
17493                 var components = getEncodingComponents( encoding );
17494                 return "vec4 " + functionName + "( vec4 value ) { return " + components[ 0 ] + "ToLinear" + components[ 1 ] + "; }";
17495
17496         }
17497
17498         function getTexelEncodingFunction( functionName, encoding ) {
17499
17500                 var components = getEncodingComponents( encoding );
17501                 return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[ 0 ] + components[ 1 ] + "; }";
17502
17503         }
17504
17505         function getToneMappingFunction( functionName, toneMapping ) {
17506
17507                 var toneMappingName;
17508
17509                 switch ( toneMapping ) {
17510
17511                         case LinearToneMapping:
17512                                 toneMappingName = "Linear";
17513                                 break;
17514
17515                         case ReinhardToneMapping:
17516                                 toneMappingName = "Reinhard";
17517                                 break;
17518
17519                         case Uncharted2ToneMapping:
17520                                 toneMappingName = "Uncharted2";
17521                                 break;
17522
17523                         case CineonToneMapping:
17524                                 toneMappingName = "OptimizedCineon";
17525                                 break;
17526
17527                         default:
17528                                 throw new Error( 'unsupported toneMapping: ' + toneMapping );
17529
17530                 }
17531
17532                 return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }";
17533
17534         }
17535
17536         function generateExtensions( extensions, parameters, rendererExtensions ) {
17537
17538                 extensions = extensions || {};
17539
17540                 var chunks = [
17541                         ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
17542                         ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
17543                         ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
17544                         ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
17545                 ];
17546
17547                 return chunks.filter( filterEmptyLine ).join( '\n' );
17548
17549         }
17550
17551         function generateDefines( defines ) {
17552
17553                 var chunks = [];
17554
17555                 for ( var name in defines ) {
17556
17557                         var value = defines[ name ];
17558
17559                         if ( value === false ) continue;
17560
17561                         chunks.push( '#define ' + name + ' ' + value );
17562
17563                 }
17564
17565                 return chunks.join( '\n' );
17566
17567         }
17568
17569         function fetchAttributeLocations( gl, program, identifiers ) {
17570
17571                 var attributes = {};
17572
17573                 var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
17574
17575                 for ( var i = 0; i < n; i ++ ) {
17576
17577                         var info = gl.getActiveAttrib( program, i );
17578                         var name = info.name;
17579
17580                         // console.log("THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:", name, i );
17581
17582                         attributes[ name ] = gl.getAttribLocation( program, name );
17583
17584                 }
17585
17586                 return attributes;
17587
17588         }
17589
17590         function filterEmptyLine( string ) {
17591
17592                 return string !== '';
17593
17594         }
17595
17596         function replaceLightNums( string, parameters ) {
17597
17598                 return string
17599                         .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
17600                         .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
17601                         .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
17602                         .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
17603                         .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
17604
17605         }
17606
17607         function parseIncludes( string ) {
17608
17609                 var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm;
17610
17611                 function replace( match, include ) {
17612
17613                         var replace = ShaderChunk[ include ];
17614
17615                         if ( replace === undefined ) {
17616
17617                                 throw new Error( 'Can not resolve #include <' + include + '>' );
17618
17619                         }
17620
17621                         return parseIncludes( replace );
17622
17623                 }
17624
17625                 return string.replace( pattern, replace );
17626
17627         }
17628
17629         function unrollLoops( string ) {
17630
17631                 var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
17632
17633                 function replace( match, start, end, snippet ) {
17634
17635                         var unroll = '';
17636
17637                         for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {
17638
17639                                 unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );
17640
17641                         }
17642
17643                         return unroll;
17644
17645                 }
17646
17647                 return string.replace( pattern, replace );
17648
17649         }
17650
17651         function WebGLProgram( renderer, extensions, code, material, shader, parameters ) {
17652
17653                 var gl = renderer.context;
17654
17655                 var defines = material.defines;
17656
17657                 var vertexShader = shader.vertexShader;
17658                 var fragmentShader = shader.fragmentShader;
17659
17660                 var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
17661
17662                 if ( parameters.shadowMapType === PCFShadowMap ) {
17663
17664                         shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
17665
17666                 } else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
17667
17668                         shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
17669
17670                 }
17671
17672                 var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
17673                 var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
17674                 var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
17675
17676                 if ( parameters.envMap ) {
17677
17678                         switch ( material.envMap.mapping ) {
17679
17680                                 case CubeReflectionMapping:
17681                                 case CubeRefractionMapping:
17682                                         envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
17683                                         break;
17684
17685                                 case CubeUVReflectionMapping:
17686                                 case CubeUVRefractionMapping:
17687                                         envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
17688                                         break;
17689
17690                                 case EquirectangularReflectionMapping:
17691                                 case EquirectangularRefractionMapping:
17692                                         envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
17693                                         break;
17694
17695                                 case SphericalReflectionMapping:
17696                                         envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
17697                                         break;
17698
17699                         }
17700
17701                         switch ( material.envMap.mapping ) {
17702
17703                                 case CubeRefractionMapping:
17704                                 case EquirectangularRefractionMapping:
17705                                         envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
17706                                         break;
17707
17708                         }
17709
17710                         switch ( material.combine ) {
17711
17712                                 case MultiplyOperation:
17713                                         envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
17714                                         break;
17715
17716                                 case MixOperation:
17717                                         envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
17718                                         break;
17719
17720                                 case AddOperation:
17721                                         envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
17722                                         break;
17723
17724                         }
17725
17726                 }
17727
17728                 var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
17729
17730                 // console.log( 'building new program ' );
17731
17732                 //
17733
17734                 var customExtensions = generateExtensions( material.extensions, parameters, extensions );
17735
17736                 var customDefines = generateDefines( defines );
17737
17738                 //
17739
17740                 var program = gl.createProgram();
17741
17742                 var prefixVertex, prefixFragment;
17743
17744                 if ( material.isRawShaderMaterial ) {
17745
17746                         prefixVertex = [
17747
17748                                 customDefines,
17749
17750                                 '\n'
17751
17752                         ].filter( filterEmptyLine ).join( '\n' );
17753
17754                         prefixFragment = [
17755
17756                                 customExtensions,
17757                                 customDefines,
17758
17759                                 '\n'
17760
17761                         ].filter( filterEmptyLine ).join( '\n' );
17762
17763                 } else {
17764
17765                         prefixVertex = [
17766
17767                                 'precision ' + parameters.precision + ' float;',
17768                                 'precision ' + parameters.precision + ' int;',
17769
17770                                 '#define SHADER_NAME ' + shader.name,
17771
17772                                 customDefines,
17773
17774                                 parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
17775
17776                                 '#define GAMMA_FACTOR ' + gammaFactorDefine,
17777
17778                                 '#define MAX_BONES ' + parameters.maxBones,
17779                                 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
17780                                 ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
17781
17782                                 parameters.map ? '#define USE_MAP' : '',
17783                                 parameters.envMap ? '#define USE_ENVMAP' : '',
17784                                 parameters.envMap ? '#define ' + envMapModeDefine : '',
17785                                 parameters.lightMap ? '#define USE_LIGHTMAP' : '',
17786                                 parameters.aoMap ? '#define USE_AOMAP' : '',
17787                                 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
17788                                 parameters.bumpMap ? '#define USE_BUMPMAP' : '',
17789                                 parameters.normalMap ? '#define USE_NORMALMAP' : '',
17790                                 parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
17791                                 parameters.specularMap ? '#define USE_SPECULARMAP' : '',
17792                                 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
17793                                 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
17794                                 parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
17795                                 parameters.vertexColors ? '#define USE_COLOR' : '',
17796
17797                                 parameters.flatShading ? '#define FLAT_SHADED' : '',
17798
17799                                 parameters.skinning ? '#define USE_SKINNING' : '',
17800                                 parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
17801
17802                                 parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
17803                                 parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
17804                                 parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
17805                                 parameters.flipSided ? '#define FLIP_SIDED' : '',
17806
17807                                 '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes,
17808
17809                                 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
17810                                 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
17811
17812                                 parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
17813
17814                                 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
17815                                 parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
17816
17817                                 'uniform mat4 modelMatrix;',
17818                                 'uniform mat4 modelViewMatrix;',
17819                                 'uniform mat4 projectionMatrix;',
17820                                 'uniform mat4 viewMatrix;',
17821                                 'uniform mat3 normalMatrix;',
17822                                 'uniform vec3 cameraPosition;',
17823
17824                                 'attribute vec3 position;',
17825                                 'attribute vec3 normal;',
17826                                 'attribute vec2 uv;',
17827
17828                                 '#ifdef USE_COLOR',
17829
17830                                 '       attribute vec3 color;',
17831
17832                                 '#endif',
17833
17834                                 '#ifdef USE_MORPHTARGETS',
17835
17836                                 '       attribute vec3 morphTarget0;',
17837                                 '       attribute vec3 morphTarget1;',
17838                                 '       attribute vec3 morphTarget2;',
17839                                 '       attribute vec3 morphTarget3;',
17840
17841                                 '       #ifdef USE_MORPHNORMALS',
17842
17843                                 '               attribute vec3 morphNormal0;',
17844                                 '               attribute vec3 morphNormal1;',
17845                                 '               attribute vec3 morphNormal2;',
17846                                 '               attribute vec3 morphNormal3;',
17847
17848                                 '       #else',
17849
17850                                 '               attribute vec3 morphTarget4;',
17851                                 '               attribute vec3 morphTarget5;',
17852                                 '               attribute vec3 morphTarget6;',
17853                                 '               attribute vec3 morphTarget7;',
17854
17855                                 '       #endif',
17856
17857                                 '#endif',
17858
17859                                 '#ifdef USE_SKINNING',
17860
17861                                 '       attribute vec4 skinIndex;',
17862                                 '       attribute vec4 skinWeight;',
17863
17864                                 '#endif',
17865
17866                                 '\n'
17867
17868                         ].filter( filterEmptyLine ).join( '\n' );
17869
17870                         prefixFragment = [
17871
17872                                 customExtensions,
17873
17874                                 'precision ' + parameters.precision + ' float;',
17875                                 'precision ' + parameters.precision + ' int;',
17876
17877                                 '#define SHADER_NAME ' + shader.name,
17878
17879                                 customDefines,
17880
17881                                 parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '',
17882
17883                                 '#define GAMMA_FACTOR ' + gammaFactorDefine,
17884
17885                                 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
17886                                 ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
17887
17888                                 parameters.map ? '#define USE_MAP' : '',
17889                                 parameters.envMap ? '#define USE_ENVMAP' : '',
17890                                 parameters.envMap ? '#define ' + envMapTypeDefine : '',
17891                                 parameters.envMap ? '#define ' + envMapModeDefine : '',
17892                                 parameters.envMap ? '#define ' + envMapBlendingDefine : '',
17893                                 parameters.lightMap ? '#define USE_LIGHTMAP' : '',
17894                                 parameters.aoMap ? '#define USE_AOMAP' : '',
17895                                 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
17896                                 parameters.bumpMap ? '#define USE_BUMPMAP' : '',
17897                                 parameters.normalMap ? '#define USE_NORMALMAP' : '',
17898                                 parameters.specularMap ? '#define USE_SPECULARMAP' : '',
17899                                 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
17900                                 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
17901                                 parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
17902                                 parameters.vertexColors ? '#define USE_COLOR' : '',
17903
17904                                 parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
17905
17906                                 parameters.flatShading ? '#define FLAT_SHADED' : '',
17907
17908                                 parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
17909                                 parameters.flipSided ? '#define FLIP_SIDED' : '',
17910
17911                                 '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes,
17912                                 '#define UNION_CLIPPING_PLANES ' + (parameters.numClippingPlanes - parameters.numClipIntersection),
17913
17914                                 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
17915                                 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
17916
17917                                 parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : '',
17918
17919                                 parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : '',
17920
17921                                 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
17922                                 parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
17923
17924                                 parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
17925
17926                                 'uniform mat4 viewMatrix;',
17927                                 'uniform vec3 cameraPosition;',
17928
17929                                 ( parameters.toneMapping !== NoToneMapping ) ? "#define TONE_MAPPING" : '',
17930                                 ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '',  // this code is required here because it is used by the toneMapping() function defined below
17931                                 ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( "toneMapping", parameters.toneMapping ) : '',
17932
17933                                 parameters.dithering ? '#define DITHERING' : '',
17934
17935                                 ( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
17936                                 parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
17937                                 parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
17938                                 parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
17939                                 parameters.outputEncoding ? getTexelEncodingFunction( "linearToOutputTexel", parameters.outputEncoding ) : '',
17940
17941                                 parameters.depthPacking ? "#define DEPTH_PACKING " + material.depthPacking : '',
17942
17943                                 '\n'
17944
17945                         ].filter( filterEmptyLine ).join( '\n' );
17946
17947                 }
17948
17949                 vertexShader = parseIncludes( vertexShader );
17950                 vertexShader = replaceLightNums( vertexShader, parameters );
17951
17952                 fragmentShader = parseIncludes( fragmentShader );
17953                 fragmentShader = replaceLightNums( fragmentShader, parameters );
17954
17955                 if ( ! material.isShaderMaterial ) {
17956
17957                         vertexShader = unrollLoops( vertexShader );
17958                         fragmentShader = unrollLoops( fragmentShader );
17959
17960                 }
17961
17962                 var vertexGlsl = prefixVertex + vertexShader;
17963                 var fragmentGlsl = prefixFragment + fragmentShader;
17964
17965                 // console.log( '*VERTEX*', vertexGlsl );
17966                 // console.log( '*FRAGMENT*', fragmentGlsl );
17967
17968                 var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
17969                 var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
17970
17971                 gl.attachShader( program, glVertexShader );
17972                 gl.attachShader( program, glFragmentShader );
17973
17974                 // Force a particular attribute to index 0.
17975
17976                 if ( material.index0AttributeName !== undefined ) {
17977
17978                         gl.bindAttribLocation( program, 0, material.index0AttributeName );
17979
17980                 } else if ( parameters.morphTargets === true ) {
17981
17982                         // programs with morphTargets displace position out of attribute 0
17983                         gl.bindAttribLocation( program, 0, 'position' );
17984
17985                 }
17986
17987                 gl.linkProgram( program );
17988
17989                 var programLog = gl.getProgramInfoLog( program );
17990                 var vertexLog = gl.getShaderInfoLog( glVertexShader );
17991                 var fragmentLog = gl.getShaderInfoLog( glFragmentShader );
17992
17993                 var runnable = true;
17994                 var haveDiagnostics = true;
17995
17996                 // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
17997                 // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
17998
17999                 if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
18000
18001                         runnable = false;
18002
18003                         console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );
18004
18005                 } else if ( programLog !== '' ) {
18006
18007                         console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
18008
18009                 } else if ( vertexLog === '' || fragmentLog === '' ) {
18010
18011                         haveDiagnostics = false;
18012
18013                 }
18014
18015                 if ( haveDiagnostics ) {
18016
18017                         this.diagnostics = {
18018
18019                                 runnable: runnable,
18020                                 material: material,
18021
18022                                 programLog: programLog,
18023
18024                                 vertexShader: {
18025
18026                                         log: vertexLog,
18027                                         prefix: prefixVertex
18028
18029                                 },
18030
18031                                 fragmentShader: {
18032
18033                                         log: fragmentLog,
18034                                         prefix: prefixFragment
18035
18036                                 }
18037
18038                         };
18039
18040                 }
18041
18042                 // clean up
18043
18044                 gl.deleteShader( glVertexShader );
18045                 gl.deleteShader( glFragmentShader );
18046
18047                 // set up caching for uniform locations
18048
18049                 var cachedUniforms;
18050
18051                 this.getUniforms = function () {
18052
18053                         if ( cachedUniforms === undefined ) {
18054
18055                                 cachedUniforms = new WebGLUniforms( gl, program, renderer );
18056
18057                         }
18058
18059                         return cachedUniforms;
18060
18061                 };
18062
18063                 // set up caching for attribute locations
18064
18065                 var cachedAttributes;
18066
18067                 this.getAttributes = function () {
18068
18069                         if ( cachedAttributes === undefined ) {
18070
18071                                 cachedAttributes = fetchAttributeLocations( gl, program );
18072
18073                         }
18074
18075                         return cachedAttributes;
18076
18077                 };
18078
18079                 // free resource
18080
18081                 this.destroy = function() {
18082
18083                         gl.deleteProgram( program );
18084                         this.program = undefined;
18085
18086                 };
18087
18088                 // DEPRECATED
18089
18090                 Object.defineProperties( this, {
18091
18092                         uniforms: {
18093                                 get: function() {
18094
18095                                         console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
18096                                         return this.getUniforms();
18097
18098                                 }
18099                         },
18100
18101                         attributes: {
18102                                 get: function() {
18103
18104                                         console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
18105                                         return this.getAttributes();
18106
18107                                 }
18108                         }
18109
18110                 } );
18111
18112
18113                 //
18114
18115                 this.id = programIdCount ++;
18116                 this.code = code;
18117                 this.usedTimes = 1;
18118                 this.program = program;
18119                 this.vertexShader = glVertexShader;
18120                 this.fragmentShader = glFragmentShader;
18121
18122                 return this;
18123
18124         }
18125
18126         /**
18127          * @author mrdoob / http://mrdoob.com/
18128          */
18129
18130         function WebGLPrograms( renderer, extensions, capabilities ) {
18131
18132                 var programs = [];
18133
18134                 var shaderIDs = {
18135                         MeshDepthMaterial: 'depth',
18136                         MeshDistanceMaterial: 'distanceRGBA',
18137                         MeshNormalMaterial: 'normal',
18138                         MeshBasicMaterial: 'basic',
18139                         MeshLambertMaterial: 'lambert',
18140                         MeshPhongMaterial: 'phong',
18141                         MeshToonMaterial: 'phong',
18142                         MeshStandardMaterial: 'physical',
18143                         MeshPhysicalMaterial: 'physical',
18144                         LineBasicMaterial: 'basic',
18145                         LineDashedMaterial: 'dashed',
18146                         PointsMaterial: 'points',
18147                         ShadowMaterial: 'shadow'
18148                 };
18149
18150                 var parameterNames = [
18151                         "precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding",
18152                         "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap",
18153                         "roughnessMap", "metalnessMap", "gradientMap",
18154                         "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
18155                         "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
18156                         "maxBones", "useVertexTexture", "morphTargets", "morphNormals",
18157                         "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
18158                         "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
18159                         "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
18160                         "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering"
18161                 ];
18162
18163
18164                 function allocateBones( object ) {
18165
18166                         var skeleton = object.skeleton;
18167                         var bones = skeleton.bones;
18168
18169                         if ( capabilities.floatVertexTextures ) {
18170
18171                                 return 1024;
18172
18173                         } else {
18174
18175                                 // default for when object is not specified
18176                                 // ( for example when prebuilding shader to be used with multiple objects )
18177                                 //
18178                                 //  - leave some extra space for other uniforms
18179                                 //  - limit here is ANGLE's 254 max uniform vectors
18180                                 //    (up to 54 should be safe)
18181
18182                                 var nVertexUniforms = capabilities.maxVertexUniforms;
18183                                 var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
18184
18185                                 var maxBones = Math.min( nVertexMatrices, bones.length );
18186
18187                                 if ( maxBones < bones.length ) {
18188
18189                                         console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
18190                                         return 0;
18191
18192                                 }
18193
18194                                 return maxBones;
18195
18196                         }
18197
18198                 }
18199
18200                 function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
18201
18202                         var encoding;
18203
18204                         if ( ! map ) {
18205
18206                                 encoding = LinearEncoding;
18207
18208                         } else if ( map.isTexture ) {
18209
18210                                 encoding = map.encoding;
18211
18212                         } else if ( map.isWebGLRenderTarget ) {
18213
18214                                 console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
18215                                 encoding = map.texture.encoding;
18216
18217                         }
18218
18219                         // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.
18220                         if ( encoding === LinearEncoding && gammaOverrideLinear ) {
18221
18222                                 encoding = GammaEncoding;
18223
18224                         }
18225
18226                         return encoding;
18227
18228                 }
18229
18230                 this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) {
18231
18232                         var shaderID = shaderIDs[ material.type ];
18233
18234                         // heuristics to create shader parameters according to lights in the scene
18235                         // (not to blow over maxLights budget)
18236
18237                         var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
18238                         var precision = capabilities.precision;
18239
18240                         if ( material.precision !== null ) {
18241
18242                                 precision = capabilities.getMaxPrecision( material.precision );
18243
18244                                 if ( precision !== material.precision ) {
18245
18246                                         console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
18247
18248                                 }
18249
18250                         }
18251
18252                         var currentRenderTarget = renderer.getRenderTarget();
18253
18254                         var parameters = {
18255
18256                                 shaderID: shaderID,
18257
18258                                 precision: precision,
18259                                 supportsVertexTextures: capabilities.vertexTextures,
18260                                 outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
18261                                 map: !! material.map,
18262                                 mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
18263                                 envMap: !! material.envMap,
18264                                 envMapMode: material.envMap && material.envMap.mapping,
18265                                 envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
18266                                 envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),
18267                                 lightMap: !! material.lightMap,
18268                                 aoMap: !! material.aoMap,
18269                                 emissiveMap: !! material.emissiveMap,
18270                                 emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
18271                                 bumpMap: !! material.bumpMap,
18272                                 normalMap: !! material.normalMap,
18273                                 displacementMap: !! material.displacementMap,
18274                                 roughnessMap: !! material.roughnessMap,
18275                                 metalnessMap: !! material.metalnessMap,
18276                                 specularMap: !! material.specularMap,
18277                                 alphaMap: !! material.alphaMap,
18278
18279                                 gradientMap: !! material.gradientMap,
18280
18281                                 combine: material.combine,
18282
18283                                 vertexColors: material.vertexColors,
18284
18285                                 fog: !! fog,
18286                                 useFog: material.fog,
18287                                 fogExp: ( fog && fog.isFogExp2 ),
18288
18289                                 flatShading: material.flatShading,
18290
18291                                 sizeAttenuation: material.sizeAttenuation,
18292                                 logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
18293
18294                                 skinning: material.skinning && maxBones > 0,
18295                                 maxBones: maxBones,
18296                                 useVertexTexture: capabilities.floatVertexTextures,
18297
18298                                 morphTargets: material.morphTargets,
18299                                 morphNormals: material.morphNormals,
18300                                 maxMorphTargets: renderer.maxMorphTargets,
18301                                 maxMorphNormals: renderer.maxMorphNormals,
18302
18303                                 numDirLights: lights.directional.length,
18304                                 numPointLights: lights.point.length,
18305                                 numSpotLights: lights.spot.length,
18306                                 numRectAreaLights: lights.rectArea.length,
18307                                 numHemiLights: lights.hemi.length,
18308
18309                                 numClippingPlanes: nClipPlanes,
18310                                 numClipIntersection: nClipIntersection,
18311
18312                                 dithering: material.dithering,
18313
18314                                 shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0,
18315                                 shadowMapType: renderer.shadowMap.type,
18316
18317                                 toneMapping: renderer.toneMapping,
18318                                 physicallyCorrectLights: renderer.physicallyCorrectLights,
18319
18320                                 premultipliedAlpha: material.premultipliedAlpha,
18321
18322                                 alphaTest: material.alphaTest,
18323                                 doubleSided: material.side === DoubleSide,
18324                                 flipSided: material.side === BackSide,
18325
18326                                 depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
18327
18328                         };
18329
18330                         return parameters;
18331
18332                 };
18333
18334                 this.getProgramCode = function ( material, parameters ) {
18335
18336                         var array = [];
18337
18338                         if ( parameters.shaderID ) {
18339
18340                                 array.push( parameters.shaderID );
18341
18342                         } else {
18343
18344                                 array.push( material.fragmentShader );
18345                                 array.push( material.vertexShader );
18346
18347                         }
18348
18349                         if ( material.defines !== undefined ) {
18350
18351                                 for ( var name in material.defines ) {
18352
18353                                         array.push( name );
18354                                         array.push( material.defines[ name ] );
18355
18356                                 }
18357
18358                         }
18359
18360                         for ( var i = 0; i < parameterNames.length; i ++ ) {
18361
18362                                 array.push( parameters[ parameterNames[ i ] ] );
18363
18364                         }
18365
18366                         array.push( material.onBeforeCompile.toString() );
18367
18368                         array.push( renderer.gammaOutput );
18369
18370                         return array.join();
18371
18372                 };
18373
18374                 this.acquireProgram = function ( material, shader, parameters, code ) {
18375
18376                         var program;
18377
18378                         // Check if code has been already compiled
18379                         for ( var p = 0, pl = programs.length; p < pl; p ++ ) {
18380
18381                                 var programInfo = programs[ p ];
18382
18383                                 if ( programInfo.code === code ) {
18384
18385                                         program = programInfo;
18386                                         ++ program.usedTimes;
18387
18388                                         break;
18389
18390                                 }
18391
18392                         }
18393
18394                         if ( program === undefined ) {
18395
18396                                 program = new WebGLProgram( renderer, extensions, code, material, shader, parameters );
18397                                 programs.push( program );
18398
18399                         }
18400
18401                         return program;
18402
18403                 };
18404
18405                 this.releaseProgram = function ( program ) {
18406
18407                         if ( -- program.usedTimes === 0 ) {
18408
18409                                 // Remove from unordered set
18410                                 var i = programs.indexOf( program );
18411                                 programs[ i ] = programs[ programs.length - 1 ];
18412                                 programs.pop();
18413
18414                                 // Free WebGL resources
18415                                 program.destroy();
18416
18417                         }
18418
18419                 };
18420
18421                 // Exposed for resource monitoring & error feedback via renderer.info:
18422                 this.programs = programs;
18423
18424         }
18425
18426         /**
18427          * @author mrdoob / http://mrdoob.com/
18428          */
18429
18430         function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, infoMemory ) {
18431
18432                 var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext );
18433
18434                 //
18435
18436                 function clampToMaxSize( image, maxSize ) {
18437
18438                         if ( image.width > maxSize || image.height > maxSize ) {
18439
18440                                 // Warning: Scaling through the canvas will only work with images that use
18441                                 // premultiplied alpha.
18442
18443                                 var scale = maxSize / Math.max( image.width, image.height );
18444
18445                                 var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
18446                                 canvas.width = Math.floor( image.width * scale );
18447                                 canvas.height = Math.floor( image.height * scale );
18448
18449                                 var context = canvas.getContext( '2d' );
18450                                 context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
18451
18452                                 console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
18453
18454                                 return canvas;
18455
18456                         }
18457
18458                         return image;
18459
18460                 }
18461
18462                 function isPowerOfTwo( image ) {
18463
18464                         return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height );
18465
18466                 }
18467
18468                 function makePowerOfTwo( image ) {
18469
18470                         if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement ) {
18471
18472                                 var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
18473                                 canvas.width = _Math.nearestPowerOfTwo( image.width );
18474                                 canvas.height = _Math.nearestPowerOfTwo( image.height );
18475
18476                                 var context = canvas.getContext( '2d' );
18477                                 context.drawImage( image, 0, 0, canvas.width, canvas.height );
18478
18479                                 console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
18480
18481                                 return canvas;
18482
18483                         }
18484
18485                         return image;
18486
18487                 }
18488
18489                 function textureNeedsPowerOfTwo( texture ) {
18490
18491                         return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
18492                                 ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
18493
18494                 }
18495
18496                 function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) {
18497
18498                         return texture.generateMipmaps && isPowerOfTwo &&
18499                                 texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
18500
18501                 }
18502
18503                 // Fallback filters for non-power-of-2 textures
18504
18505                 function filterFallback( f ) {
18506
18507                         if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) {
18508
18509                                 return _gl.NEAREST;
18510
18511                         }
18512
18513                         return _gl.LINEAR;
18514
18515                 }
18516
18517                 //
18518
18519                 function onTextureDispose( event ) {
18520
18521                         var texture = event.target;
18522
18523                         texture.removeEventListener( 'dispose', onTextureDispose );
18524
18525                         deallocateTexture( texture );
18526
18527                         infoMemory.textures --;
18528
18529
18530                 }
18531
18532                 function onRenderTargetDispose( event ) {
18533
18534                         var renderTarget = event.target;
18535
18536                         renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
18537
18538                         deallocateRenderTarget( renderTarget );
18539
18540                         infoMemory.textures --;
18541
18542                 }
18543
18544                 //
18545
18546                 function deallocateTexture( texture ) {
18547
18548                         var textureProperties = properties.get( texture );
18549
18550                         if ( texture.image && textureProperties.__image__webglTextureCube ) {
18551
18552                                 // cube texture
18553
18554                                 _gl.deleteTexture( textureProperties.__image__webglTextureCube );
18555
18556                         } else {
18557
18558                                 // 2D texture
18559
18560                                 if ( textureProperties.__webglInit === undefined ) return;
18561
18562                                 _gl.deleteTexture( textureProperties.__webglTexture );
18563
18564                         }
18565
18566                         // remove all webgl properties
18567                         properties.remove( texture );
18568
18569                 }
18570
18571                 function deallocateRenderTarget( renderTarget ) {
18572
18573                         var renderTargetProperties = properties.get( renderTarget );
18574                         var textureProperties = properties.get( renderTarget.texture );
18575
18576                         if ( ! renderTarget ) return;
18577
18578                         if ( textureProperties.__webglTexture !== undefined ) {
18579
18580                                 _gl.deleteTexture( textureProperties.__webglTexture );
18581
18582                         }
18583
18584                         if ( renderTarget.depthTexture ) {
18585
18586                                 renderTarget.depthTexture.dispose();
18587
18588                         }
18589
18590                         if ( renderTarget.isWebGLRenderTargetCube ) {
18591
18592                                 for ( var i = 0; i < 6; i ++ ) {
18593
18594                                         _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
18595                                         if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
18596
18597                                 }
18598
18599                         } else {
18600
18601                                 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
18602                                 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
18603
18604                         }
18605
18606                         properties.remove( renderTarget.texture );
18607                         properties.remove( renderTarget );
18608
18609                 }
18610
18611                 //
18612
18613
18614
18615                 function setTexture2D( texture, slot ) {
18616
18617                         var textureProperties = properties.get( texture );
18618
18619                         if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
18620
18621                                 var image = texture.image;
18622
18623                                 if ( image === undefined ) {
18624
18625                                         console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
18626
18627                                 } else if ( image.complete === false ) {
18628
18629                                         console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
18630
18631                                 } else {
18632
18633                                         uploadTexture( textureProperties, texture, slot );
18634                                         return;
18635
18636                                 }
18637
18638                         }
18639
18640                         state.activeTexture( _gl.TEXTURE0 + slot );
18641                         state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
18642
18643                 }
18644
18645                 function setTextureCube( texture, slot ) {
18646
18647                         var textureProperties = properties.get( texture );
18648
18649                         if ( texture.image.length === 6 ) {
18650
18651                                 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
18652
18653                                         if ( ! textureProperties.__image__webglTextureCube ) {
18654
18655                                                 texture.addEventListener( 'dispose', onTextureDispose );
18656
18657                                                 textureProperties.__image__webglTextureCube = _gl.createTexture();
18658
18659                                                 infoMemory.textures ++;
18660
18661                                         }
18662
18663                                         state.activeTexture( _gl.TEXTURE0 + slot );
18664                                         state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
18665
18666                                         _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
18667
18668                                         var isCompressed = ( texture && texture.isCompressedTexture );
18669                                         var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
18670
18671                                         var cubeImage = [];
18672
18673                                         for ( var i = 0; i < 6; i ++ ) {
18674
18675                                                 if ( ! isCompressed && ! isDataTexture ) {
18676
18677                                                         cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize );
18678
18679                                                 } else {
18680
18681                                                         cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
18682
18683                                                 }
18684
18685                                         }
18686
18687                                         var image = cubeImage[ 0 ],
18688                                         isPowerOfTwoImage = isPowerOfTwo( image ),
18689                                         glFormat = utils.convert( texture.format ),
18690                                         glType = utils.convert( texture.type );
18691
18692                                         setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
18693
18694                                         for ( var i = 0; i < 6; i ++ ) {
18695
18696                                                 if ( ! isCompressed ) {
18697
18698                                                         if ( isDataTexture ) {
18699
18700                                                                 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
18701
18702                                                         } else {
18703
18704                                                                 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
18705
18706                                                         }
18707
18708                                                 } else {
18709
18710                                                         var mipmap, mipmaps = cubeImage[ i ].mipmaps;
18711
18712                                                         for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
18713
18714                                                                 mipmap = mipmaps[ j ];
18715
18716                                                                 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
18717
18718                                                                         if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
18719
18720                                                                                 state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
18721
18722                                                                         } else {
18723
18724                                                                                 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
18725
18726                                                                         }
18727
18728                                                                 } else {
18729
18730                                                                         state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
18731
18732                                                                 }
18733
18734                                                         }
18735
18736                                                 }
18737
18738                                         }
18739
18740                                         if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
18741
18742                                                 _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
18743
18744                                         }
18745
18746                                         textureProperties.__version = texture.version;
18747
18748                                         if ( texture.onUpdate ) texture.onUpdate( texture );
18749
18750                                 } else {
18751
18752                                         state.activeTexture( _gl.TEXTURE0 + slot );
18753                                         state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
18754
18755                                 }
18756
18757                         }
18758
18759                 }
18760
18761                 function setTextureCubeDynamic( texture, slot ) {
18762
18763                         state.activeTexture( _gl.TEXTURE0 + slot );
18764                         state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );
18765
18766                 }
18767
18768                 function setTextureParameters( textureType, texture, isPowerOfTwoImage ) {
18769
18770                         var extension;
18771
18772                         if ( isPowerOfTwoImage ) {
18773
18774                                 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) );
18775                                 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) );
18776
18777                                 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) );
18778                                 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) );
18779
18780                         } else {
18781
18782                                 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
18783                                 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
18784
18785                                 if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
18786
18787                                         console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture );
18788
18789                                 }
18790
18791                                 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
18792                                 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
18793
18794                                 if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
18795
18796                                         console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture );
18797
18798                                 }
18799
18800                         }
18801
18802                         extension = extensions.get( 'EXT_texture_filter_anisotropic' );
18803
18804                         if ( extension ) {
18805
18806                                 if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
18807                                 if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
18808
18809                                 if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
18810
18811                                         _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
18812                                         properties.get( texture ).__currentAnisotropy = texture.anisotropy;
18813
18814                                 }
18815
18816                         }
18817
18818                 }
18819
18820                 function uploadTexture( textureProperties, texture, slot ) {
18821
18822                         if ( textureProperties.__webglInit === undefined ) {
18823
18824                                 textureProperties.__webglInit = true;
18825
18826                                 texture.addEventListener( 'dispose', onTextureDispose );
18827
18828                                 textureProperties.__webglTexture = _gl.createTexture();
18829
18830                                 infoMemory.textures ++;
18831
18832                         }
18833
18834                         state.activeTexture( _gl.TEXTURE0 + slot );
18835                         state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
18836
18837                         _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
18838                         _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
18839                         _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
18840
18841                         var image = clampToMaxSize( texture.image, capabilities.maxTextureSize );
18842
18843                         if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) {
18844
18845                                 image = makePowerOfTwo( image );
18846
18847                         }
18848
18849                         var isPowerOfTwoImage = isPowerOfTwo( image ),
18850                         glFormat = utils.convert( texture.format ),
18851                         glType = utils.convert( texture.type );
18852
18853                         setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
18854
18855                         var mipmap, mipmaps = texture.mipmaps;
18856
18857                         if ( texture.isDepthTexture ) {
18858
18859                                 // populate depth texture with dummy data
18860
18861                                 var internalFormat = _gl.DEPTH_COMPONENT;
18862
18863                                 if ( texture.type === FloatType ) {
18864
18865                                         if ( !_isWebGL2 ) throw new Error('Float Depth Texture only supported in WebGL2.0');
18866                                         internalFormat = _gl.DEPTH_COMPONENT32F;
18867
18868                                 } else if ( _isWebGL2 ) {
18869
18870                                         // WebGL 2.0 requires signed internalformat for glTexImage2D
18871                                         internalFormat = _gl.DEPTH_COMPONENT16;
18872
18873                                 }
18874
18875                                 if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) {
18876
18877                                         // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
18878                                         // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
18879                                         // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
18880                                         if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
18881
18882                                                 console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
18883
18884                                                 texture.type = UnsignedShortType;
18885                                                 glType = utils.convert( texture.type );
18886
18887                                         }
18888
18889                                 }
18890
18891                                 // Depth stencil textures need the DEPTH_STENCIL internal format
18892                                 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
18893                                 if ( texture.format === DepthStencilFormat ) {
18894
18895                                         internalFormat = _gl.DEPTH_STENCIL;
18896
18897                                         // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
18898                                         // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
18899                                         // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
18900                                         if ( texture.type !== UnsignedInt248Type ) {
18901
18902                                                 console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
18903
18904                                                 texture.type = UnsignedInt248Type;
18905                                                 glType = utils.convert( texture.type );
18906
18907                                         }
18908
18909                                 }
18910
18911                                 state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null );
18912
18913                         } else if ( texture.isDataTexture ) {
18914
18915                                 // use manually created mipmaps if available
18916                                 // if there are no manual mipmaps
18917                                 // set 0 level mipmap and then use GL to generate other mipmap levels
18918
18919                                 if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
18920
18921                                         for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
18922
18923                                                 mipmap = mipmaps[ i ];
18924                                                 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
18925
18926                                         }
18927
18928                                         texture.generateMipmaps = false;
18929
18930                                 } else {
18931
18932                                         state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
18933
18934                                 }
18935
18936                         } else if ( texture.isCompressedTexture ) {
18937
18938                                 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
18939
18940                                         mipmap = mipmaps[ i ];
18941
18942                                         if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
18943
18944                                                 if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
18945
18946                                                         state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
18947
18948                                                 } else {
18949
18950                                                         console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
18951
18952                                                 }
18953
18954                                         } else {
18955
18956                                                 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
18957
18958                                         }
18959
18960                                 }
18961
18962                         } else {
18963
18964                                 // regular Texture (image, video, canvas)
18965
18966                                 // use manually created mipmaps if available
18967                                 // if there are no manual mipmaps
18968                                 // set 0 level mipmap and then use GL to generate other mipmap levels
18969
18970                                 if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
18971
18972                                         for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
18973
18974                                                 mipmap = mipmaps[ i ];
18975                                                 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
18976
18977                                         }
18978
18979                                         texture.generateMipmaps = false;
18980
18981                                 } else {
18982
18983                                         state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
18984
18985                                 }
18986
18987                         }
18988
18989                         if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) _gl.generateMipmap( _gl.TEXTURE_2D );
18990
18991                         textureProperties.__version = texture.version;
18992
18993                         if ( texture.onUpdate ) texture.onUpdate( texture );
18994
18995                 }
18996
18997                 // Render targets
18998
18999                 // Setup storage for target texture and bind it to correct framebuffer
19000                 function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
19001
19002                         var glFormat = utils.convert( renderTarget.texture.format );
19003                         var glType = utils.convert( renderTarget.texture.type );
19004                         state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
19005                         _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
19006                         _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
19007                         _gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
19008
19009                 }
19010
19011                 // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
19012                 function setupRenderBufferStorage( renderbuffer, renderTarget ) {
19013
19014                         _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
19015
19016                         if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
19017
19018                                 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
19019                                 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
19020
19021                         } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
19022
19023                                 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
19024                                 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
19025
19026                         } else {
19027
19028                                 // FIXME: We don't support !depth !stencil
19029                                 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
19030
19031                         }
19032
19033                         _gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
19034
19035                 }
19036
19037                 // Setup resources for a Depth Texture for a FBO (needs an extension)
19038                 function setupDepthTexture( framebuffer, renderTarget ) {
19039
19040                         var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );
19041                         if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
19042
19043                         _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
19044
19045                         if ( !( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
19046
19047                                 throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
19048
19049                         }
19050
19051                         // upload an empty depth texture with framebuffer size
19052                         if ( !properties.get( renderTarget.depthTexture ).__webglTexture ||
19053                                         renderTarget.depthTexture.image.width !== renderTarget.width ||
19054                                         renderTarget.depthTexture.image.height !== renderTarget.height ) {
19055                                 renderTarget.depthTexture.image.width = renderTarget.width;
19056                                 renderTarget.depthTexture.image.height = renderTarget.height;
19057                                 renderTarget.depthTexture.needsUpdate = true;
19058                         }
19059
19060                         setTexture2D( renderTarget.depthTexture, 0 );
19061
19062                         var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
19063
19064                         if ( renderTarget.depthTexture.format === DepthFormat ) {
19065
19066                                 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
19067
19068                         } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
19069
19070                                 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
19071
19072                         } else {
19073
19074                                 throw new Error( 'Unknown depthTexture format' );
19075
19076                         }
19077
19078                 }
19079
19080                 // Setup GL resources for a non-texture depth buffer
19081                 function setupDepthRenderbuffer( renderTarget ) {
19082
19083                         var renderTargetProperties = properties.get( renderTarget );
19084
19085                         var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
19086
19087                         if ( renderTarget.depthTexture ) {
19088
19089                                 if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
19090
19091                                 setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
19092
19093                         } else {
19094
19095                                 if ( isCube ) {
19096
19097                                         renderTargetProperties.__webglDepthbuffer = [];
19098
19099                                         for ( var i = 0; i < 6; i ++ ) {
19100
19101                                                 _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );
19102                                                 renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
19103                                                 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );
19104
19105                                         }
19106
19107                                 } else {
19108
19109                                         _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
19110                                         renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
19111                                         setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );
19112
19113                                 }
19114
19115                         }
19116
19117                         _gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
19118
19119                 }
19120
19121                 // Set up GL resources for the render target
19122                 function setupRenderTarget( renderTarget ) {
19123
19124                         var renderTargetProperties = properties.get( renderTarget );
19125                         var textureProperties = properties.get( renderTarget.texture );
19126
19127                         renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
19128
19129                         textureProperties.__webglTexture = _gl.createTexture();
19130
19131                         infoMemory.textures ++;
19132
19133                         var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
19134                         var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
19135
19136                         // Setup framebuffer
19137
19138                         if ( isCube ) {
19139
19140                                 renderTargetProperties.__webglFramebuffer = [];
19141
19142                                 for ( var i = 0; i < 6; i ++ ) {
19143
19144                                         renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
19145
19146                                 }
19147
19148                         } else {
19149
19150                                 renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
19151
19152                         }
19153
19154                         // Setup color buffer
19155
19156                         if ( isCube ) {
19157
19158                                 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
19159                                 setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo );
19160
19161                                 for ( var i = 0; i < 6; i ++ ) {
19162
19163                                         setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
19164
19165                                 }
19166
19167                                 if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
19168                                 state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
19169
19170                         } else {
19171
19172                                 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
19173                                 setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo );
19174                                 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );
19175
19176                                 if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_2D );
19177                                 state.bindTexture( _gl.TEXTURE_2D, null );
19178
19179                         }
19180
19181                         // Setup depth and stencil buffers
19182
19183                         if ( renderTarget.depthBuffer ) {
19184
19185                                 setupDepthRenderbuffer( renderTarget );
19186
19187                         }
19188
19189                 }
19190
19191                 function updateRenderTargetMipmap( renderTarget ) {
19192
19193                         var texture = renderTarget.texture;
19194                         var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
19195
19196                         if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) {
19197
19198                                 var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
19199                                 var webglTexture = properties.get( texture ).__webglTexture;
19200
19201                                 state.bindTexture( target, webglTexture );
19202                                 _gl.generateMipmap( target );
19203                                 state.bindTexture( target, null );
19204
19205                         }
19206
19207                 }
19208
19209                 this.setTexture2D = setTexture2D;
19210                 this.setTextureCube = setTextureCube;
19211                 this.setTextureCubeDynamic = setTextureCubeDynamic;
19212                 this.setupRenderTarget = setupRenderTarget;
19213                 this.updateRenderTargetMipmap = updateRenderTargetMipmap;
19214
19215         }
19216
19217         /**
19218          * @author fordacious / fordacious.github.io
19219          */
19220
19221         function WebGLProperties() {
19222
19223                 var properties = {};
19224
19225                 function get( object ) {
19226
19227                         var uuid = object.uuid;
19228                         var map = properties[ uuid ];
19229
19230                         if ( map === undefined ) {
19231
19232                                 map = {};
19233                                 properties[ uuid ] = map;
19234
19235                         }
19236
19237                         return map;
19238
19239                 }
19240
19241                 function remove( object ) {
19242
19243                         delete properties[ object.uuid ];
19244
19245                 }
19246
19247                 function clear() {
19248
19249                         properties = {};
19250
19251                 }
19252
19253                 return {
19254                         get: get,
19255                         remove: remove,
19256                         clear: clear
19257                 };
19258
19259         }
19260
19261         /**
19262          * @author mrdoob / http://mrdoob.com/
19263          */
19264
19265         function WebGLState( gl, extensions, utils ) {
19266
19267                 function ColorBuffer() {
19268
19269                         var locked = false;
19270
19271                         var color = new Vector4();
19272                         var currentColorMask = null;
19273                         var currentColorClear = new Vector4( 0, 0, 0, 0 );
19274
19275                         return {
19276
19277                                 setMask: function ( colorMask ) {
19278
19279                                         if ( currentColorMask !== colorMask && ! locked ) {
19280
19281                                                 gl.colorMask( colorMask, colorMask, colorMask, colorMask );
19282                                                 currentColorMask = colorMask;
19283
19284                                         }
19285
19286                                 },
19287
19288                                 setLocked: function ( lock ) {
19289
19290                                         locked = lock;
19291
19292                                 },
19293
19294                                 setClear: function ( r, g, b, a, premultipliedAlpha ) {
19295
19296                                         if ( premultipliedAlpha === true ) {
19297
19298                                                 r *= a; g *= a; b *= a;
19299
19300                                         }
19301
19302                                         color.set( r, g, b, a );
19303
19304                                         if ( currentColorClear.equals( color ) === false ) {
19305
19306                                                 gl.clearColor( r, g, b, a );
19307                                                 currentColorClear.copy( color );
19308
19309                                         }
19310
19311                                 },
19312
19313                                 reset: function () {
19314
19315                                         locked = false;
19316
19317                                         currentColorMask = null;
19318                                         currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
19319
19320                                 }
19321
19322                         };
19323
19324                 }
19325
19326                 function DepthBuffer() {
19327
19328                         var locked = false;
19329
19330                         var currentDepthMask = null;
19331                         var currentDepthFunc = null;
19332                         var currentDepthClear = null;
19333
19334                         return {
19335
19336                                 setTest: function ( depthTest ) {
19337
19338                                         if ( depthTest ) {
19339
19340                                                 enable( gl.DEPTH_TEST );
19341
19342                                         } else {
19343
19344                                                 disable( gl.DEPTH_TEST );
19345
19346                                         }
19347
19348                                 },
19349
19350                                 setMask: function ( depthMask ) {
19351
19352                                         if ( currentDepthMask !== depthMask && ! locked ) {
19353
19354                                                 gl.depthMask( depthMask );
19355                                                 currentDepthMask = depthMask;
19356
19357                                         }
19358
19359                                 },
19360
19361                                 setFunc: function ( depthFunc ) {
19362
19363                                         if ( currentDepthFunc !== depthFunc ) {
19364
19365                                                 if ( depthFunc ) {
19366
19367                                                         switch ( depthFunc ) {
19368
19369                                                                 case NeverDepth:
19370
19371                                                                         gl.depthFunc( gl.NEVER );
19372                                                                         break;
19373
19374                                                                 case AlwaysDepth:
19375
19376                                                                         gl.depthFunc( gl.ALWAYS );
19377                                                                         break;
19378
19379                                                                 case LessDepth:
19380
19381                                                                         gl.depthFunc( gl.LESS );
19382                                                                         break;
19383
19384                                                                 case LessEqualDepth:
19385
19386                                                                         gl.depthFunc( gl.LEQUAL );
19387                                                                         break;
19388
19389                                                                 case EqualDepth:
19390
19391                                                                         gl.depthFunc( gl.EQUAL );
19392                                                                         break;
19393
19394                                                                 case GreaterEqualDepth:
19395
19396                                                                         gl.depthFunc( gl.GEQUAL );
19397                                                                         break;
19398
19399                                                                 case GreaterDepth:
19400
19401                                                                         gl.depthFunc( gl.GREATER );
19402                                                                         break;
19403
19404                                                                 case NotEqualDepth:
19405
19406                                                                         gl.depthFunc( gl.NOTEQUAL );
19407                                                                         break;
19408
19409                                                                 default:
19410
19411                                                                         gl.depthFunc( gl.LEQUAL );
19412
19413                                                         }
19414
19415                                                 } else {
19416
19417                                                         gl.depthFunc( gl.LEQUAL );
19418
19419                                                 }
19420
19421                                                 currentDepthFunc = depthFunc;
19422
19423                                         }
19424
19425                                 },
19426
19427                                 setLocked: function ( lock ) {
19428
19429                                         locked = lock;
19430
19431                                 },
19432
19433                                 setClear: function ( depth ) {
19434
19435                                         if ( currentDepthClear !== depth ) {
19436
19437                                                 gl.clearDepth( depth );
19438                                                 currentDepthClear = depth;
19439
19440                                         }
19441
19442                                 },
19443
19444                                 reset: function () {
19445
19446                                         locked = false;
19447
19448                                         currentDepthMask = null;
19449                                         currentDepthFunc = null;
19450                                         currentDepthClear = null;
19451
19452                                 }
19453
19454                         };
19455
19456                 }
19457
19458                 function StencilBuffer() {
19459
19460                         var locked = false;
19461
19462                         var currentStencilMask = null;
19463                         var currentStencilFunc = null;
19464                         var currentStencilRef = null;
19465                         var currentStencilFuncMask = null;
19466                         var currentStencilFail = null;
19467                         var currentStencilZFail = null;
19468                         var currentStencilZPass = null;
19469                         var currentStencilClear = null;
19470
19471                         return {
19472
19473                                 setTest: function ( stencilTest ) {
19474
19475                                         if ( stencilTest ) {
19476
19477                                                 enable( gl.STENCIL_TEST );
19478
19479                                         } else {
19480
19481                                                 disable( gl.STENCIL_TEST );
19482
19483                                         }
19484
19485                                 },
19486
19487                                 setMask: function ( stencilMask ) {
19488
19489                                         if ( currentStencilMask !== stencilMask && ! locked ) {
19490
19491                                                 gl.stencilMask( stencilMask );
19492                                                 currentStencilMask = stencilMask;
19493
19494                                         }
19495
19496                                 },
19497
19498                                 setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
19499
19500                                         if ( currentStencilFunc !== stencilFunc ||
19501                                              currentStencilRef  !== stencilRef  ||
19502                                              currentStencilFuncMask !== stencilMask ) {
19503
19504                                                 gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
19505
19506                                                 currentStencilFunc = stencilFunc;
19507                                                 currentStencilRef = stencilRef;
19508                                                 currentStencilFuncMask = stencilMask;
19509
19510                                         }
19511
19512                                 },
19513
19514                                 setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
19515
19516                                         if ( currentStencilFail  !== stencilFail        ||
19517                                              currentStencilZFail !== stencilZFail ||
19518                                              currentStencilZPass !== stencilZPass ) {
19519
19520                                                 gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
19521
19522                                                 currentStencilFail = stencilFail;
19523                                                 currentStencilZFail = stencilZFail;
19524                                                 currentStencilZPass = stencilZPass;
19525
19526                                         }
19527
19528                                 },
19529
19530                                 setLocked: function ( lock ) {
19531
19532                                         locked = lock;
19533
19534                                 },
19535
19536                                 setClear: function ( stencil ) {
19537
19538                                         if ( currentStencilClear !== stencil ) {
19539
19540                                                 gl.clearStencil( stencil );
19541                                                 currentStencilClear = stencil;
19542
19543                                         }
19544
19545                                 },
19546
19547                                 reset: function () {
19548
19549                                         locked = false;
19550
19551                                         currentStencilMask = null;
19552                                         currentStencilFunc = null;
19553                                         currentStencilRef = null;
19554                                         currentStencilFuncMask = null;
19555                                         currentStencilFail = null;
19556                                         currentStencilZFail = null;
19557                                         currentStencilZPass = null;
19558                                         currentStencilClear = null;
19559
19560                                 }
19561
19562                         };
19563
19564                 }
19565
19566                 //
19567
19568                 var colorBuffer = new ColorBuffer();
19569                 var depthBuffer = new DepthBuffer();
19570                 var stencilBuffer = new StencilBuffer();
19571
19572                 var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
19573                 var newAttributes = new Uint8Array( maxVertexAttributes );
19574                 var enabledAttributes = new Uint8Array( maxVertexAttributes );
19575                 var attributeDivisors = new Uint8Array( maxVertexAttributes );
19576
19577                 var capabilities = {};
19578
19579                 var compressedTextureFormats = null;
19580
19581                 var currentProgram = null;
19582
19583                 var currentBlending = null;
19584                 var currentBlendEquation = null;
19585                 var currentBlendSrc = null;
19586                 var currentBlendDst = null;
19587                 var currentBlendEquationAlpha = null;
19588                 var currentBlendSrcAlpha = null;
19589                 var currentBlendDstAlpha = null;
19590                 var currentPremultipledAlpha = false;
19591
19592                 var currentFlipSided = null;
19593                 var currentCullFace = null;
19594
19595                 var currentLineWidth = null;
19596
19597                 var currentPolygonOffsetFactor = null;
19598                 var currentPolygonOffsetUnits = null;
19599
19600                 var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );
19601
19602                 var version = parseFloat( /^WebGL\ ([0-9])/.exec( gl.getParameter( gl.VERSION ) )[ 1 ] );
19603                 var lineWidthAvailable = parseFloat( version ) >= 1.0;
19604
19605                 var currentTextureSlot = null;
19606                 var currentBoundTextures = {};
19607
19608                 var currentScissor = new Vector4();
19609                 var currentViewport = new Vector4();
19610
19611                 function createTexture( type, target, count ) {
19612
19613                         var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
19614                         var texture = gl.createTexture();
19615
19616                         gl.bindTexture( type, texture );
19617                         gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
19618                         gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
19619
19620                         for ( var i = 0; i < count; i ++ ) {
19621
19622                                 gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
19623
19624                         }
19625
19626                         return texture;
19627
19628                 }
19629
19630                 var emptyTextures = {};
19631                 emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );
19632                 emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );
19633
19634                 // init
19635
19636                 colorBuffer.setClear( 0, 0, 0, 1 );
19637                 depthBuffer.setClear( 1 );
19638                 stencilBuffer.setClear( 0 );
19639
19640                 enable( gl.DEPTH_TEST );
19641                 depthBuffer.setFunc( LessEqualDepth );
19642
19643                 setFlipSided( false );
19644                 setCullFace( CullFaceBack );
19645                 enable( gl.CULL_FACE );
19646
19647                 enable( gl.BLEND );
19648                 setBlending( NormalBlending );
19649
19650                 //
19651
19652                 function initAttributes() {
19653
19654                         for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
19655
19656                                 newAttributes[ i ] = 0;
19657
19658                         }
19659
19660                 }
19661
19662                 function enableAttribute( attribute ) {
19663
19664                         newAttributes[ attribute ] = 1;
19665
19666                         if ( enabledAttributes[ attribute ] === 0 ) {
19667
19668                                 gl.enableVertexAttribArray( attribute );
19669                                 enabledAttributes[ attribute ] = 1;
19670
19671                         }
19672
19673                         if ( attributeDivisors[ attribute ] !== 0 ) {
19674
19675                                 var extension = extensions.get( 'ANGLE_instanced_arrays' );
19676
19677                                 extension.vertexAttribDivisorANGLE( attribute, 0 );
19678                                 attributeDivisors[ attribute ] = 0;
19679
19680                         }
19681
19682                 }
19683
19684                 function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
19685
19686                         newAttributes[ attribute ] = 1;
19687
19688                         if ( enabledAttributes[ attribute ] === 0 ) {
19689
19690                                 gl.enableVertexAttribArray( attribute );
19691                                 enabledAttributes[ attribute ] = 1;
19692
19693                         }
19694
19695                         if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
19696
19697                                 var extension = extensions.get( 'ANGLE_instanced_arrays' );
19698
19699                                 extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
19700                                 attributeDivisors[ attribute ] = meshPerAttribute;
19701
19702                         }
19703
19704                 }
19705
19706                 function disableUnusedAttributes() {
19707
19708                         for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {
19709
19710                                 if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
19711
19712                                         gl.disableVertexAttribArray( i );
19713                                         enabledAttributes[ i ] = 0;
19714
19715                                 }
19716
19717                         }
19718
19719                 }
19720
19721                 function enable( id ) {
19722
19723                         if ( capabilities[ id ] !== true ) {
19724
19725                                 gl.enable( id );
19726                                 capabilities[ id ] = true;
19727
19728                         }
19729
19730                 }
19731
19732                 function disable( id ) {
19733
19734                         if ( capabilities[ id ] !== false ) {
19735
19736                                 gl.disable( id );
19737                                 capabilities[ id ] = false;
19738
19739                         }
19740
19741                 }
19742
19743                 function getCompressedTextureFormats() {
19744
19745                         if ( compressedTextureFormats === null ) {
19746
19747                                 compressedTextureFormats = [];
19748
19749                                 if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
19750                                      extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
19751                                      extensions.get( 'WEBGL_compressed_texture_etc1' ) ) {
19752
19753                                         var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
19754
19755                                         for ( var i = 0; i < formats.length; i ++ ) {
19756
19757                                                 compressedTextureFormats.push( formats[ i ] );
19758
19759                                         }
19760
19761                                 }
19762
19763                         }
19764
19765                         return compressedTextureFormats;
19766
19767                 }
19768
19769                 function useProgram( program ) {
19770
19771                         if ( currentProgram !== program ) {
19772
19773                                 gl.useProgram( program );
19774
19775                                 currentProgram = program;
19776
19777                                 return true;
19778
19779                         }
19780
19781                         return false;
19782
19783                 }
19784
19785                 function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
19786
19787                         if ( blending !== NoBlending ) {
19788
19789                                 enable( gl.BLEND );
19790
19791                         } else {
19792
19793                                 disable( gl.BLEND );
19794
19795                         }
19796
19797                         if ( blending !== CustomBlending ) {
19798
19799                                 if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
19800
19801                                         switch ( blending ) {
19802
19803                                                 case AdditiveBlending:
19804
19805                                                         if ( premultipliedAlpha ) {
19806
19807                                                                 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19808                                                                 gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE );
19809
19810                                                         } else {
19811
19812                                                                 gl.blendEquation( gl.FUNC_ADD );
19813                                                                 gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
19814
19815                                                         }
19816                                                         break;
19817
19818                                                 case SubtractiveBlending:
19819
19820                                                         if ( premultipliedAlpha ) {
19821
19822                                                                 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19823                                                                 gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA );
19824
19825                                                         } else {
19826
19827                                                                 gl.blendEquation( gl.FUNC_ADD );
19828                                                                 gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );
19829
19830                                                         }
19831                                                         break;
19832
19833                                                 case MultiplyBlending:
19834
19835                                                         if ( premultipliedAlpha ) {
19836
19837                                                                 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19838                                                                 gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );
19839
19840                                                         } else {
19841
19842                                                                 gl.blendEquation( gl.FUNC_ADD );
19843                                                                 gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
19844
19845                                                         }
19846                                                         break;
19847
19848                                                 default:
19849
19850                                                         if ( premultipliedAlpha ) {
19851
19852                                                                 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19853                                                                 gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
19854
19855                                                         } else {
19856
19857                                                                 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19858                                                                 gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
19859
19860                                                         }
19861
19862                                         }
19863
19864                                 }
19865
19866                                 currentBlendEquation = null;
19867                                 currentBlendSrc = null;
19868                                 currentBlendDst = null;
19869                                 currentBlendEquationAlpha = null;
19870                                 currentBlendSrcAlpha = null;
19871                                 currentBlendDstAlpha = null;
19872
19873                         } else {
19874
19875                                 blendEquationAlpha = blendEquationAlpha || blendEquation;
19876                                 blendSrcAlpha = blendSrcAlpha || blendSrc;
19877                                 blendDstAlpha = blendDstAlpha || blendDst;
19878
19879                                 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
19880
19881                                         gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) );
19882
19883                                         currentBlendEquation = blendEquation;
19884                                         currentBlendEquationAlpha = blendEquationAlpha;
19885
19886                                 }
19887
19888                                 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
19889
19890                                         gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) );
19891
19892                                         currentBlendSrc = blendSrc;
19893                                         currentBlendDst = blendDst;
19894                                         currentBlendSrcAlpha = blendSrcAlpha;
19895                                         currentBlendDstAlpha = blendDstAlpha;
19896
19897                                 }
19898
19899                         }
19900
19901                         currentBlending = blending;
19902                         currentPremultipledAlpha = premultipliedAlpha;
19903
19904                 }
19905
19906                 function setMaterial( material ) {
19907
19908                         material.side === DoubleSide
19909                                 ? disable( gl.CULL_FACE )
19910                                 : enable( gl.CULL_FACE );
19911
19912                         setFlipSided( material.side === BackSide );
19913
19914                         material.transparent === true
19915                                 ? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha )
19916                                 : setBlending( NoBlending );
19917
19918                         depthBuffer.setFunc( material.depthFunc );
19919                         depthBuffer.setTest( material.depthTest );
19920                         depthBuffer.setMask( material.depthWrite );
19921                         colorBuffer.setMask( material.colorWrite );
19922
19923                         setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
19924
19925                 }
19926
19927                 //
19928
19929                 function setFlipSided( flipSided ) {
19930
19931                         if ( currentFlipSided !== flipSided ) {
19932
19933                                 if ( flipSided ) {
19934
19935                                         gl.frontFace( gl.CW );
19936
19937                                 } else {
19938
19939                                         gl.frontFace( gl.CCW );
19940
19941                                 }
19942
19943                                 currentFlipSided = flipSided;
19944
19945                         }
19946
19947                 }
19948
19949                 function setCullFace( cullFace ) {
19950
19951                         if ( cullFace !== CullFaceNone ) {
19952
19953                                 enable( gl.CULL_FACE );
19954
19955                                 if ( cullFace !== currentCullFace ) {
19956
19957                                         if ( cullFace === CullFaceBack ) {
19958
19959                                                 gl.cullFace( gl.BACK );
19960
19961                                         } else if ( cullFace === CullFaceFront ) {
19962
19963                                                 gl.cullFace( gl.FRONT );
19964
19965                                         } else {
19966
19967                                                 gl.cullFace( gl.FRONT_AND_BACK );
19968
19969                                         }
19970
19971                                 }
19972
19973                         } else {
19974
19975                                 disable( gl.CULL_FACE );
19976
19977                         }
19978
19979                         currentCullFace = cullFace;
19980
19981                 }
19982
19983                 function setLineWidth( width ) {
19984
19985                         if ( width !== currentLineWidth ) {
19986
19987                                 if ( lineWidthAvailable ) gl.lineWidth( width );
19988
19989                                 currentLineWidth = width;
19990
19991                         }
19992
19993                 }
19994
19995                 function setPolygonOffset( polygonOffset, factor, units ) {
19996
19997                         if ( polygonOffset ) {
19998
19999                                 enable( gl.POLYGON_OFFSET_FILL );
20000
20001                                 if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
20002
20003                                         gl.polygonOffset( factor, units );
20004
20005                                         currentPolygonOffsetFactor = factor;
20006                                         currentPolygonOffsetUnits = units;
20007
20008                                 }
20009
20010                         } else {
20011
20012                                 disable( gl.POLYGON_OFFSET_FILL );
20013
20014                         }
20015
20016                 }
20017
20018                 function setScissorTest( scissorTest ) {
20019
20020                         if ( scissorTest ) {
20021
20022                                 enable( gl.SCISSOR_TEST );
20023
20024                         } else {
20025
20026                                 disable( gl.SCISSOR_TEST );
20027
20028                         }
20029
20030                 }
20031
20032                 // texture
20033
20034                 function activeTexture( webglSlot ) {
20035
20036                         if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
20037
20038                         if ( currentTextureSlot !== webglSlot ) {
20039
20040                                 gl.activeTexture( webglSlot );
20041                                 currentTextureSlot = webglSlot;
20042
20043                         }
20044
20045                 }
20046
20047                 function bindTexture( webglType, webglTexture ) {
20048
20049                         if ( currentTextureSlot === null ) {
20050
20051                                 activeTexture();
20052
20053                         }
20054
20055                         var boundTexture = currentBoundTextures[ currentTextureSlot ];
20056
20057                         if ( boundTexture === undefined ) {
20058
20059                                 boundTexture = { type: undefined, texture: undefined };
20060                                 currentBoundTextures[ currentTextureSlot ] = boundTexture;
20061
20062                         }
20063
20064                         if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
20065
20066                                 gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
20067
20068                                 boundTexture.type = webglType;
20069                                 boundTexture.texture = webglTexture;
20070
20071                         }
20072
20073                 }
20074
20075                 function compressedTexImage2D() {
20076
20077                         try {
20078
20079                                 gl.compressedTexImage2D.apply( gl, arguments );
20080
20081                         } catch ( error ) {
20082
20083                                 console.error( 'THREE.WebGLState:', error );
20084
20085                         }
20086
20087                 }
20088
20089                 function texImage2D() {
20090
20091                         try {
20092
20093                                 gl.texImage2D.apply( gl, arguments );
20094
20095                         } catch ( error ) {
20096
20097                                 console.error( 'THREE.WebGLState:', error );
20098
20099                         }
20100
20101                 }
20102
20103                 //
20104
20105                 function scissor( scissor ) {
20106
20107                         if ( currentScissor.equals( scissor ) === false ) {
20108
20109                                 gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
20110                                 currentScissor.copy( scissor );
20111
20112                         }
20113
20114                 }
20115
20116                 function viewport( viewport ) {
20117
20118                         if ( currentViewport.equals( viewport ) === false ) {
20119
20120                                 gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
20121                                 currentViewport.copy( viewport );
20122
20123                         }
20124
20125                 }
20126
20127                 //
20128
20129                 function reset() {
20130
20131                         for ( var i = 0; i < enabledAttributes.length; i ++ ) {
20132
20133                                 if ( enabledAttributes[ i ] === 1 ) {
20134
20135                                         gl.disableVertexAttribArray( i );
20136                                         enabledAttributes[ i ] = 0;
20137
20138                                 }
20139
20140                         }
20141
20142                         capabilities = {};
20143
20144                         compressedTextureFormats = null;
20145
20146                         currentTextureSlot = null;
20147                         currentBoundTextures = {};
20148
20149                         currentProgram = null;
20150
20151                         currentBlending = null;
20152
20153                         currentFlipSided = null;
20154                         currentCullFace = null;
20155
20156                         colorBuffer.reset();
20157                         depthBuffer.reset();
20158                         stencilBuffer.reset();
20159
20160                 }
20161
20162                 return {
20163
20164                         buffers: {
20165                                 color: colorBuffer,
20166                                 depth: depthBuffer,
20167                                 stencil: stencilBuffer
20168                         },
20169
20170                         initAttributes: initAttributes,
20171                         enableAttribute: enableAttribute,
20172                         enableAttributeAndDivisor: enableAttributeAndDivisor,
20173                         disableUnusedAttributes: disableUnusedAttributes,
20174                         enable: enable,
20175                         disable: disable,
20176                         getCompressedTextureFormats: getCompressedTextureFormats,
20177
20178                         useProgram: useProgram,
20179
20180                         setBlending: setBlending,
20181                         setMaterial: setMaterial,
20182
20183                         setFlipSided: setFlipSided,
20184                         setCullFace: setCullFace,
20185
20186                         setLineWidth: setLineWidth,
20187                         setPolygonOffset: setPolygonOffset,
20188
20189                         setScissorTest: setScissorTest,
20190
20191                         activeTexture: activeTexture,
20192                         bindTexture: bindTexture,
20193                         compressedTexImage2D: compressedTexImage2D,
20194                         texImage2D: texImage2D,
20195
20196                         scissor: scissor,
20197                         viewport: viewport,
20198
20199                         reset: reset
20200
20201                 };
20202
20203         }
20204
20205         /**
20206          * @author mrdoob / http://mrdoob.com/
20207          */
20208
20209         function WebGLCapabilities( gl, extensions, parameters ) {
20210
20211                 var maxAnisotropy;
20212
20213                 function getMaxAnisotropy() {
20214
20215                         if ( maxAnisotropy !== undefined ) return maxAnisotropy;
20216
20217                         var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
20218
20219                         if ( extension !== null ) {
20220
20221                                 maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
20222
20223                         } else {
20224
20225                                 maxAnisotropy = 0;
20226
20227                         }
20228
20229                         return maxAnisotropy;
20230
20231                 }
20232
20233                 function getMaxPrecision( precision ) {
20234
20235                         if ( precision === 'highp' ) {
20236
20237                                 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
20238                                      gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
20239
20240                                         return 'highp';
20241
20242                                 }
20243
20244                                 precision = 'mediump';
20245
20246                         }
20247
20248                         if ( precision === 'mediump' ) {
20249
20250                                 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
20251                                      gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
20252
20253                                         return 'mediump';
20254
20255                                 }
20256
20257                         }
20258
20259                         return 'lowp';
20260
20261                 }
20262
20263                 var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
20264                 var maxPrecision = getMaxPrecision( precision );
20265
20266                 if ( maxPrecision !== precision ) {
20267
20268                         console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
20269                         precision = maxPrecision;
20270
20271                 }
20272
20273                 var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true && !! extensions.get( 'EXT_frag_depth' );
20274
20275                 var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
20276                 var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
20277                 var maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
20278                 var maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
20279
20280                 var maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
20281                 var maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
20282                 var maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
20283                 var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
20284
20285                 var vertexTextures = maxVertexTextures > 0;
20286                 var floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
20287                 var floatVertexTextures = vertexTextures && floatFragmentTextures;
20288
20289                 return {
20290
20291                         getMaxAnisotropy: getMaxAnisotropy,
20292                         getMaxPrecision: getMaxPrecision,
20293
20294                         precision: precision,
20295                         logarithmicDepthBuffer: logarithmicDepthBuffer,
20296
20297                         maxTextures: maxTextures,
20298                         maxVertexTextures: maxVertexTextures,
20299                         maxTextureSize: maxTextureSize,
20300                         maxCubemapSize: maxCubemapSize,
20301
20302                         maxAttributes: maxAttributes,
20303                         maxVertexUniforms: maxVertexUniforms,
20304                         maxVaryings: maxVaryings,
20305                         maxFragmentUniforms: maxFragmentUniforms,
20306
20307                         vertexTextures: vertexTextures,
20308                         floatFragmentTextures: floatFragmentTextures,
20309                         floatVertexTextures: floatVertexTextures
20310
20311                 };
20312
20313         }
20314
20315         /**
20316          * @author mrdoob / http://mrdoob.com/
20317          */
20318
20319         function ArrayCamera( array ) {
20320
20321                 PerspectiveCamera.call( this );
20322
20323                 this.cameras = array || [];
20324
20325         }
20326
20327         ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
20328
20329                 constructor: ArrayCamera,
20330
20331                 isArrayCamera: true
20332
20333         } );
20334
20335         /**
20336          * @author mrdoob / http://mrdoob.com/
20337          */
20338
20339         function WebVRManager( renderer ) {
20340
20341                 var scope = this;
20342
20343                 var device = null;
20344                 var frameData = null;
20345
20346                 if ( 'VRFrameData' in window ) {
20347
20348                         frameData = new window.VRFrameData();
20349
20350                 }
20351
20352                 var matrixWorldInverse = new Matrix4();
20353
20354                 var standingMatrix = new Matrix4();
20355                 var standingMatrixInverse = new Matrix4();
20356
20357                 var cameraL = new PerspectiveCamera();
20358                 cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
20359                 cameraL.layers.enable( 1 );
20360
20361                 var cameraR = new PerspectiveCamera();
20362                 cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
20363                 cameraR.layers.enable( 2 );
20364
20365                 var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
20366                 cameraVR.layers.enable( 1 );
20367                 cameraVR.layers.enable( 2 );
20368
20369                 //
20370
20371                 var currentSize, currentPixelRatio;
20372
20373                 function onVRDisplayPresentChange() {
20374
20375                         if ( device !== null && device.isPresenting ) {
20376
20377                                 var eyeParameters = device.getEyeParameters( 'left' );
20378                                 var renderWidth = eyeParameters.renderWidth;
20379                                 var renderHeight = eyeParameters.renderHeight;
20380
20381                                 currentPixelRatio = renderer.getPixelRatio();
20382                                 currentSize = renderer.getSize();
20383
20384                                 renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
20385
20386                         } else if ( scope.enabled ) {
20387
20388                                 renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio );
20389
20390                         }
20391
20392                 }
20393
20394                 window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
20395
20396                 //
20397
20398                 this.enabled = false;
20399                 this.standing = false;
20400
20401                 this.getDevice = function () {
20402
20403                         return device;
20404
20405                 };
20406
20407                 this.setDevice = function ( value ) {
20408
20409                         if ( value !== undefined ) device = value;
20410
20411                 };
20412
20413                 this.getCamera = function ( camera ) {
20414
20415                         if ( device === null ) return camera;
20416
20417                         device.depthNear = camera.near;
20418                         device.depthFar = camera.far;
20419
20420                         device.getFrameData( frameData );
20421
20422                         //
20423
20424                         var pose = frameData.pose;
20425
20426                         if ( pose.position !== null ) {
20427
20428                                 camera.position.fromArray( pose.position );
20429
20430                         } else {
20431
20432                                 camera.position.set( 0, 0, 0 );
20433
20434                         }
20435
20436                         if ( pose.orientation !== null ) {
20437
20438                                 camera.quaternion.fromArray( pose.orientation );
20439
20440                         }
20441
20442                         camera.updateMatrixWorld();
20443
20444                         var stageParameters = device.stageParameters;
20445
20446                         if ( this.standing && stageParameters ) {
20447
20448                                 standingMatrix.fromArray( stageParameters.sittingToStandingTransform );
20449                                 standingMatrixInverse.getInverse( standingMatrix );
20450
20451                                 camera.matrixWorld.multiply( standingMatrix );
20452                                 camera.matrixWorldInverse.multiply( standingMatrixInverse );
20453
20454                         }
20455
20456                         if ( device.isPresenting === false ) return camera;
20457
20458                         //
20459
20460                         cameraL.near = camera.near;
20461                         cameraR.near = camera.near;
20462
20463                         cameraL.far = camera.far;
20464                         cameraR.far = camera.far;
20465
20466                         cameraVR.matrixWorld.copy( camera.matrixWorld );
20467                         cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse );
20468
20469                         cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
20470                         cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
20471
20472                         if ( this.standing && stageParameters ) {
20473
20474                                 cameraL.matrixWorldInverse.multiply( standingMatrixInverse );
20475                                 cameraR.matrixWorldInverse.multiply( standingMatrixInverse );
20476
20477                         }
20478
20479                         var parent = camera.parent;
20480
20481                         if ( parent !== null ) {
20482
20483                                 matrixWorldInverse.getInverse( parent.matrixWorld );
20484
20485                                 cameraL.matrixWorldInverse.multiply( matrixWorldInverse );
20486                                 cameraR.matrixWorldInverse.multiply( matrixWorldInverse );
20487
20488                         }
20489
20490                         // envMap and Mirror needs camera.matrixWorld
20491
20492                         cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse );
20493                         cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse );
20494
20495                         cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
20496                         cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
20497
20498                         // HACK @mrdoob
20499                         // https://github.com/w3c/webvr/issues/203
20500
20501                         cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
20502
20503                         //
20504
20505                         var layers = device.getLayers();
20506
20507                         if ( layers.length ) {
20508
20509                                 var layer = layers[ 0 ];
20510
20511                                 if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) {
20512
20513                                         cameraL.bounds.fromArray( layer.leftBounds );
20514
20515                                 }
20516
20517                                 if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) {
20518
20519                                         cameraR.bounds.fromArray( layer.rightBounds );
20520
20521                                 }
20522
20523                         }
20524
20525                         return cameraVR;
20526
20527                 };
20528
20529                 this.getStandingMatrix = function () {
20530
20531                         return standingMatrix;
20532
20533                 };
20534
20535                 this.submitFrame = function () {
20536
20537                         if ( device && device.isPresenting ) device.submitFrame();
20538
20539                 };
20540
20541                 this.dispose = function() {
20542
20543                         window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange );
20544
20545                 };
20546
20547         }
20548
20549         /**
20550          * @author mrdoob / http://mrdoob.com/
20551          */
20552
20553         function WebGLExtensions( gl ) {
20554
20555                 var extensions = {};
20556
20557                 return {
20558
20559                         get: function ( name ) {
20560
20561                                 if ( extensions[ name ] !== undefined ) {
20562
20563                                         return extensions[ name ];
20564
20565                                 }
20566
20567                                 var extension;
20568
20569                                 switch ( name ) {
20570
20571                                         case 'WEBGL_depth_texture':
20572                                                 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
20573                                                 break;
20574
20575                                         case 'EXT_texture_filter_anisotropic':
20576                                                 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
20577                                                 break;
20578
20579                                         case 'WEBGL_compressed_texture_s3tc':
20580                                                 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
20581                                                 break;
20582
20583                                         case 'WEBGL_compressed_texture_pvrtc':
20584                                                 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
20585                                                 break;
20586
20587                                         case 'WEBGL_compressed_texture_etc1':
20588                                                 extension = gl.getExtension( 'WEBGL_compressed_texture_etc1' );
20589                                                 break;
20590
20591                                         default:
20592                                                 extension = gl.getExtension( name );
20593
20594                                 }
20595
20596                                 if ( extension === null ) {
20597
20598                                         console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
20599
20600                                 }
20601
20602                                 extensions[ name ] = extension;
20603
20604                                 return extension;
20605
20606                         }
20607
20608                 };
20609
20610         }
20611
20612         /**
20613          * @author tschw
20614          */
20615
20616         function WebGLClipping() {
20617
20618                 var scope = this,
20619
20620                         globalState = null,
20621                         numGlobalPlanes = 0,
20622                         localClippingEnabled = false,
20623                         renderingShadows = false,
20624
20625                         plane = new Plane(),
20626                         viewNormalMatrix = new Matrix3(),
20627
20628                         uniform = { value: null, needsUpdate: false };
20629
20630                 this.uniform = uniform;
20631                 this.numPlanes = 0;
20632                 this.numIntersection = 0;
20633
20634                 this.init = function( planes, enableLocalClipping, camera ) {
20635
20636                         var enabled =
20637                                 planes.length !== 0 ||
20638                                 enableLocalClipping ||
20639                                 // enable state of previous frame - the clipping code has to
20640                                 // run another frame in order to reset the state:
20641                                 numGlobalPlanes !== 0 ||
20642                                 localClippingEnabled;
20643
20644                         localClippingEnabled = enableLocalClipping;
20645
20646                         globalState = projectPlanes( planes, camera, 0 );
20647                         numGlobalPlanes = planes.length;
20648
20649                         return enabled;
20650
20651                 };
20652
20653                 this.beginShadows = function() {
20654
20655                         renderingShadows = true;
20656                         projectPlanes( null );
20657
20658                 };
20659
20660                 this.endShadows = function() {
20661
20662                         renderingShadows = false;
20663                         resetGlobalState();
20664
20665                 };
20666
20667                 this.setState = function( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {
20668
20669                         if ( ! localClippingEnabled ||
20670                                         planes === null || planes.length === 0 ||
20671                                         renderingShadows && ! clipShadows ) {
20672                                 // there's no local clipping
20673
20674                                 if ( renderingShadows ) {
20675                                         // there's no global clipping
20676
20677                                         projectPlanes( null );
20678
20679                                 } else {
20680
20681                                         resetGlobalState();
20682                                 }
20683
20684                         } else {
20685
20686                                 var nGlobal = renderingShadows ? 0 : numGlobalPlanes,
20687                                         lGlobal = nGlobal * 4,
20688
20689                                         dstArray = cache.clippingState || null;
20690
20691                                 uniform.value = dstArray; // ensure unique state
20692
20693                                 dstArray = projectPlanes( planes, camera, lGlobal, fromCache );
20694
20695                                 for ( var i = 0; i !== lGlobal; ++ i ) {
20696
20697                                         dstArray[ i ] = globalState[ i ];
20698
20699                                 }
20700
20701                                 cache.clippingState = dstArray;
20702                                 this.numIntersection = clipIntersection ? this.numPlanes : 0;
20703                                 this.numPlanes += nGlobal;
20704
20705                         }
20706
20707
20708                 };
20709
20710                 function resetGlobalState() {
20711
20712                         if ( uniform.value !== globalState ) {
20713
20714                                 uniform.value = globalState;
20715                                 uniform.needsUpdate = numGlobalPlanes > 0;
20716
20717                         }
20718
20719                         scope.numPlanes = numGlobalPlanes;
20720                         scope.numIntersection = 0;
20721
20722                 }
20723
20724                 function projectPlanes( planes, camera, dstOffset, skipTransform ) {
20725
20726                         var nPlanes = planes !== null ? planes.length : 0,
20727                                 dstArray = null;
20728
20729                         if ( nPlanes !== 0 ) {
20730
20731                                 dstArray = uniform.value;
20732
20733                                 if ( skipTransform !== true || dstArray === null ) {
20734
20735                                         var flatSize = dstOffset + nPlanes * 4,
20736                                                 viewMatrix = camera.matrixWorldInverse;
20737
20738                                         viewNormalMatrix.getNormalMatrix( viewMatrix );
20739
20740                                         if ( dstArray === null || dstArray.length < flatSize ) {
20741
20742                                                 dstArray = new Float32Array( flatSize );
20743
20744                                         }
20745
20746                                         for ( var i = 0, i4 = dstOffset;
20747                                                                                 i !== nPlanes; ++ i, i4 += 4 ) {
20748
20749                                                 plane.copy( planes[ i ] ).
20750                                                                 applyMatrix4( viewMatrix, viewNormalMatrix );
20751
20752                                                 plane.normal.toArray( dstArray, i4 );
20753                                                 dstArray[ i4 + 3 ] = plane.constant;
20754
20755                                         }
20756
20757                                 }
20758
20759                                 uniform.value = dstArray;
20760                                 uniform.needsUpdate = true;
20761
20762                         }
20763
20764                         scope.numPlanes = nPlanes;
20765                         
20766                         return dstArray;
20767
20768                 }
20769
20770         }
20771
20772         /**
20773          * @author thespite / http://www.twitter.com/thespite
20774          */
20775
20776         function WebGLUtils ( gl, extensions ) {
20777
20778                 function convert ( p ) {
20779
20780                         var extension;
20781
20782                         if ( p === RepeatWrapping ) return gl.REPEAT;
20783                         if ( p === ClampToEdgeWrapping ) return gl.CLAMP_TO_EDGE;
20784                         if ( p === MirroredRepeatWrapping ) return gl.MIRRORED_REPEAT;
20785
20786                         if ( p === NearestFilter ) return gl.NEAREST;
20787                         if ( p === NearestMipMapNearestFilter ) return gl.NEAREST_MIPMAP_NEAREST;
20788                         if ( p === NearestMipMapLinearFilter ) return gl.NEAREST_MIPMAP_LINEAR;
20789
20790                         if ( p === LinearFilter ) return gl.LINEAR;
20791                         if ( p === LinearMipMapNearestFilter ) return gl.LINEAR_MIPMAP_NEAREST;
20792                         if ( p === LinearMipMapLinearFilter ) return gl.LINEAR_MIPMAP_LINEAR;
20793
20794                         if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE;
20795                         if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4;
20796                         if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1;
20797                         if ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5;
20798
20799                         if ( p === ByteType ) return gl.BYTE;
20800                         if ( p === ShortType ) return gl.SHORT;
20801                         if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT;
20802                         if ( p === IntType ) return gl.INT;
20803                         if ( p === UnsignedIntType ) return gl.UNSIGNED_INT;
20804                         if ( p === FloatType ) return gl.FLOAT;
20805
20806                         if ( p === HalfFloatType ) {
20807
20808                                 extension = extensions.get( 'OES_texture_half_float' );
20809
20810                                 if ( extension !== null ) return extension.HALF_FLOAT_OES;
20811
20812                         }
20813
20814                         if ( p === AlphaFormat ) return gl.ALPHA;
20815                         if ( p === RGBFormat ) return gl.RGB;
20816                         if ( p === RGBAFormat ) return gl.RGBA;
20817                         if ( p === LuminanceFormat ) return gl.LUMINANCE;
20818                         if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA;
20819                         if ( p === DepthFormat ) return gl.DEPTH_COMPONENT;
20820                         if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL;
20821
20822                         if ( p === AddEquation ) return gl.FUNC_ADD;
20823                         if ( p === SubtractEquation ) return gl.FUNC_SUBTRACT;
20824                         if ( p === ReverseSubtractEquation ) return gl.FUNC_REVERSE_SUBTRACT;
20825
20826                         if ( p === ZeroFactor ) return gl.ZERO;
20827                         if ( p === OneFactor ) return gl.ONE;
20828                         if ( p === SrcColorFactor ) return gl.SRC_COLOR;
20829                         if ( p === OneMinusSrcColorFactor ) return gl.ONE_MINUS_SRC_COLOR;
20830                         if ( p === SrcAlphaFactor ) return gl.SRC_ALPHA;
20831                         if ( p === OneMinusSrcAlphaFactor ) return gl.ONE_MINUS_SRC_ALPHA;
20832                         if ( p === DstAlphaFactor ) return gl.DST_ALPHA;
20833                         if ( p === OneMinusDstAlphaFactor ) return gl.ONE_MINUS_DST_ALPHA;
20834
20835                         if ( p === DstColorFactor ) return gl.DST_COLOR;
20836                         if ( p === OneMinusDstColorFactor ) return gl.ONE_MINUS_DST_COLOR;
20837                         if ( p === SrcAlphaSaturateFactor ) return gl.SRC_ALPHA_SATURATE;
20838
20839                         if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
20840                                 p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
20841
20842                                 extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
20843
20844                                 if ( extension !== null ) {
20845
20846                                         if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
20847                                         if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
20848                                         if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
20849                                         if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
20850
20851                                 }
20852
20853                         }
20854
20855                         if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
20856                                 p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
20857
20858                                 extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
20859
20860                                 if ( extension !== null ) {
20861
20862                                         if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
20863                                         if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
20864                                         if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
20865                                         if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
20866
20867                                 }
20868
20869                         }
20870
20871                         if ( p === RGB_ETC1_Format ) {
20872
20873                                 extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
20874
20875                                 if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL;
20876
20877                         }
20878
20879                         if ( p === MinEquation || p === MaxEquation ) {
20880
20881                                 extension = extensions.get( 'EXT_blend_minmax' );
20882
20883                                 if ( extension !== null ) {
20884
20885                                         if ( p === MinEquation ) return extension.MIN_EXT;
20886                                         if ( p === MaxEquation ) return extension.MAX_EXT;
20887
20888                                 }
20889
20890                         }
20891
20892                         if ( p === UnsignedInt248Type ) {
20893
20894                                 extension = extensions.get( 'WEBGL_depth_texture' );
20895
20896                                 if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
20897
20898                         }
20899
20900                         return 0;
20901
20902                 }
20903
20904                 return { convert: convert }
20905
20906         }
20907
20908         // import { Sphere } from '../math/Sphere';
20909         /**
20910          * @author supereggbert / http://www.paulbrunt.co.uk/
20911          * @author mrdoob / http://mrdoob.com/
20912          * @author alteredq / http://alteredqualia.com/
20913          * @author szimek / https://github.com/szimek/
20914          * @author tschw
20915          */
20916
20917         function WebGLRenderer( parameters ) {
20918
20919                 console.log( 'THREE.WebGLRenderer', REVISION );
20920
20921                 parameters = parameters || {};
20922
20923                 var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),
20924                         _context = parameters.context !== undefined ? parameters.context : null,
20925
20926                         _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
20927                         _depth = parameters.depth !== undefined ? parameters.depth : true,
20928                         _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
20929                         _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
20930                         _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
20931                         _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false;
20932
20933                 var lightsArray = [];
20934                 var shadowsArray = [];
20935
20936                 var currentRenderList = null;
20937
20938                 var spritesArray = [];
20939                 var flaresArray = [];
20940
20941                 // public properties
20942
20943                 this.domElement = _canvas;
20944                 this.context = null;
20945
20946                 // clearing
20947
20948                 this.autoClear = true;
20949                 this.autoClearColor = true;
20950                 this.autoClearDepth = true;
20951                 this.autoClearStencil = true;
20952
20953                 // scene graph
20954
20955                 this.sortObjects = true;
20956
20957                 // user-defined clipping
20958
20959                 this.clippingPlanes = [];
20960                 this.localClippingEnabled = false;
20961
20962                 // physically based shading
20963
20964                 this.gammaFactor = 2.0; // for backwards compatibility
20965                 this.gammaInput = false;
20966                 this.gammaOutput = false;
20967
20968                 // physical lights
20969
20970                 this.physicallyCorrectLights = false;
20971
20972                 // tone mapping
20973
20974                 this.toneMapping = LinearToneMapping;
20975                 this.toneMappingExposure = 1.0;
20976                 this.toneMappingWhitePoint = 1.0;
20977
20978                 // morphs
20979
20980                 this.maxMorphTargets = 8;
20981                 this.maxMorphNormals = 4;
20982
20983                 // internal properties
20984
20985                 var _this = this,
20986
20987                         _isContextLost = false,
20988
20989                         // internal state cache
20990
20991                         _currentRenderTarget = null,
20992                         _currentFramebuffer = null,
20993                         _currentMaterialId = - 1,
20994                         _currentGeometryProgram = '',
20995
20996                         _currentCamera = null,
20997                         _currentArrayCamera = null,
20998
20999                         _currentViewport = new Vector4(),
21000                         _currentScissor = new Vector4(),
21001                         _currentScissorTest = null,
21002
21003                         //
21004
21005                         _usedTextureUnits = 0,
21006
21007                         //
21008
21009                         _width = _canvas.width,
21010                         _height = _canvas.height,
21011
21012                         _pixelRatio = 1,
21013
21014                         _viewport = new Vector4( 0, 0, _width, _height ),
21015                         _scissor = new Vector4( 0, 0, _width, _height ),
21016                         _scissorTest = false,
21017
21018                         // frustum
21019
21020                         _frustum = new Frustum(),
21021
21022                         // clipping
21023
21024                         _clipping = new WebGLClipping(),
21025                         _clippingEnabled = false,
21026                         _localClippingEnabled = false,
21027
21028                         // camera matrices cache
21029
21030                         _projScreenMatrix = new Matrix4(),
21031
21032                         _vector3 = new Vector3(),
21033
21034                         // info
21035
21036                         _infoMemory = {
21037                                 geometries: 0,
21038                                 textures: 0
21039                         },
21040
21041                         _infoRender = {
21042
21043                                 frame: 0,
21044                                 calls: 0,
21045                                 vertices: 0,
21046                                 faces: 0,
21047                                 points: 0
21048
21049                         };
21050
21051                 this.info = {
21052
21053                         render: _infoRender,
21054                         memory: _infoMemory,
21055                         programs: null
21056
21057                 };
21058
21059                 function getTargetPixelRatio() {
21060
21061                         return _currentRenderTarget === null ? _pixelRatio : 1;
21062
21063                 }
21064
21065                 // initialize
21066
21067                 var _gl;
21068
21069                 try {
21070
21071                         var contextAttributes = {
21072                                 alpha: _alpha,
21073                                 depth: _depth,
21074                                 stencil: _stencil,
21075                                 antialias: _antialias,
21076                                 premultipliedAlpha: _premultipliedAlpha,
21077                                 preserveDrawingBuffer: _preserveDrawingBuffer
21078                         };
21079
21080                         _gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );
21081
21082                         if ( _gl === null ) {
21083
21084                                 if ( _canvas.getContext( 'webgl' ) !== null ) {
21085
21086                                         throw 'Error creating WebGL context with your selected attributes.';
21087
21088                                 } else {
21089
21090                                         throw 'Error creating WebGL context.';
21091
21092                                 }
21093
21094                         }
21095
21096                         // Some experimental-webgl implementations do not have getShaderPrecisionFormat
21097
21098                         if ( _gl.getShaderPrecisionFormat === undefined ) {
21099
21100                                 _gl.getShaderPrecisionFormat = function () {
21101
21102                                         return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
21103
21104                                 };
21105
21106                         }
21107
21108                         _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
21109                         _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
21110
21111                 } catch ( error ) {
21112
21113                         console.error( 'THREE.WebGLRenderer: ' + error );
21114
21115                 }
21116
21117                 var extensions, capabilities, state;
21118                 var properties, textures, attributes, geometries, objects, lights;
21119                 var programCache, renderLists;
21120
21121                 var background, morphtargets, bufferRenderer, indexedBufferRenderer;
21122                 var flareRenderer, spriteRenderer;
21123
21124                 var utils;
21125
21126                 function initGLContext() {
21127
21128                         extensions = new WebGLExtensions( _gl );
21129                         extensions.get( 'WEBGL_depth_texture' );
21130                         extensions.get( 'OES_texture_float' );
21131                         extensions.get( 'OES_texture_float_linear' );
21132                         extensions.get( 'OES_texture_half_float' );
21133                         extensions.get( 'OES_texture_half_float_linear' );
21134                         extensions.get( 'OES_standard_derivatives' );
21135                         extensions.get( 'ANGLE_instanced_arrays' );
21136
21137                         if ( extensions.get( 'OES_element_index_uint' ) ) {
21138
21139                                 BufferGeometry.MaxIndex = 4294967296;
21140
21141                         }
21142
21143                         utils = new WebGLUtils( _gl, extensions );
21144
21145                         capabilities = new WebGLCapabilities( _gl, extensions, parameters );
21146
21147                         state = new WebGLState( _gl, extensions, utils );
21148                         state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
21149                         state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
21150
21151                         properties = new WebGLProperties();
21152                         textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _infoMemory );
21153                         attributes = new WebGLAttributes( _gl );
21154                         geometries = new WebGLGeometries( _gl, attributes, _infoMemory );
21155                         objects = new WebGLObjects( geometries, _infoRender );
21156                         morphtargets = new WebGLMorphtargets( _gl );
21157                         programCache = new WebGLPrograms( _this, extensions, capabilities );
21158                         lights = new WebGLLights();
21159                         renderLists = new WebGLRenderLists();
21160
21161                         background = new WebGLBackground( _this, state, geometries, _premultipliedAlpha );
21162
21163                         bufferRenderer = new WebGLBufferRenderer( _gl, extensions, _infoRender );
21164                         indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, _infoRender );
21165
21166                         flareRenderer = new WebGLFlareRenderer( _this, _gl, state, textures, capabilities );
21167                         spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities );
21168
21169                         _this.info.programs = programCache.programs;
21170
21171                         _this.context = _gl;
21172                         _this.capabilities = capabilities;
21173                         _this.extensions = extensions;
21174                         _this.properties = properties;
21175                         _this.renderLists = renderLists;
21176                         _this.state = state;
21177
21178                 }
21179
21180                 initGLContext();
21181
21182                 // vr
21183
21184                 var vr = new WebVRManager( _this );
21185
21186                 this.vr = vr;
21187
21188                 // shadow map
21189
21190                 var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
21191
21192                 this.shadowMap = shadowMap;
21193
21194                 // API
21195
21196                 this.getContext = function () {
21197
21198                         return _gl;
21199
21200                 };
21201
21202                 this.getContextAttributes = function () {
21203
21204                         return _gl.getContextAttributes();
21205
21206                 };
21207
21208                 this.forceContextLoss = function () {
21209
21210                         var extension = extensions.get( 'WEBGL_lose_context' );
21211                         if ( extension ) extension.loseContext();
21212
21213                 };
21214
21215                 this.forceContextRestore = function () {
21216
21217                         var extension = extensions.get( 'WEBGL_lose_context' );
21218                         if ( extension ) extension.restoreContext();
21219
21220                 };
21221
21222                 this.getPixelRatio = function () {
21223
21224                         return _pixelRatio;
21225
21226                 };
21227
21228                 this.setPixelRatio = function ( value ) {
21229
21230                         if ( value === undefined ) return;
21231
21232                         _pixelRatio = value;
21233
21234                         this.setSize( _width, _height, false );
21235
21236                 };
21237
21238                 this.getSize = function () {
21239
21240                         return {
21241                                 width: _width,
21242                                 height: _height
21243                         };
21244
21245                 };
21246
21247                 this.setSize = function ( width, height, updateStyle ) {
21248
21249                         var device = vr.getDevice();
21250
21251                         if ( device && device.isPresenting ) {
21252
21253                                 console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
21254                                 return;
21255
21256                         }
21257
21258                         _width = width;
21259                         _height = height;
21260
21261                         _canvas.width = width * _pixelRatio;
21262                         _canvas.height = height * _pixelRatio;
21263
21264                         if ( updateStyle !== false ) {
21265
21266                                 _canvas.style.width = width + 'px';
21267                                 _canvas.style.height = height + 'px';
21268
21269                         }
21270
21271                         this.setViewport( 0, 0, width, height );
21272
21273                 };
21274
21275                 this.getDrawingBufferSize = function () {
21276
21277                         return {
21278                                 width: _width * _pixelRatio,
21279                                 height: _height * _pixelRatio
21280                         };
21281
21282                 };
21283
21284                 this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
21285
21286                         _width = width;
21287                         _height = height;
21288
21289                         _pixelRatio = pixelRatio;
21290
21291                         _canvas.width = width * pixelRatio;
21292                         _canvas.height = height * pixelRatio;
21293
21294                         this.setViewport( 0, 0, width, height );
21295
21296                 };
21297
21298                 this.setViewport = function ( x, y, width, height ) {
21299
21300                         _viewport.set( x, _height - y - height, width, height );
21301                         state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
21302
21303                 };
21304
21305                 this.setScissor = function ( x, y, width, height ) {
21306
21307                         _scissor.set( x, _height - y - height, width, height );
21308                         state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
21309
21310                 };
21311
21312                 this.setScissorTest = function ( boolean ) {
21313
21314                         state.setScissorTest( _scissorTest = boolean );
21315
21316                 };
21317
21318                 // Clearing
21319
21320                 this.getClearColor = background.getClearColor;
21321                 this.setClearColor = background.setClearColor;
21322                 this.getClearAlpha = background.getClearAlpha;
21323                 this.setClearAlpha = background.setClearAlpha;
21324
21325                 this.clear = function ( color, depth, stencil ) {
21326
21327                         var bits = 0;
21328
21329                         if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
21330                         if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
21331                         if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
21332
21333                         _gl.clear( bits );
21334
21335                 };
21336
21337                 this.clearColor = function () {
21338
21339                         this.clear( true, false, false );
21340
21341                 };
21342
21343                 this.clearDepth = function () {
21344
21345                         this.clear( false, true, false );
21346
21347                 };
21348
21349                 this.clearStencil = function () {
21350
21351                         this.clear( false, false, true );
21352
21353                 };
21354
21355                 this.clearTarget = function ( renderTarget, color, depth, stencil ) {
21356
21357                         this.setRenderTarget( renderTarget );
21358                         this.clear( color, depth, stencil );
21359
21360                 };
21361
21362                 //
21363
21364                 this.dispose = function () {
21365
21366                         _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
21367                         _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
21368
21369                         renderLists.dispose();
21370
21371                         vr.dispose();
21372
21373                 };
21374
21375                 // Events
21376
21377                 function onContextLost( event ) {
21378
21379                         event.preventDefault();
21380
21381                         console.log( 'THREE.WebGLRenderer: Context Lost.' );
21382
21383                         _isContextLost = true;
21384
21385                 }
21386
21387                 function onContextRestore( event ) {
21388
21389                         console.log( 'THREE.WebGLRenderer: Context Restored.' );
21390
21391                         _isContextLost = false;
21392
21393                         initGLContext();
21394
21395                 }
21396
21397                 function onMaterialDispose( event ) {
21398
21399                         var material = event.target;
21400
21401                         material.removeEventListener( 'dispose', onMaterialDispose );
21402
21403                         deallocateMaterial( material );
21404
21405                 }
21406
21407                 // Buffer deallocation
21408
21409                 function deallocateMaterial( material ) {
21410
21411                         releaseMaterialProgramReference( material );
21412
21413                         properties.remove( material );
21414
21415                 }
21416
21417
21418                 function releaseMaterialProgramReference( material ) {
21419
21420                         var programInfo = properties.get( material ).program;
21421
21422                         material.program = undefined;
21423
21424                         if ( programInfo !== undefined ) {
21425
21426                                 programCache.releaseProgram( programInfo );
21427
21428                         }
21429
21430                 }
21431
21432                 // Buffer rendering
21433
21434                 function renderObjectImmediate( object, program, material ) {
21435
21436                         object.render( function ( object ) {
21437
21438                                 _this.renderBufferImmediate( object, program, material );
21439
21440                         } );
21441
21442                 }
21443
21444                 this.renderBufferImmediate = function ( object, program, material ) {
21445
21446                         state.initAttributes();
21447
21448                         var buffers = properties.get( object );
21449
21450                         if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
21451                         if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
21452                         if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
21453                         if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
21454
21455                         var programAttributes = program.getAttributes();
21456
21457                         if ( object.hasPositions ) {
21458
21459                                 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
21460                                 _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
21461
21462                                 state.enableAttribute( programAttributes.position );
21463                                 _gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 );
21464
21465                         }
21466
21467                         if ( object.hasNormals ) {
21468
21469                                 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );
21470
21471                                 if ( ! material.isMeshPhongMaterial &&
21472                                         ! material.isMeshStandardMaterial &&
21473                                         ! material.isMeshNormalMaterial &&
21474                                         material.flatShading === true ) {
21475
21476                                         for ( var i = 0, l = object.count * 3; i < l; i += 9 ) {
21477
21478                                                 var array = object.normalArray;
21479
21480                                                 var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3;
21481                                                 var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3;
21482                                                 var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3;
21483
21484                                                 array[ i + 0 ] = nx;
21485                                                 array[ i + 1 ] = ny;
21486                                                 array[ i + 2 ] = nz;
21487
21488                                                 array[ i + 3 ] = nx;
21489                                                 array[ i + 4 ] = ny;
21490                                                 array[ i + 5 ] = nz;
21491
21492                                                 array[ i + 6 ] = nx;
21493                                                 array[ i + 7 ] = ny;
21494                                                 array[ i + 8 ] = nz;
21495
21496                                         }
21497
21498                                 }
21499
21500                                 _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
21501
21502                                 state.enableAttribute( programAttributes.normal );
21503
21504                                 _gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 );
21505
21506                         }
21507
21508                         if ( object.hasUvs && material.map ) {
21509
21510                                 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
21511                                 _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
21512
21513                                 state.enableAttribute( programAttributes.uv );
21514
21515                                 _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 );
21516
21517                         }
21518
21519                         if ( object.hasColors && material.vertexColors !== NoColors ) {
21520
21521                                 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
21522                                 _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
21523
21524                                 state.enableAttribute( programAttributes.color );
21525
21526                                 _gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 );
21527
21528                         }
21529
21530                         state.disableUnusedAttributes();
21531
21532                         _gl.drawArrays( _gl.TRIANGLES, 0, object.count );
21533
21534                         object.count = 0;
21535
21536                 };
21537
21538                 this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
21539
21540                         state.setMaterial( material );
21541
21542                         var program = setProgram( camera, fog, material, object );
21543                         var geometryProgram = geometry.id + '_' + program.id + '_' + ( material.wireframe === true );
21544
21545                         var updateBuffers = false;
21546
21547                         if ( geometryProgram !== _currentGeometryProgram ) {
21548
21549                                 _currentGeometryProgram = geometryProgram;
21550                                 updateBuffers = true;
21551
21552                         }
21553
21554                         if ( object.morphTargetInfluences ) {
21555
21556                                 morphtargets.update( object, geometry, material, program );
21557
21558                                 updateBuffers = true;
21559
21560                         }
21561
21562                         //
21563
21564                         var index = geometry.index;
21565                         var position = geometry.attributes.position;
21566                         var rangeFactor = 1;
21567
21568                         if ( material.wireframe === true ) {
21569
21570                                 index = geometries.getWireframeAttribute( geometry );
21571                                 rangeFactor = 2;
21572
21573                         }
21574
21575                         var attribute;
21576                         var renderer = bufferRenderer;
21577
21578                         if ( index !== null ) {
21579
21580                                 attribute = attributes.get( index );
21581
21582                                 renderer = indexedBufferRenderer;
21583                                 renderer.setIndex( attribute );
21584
21585                         }
21586
21587                         if ( updateBuffers ) {
21588
21589                                 setupVertexAttributes( material, program, geometry );
21590
21591                                 if ( index !== null ) {
21592
21593                                         _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer );
21594
21595                                 }
21596
21597                         }
21598
21599                         //
21600
21601                         var dataCount = 0;
21602
21603                         if ( index !== null ) {
21604
21605                                 dataCount = index.count;
21606
21607                         } else if ( position !== undefined ) {
21608
21609                                 dataCount = position.count;
21610
21611                         }
21612
21613                         var rangeStart = geometry.drawRange.start * rangeFactor;
21614                         var rangeCount = geometry.drawRange.count * rangeFactor;
21615
21616                         var groupStart = group !== null ? group.start * rangeFactor : 0;
21617                         var groupCount = group !== null ? group.count * rangeFactor : Infinity;
21618
21619                         var drawStart = Math.max( rangeStart, groupStart );
21620                         var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
21621
21622                         var drawCount = Math.max( 0, drawEnd - drawStart + 1 );
21623
21624                         if ( drawCount === 0 ) return;
21625
21626                         //
21627
21628                         if ( object.isMesh ) {
21629
21630                                 if ( material.wireframe === true ) {
21631
21632                                         state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
21633                                         renderer.setMode( _gl.LINES );
21634
21635                                 } else {
21636
21637                                         switch ( object.drawMode ) {
21638
21639                                                 case TrianglesDrawMode:
21640                                                         renderer.setMode( _gl.TRIANGLES );
21641                                                         break;
21642
21643                                                 case TriangleStripDrawMode:
21644                                                         renderer.setMode( _gl.TRIANGLE_STRIP );
21645                                                         break;
21646
21647                                                 case TriangleFanDrawMode:
21648                                                         renderer.setMode( _gl.TRIANGLE_FAN );
21649                                                         break;
21650
21651                                         }
21652
21653                                 }
21654
21655
21656                         } else if ( object.isLine ) {
21657
21658                                 var lineWidth = material.linewidth;
21659
21660                                 if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
21661
21662                                 state.setLineWidth( lineWidth * getTargetPixelRatio() );
21663
21664                                 if ( object.isLineSegments ) {
21665
21666                                         renderer.setMode( _gl.LINES );
21667
21668                                 } else if ( object.isLineLoop ) {
21669
21670                                         renderer.setMode( _gl.LINE_LOOP );
21671
21672                                 } else {
21673
21674                                         renderer.setMode( _gl.LINE_STRIP );
21675
21676                                 }
21677
21678                         } else if ( object.isPoints ) {
21679
21680                                 renderer.setMode( _gl.POINTS );
21681
21682                         }
21683
21684                         if ( geometry && geometry.isInstancedBufferGeometry ) {
21685
21686                                 if ( geometry.maxInstancedCount > 0 ) {
21687
21688                                         renderer.renderInstances( geometry, drawStart, drawCount );
21689
21690                                 }
21691
21692                         } else {
21693
21694                                 renderer.render( drawStart, drawCount );
21695
21696                         }
21697
21698                 };
21699
21700                 function setupVertexAttributes( material, program, geometry, startIndex ) {
21701
21702                         if ( geometry && geometry.isInstancedBufferGeometry ) {
21703
21704                                 if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
21705
21706                                         console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
21707                                         return;
21708
21709                                 }
21710
21711                         }
21712
21713                         if ( startIndex === undefined ) startIndex = 0;
21714
21715                         state.initAttributes();
21716
21717                         var geometryAttributes = geometry.attributes;
21718
21719                         var programAttributes = program.getAttributes();
21720
21721                         var materialDefaultAttributeValues = material.defaultAttributeValues;
21722
21723                         for ( var name in programAttributes ) {
21724
21725                                 var programAttribute = programAttributes[ name ];
21726
21727                                 if ( programAttribute >= 0 ) {
21728
21729                                         var geometryAttribute = geometryAttributes[ name ];
21730
21731                                         if ( geometryAttribute !== undefined ) {
21732
21733                                                 var normalized = geometryAttribute.normalized;
21734                                                 var size = geometryAttribute.itemSize;
21735
21736                                                 var attribute = attributes.get( geometryAttribute );
21737
21738                                                 // TODO Attribute may not be available on context restore
21739
21740                                                 if ( attribute === undefined ) continue;
21741
21742                                                 var buffer = attribute.buffer;
21743                                                 var type = attribute.type;
21744                                                 var bytesPerElement = attribute.bytesPerElement;
21745
21746                                                 if ( geometryAttribute.isInterleavedBufferAttribute ) {
21747
21748                                                         var data = geometryAttribute.data;
21749                                                         var stride = data.stride;
21750                                                         var offset = geometryAttribute.offset;
21751
21752                                                         if ( data && data.isInstancedInterleavedBuffer ) {
21753
21754                                                                 state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
21755
21756                                                                 if ( geometry.maxInstancedCount === undefined ) {
21757
21758                                                                         geometry.maxInstancedCount = data.meshPerAttribute * data.count;
21759
21760                                                                 }
21761
21762                                                         } else {
21763
21764                                                                 state.enableAttribute( programAttribute );
21765
21766                                                         }
21767
21768                                                         _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
21769                                                         _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, ( startIndex * stride + offset ) * bytesPerElement );
21770
21771                                                 } else {
21772
21773                                                         if ( geometryAttribute.isInstancedBufferAttribute ) {
21774
21775                                                                 state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
21776
21777                                                                 if ( geometry.maxInstancedCount === undefined ) {
21778
21779                                                                         geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
21780
21781                                                                 }
21782
21783                                                         } else {
21784
21785                                                                 state.enableAttribute( programAttribute );
21786
21787                                                         }
21788
21789                                                         _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
21790                                                         _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, startIndex * size * bytesPerElement );
21791
21792                                                 }
21793
21794                                         } else if ( materialDefaultAttributeValues !== undefined ) {
21795
21796                                                 var value = materialDefaultAttributeValues[ name ];
21797
21798                                                 if ( value !== undefined ) {
21799
21800                                                         switch ( value.length ) {
21801
21802                                                                 case 2:
21803                                                                         _gl.vertexAttrib2fv( programAttribute, value );
21804                                                                         break;
21805
21806                                                                 case 3:
21807                                                                         _gl.vertexAttrib3fv( programAttribute, value );
21808                                                                         break;
21809
21810                                                                 case 4:
21811                                                                         _gl.vertexAttrib4fv( programAttribute, value );
21812                                                                         break;
21813
21814                                                                 default:
21815                                                                         _gl.vertexAttrib1fv( programAttribute, value );
21816
21817                                                         }
21818
21819                                                 }
21820
21821                                         }
21822
21823                                 }
21824
21825                         }
21826
21827                         state.disableUnusedAttributes();
21828
21829                 }
21830
21831                 // Compile
21832
21833                 this.compile = function ( scene, camera ) {
21834
21835                         lightsArray.length = 0;
21836                         shadowsArray.length = 0;
21837
21838                         scene.traverse( function ( object ) {
21839
21840                                 if ( object.isLight ) {
21841
21842                                         lightsArray.push( object );
21843
21844                                         if ( object.castShadow ) {
21845
21846                                                 shadowsArray.push( object );
21847
21848                                         }
21849
21850                                 }
21851
21852                         } );
21853
21854                         lights.setup( lightsArray, shadowsArray, camera );
21855
21856                         scene.traverse( function ( object ) {
21857
21858                                 if ( object.material ) {
21859
21860                                         if ( Array.isArray( object.material ) ) {
21861
21862                                                 for ( var i = 0; i < object.material.length; i ++ ) {
21863
21864                                                         initMaterial( object.material[ i ], scene.fog, object );
21865
21866                                                 }
21867
21868                                         } else {
21869
21870                                                 initMaterial( object.material, scene.fog, object );
21871
21872                                         }
21873
21874                                 }
21875
21876                         } );
21877
21878                 };
21879
21880                 // Animation Loop
21881
21882                 var isAnimating = false;
21883                 var onAnimationFrame = null;
21884
21885                 function start() {
21886
21887                         if ( isAnimating ) return;
21888                         ( vr.getDevice() || window ).requestAnimationFrame( loop );
21889                         isAnimating = true;
21890
21891                 }
21892
21893                 function loop( time ) {
21894
21895                         if ( onAnimationFrame !== null ) onAnimationFrame( time );
21896                         ( vr.getDevice() || window ).requestAnimationFrame( loop );
21897
21898                 }
21899
21900                 this.animate = function ( callback ) {
21901
21902                         onAnimationFrame = callback;
21903                         start();
21904
21905                 };
21906
21907                 // Rendering
21908
21909                 this.render = function ( scene, camera, renderTarget, forceClear ) {
21910
21911                         if ( ! ( camera && camera.isCamera ) ) {
21912
21913                                 console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
21914                                 return;
21915
21916                         }
21917
21918                         if ( _isContextLost ) return;
21919
21920                         // reset caching for this frame
21921
21922                         _currentGeometryProgram = '';
21923                         _currentMaterialId = - 1;
21924                         _currentCamera = null;
21925
21926                         // update scene graph
21927
21928                         if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
21929
21930                         // update camera matrices and frustum
21931
21932                         if ( camera.parent === null ) camera.updateMatrixWorld();
21933
21934                         if ( vr.enabled ) {
21935
21936                                 camera = vr.getCamera( camera );
21937
21938                         }
21939
21940                         _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
21941                         _frustum.setFromMatrix( _projScreenMatrix );
21942
21943                         lightsArray.length = 0;
21944                         shadowsArray.length = 0;
21945
21946                         spritesArray.length = 0;
21947                         flaresArray.length = 0;
21948
21949                         _localClippingEnabled = this.localClippingEnabled;
21950                         _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
21951
21952                         currentRenderList = renderLists.get( scene, camera );
21953                         currentRenderList.init();
21954
21955                         projectObject( scene, camera, _this.sortObjects );
21956
21957                         if ( _this.sortObjects === true ) {
21958
21959                                 currentRenderList.sort();
21960
21961                         }
21962
21963                         //
21964
21965                         if ( _clippingEnabled ) _clipping.beginShadows();
21966
21967                         shadowMap.render( shadowsArray, scene, camera );
21968
21969                         lights.setup( lightsArray, shadowsArray, camera );
21970
21971                         if ( _clippingEnabled ) _clipping.endShadows();
21972
21973                         //
21974
21975                         _infoRender.frame ++;
21976                         _infoRender.calls = 0;
21977                         _infoRender.vertices = 0;
21978                         _infoRender.faces = 0;
21979                         _infoRender.points = 0;
21980
21981                         if ( renderTarget === undefined ) {
21982
21983                                 renderTarget = null;
21984
21985                         }
21986
21987                         this.setRenderTarget( renderTarget );
21988
21989                         //
21990
21991                         background.render( currentRenderList, scene, camera, forceClear );
21992
21993                         // render scene
21994
21995                         var opaqueObjects = currentRenderList.opaque;
21996                         var transparentObjects = currentRenderList.transparent;
21997
21998                         if ( scene.overrideMaterial ) {
21999
22000                                 var overrideMaterial = scene.overrideMaterial;
22001
22002                                 if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial );
22003                                 if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial );
22004
22005                         } else {
22006
22007                                 // opaque pass (front-to-back order)
22008
22009                                 if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera );
22010
22011                                 // transparent pass (back-to-front order)
22012
22013                                 if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera );
22014
22015                         }
22016
22017                         // custom renderers
22018
22019                         spriteRenderer.render( spritesArray, scene, camera );
22020                         flareRenderer.render( flaresArray, scene, camera, _currentViewport );
22021
22022                         // Generate mipmap if we're using any kind of mipmap filtering
22023
22024                         if ( renderTarget ) {
22025
22026                                 textures.updateRenderTargetMipmap( renderTarget );
22027
22028                         }
22029
22030                         // Ensure depth buffer writing is enabled so it can be cleared on next render
22031
22032                         state.buffers.depth.setTest( true );
22033                         state.buffers.depth.setMask( true );
22034                         state.buffers.color.setMask( true );
22035
22036                         state.setPolygonOffset( false );
22037
22038                         if ( vr.enabled ) {
22039
22040                                 vr.submitFrame();
22041
22042                         }
22043
22044                         // _gl.finish();
22045
22046                 };
22047
22048                 /*
22049                 // TODO Duplicated code (Frustum)
22050
22051                 var _sphere = new Sphere();
22052
22053                 function isObjectViewable( object ) {
22054
22055                         var geometry = object.geometry;
22056
22057                         if ( geometry.boundingSphere === null )
22058                                 geometry.computeBoundingSphere();
22059
22060                         _sphere.copy( geometry.boundingSphere ).
22061                         applyMatrix4( object.matrixWorld );
22062
22063                         return isSphereViewable( _sphere );
22064
22065                 }
22066
22067                 function isSpriteViewable( sprite ) {
22068
22069                         _sphere.center.set( 0, 0, 0 );
22070                         _sphere.radius = 0.7071067811865476;
22071                         _sphere.applyMatrix4( sprite.matrixWorld );
22072
22073                         return isSphereViewable( _sphere );
22074
22075                 }
22076
22077                 function isSphereViewable( sphere ) {
22078
22079                         if ( ! _frustum.intersectsSphere( sphere ) ) return false;
22080
22081                         var numPlanes = _clipping.numPlanes;
22082
22083                         if ( numPlanes === 0 ) return true;
22084
22085                         var planes = _this.clippingPlanes,
22086
22087                                 center = sphere.center,
22088                                 negRad = - sphere.radius,
22089                                 i = 0;
22090
22091                         do {
22092
22093                                 // out when deeper than radius in the negative halfspace
22094                                 if ( planes[ i ].distanceToPoint( center ) < negRad ) return false;
22095
22096                         } while ( ++ i !== numPlanes );
22097
22098                         return true;
22099
22100                 }
22101                 */
22102
22103                 function projectObject( object, camera, sortObjects ) {
22104
22105                         if ( ! object.visible ) return;
22106
22107                         var visible = object.layers.test( camera.layers );
22108
22109                         if ( visible ) {
22110
22111                                 if ( object.isLight ) {
22112
22113                                         lightsArray.push( object );
22114
22115                                         if ( object.castShadow ) {
22116
22117                                                 shadowsArray.push( object );
22118
22119                                         }
22120
22121                                 } else if ( object.isSprite ) {
22122
22123                                         if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
22124
22125                                                 spritesArray.push( object );
22126
22127                                         }
22128
22129                                 } else if ( object.isLensFlare ) {
22130
22131                                         flaresArray.push( object );
22132
22133                                 } else if ( object.isImmediateRenderObject ) {
22134
22135                                         if ( sortObjects ) {
22136
22137                                                 _vector3.setFromMatrixPosition( object.matrixWorld )
22138                                                         .applyMatrix4( _projScreenMatrix );
22139
22140                                         }
22141
22142                                         currentRenderList.push( object, null, object.material, _vector3.z, null );
22143
22144                                 } else if ( object.isMesh || object.isLine || object.isPoints ) {
22145
22146                                         if ( object.isSkinnedMesh ) {
22147
22148                                                 object.skeleton.update();
22149
22150                                         }
22151
22152                                         if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
22153
22154                                                 if ( sortObjects ) {
22155
22156                                                         _vector3.setFromMatrixPosition( object.matrixWorld )
22157                                                                 .applyMatrix4( _projScreenMatrix );
22158
22159                                                 }
22160
22161                                                 var geometry = objects.update( object );
22162                                                 var material = object.material;
22163
22164                                                 if ( Array.isArray( material ) ) {
22165
22166                                                         var groups = geometry.groups;
22167
22168                                                         for ( var i = 0, l = groups.length; i < l; i ++ ) {
22169
22170                                                                 var group = groups[ i ];
22171                                                                 var groupMaterial = material[ group.materialIndex ];
22172
22173                                                                 if ( groupMaterial && groupMaterial.visible ) {
22174
22175                                                                         currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group );
22176
22177                                                                 }
22178
22179                                                         }
22180
22181                                                 } else if ( material.visible ) {
22182
22183                                                         currentRenderList.push( object, geometry, material, _vector3.z, null );
22184
22185                                                 }
22186
22187                                         }
22188
22189                                 }
22190
22191                         }
22192
22193                         var children = object.children;
22194
22195                         for ( var i = 0, l = children.length; i < l; i ++ ) {
22196
22197                                 projectObject( children[ i ], camera, sortObjects );
22198
22199                         }
22200
22201                 }
22202
22203                 function renderObjects( renderList, scene, camera, overrideMaterial ) {
22204
22205                         for ( var i = 0, l = renderList.length; i < l; i ++ ) {
22206
22207                                 var renderItem = renderList[ i ];
22208
22209                                 var object = renderItem.object;
22210                                 var geometry = renderItem.geometry;
22211                                 var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
22212                                 var group = renderItem.group;
22213
22214                                 if ( camera.isArrayCamera ) {
22215
22216                                         _currentArrayCamera = camera;
22217
22218                                         var cameras = camera.cameras;
22219
22220                                         for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
22221
22222                                                 var camera2 = cameras[ j ];
22223
22224                                                 if ( object.layers.test( camera2.layers ) ) {
22225
22226                                                         var bounds = camera2.bounds;
22227
22228                                                         var x = bounds.x * _width;
22229                                                         var y = bounds.y * _height;
22230                                                         var width = bounds.z * _width;
22231                                                         var height = bounds.w * _height;
22232
22233                                                         state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) );
22234
22235                                                         renderObject( object, scene, camera2, geometry, material, group );
22236
22237                                                 }
22238
22239                                         }
22240
22241                                 } else {
22242
22243                                         _currentArrayCamera = null;
22244
22245                                         renderObject( object, scene, camera, geometry, material, group );
22246
22247                                 }
22248
22249                         }
22250
22251                 }
22252
22253                 function renderObject( object, scene, camera, geometry, material, group ) {
22254
22255                         object.onBeforeRender( _this, scene, camera, geometry, material, group );
22256
22257                         object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
22258                         object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
22259
22260                         if ( object.isImmediateRenderObject ) {
22261
22262                                 state.setMaterial( material );
22263
22264                                 var program = setProgram( camera, scene.fog, material, object );
22265
22266                                 _currentGeometryProgram = '';
22267
22268                                 renderObjectImmediate( object, program, material );
22269
22270                         } else {
22271
22272                                 _this.renderBufferDirect( camera, scene.fog, geometry, material, object, group );
22273
22274                         }
22275
22276                         object.onAfterRender( _this, scene, camera, geometry, material, group );
22277
22278                 }
22279
22280                 function initMaterial( material, fog, object ) {
22281
22282                         var materialProperties = properties.get( material );
22283
22284                         var parameters = programCache.getParameters(
22285                                 material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object );
22286
22287                         var code = programCache.getProgramCode( material, parameters );
22288
22289                         var program = materialProperties.program;
22290                         var programChange = true;
22291
22292                         if ( program === undefined ) {
22293
22294                                 // new material
22295                                 material.addEventListener( 'dispose', onMaterialDispose );
22296
22297                         } else if ( program.code !== code ) {
22298
22299                                 // changed glsl or parameters
22300                                 releaseMaterialProgramReference( material );
22301
22302                         } else if ( parameters.shaderID !== undefined ) {
22303
22304                                 // same glsl and uniform list
22305                                 return;
22306
22307                         } else {
22308
22309                                 // only rebuild uniform list
22310                                 programChange = false;
22311
22312                         }
22313
22314                         if ( programChange ) {
22315
22316                                 if ( parameters.shaderID ) {
22317
22318                                         var shader = ShaderLib[ parameters.shaderID ];
22319
22320                                         materialProperties.shader = {
22321                                                 name: material.type,
22322                                                 uniforms: UniformsUtils.clone( shader.uniforms ),
22323                                                 vertexShader: shader.vertexShader,
22324                                                 fragmentShader: shader.fragmentShader
22325                                         };
22326
22327                                 } else {
22328
22329                                         materialProperties.shader = {
22330                                                 name: material.type,
22331                                                 uniforms: material.uniforms,
22332                                                 vertexShader: material.vertexShader,
22333                                                 fragmentShader: material.fragmentShader
22334                                         };
22335
22336                                 }
22337
22338                                 material.onBeforeCompile( materialProperties.shader );
22339
22340                                 program = programCache.acquireProgram( material, materialProperties.shader, parameters, code );
22341
22342                                 materialProperties.program = program;
22343                                 material.program = program;
22344
22345                         }
22346
22347                         var programAttributes = program.getAttributes();
22348
22349                         if ( material.morphTargets ) {
22350
22351                                 material.numSupportedMorphTargets = 0;
22352
22353                                 for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
22354
22355                                         if ( programAttributes[ 'morphTarget' + i ] >= 0 ) {
22356
22357                                                 material.numSupportedMorphTargets ++;
22358
22359                                         }
22360
22361                                 }
22362
22363                         }
22364
22365                         if ( material.morphNormals ) {
22366
22367                                 material.numSupportedMorphNormals = 0;
22368
22369                                 for ( var i = 0; i < _this.maxMorphNormals; i ++ ) {
22370
22371                                         if ( programAttributes[ 'morphNormal' + i ] >= 0 ) {
22372
22373                                                 material.numSupportedMorphNormals ++;
22374
22375                                         }
22376
22377                                 }
22378
22379                         }
22380
22381                         var uniforms = materialProperties.shader.uniforms;
22382
22383                         if ( ! material.isShaderMaterial &&
22384                                 ! material.isRawShaderMaterial ||
22385                                 material.clipping === true ) {
22386
22387                                 materialProperties.numClippingPlanes = _clipping.numPlanes;
22388                                 materialProperties.numIntersection = _clipping.numIntersection;
22389                                 uniforms.clippingPlanes = _clipping.uniform;
22390
22391                         }
22392
22393                         materialProperties.fog = fog;
22394
22395                         // store the light setup it was created for
22396
22397                         materialProperties.lightsHash = lights.state.hash;
22398
22399                         if ( material.lights ) {
22400
22401                                 // wire up the material to this renderer's lighting state
22402
22403                                 uniforms.ambientLightColor.value = lights.state.ambient;
22404                                 uniforms.directionalLights.value = lights.state.directional;
22405                                 uniforms.spotLights.value = lights.state.spot;
22406                                 uniforms.rectAreaLights.value = lights.state.rectArea;
22407                                 uniforms.pointLights.value = lights.state.point;
22408                                 uniforms.hemisphereLights.value = lights.state.hemi;
22409
22410                                 uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
22411                                 uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
22412                                 uniforms.spotShadowMap.value = lights.state.spotShadowMap;
22413                                 uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
22414                                 uniforms.pointShadowMap.value = lights.state.pointShadowMap;
22415                                 uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
22416                                 // TODO (abelnation): add area lights shadow info to uniforms
22417
22418                         }
22419
22420                         var progUniforms = materialProperties.program.getUniforms(),
22421                                 uniformsList =
22422                                         WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
22423
22424                         materialProperties.uniformsList = uniformsList;
22425
22426                 }
22427
22428                 function setProgram( camera, fog, material, object ) {
22429
22430                         _usedTextureUnits = 0;
22431
22432                         var materialProperties = properties.get( material );
22433
22434                         if ( _clippingEnabled ) {
22435
22436                                 if ( _localClippingEnabled || camera !== _currentCamera ) {
22437
22438                                         var useCache =
22439                                                 camera === _currentCamera &&
22440                                                 material.id === _currentMaterialId;
22441
22442                                         // we might want to call this function with some ClippingGroup
22443                                         // object instead of the material, once it becomes feasible
22444                                         // (#8465, #8379)
22445                                         _clipping.setState(
22446                                                 material.clippingPlanes, material.clipIntersection, material.clipShadows,
22447                                                 camera, materialProperties, useCache );
22448
22449                                 }
22450
22451                         }
22452
22453                         if ( material.needsUpdate === false ) {
22454
22455                                 if ( materialProperties.program === undefined ) {
22456
22457                                         material.needsUpdate = true;
22458
22459                                 } else if ( material.fog && materialProperties.fog !== fog ) {
22460
22461                                         material.needsUpdate = true;
22462
22463                                 } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) {
22464
22465                                         material.needsUpdate = true;
22466
22467                                 } else if ( materialProperties.numClippingPlanes !== undefined &&
22468                                         ( materialProperties.numClippingPlanes !== _clipping.numPlanes ||
22469                                         materialProperties.numIntersection !== _clipping.numIntersection ) ) {
22470
22471                                         material.needsUpdate = true;
22472
22473                                 }
22474
22475                         }
22476
22477                         if ( material.needsUpdate ) {
22478
22479                                 initMaterial( material, fog, object );
22480                                 material.needsUpdate = false;
22481
22482                         }
22483
22484                         var refreshProgram = false;
22485                         var refreshMaterial = false;
22486                         var refreshLights = false;
22487
22488                         var program = materialProperties.program,
22489                                 p_uniforms = program.getUniforms(),
22490                                 m_uniforms = materialProperties.shader.uniforms;
22491
22492                         if ( state.useProgram( program.program ) ) {
22493
22494                                 refreshProgram = true;
22495                                 refreshMaterial = true;
22496                                 refreshLights = true;
22497
22498                         }
22499
22500                         if ( material.id !== _currentMaterialId ) {
22501
22502                                 _currentMaterialId = material.id;
22503
22504                                 refreshMaterial = true;
22505
22506                         }
22507
22508                         if ( refreshProgram || camera !== _currentCamera ) {
22509
22510                                 p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
22511
22512                                 if ( capabilities.logarithmicDepthBuffer ) {
22513
22514                                         p_uniforms.setValue( _gl, 'logDepthBufFC',
22515                                                 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
22516
22517                                 }
22518
22519                                 // Avoid unneeded uniform updates per ArrayCamera's sub-camera
22520
22521                                 if ( _currentCamera !== ( _currentArrayCamera || camera ) ) {
22522
22523                                         _currentCamera = ( _currentArrayCamera || camera );
22524
22525                                         // lighting uniforms depend on the camera so enforce an update
22526                                         // now, in case this material supports lights - or later, when
22527                                         // the next material that does gets activated:
22528
22529                                         refreshMaterial = true;         // set to true on material change
22530                                         refreshLights = true;           // remains set until update done
22531
22532                                 }
22533
22534                                 // load material specific uniforms
22535                                 // (shader material also gets them for the sake of genericity)
22536
22537                                 if ( material.isShaderMaterial ||
22538                                         material.isMeshPhongMaterial ||
22539                                         material.isMeshStandardMaterial ||
22540                                         material.envMap ) {
22541
22542                                         var uCamPos = p_uniforms.map.cameraPosition;
22543
22544                                         if ( uCamPos !== undefined ) {
22545
22546                                                 uCamPos.setValue( _gl,
22547                                                         _vector3.setFromMatrixPosition( camera.matrixWorld ) );
22548
22549                                         }
22550
22551                                 }
22552
22553                                 if ( material.isMeshPhongMaterial ||
22554                                         material.isMeshLambertMaterial ||
22555                                         material.isMeshBasicMaterial ||
22556                                         material.isMeshStandardMaterial ||
22557                                         material.isShaderMaterial ||
22558                                         material.skinning ) {
22559
22560                                         p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
22561
22562                                 }
22563
22564                         }
22565
22566                         // skinning uniforms must be set even if material didn't change
22567                         // auto-setting of texture unit for bone texture must go before other textures
22568                         // not sure why, but otherwise weird things happen
22569
22570                         if ( material.skinning ) {
22571
22572                                 p_uniforms.setOptional( _gl, object, 'bindMatrix' );
22573                                 p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
22574
22575                                 var skeleton = object.skeleton;
22576
22577                                 if ( skeleton ) {
22578
22579                                         var bones = skeleton.bones;
22580
22581                                         if ( capabilities.floatVertexTextures ) {
22582
22583                                                 if ( skeleton.boneTexture === undefined ) {
22584
22585                                                         // layout (1 matrix = 4 pixels)
22586                                                         //      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
22587                                                         //  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
22588                                                         //       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
22589                                                         //       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
22590                                                         //       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
22591
22592
22593                                                         var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
22594                                                         size = _Math.nextPowerOfTwo( Math.ceil( size ) );
22595                                                         size = Math.max( size, 4 );
22596
22597                                                         var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
22598                                                         boneMatrices.set( skeleton.boneMatrices ); // copy current values
22599
22600                                                         var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
22601
22602                                                         skeleton.boneMatrices = boneMatrices;
22603                                                         skeleton.boneTexture = boneTexture;
22604                                                         skeleton.boneTextureSize = size;
22605
22606                                                 }
22607
22608                                                 p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture );
22609                                                 p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
22610
22611                                         } else {
22612
22613                                                 p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
22614
22615                                         }
22616
22617                                 }
22618
22619                         }
22620
22621                         if ( refreshMaterial ) {
22622
22623                                 p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
22624                                 p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );
22625
22626                                 if ( material.lights ) {
22627
22628                                         // the current material requires lighting info
22629
22630                                         // note: all lighting uniforms are always set correctly
22631                                         // they simply reference the renderer's state for their
22632                                         // values
22633                                         //
22634                                         // use the current material's .needsUpdate flags to set
22635                                         // the GL state when required
22636
22637                                         markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
22638
22639                                 }
22640
22641                                 // refresh uniforms common to several materials
22642
22643                                 if ( fog && material.fog ) {
22644
22645                                         refreshUniformsFog( m_uniforms, fog );
22646
22647                                 }
22648
22649                                 if ( material.isMeshBasicMaterial ) {
22650
22651                                         refreshUniformsCommon( m_uniforms, material );
22652
22653                                 } else if ( material.isMeshLambertMaterial ) {
22654
22655                                         refreshUniformsCommon( m_uniforms, material );
22656                                         refreshUniformsLambert( m_uniforms, material );
22657
22658                                 } else if ( material.isMeshPhongMaterial ) {
22659
22660                                         refreshUniformsCommon( m_uniforms, material );
22661
22662                                         if ( material.isMeshToonMaterial ) {
22663
22664                                                 refreshUniformsToon( m_uniforms, material );
22665
22666                                         } else {
22667
22668                                                 refreshUniformsPhong( m_uniforms, material );
22669
22670                                         }
22671
22672                                 } else if ( material.isMeshStandardMaterial ) {
22673
22674                                         refreshUniformsCommon( m_uniforms, material );
22675
22676                                         if ( material.isMeshPhysicalMaterial ) {
22677
22678                                                 refreshUniformsPhysical( m_uniforms, material );
22679
22680                                         } else {
22681
22682                                                 refreshUniformsStandard( m_uniforms, material );
22683
22684                                         }
22685
22686                                 } else if ( material.isMeshDepthMaterial ) {
22687
22688                                         refreshUniformsCommon( m_uniforms, material );
22689                                         refreshUniformsDepth( m_uniforms, material );
22690
22691                                 } else if ( material.isMeshDistanceMaterial ) {
22692
22693                                         refreshUniformsCommon( m_uniforms, material );
22694                                         refreshUniformsDistance( m_uniforms, material );
22695
22696                                 } else if ( material.isMeshNormalMaterial ) {
22697
22698                                         refreshUniformsCommon( m_uniforms, material );
22699                                         refreshUniformsNormal( m_uniforms, material );
22700
22701                                 } else if ( material.isLineBasicMaterial ) {
22702
22703                                         refreshUniformsLine( m_uniforms, material );
22704
22705                                         if ( material.isLineDashedMaterial ) {
22706
22707                                                 refreshUniformsDash( m_uniforms, material );
22708
22709                                         }
22710
22711                                 } else if ( material.isPointsMaterial ) {
22712
22713                                         refreshUniformsPoints( m_uniforms, material );
22714
22715                                 } else if ( material.isShadowMaterial ) {
22716
22717                                         m_uniforms.color.value = material.color;
22718                                         m_uniforms.opacity.value = material.opacity;
22719
22720                                 }
22721
22722                                 // RectAreaLight Texture
22723                                 // TODO (mrdoob): Find a nicer implementation
22724
22725                                 if ( m_uniforms.ltcMat !== undefined ) m_uniforms.ltcMat.value = UniformsLib.LTC_MAT_TEXTURE;
22726                                 if ( m_uniforms.ltcMag !== undefined ) m_uniforms.ltcMag.value = UniformsLib.LTC_MAG_TEXTURE;
22727
22728                                 WebGLUniforms.upload(
22729                                         _gl, materialProperties.uniformsList, m_uniforms, _this );
22730
22731                         }
22732
22733
22734                         // common matrices
22735
22736                         p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
22737                         p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
22738                         p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
22739
22740                         return program;
22741
22742                 }
22743
22744                 // Uniforms (refresh uniforms objects)
22745
22746                 function refreshUniformsCommon( uniforms, material ) {
22747
22748                         uniforms.opacity.value = material.opacity;
22749
22750                         if ( material.color ) {
22751
22752                                 uniforms.diffuse.value = material.color;
22753
22754                         }
22755
22756                         if ( material.emissive ) {
22757
22758                                 uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
22759
22760                         }
22761
22762                         if ( material.map ) {
22763
22764                                 uniforms.map.value = material.map;
22765
22766                         }
22767
22768                         if ( material.alphaMap ) {
22769
22770                                 uniforms.alphaMap.value = material.alphaMap;
22771
22772                         }
22773
22774                         if ( material.specularMap ) {
22775
22776                                 uniforms.specularMap.value = material.specularMap;
22777
22778                         }
22779
22780                         if ( material.envMap ) {
22781
22782                                 uniforms.envMap.value = material.envMap;
22783
22784                                 // don't flip CubeTexture envMaps, flip everything else:
22785                                 //  WebGLRenderTargetCube will be flipped for backwards compatibility
22786                                 //  WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture
22787                                 // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future
22788                                 uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1;
22789
22790                                 uniforms.reflectivity.value = material.reflectivity;
22791                                 uniforms.refractionRatio.value = material.refractionRatio;
22792
22793                         }
22794
22795                         if ( material.lightMap ) {
22796
22797                                 uniforms.lightMap.value = material.lightMap;
22798                                 uniforms.lightMapIntensity.value = material.lightMapIntensity;
22799
22800                         }
22801
22802                         if ( material.aoMap ) {
22803
22804                                 uniforms.aoMap.value = material.aoMap;
22805                                 uniforms.aoMapIntensity.value = material.aoMapIntensity;
22806
22807                         }
22808
22809                         // uv repeat and offset setting priorities
22810                         // 1. color map
22811                         // 2. specular map
22812                         // 3. normal map
22813                         // 4. bump map
22814                         // 5. alpha map
22815                         // 6. emissive map
22816
22817                         var uvScaleMap;
22818
22819                         if ( material.map ) {
22820
22821                                 uvScaleMap = material.map;
22822
22823                         } else if ( material.specularMap ) {
22824
22825                                 uvScaleMap = material.specularMap;
22826
22827                         } else if ( material.displacementMap ) {
22828
22829                                 uvScaleMap = material.displacementMap;
22830
22831                         } else if ( material.normalMap ) {
22832
22833                                 uvScaleMap = material.normalMap;
22834
22835                         } else if ( material.bumpMap ) {
22836
22837                                 uvScaleMap = material.bumpMap;
22838
22839                         } else if ( material.roughnessMap ) {
22840
22841                                 uvScaleMap = material.roughnessMap;
22842
22843                         } else if ( material.metalnessMap ) {
22844
22845                                 uvScaleMap = material.metalnessMap;
22846
22847                         } else if ( material.alphaMap ) {
22848
22849                                 uvScaleMap = material.alphaMap;
22850
22851                         } else if ( material.emissiveMap ) {
22852
22853                                 uvScaleMap = material.emissiveMap;
22854
22855                         }
22856
22857                         if ( uvScaleMap !== undefined ) {
22858
22859                                 // backwards compatibility
22860                                 if ( uvScaleMap.isWebGLRenderTarget ) {
22861
22862                                         uvScaleMap = uvScaleMap.texture;
22863
22864                                 }
22865
22866                                 var offset = uvScaleMap.offset;
22867                                 var repeat = uvScaleMap.repeat;
22868
22869                                 uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
22870
22871                         }
22872
22873                 }
22874
22875                 function refreshUniformsLine( uniforms, material ) {
22876
22877                         uniforms.diffuse.value = material.color;
22878                         uniforms.opacity.value = material.opacity;
22879
22880                 }
22881
22882                 function refreshUniformsDash( uniforms, material ) {
22883
22884                         uniforms.dashSize.value = material.dashSize;
22885                         uniforms.totalSize.value = material.dashSize + material.gapSize;
22886                         uniforms.scale.value = material.scale;
22887
22888                 }
22889
22890                 function refreshUniformsPoints( uniforms, material ) {
22891
22892                         uniforms.diffuse.value = material.color;
22893                         uniforms.opacity.value = material.opacity;
22894                         uniforms.size.value = material.size * _pixelRatio;
22895                         uniforms.scale.value = _height * 0.5;
22896
22897                         uniforms.map.value = material.map;
22898
22899                         if ( material.map !== null ) {
22900
22901                                 var offset = material.map.offset;
22902                                 var repeat = material.map.repeat;
22903
22904                                 uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
22905
22906                         }
22907
22908                 }
22909
22910                 function refreshUniformsFog( uniforms, fog ) {
22911
22912                         uniforms.fogColor.value = fog.color;
22913
22914                         if ( fog.isFog ) {
22915
22916                                 uniforms.fogNear.value = fog.near;
22917                                 uniforms.fogFar.value = fog.far;
22918
22919                         } else if ( fog.isFogExp2 ) {
22920
22921                                 uniforms.fogDensity.value = fog.density;
22922
22923                         }
22924
22925                 }
22926
22927                 function refreshUniformsLambert( uniforms, material ) {
22928
22929                         if ( material.emissiveMap ) {
22930
22931                                 uniforms.emissiveMap.value = material.emissiveMap;
22932
22933                         }
22934
22935                 }
22936
22937                 function refreshUniformsPhong( uniforms, material ) {
22938
22939                         uniforms.specular.value = material.specular;
22940                         uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
22941
22942                         if ( material.emissiveMap ) {
22943
22944                                 uniforms.emissiveMap.value = material.emissiveMap;
22945
22946                         }
22947
22948                         if ( material.bumpMap ) {
22949
22950                                 uniforms.bumpMap.value = material.bumpMap;
22951                                 uniforms.bumpScale.value = material.bumpScale;
22952
22953                         }
22954
22955                         if ( material.normalMap ) {
22956
22957                                 uniforms.normalMap.value = material.normalMap;
22958                                 uniforms.normalScale.value.copy( material.normalScale );
22959
22960                         }
22961
22962                         if ( material.displacementMap ) {
22963
22964                                 uniforms.displacementMap.value = material.displacementMap;
22965                                 uniforms.displacementScale.value = material.displacementScale;
22966                                 uniforms.displacementBias.value = material.displacementBias;
22967
22968                         }
22969
22970                 }
22971
22972                 function refreshUniformsToon( uniforms, material ) {
22973
22974                         refreshUniformsPhong( uniforms, material );
22975
22976                         if ( material.gradientMap ) {
22977
22978                                 uniforms.gradientMap.value = material.gradientMap;
22979
22980                         }
22981
22982                 }
22983
22984                 function refreshUniformsStandard( uniforms, material ) {
22985
22986                         uniforms.roughness.value = material.roughness;
22987                         uniforms.metalness.value = material.metalness;
22988
22989                         if ( material.roughnessMap ) {
22990
22991                                 uniforms.roughnessMap.value = material.roughnessMap;
22992
22993                         }
22994
22995                         if ( material.metalnessMap ) {
22996
22997                                 uniforms.metalnessMap.value = material.metalnessMap;
22998
22999                         }
23000
23001                         if ( material.emissiveMap ) {
23002
23003                                 uniforms.emissiveMap.value = material.emissiveMap;
23004
23005                         }
23006
23007                         if ( material.bumpMap ) {
23008
23009                                 uniforms.bumpMap.value = material.bumpMap;
23010                                 uniforms.bumpScale.value = material.bumpScale;
23011
23012                         }
23013
23014                         if ( material.normalMap ) {
23015
23016                                 uniforms.normalMap.value = material.normalMap;
23017                                 uniforms.normalScale.value.copy( material.normalScale );
23018
23019                         }
23020
23021                         if ( material.displacementMap ) {
23022
23023                                 uniforms.displacementMap.value = material.displacementMap;
23024                                 uniforms.displacementScale.value = material.displacementScale;
23025                                 uniforms.displacementBias.value = material.displacementBias;
23026
23027                         }
23028
23029                         if ( material.envMap ) {
23030
23031                                 //uniforms.envMap.value = material.envMap; // part of uniforms common
23032                                 uniforms.envMapIntensity.value = material.envMapIntensity;
23033
23034                         }
23035
23036                 }
23037
23038                 function refreshUniformsPhysical( uniforms, material ) {
23039
23040                         uniforms.clearCoat.value = material.clearCoat;
23041                         uniforms.clearCoatRoughness.value = material.clearCoatRoughness;
23042
23043                         refreshUniformsStandard( uniforms, material );
23044
23045                 }
23046
23047                 function refreshUniformsDepth( uniforms, material ) {
23048
23049                         if ( material.displacementMap ) {
23050
23051                                 uniforms.displacementMap.value = material.displacementMap;
23052                                 uniforms.displacementScale.value = material.displacementScale;
23053                                 uniforms.displacementBias.value = material.displacementBias;
23054
23055                         }
23056
23057                 }
23058
23059                 function refreshUniformsDistance( uniforms, material ) {
23060
23061                         if ( material.displacementMap ) {
23062
23063                                 uniforms.displacementMap.value = material.displacementMap;
23064                                 uniforms.displacementScale.value = material.displacementScale;
23065                                 uniforms.displacementBias.value = material.displacementBias;
23066
23067                         }
23068
23069                         uniforms.referencePosition.value.copy( material.referencePosition );
23070                         uniforms.nearDistance.value = material.nearDistance;
23071                         uniforms.farDistance.value = material.farDistance;
23072
23073                 }
23074
23075                 function refreshUniformsNormal( uniforms, material ) {
23076
23077                         if ( material.bumpMap ) {
23078
23079                                 uniforms.bumpMap.value = material.bumpMap;
23080                                 uniforms.bumpScale.value = material.bumpScale;
23081
23082                         }
23083
23084                         if ( material.normalMap ) {
23085
23086                                 uniforms.normalMap.value = material.normalMap;
23087                                 uniforms.normalScale.value.copy( material.normalScale );
23088
23089                         }
23090
23091                         if ( material.displacementMap ) {
23092
23093                                 uniforms.displacementMap.value = material.displacementMap;
23094                                 uniforms.displacementScale.value = material.displacementScale;
23095                                 uniforms.displacementBias.value = material.displacementBias;
23096
23097                         }
23098
23099                 }
23100
23101                 // If uniforms are marked as clean, they don't need to be loaded to the GPU.
23102
23103                 function markUniformsLightsNeedsUpdate( uniforms, value ) {
23104
23105                         uniforms.ambientLightColor.needsUpdate = value;
23106
23107                         uniforms.directionalLights.needsUpdate = value;
23108                         uniforms.pointLights.needsUpdate = value;
23109                         uniforms.spotLights.needsUpdate = value;
23110                         uniforms.rectAreaLights.needsUpdate = value;
23111                         uniforms.hemisphereLights.needsUpdate = value;
23112
23113                 }
23114
23115                 // GL state setting
23116
23117                 this.setFaceCulling = function ( cullFace, frontFaceDirection ) {
23118
23119                         state.setCullFace( cullFace );
23120                         state.setFlipSided( frontFaceDirection === FrontFaceDirectionCW );
23121
23122                 };
23123
23124                 // Textures
23125
23126                 function allocTextureUnit() {
23127
23128                         var textureUnit = _usedTextureUnits;
23129
23130                         if ( textureUnit >= capabilities.maxTextures ) {
23131
23132                                 console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
23133
23134                         }
23135
23136                         _usedTextureUnits += 1;
23137
23138                         return textureUnit;
23139
23140                 }
23141
23142                 this.allocTextureUnit = allocTextureUnit;
23143
23144                 // this.setTexture2D = setTexture2D;
23145                 this.setTexture2D = ( function () {
23146
23147                         var warned = false;
23148
23149                         // backwards compatibility: peel texture.texture
23150                         return function setTexture2D( texture, slot ) {
23151
23152                                 if ( texture && texture.isWebGLRenderTarget ) {
23153
23154                                         if ( ! warned ) {
23155
23156                                                 console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." );
23157                                                 warned = true;
23158
23159                                         }
23160
23161                                         texture = texture.texture;
23162
23163                                 }
23164
23165                                 textures.setTexture2D( texture, slot );
23166
23167                         };
23168
23169                 }() );
23170
23171                 this.setTexture = ( function () {
23172
23173                         var warned = false;
23174
23175                         return function setTexture( texture, slot ) {
23176
23177                                 if ( ! warned ) {
23178
23179                                         console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." );
23180                                         warned = true;
23181
23182                                 }
23183
23184                                 textures.setTexture2D( texture, slot );
23185
23186                         };
23187
23188                 }() );
23189
23190                 this.setTextureCube = ( function () {
23191
23192                         var warned = false;
23193
23194                         return function setTextureCube( texture, slot ) {
23195
23196                                 // backwards compatibility: peel texture.texture
23197                                 if ( texture && texture.isWebGLRenderTargetCube ) {
23198
23199                                         if ( ! warned ) {
23200
23201                                                 console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." );
23202                                                 warned = true;
23203
23204                                         }
23205
23206                                         texture = texture.texture;
23207
23208                                 }
23209
23210                                 // currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture
23211                                 // TODO: unify these code paths
23212                                 if ( ( texture && texture.isCubeTexture ) ||
23213                                         ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
23214
23215                                         // CompressedTexture can have Array in image :/
23216
23217                                         // this function alone should take care of cube textures
23218                                         textures.setTextureCube( texture, slot );
23219
23220                                 } else {
23221
23222                                         // assumed: texture property of THREE.WebGLRenderTargetCube
23223
23224                                         textures.setTextureCubeDynamic( texture, slot );
23225
23226                                 }
23227
23228                         };
23229
23230                 }() );
23231
23232                 this.getRenderTarget = function () {
23233
23234                         return _currentRenderTarget;
23235
23236                 };
23237
23238                 this.setRenderTarget = function ( renderTarget ) {
23239
23240                         _currentRenderTarget = renderTarget;
23241
23242                         if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
23243
23244                                 textures.setupRenderTarget( renderTarget );
23245
23246                         }
23247
23248                         var framebuffer = null;
23249                         var isCube = false;
23250
23251                         if ( renderTarget ) {
23252
23253                                 var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
23254
23255                                 if ( renderTarget.isWebGLRenderTargetCube ) {
23256
23257                                         framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ];
23258                                         isCube = true;
23259
23260                                 } else {
23261
23262                                         framebuffer = __webglFramebuffer;
23263
23264                                 }
23265
23266                                 _currentViewport.copy( renderTarget.viewport );
23267                                 _currentScissor.copy( renderTarget.scissor );
23268                                 _currentScissorTest = renderTarget.scissorTest;
23269
23270                         } else {
23271
23272                                 _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio );
23273                                 _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio );
23274                                 _currentScissorTest = _scissorTest;
23275
23276                         }
23277
23278                         if ( _currentFramebuffer !== framebuffer ) {
23279
23280                                 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
23281                                 _currentFramebuffer = framebuffer;
23282
23283                         }
23284
23285                         state.viewport( _currentViewport );
23286                         state.scissor( _currentScissor );
23287                         state.setScissorTest( _currentScissorTest );
23288
23289                         if ( isCube ) {
23290
23291                                 var textureProperties = properties.get( renderTarget.texture );
23292                                 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel );
23293
23294                         }
23295
23296                 };
23297
23298                 this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) {
23299
23300                         if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
23301
23302                                 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
23303                                 return;
23304
23305                         }
23306
23307                         var framebuffer = properties.get( renderTarget ).__webglFramebuffer;
23308
23309                         if ( framebuffer ) {
23310
23311                                 var restore = false;
23312
23313                                 if ( framebuffer !== _currentFramebuffer ) {
23314
23315                                         _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
23316
23317                                         restore = true;
23318
23319                                 }
23320
23321                                 try {
23322
23323                                         var texture = renderTarget.texture;
23324                                         var textureFormat = texture.format;
23325                                         var textureType = texture.type;
23326
23327                                         if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
23328
23329                                                 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
23330                                                 return;
23331
23332                                         }
23333
23334                                         if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)
23335                                                 ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
23336                                                 ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
23337
23338                                                 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
23339                                                 return;
23340
23341                                         }
23342
23343                                         if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {
23344
23345                                                 // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
23346
23347                                                 if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
23348
23349                                                         _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
23350
23351                                                 }
23352
23353                                         } else {
23354
23355                                                 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
23356
23357                                         }
23358
23359                                 } finally {
23360
23361                                         if ( restore ) {
23362
23363                                                 _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );
23364
23365                                         }
23366
23367                                 }
23368
23369                         }
23370
23371                 };
23372
23373         }
23374
23375         /**
23376          * @author mrdoob / http://mrdoob.com/
23377          * @author alteredq / http://alteredqualia.com/
23378          */
23379
23380         function FogExp2 ( color, density ) {
23381
23382                 this.name = '';
23383
23384                 this.color = new Color( color );
23385                 this.density = ( density !== undefined ) ? density : 0.00025;
23386
23387         }
23388
23389         FogExp2.prototype.isFogExp2 = true;
23390
23391         FogExp2.prototype.clone = function () {
23392
23393                 return new FogExp2( this.color.getHex(), this.density );
23394
23395         };
23396
23397         FogExp2.prototype.toJSON = function ( meta ) {
23398
23399                 return {
23400                         type: 'FogExp2',
23401                         color: this.color.getHex(),
23402                         density: this.density
23403                 };
23404
23405         };
23406
23407         /**
23408          * @author mrdoob / http://mrdoob.com/
23409          * @author alteredq / http://alteredqualia.com/
23410          */
23411
23412         function Fog ( color, near, far ) {
23413
23414                 this.name = '';
23415
23416                 this.color = new Color( color );
23417
23418                 this.near = ( near !== undefined ) ? near : 1;
23419                 this.far = ( far !== undefined ) ? far : 1000;
23420
23421         }
23422
23423         Fog.prototype.isFog = true;
23424
23425         Fog.prototype.clone = function () {
23426
23427                 return new Fog( this.color.getHex(), this.near, this.far );
23428
23429         };
23430
23431         Fog.prototype.toJSON = function ( meta ) {
23432
23433                 return {
23434                         type: 'Fog',
23435                         color: this.color.getHex(),
23436                         near: this.near,
23437                         far: this.far
23438                 };
23439
23440         };
23441
23442         /**
23443          * @author mrdoob / http://mrdoob.com/
23444          */
23445
23446         function Scene () {
23447
23448                 Object3D.call( this );
23449
23450                 this.type = 'Scene';
23451
23452                 this.background = null;
23453                 this.fog = null;
23454                 this.overrideMaterial = null;
23455
23456                 this.autoUpdate = true; // checked by the renderer
23457
23458         }
23459
23460         Scene.prototype = Object.assign( Object.create( Object3D.prototype ), {
23461
23462                 constructor: Scene,
23463
23464                 copy: function ( source, recursive ) {
23465
23466                         Object3D.prototype.copy.call( this, source, recursive );
23467
23468                         if ( source.background !== null ) this.background = source.background.clone();
23469                         if ( source.fog !== null ) this.fog = source.fog.clone();
23470                         if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
23471
23472                         this.autoUpdate = source.autoUpdate;
23473                         this.matrixAutoUpdate = source.matrixAutoUpdate;
23474
23475                         return this;
23476
23477                 },
23478
23479                 toJSON: function ( meta ) {
23480
23481                         var data = Object3D.prototype.toJSON.call( this, meta );
23482
23483                         if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
23484                         if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
23485
23486                         return data;
23487
23488                 }
23489
23490         } );
23491
23492         /**
23493          * @author mikael emtinger / http://gomo.se/
23494          * @author alteredq / http://alteredqualia.com/
23495          */
23496
23497         function LensFlare( texture, size, distance, blending, color ) {
23498
23499                 Object3D.call( this );
23500
23501                 this.lensFlares = [];
23502
23503                 this.positionScreen = new Vector3();
23504                 this.customUpdateCallback = undefined;
23505
23506                 if ( texture !== undefined ) {
23507
23508                         this.add( texture, size, distance, blending, color );
23509
23510                 }
23511
23512         }
23513
23514         LensFlare.prototype = Object.assign( Object.create( Object3D.prototype ), {
23515
23516                 constructor: LensFlare,
23517
23518                 isLensFlare: true,
23519
23520                 copy: function ( source ) {
23521
23522                         Object3D.prototype.copy.call( this, source );
23523
23524                         this.positionScreen.copy( source.positionScreen );
23525                         this.customUpdateCallback = source.customUpdateCallback;
23526
23527                         for ( var i = 0, l = source.lensFlares.length; i < l; i ++ ) {
23528
23529                                 this.lensFlares.push( source.lensFlares[ i ] );
23530
23531                         }
23532
23533                         return this;
23534
23535                 },
23536
23537                 add: function ( texture, size, distance, blending, color, opacity ) {
23538
23539                         if ( size === undefined ) size = - 1;
23540                         if ( distance === undefined ) distance = 0;
23541                         if ( opacity === undefined ) opacity = 1;
23542                         if ( color === undefined ) color = new Color( 0xffffff );
23543                         if ( blending === undefined ) blending = NormalBlending;
23544
23545                         distance = Math.min( distance, Math.max( 0, distance ) );
23546
23547                         this.lensFlares.push( {
23548                                 texture: texture,       // THREE.Texture
23549                                 size: size,             // size in pixels (-1 = use texture.width)
23550                                 distance: distance,     // distance (0-1) from light source (0=at light source)
23551                                 x: 0, y: 0, z: 0,       // screen position (-1 => 1) z = 0 is in front z = 1 is back
23552                                 scale: 1,               // scale
23553                                 rotation: 0,            // rotation
23554                                 opacity: opacity,       // opacity
23555                                 color: color,           // color
23556                                 blending: blending      // blending
23557                         } );
23558
23559                 },
23560
23561                 /*
23562                  * Update lens flares update positions on all flares based on the screen position
23563                  * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way.
23564                  */
23565
23566                 updateLensFlares: function () {
23567
23568                         var f, fl = this.lensFlares.length;
23569                         var flare;
23570                         var vecX = - this.positionScreen.x * 2;
23571                         var vecY = - this.positionScreen.y * 2;
23572
23573                         for ( f = 0; f < fl; f ++ ) {
23574
23575                                 flare = this.lensFlares[ f ];
23576
23577                                 flare.x = this.positionScreen.x + vecX * flare.distance;
23578                                 flare.y = this.positionScreen.y + vecY * flare.distance;
23579
23580                                 flare.wantedRotation = flare.x * Math.PI * 0.25;
23581                                 flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25;
23582
23583                         }
23584
23585                 }
23586
23587         } );
23588
23589         /**
23590          * @author alteredq / http://alteredqualia.com/
23591          *
23592          * parameters = {
23593          *  color: <hex>,
23594          *  opacity: <float>,
23595          *  map: new THREE.Texture( <Image> ),
23596          *
23597          *      uvOffset: new THREE.Vector2(),
23598          *      uvScale: new THREE.Vector2()
23599          * }
23600          */
23601
23602         function SpriteMaterial( parameters ) {
23603
23604                 Material.call( this );
23605
23606                 this.type = 'SpriteMaterial';
23607
23608                 this.color = new Color( 0xffffff );
23609                 this.map = null;
23610
23611                 this.rotation = 0;
23612
23613                 this.fog = false;
23614                 this.lights = false;
23615
23616                 this.setValues( parameters );
23617
23618         }
23619
23620         SpriteMaterial.prototype = Object.create( Material.prototype );
23621         SpriteMaterial.prototype.constructor = SpriteMaterial;
23622         SpriteMaterial.prototype.isSpriteMaterial = true;
23623
23624         SpriteMaterial.prototype.copy = function ( source ) {
23625
23626                 Material.prototype.copy.call( this, source );
23627
23628                 this.color.copy( source.color );
23629                 this.map = source.map;
23630
23631                 this.rotation = source.rotation;
23632
23633                 return this;
23634
23635         };
23636
23637         /**
23638          * @author mikael emtinger / http://gomo.se/
23639          * @author alteredq / http://alteredqualia.com/
23640          */
23641
23642         function Sprite( material ) {
23643
23644                 Object3D.call( this );
23645
23646                 this.type = 'Sprite';
23647
23648                 this.material = ( material !== undefined ) ? material : new SpriteMaterial();
23649
23650         }
23651
23652         Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
23653
23654                 constructor: Sprite,
23655
23656                 isSprite: true,
23657
23658                 raycast: ( function () {
23659
23660                         var intersectPoint = new Vector3();
23661                         var worldPosition = new Vector3();
23662                         var worldScale = new Vector3();
23663
23664                         return function raycast( raycaster, intersects ) {
23665
23666                                 worldPosition.setFromMatrixPosition( this.matrixWorld );
23667                                 raycaster.ray.closestPointToPoint( worldPosition, intersectPoint );
23668
23669                                 worldScale.setFromMatrixScale( this.matrixWorld );
23670                                 var guessSizeSq = worldScale.x * worldScale.y / 4;
23671
23672                                 if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) return;
23673
23674                                 var distance = raycaster.ray.origin.distanceTo( intersectPoint );
23675
23676                                 if ( distance < raycaster.near || distance > raycaster.far ) return;
23677
23678                                 intersects.push( {
23679
23680                                         distance: distance,
23681                                         point: intersectPoint.clone(),
23682                                         face: null,
23683                                         object: this
23684
23685                                 } );
23686
23687                         };
23688
23689                 }() ),
23690
23691                 clone: function () {
23692
23693                         return new this.constructor( this.material ).copy( this );
23694
23695                 }
23696
23697         } );
23698
23699         /**
23700          * @author mikael emtinger / http://gomo.se/
23701          * @author alteredq / http://alteredqualia.com/
23702          * @author mrdoob / http://mrdoob.com/
23703          */
23704
23705         function LOD() {
23706
23707                 Object3D.call( this );
23708
23709                 this.type = 'LOD';
23710
23711                 Object.defineProperties( this, {
23712                         levels: {
23713                                 enumerable: true,
23714                                 value: []
23715                         }
23716                 } );
23717
23718         }
23719
23720         LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
23721
23722                 constructor: LOD,
23723
23724                 copy: function ( source ) {
23725
23726                         Object3D.prototype.copy.call( this, source, false );
23727
23728                         var levels = source.levels;
23729
23730                         for ( var i = 0, l = levels.length; i < l; i ++ ) {
23731
23732                                 var level = levels[ i ];
23733
23734                                 this.addLevel( level.object.clone(), level.distance );
23735
23736                         }
23737
23738                         return this;
23739
23740                 },
23741
23742                 addLevel: function ( object, distance ) {
23743
23744                         if ( distance === undefined ) distance = 0;
23745
23746                         distance = Math.abs( distance );
23747
23748                         var levels = this.levels;
23749
23750                         for ( var l = 0; l < levels.length; l ++ ) {
23751
23752                                 if ( distance < levels[ l ].distance ) {
23753
23754                                         break;
23755
23756                                 }
23757
23758                         }
23759
23760                         levels.splice( l, 0, { distance: distance, object: object } );
23761
23762                         this.add( object );
23763
23764                 },
23765
23766                 getObjectForDistance: function ( distance ) {
23767
23768                         var levels = this.levels;
23769
23770                         for ( var i = 1, l = levels.length; i < l; i ++ ) {
23771
23772                                 if ( distance < levels[ i ].distance ) {
23773
23774                                         break;
23775
23776                                 }
23777
23778                         }
23779
23780                         return levels[ i - 1 ].object;
23781
23782                 },
23783
23784                 raycast: ( function () {
23785
23786                         var matrixPosition = new Vector3();
23787
23788                         return function raycast( raycaster, intersects ) {
23789
23790                                 matrixPosition.setFromMatrixPosition( this.matrixWorld );
23791
23792                                 var distance = raycaster.ray.origin.distanceTo( matrixPosition );
23793
23794                                 this.getObjectForDistance( distance ).raycast( raycaster, intersects );
23795
23796                         };
23797
23798                 }() ),
23799
23800                 update: function () {
23801
23802                         var v1 = new Vector3();
23803                         var v2 = new Vector3();
23804
23805                         return function update( camera ) {
23806
23807                                 var levels = this.levels;
23808
23809                                 if ( levels.length > 1 ) {
23810
23811                                         v1.setFromMatrixPosition( camera.matrixWorld );
23812                                         v2.setFromMatrixPosition( this.matrixWorld );
23813
23814                                         var distance = v1.distanceTo( v2 );
23815
23816                                         levels[ 0 ].object.visible = true;
23817
23818                                         for ( var i = 1, l = levels.length; i < l; i ++ ) {
23819
23820                                                 if ( distance >= levels[ i ].distance ) {
23821
23822                                                         levels[ i - 1 ].object.visible = false;
23823                                                         levels[ i ].object.visible = true;
23824
23825                                                 } else {
23826
23827                                                         break;
23828
23829                                                 }
23830
23831                                         }
23832
23833                                         for ( ; i < l; i ++ ) {
23834
23835                                                 levels[ i ].object.visible = false;
23836
23837                                         }
23838
23839                                 }
23840
23841                         };
23842
23843                 }(),
23844
23845                 toJSON: function ( meta ) {
23846
23847                         var data = Object3D.prototype.toJSON.call( this, meta );
23848
23849                         data.object.levels = [];
23850
23851                         var levels = this.levels;
23852
23853                         for ( var i = 0, l = levels.length; i < l; i ++ ) {
23854
23855                                 var level = levels[ i ];
23856
23857                                 data.object.levels.push( {
23858                                         object: level.object.uuid,
23859                                         distance: level.distance
23860                                 } );
23861
23862                         }
23863
23864                         return data;
23865
23866                 }
23867
23868         } );
23869
23870         /**
23871          * @author mikael emtinger / http://gomo.se/
23872          * @author alteredq / http://alteredqualia.com/
23873          * @author michael guerrero / http://realitymeltdown.com
23874          * @author ikerr / http://verold.com
23875          */
23876
23877         function Skeleton( bones, boneInverses ) {
23878
23879                 // copy the bone array
23880
23881                 bones = bones || [];
23882
23883                 this.bones = bones.slice( 0 );
23884                 this.boneMatrices = new Float32Array( this.bones.length * 16 );
23885
23886                 // use the supplied bone inverses or calculate the inverses
23887
23888                 if ( boneInverses === undefined ) {
23889
23890                         this.calculateInverses();
23891
23892                 } else {
23893
23894                         if ( this.bones.length === boneInverses.length ) {
23895
23896                                 this.boneInverses = boneInverses.slice( 0 );
23897
23898                         } else {
23899
23900                                 console.warn( 'THREE.Skeleton boneInverses is the wrong length.' );
23901
23902                                 this.boneInverses = [];
23903
23904                                 for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
23905
23906                                         this.boneInverses.push( new Matrix4() );
23907
23908                                 }
23909
23910                         }
23911
23912                 }
23913
23914         }
23915
23916         Object.assign( Skeleton.prototype, {
23917
23918                 calculateInverses: function () {
23919
23920                         this.boneInverses = [];
23921
23922                         for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
23923
23924                                 var inverse = new Matrix4();
23925
23926                                 if ( this.bones[ i ] ) {
23927
23928                                         inverse.getInverse( this.bones[ i ].matrixWorld );
23929
23930                                 }
23931
23932                                 this.boneInverses.push( inverse );
23933
23934                         }
23935
23936                 },
23937
23938                 pose: function () {
23939
23940                         var bone, i, il;
23941
23942                         // recover the bind-time world matrices
23943
23944                         for ( i = 0, il = this.bones.length; i < il; i ++ ) {
23945
23946                                 bone = this.bones[ i ];
23947
23948                                 if ( bone ) {
23949
23950                                         bone.matrixWorld.getInverse( this.boneInverses[ i ] );
23951
23952                                 }
23953
23954                         }
23955
23956                         // compute the local matrices, positions, rotations and scales
23957
23958                         for ( i = 0, il = this.bones.length; i < il; i ++ ) {
23959
23960                                 bone = this.bones[ i ];
23961
23962                                 if ( bone ) {
23963
23964                                         if ( bone.parent && bone.parent.isBone ) {
23965
23966                                                 bone.matrix.getInverse( bone.parent.matrixWorld );
23967                                                 bone.matrix.multiply( bone.matrixWorld );
23968
23969                                         } else {
23970
23971                                                 bone.matrix.copy( bone.matrixWorld );
23972
23973                                         }
23974
23975                                         bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
23976
23977                                 }
23978
23979                         }
23980
23981                 },
23982
23983                 update: ( function () {
23984
23985                         var offsetMatrix = new Matrix4();
23986                         var identityMatrix = new Matrix4();
23987
23988                         return function update() {
23989
23990                                 var bones = this.bones;
23991                                 var boneInverses = this.boneInverses;
23992                                 var boneMatrices = this.boneMatrices;
23993                                 var boneTexture = this.boneTexture;
23994
23995                                 // flatten bone matrices to array
23996
23997                                 for ( var i = 0, il = bones.length; i < il; i ++ ) {
23998
23999                                         // compute the offset between the current and the original transform
24000
24001                                         var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix;
24002
24003                                         offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
24004                                         offsetMatrix.toArray( boneMatrices, i * 16 );
24005
24006                                 }
24007
24008                                 if ( boneTexture !== undefined ) {
24009
24010                                         boneTexture.needsUpdate = true;
24011
24012                                 }
24013
24014                         };
24015
24016                 } )(),
24017
24018                 clone: function () {
24019
24020                         return new Skeleton( this.bones, this.boneInverses );
24021
24022                 }
24023
24024         } );
24025
24026         /**
24027          * @author mikael emtinger / http://gomo.se/
24028          * @author alteredq / http://alteredqualia.com/
24029          * @author ikerr / http://verold.com
24030          */
24031
24032         function Bone() {
24033
24034                 Object3D.call( this );
24035
24036                 this.type = 'Bone';
24037
24038         }
24039
24040         Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
24041
24042                 constructor: Bone,
24043
24044                 isBone: true
24045
24046         } );
24047
24048         /**
24049          * @author mikael emtinger / http://gomo.se/
24050          * @author alteredq / http://alteredqualia.com/
24051          * @author ikerr / http://verold.com
24052          */
24053
24054         function SkinnedMesh( geometry, material ) {
24055
24056                 Mesh.call( this, geometry, material );
24057
24058                 this.type = 'SkinnedMesh';
24059
24060                 this.bindMode = 'attached';
24061                 this.bindMatrix = new Matrix4();
24062                 this.bindMatrixInverse = new Matrix4();
24063
24064                 var bones = this.initBones();
24065                 var skeleton = new Skeleton( bones );
24066
24067                 this.bind( skeleton, this.matrixWorld );
24068
24069                 this.normalizeSkinWeights();
24070
24071         }
24072
24073         SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
24074
24075                 constructor: SkinnedMesh,
24076
24077                 isSkinnedMesh: true,
24078
24079                 initBones: function () {
24080
24081                         var bones = [], bone, gbone;
24082                         var i, il;
24083
24084                         if ( this.geometry && this.geometry.bones !== undefined ) {
24085
24086                                 // first, create array of 'Bone' objects from geometry data
24087
24088                                 for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
24089
24090                                         gbone = this.geometry.bones[ i ];
24091
24092                                         // create new 'Bone' object
24093
24094                                         bone = new Bone();
24095                                         bones.push( bone );
24096
24097                                         // apply values
24098
24099                                         bone.name = gbone.name;
24100                                         bone.position.fromArray( gbone.pos );
24101                                         bone.quaternion.fromArray( gbone.rotq );
24102                                         if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
24103
24104                                 }
24105
24106                                 // second, create bone hierarchy
24107
24108                                 for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
24109
24110                                         gbone = this.geometry.bones[ i ];
24111
24112                                         if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
24113
24114                                                 // subsequent bones in the hierarchy
24115
24116                                                 bones[ gbone.parent ].add( bones[ i ] );
24117
24118                                         } else {
24119
24120                                                 // topmost bone, immediate child of the skinned mesh
24121
24122                                                 this.add( bones[ i ] );
24123
24124                                         }
24125
24126                                 }
24127
24128                         }
24129
24130                         // now the bones are part of the scene graph and children of the skinned mesh.
24131                         // let's update the corresponding matrices
24132
24133                         this.updateMatrixWorld( true );
24134
24135                         return bones;
24136
24137                 },
24138
24139                 bind: function ( skeleton, bindMatrix ) {
24140
24141                         this.skeleton = skeleton;
24142
24143                         if ( bindMatrix === undefined ) {
24144
24145                                 this.updateMatrixWorld( true );
24146
24147                                 this.skeleton.calculateInverses();
24148
24149                                 bindMatrix = this.matrixWorld;
24150
24151                         }
24152
24153                         this.bindMatrix.copy( bindMatrix );
24154                         this.bindMatrixInverse.getInverse( bindMatrix );
24155
24156                 },
24157
24158                 pose: function () {
24159
24160                         this.skeleton.pose();
24161
24162                 },
24163
24164                 normalizeSkinWeights: function () {
24165
24166                         var scale, i;
24167
24168                         if ( this.geometry && this.geometry.isGeometry ) {
24169
24170                                 for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) {
24171
24172                                         var sw = this.geometry.skinWeights[ i ];
24173
24174                                         scale = 1.0 / sw.lengthManhattan();
24175
24176                                         if ( scale !== Infinity ) {
24177
24178                                                 sw.multiplyScalar( scale );
24179
24180                                         } else {
24181
24182                                                 sw.set( 1, 0, 0, 0 ); // do something reasonable
24183
24184                                         }
24185
24186                                 }
24187
24188                         } else if ( this.geometry && this.geometry.isBufferGeometry ) {
24189
24190                                 var vec = new Vector4();
24191
24192                                 var skinWeight = this.geometry.attributes.skinWeight;
24193
24194                                 for ( i = 0; i < skinWeight.count; i ++ ) {
24195
24196                                         vec.x = skinWeight.getX( i );
24197                                         vec.y = skinWeight.getY( i );
24198                                         vec.z = skinWeight.getZ( i );
24199                                         vec.w = skinWeight.getW( i );
24200
24201                                         scale = 1.0 / vec.lengthManhattan();
24202
24203                                         if ( scale !== Infinity ) {
24204
24205                                                 vec.multiplyScalar( scale );
24206
24207                                         } else {
24208
24209                                                 vec.set( 1, 0, 0, 0 ); // do something reasonable
24210
24211                                         }
24212
24213                                         skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w );
24214
24215                                 }
24216
24217                         }
24218
24219                 },
24220
24221                 updateMatrixWorld: function ( force ) {
24222
24223                         Mesh.prototype.updateMatrixWorld.call( this, force );
24224
24225                         if ( this.bindMode === 'attached' ) {
24226
24227                                 this.bindMatrixInverse.getInverse( this.matrixWorld );
24228
24229                         } else if ( this.bindMode === 'detached' ) {
24230
24231                                 this.bindMatrixInverse.getInverse( this.bindMatrix );
24232
24233                         } else {
24234
24235                                 console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
24236
24237                         }
24238
24239                 },
24240
24241                 clone: function () {
24242
24243                         return new this.constructor( this.geometry, this.material ).copy( this );
24244
24245                 }
24246
24247         } );
24248
24249         /**
24250          * @author mrdoob / http://mrdoob.com/
24251          * @author alteredq / http://alteredqualia.com/
24252          *
24253          * parameters = {
24254          *  color: <hex>,
24255          *  opacity: <float>,
24256          *
24257          *  linewidth: <float>,
24258          *  linecap: "round",
24259          *  linejoin: "round"
24260          * }
24261          */
24262
24263         function LineBasicMaterial( parameters ) {
24264
24265                 Material.call( this );
24266
24267                 this.type = 'LineBasicMaterial';
24268
24269                 this.color = new Color( 0xffffff );
24270
24271                 this.linewidth = 1;
24272                 this.linecap = 'round';
24273                 this.linejoin = 'round';
24274
24275                 this.lights = false;
24276
24277                 this.setValues( parameters );
24278
24279         }
24280
24281         LineBasicMaterial.prototype = Object.create( Material.prototype );
24282         LineBasicMaterial.prototype.constructor = LineBasicMaterial;
24283
24284         LineBasicMaterial.prototype.isLineBasicMaterial = true;
24285
24286         LineBasicMaterial.prototype.copy = function ( source ) {
24287
24288                 Material.prototype.copy.call( this, source );
24289
24290                 this.color.copy( source.color );
24291
24292                 this.linewidth = source.linewidth;
24293                 this.linecap = source.linecap;
24294                 this.linejoin = source.linejoin;
24295
24296                 return this;
24297
24298         };
24299
24300         /**
24301          * @author mrdoob / http://mrdoob.com/
24302          */
24303
24304         function Line( geometry, material, mode ) {
24305
24306                 if ( mode === 1 ) {
24307
24308                         console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' );
24309                         return new LineSegments( geometry, material );
24310
24311                 }
24312
24313                 Object3D.call( this );
24314
24315                 this.type = 'Line';
24316
24317                 this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
24318                 this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } );
24319
24320         }
24321
24322         Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
24323
24324                 constructor: Line,
24325
24326                 isLine: true,
24327
24328                 raycast: ( function () {
24329
24330                         var inverseMatrix = new Matrix4();
24331                         var ray = new Ray();
24332                         var sphere = new Sphere();
24333
24334                         return function raycast( raycaster, intersects ) {
24335
24336                                 var precision = raycaster.linePrecision;
24337                                 var precisionSq = precision * precision;
24338
24339                                 var geometry = this.geometry;
24340                                 var matrixWorld = this.matrixWorld;
24341
24342                                 // Checking boundingSphere distance to ray
24343
24344                                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
24345
24346                                 sphere.copy( geometry.boundingSphere );
24347                                 sphere.applyMatrix4( matrixWorld );
24348
24349                                 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
24350
24351                                 //
24352
24353                                 inverseMatrix.getInverse( matrixWorld );
24354                                 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
24355
24356                                 var vStart = new Vector3();
24357                                 var vEnd = new Vector3();
24358                                 var interSegment = new Vector3();
24359                                 var interRay = new Vector3();
24360                                 var step = (this && this.isLineSegments) ? 2 : 1;
24361
24362                                 if ( geometry.isBufferGeometry ) {
24363
24364                                         var index = geometry.index;
24365                                         var attributes = geometry.attributes;
24366                                         var positions = attributes.position.array;
24367
24368                                         if ( index !== null ) {
24369
24370                                                 var indices = index.array;
24371
24372                                                 for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
24373
24374                                                         var a = indices[ i ];
24375                                                         var b = indices[ i + 1 ];
24376
24377                                                         vStart.fromArray( positions, a * 3 );
24378                                                         vEnd.fromArray( positions, b * 3 );
24379
24380                                                         var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
24381
24382                                                         if ( distSq > precisionSq ) continue;
24383
24384                                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
24385
24386                                                         var distance = raycaster.ray.origin.distanceTo( interRay );
24387
24388                                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
24389
24390                                                         intersects.push( {
24391
24392                                                                 distance: distance,
24393                                                                 // What do we want? intersection point on the ray or on the segment??
24394                                                                 // point: raycaster.ray.at( distance ),
24395                                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
24396                                                                 index: i,
24397                                                                 face: null,
24398                                                                 faceIndex: null,
24399                                                                 object: this
24400
24401                                                         } );
24402
24403                                                 }
24404
24405                                         } else {
24406
24407                                                 for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
24408
24409                                                         vStart.fromArray( positions, 3 * i );
24410                                                         vEnd.fromArray( positions, 3 * i + 3 );
24411
24412                                                         var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
24413
24414                                                         if ( distSq > precisionSq ) continue;
24415
24416                                                         interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
24417
24418                                                         var distance = raycaster.ray.origin.distanceTo( interRay );
24419
24420                                                         if ( distance < raycaster.near || distance > raycaster.far ) continue;
24421
24422                                                         intersects.push( {
24423
24424                                                                 distance: distance,
24425                                                                 // What do we want? intersection point on the ray or on the segment??
24426                                                                 // point: raycaster.ray.at( distance ),
24427                                                                 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
24428                                                                 index: i,
24429                                                                 face: null,
24430                                                                 faceIndex: null,
24431                                                                 object: this
24432
24433                                                         } );
24434
24435                                                 }
24436
24437                                         }
24438
24439                                 } else if ( geometry.isGeometry ) {
24440
24441                                         var vertices = geometry.vertices;
24442                                         var nbVertices = vertices.length;
24443
24444                                         for ( var i = 0; i < nbVertices - 1; i += step ) {
24445
24446                                                 var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
24447
24448                                                 if ( distSq > precisionSq ) continue;
24449
24450                                                 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
24451
24452                                                 var distance = raycaster.ray.origin.distanceTo( interRay );
24453
24454                                                 if ( distance < raycaster.near || distance > raycaster.far ) continue;
24455
24456                                                 intersects.push( {
24457
24458                                                         distance: distance,
24459                                                         // What do we want? intersection point on the ray or on the segment??
24460                                                         // point: raycaster.ray.at( distance ),
24461                                                         point: interSegment.clone().applyMatrix4( this.matrixWorld ),
24462                                                         index: i,
24463                                                         face: null,
24464                                                         faceIndex: null,
24465                                                         object: this
24466
24467                                                 } );
24468
24469                                         }
24470
24471                                 }
24472
24473                         };
24474
24475                 }() ),
24476
24477                 clone: function () {
24478
24479                         return new this.constructor( this.geometry, this.material ).copy( this );
24480
24481                 }
24482
24483         } );
24484
24485         /**
24486          * @author mrdoob / http://mrdoob.com/
24487          */
24488
24489         function LineSegments( geometry, material ) {
24490
24491                 Line.call( this, geometry, material );
24492
24493                 this.type = 'LineSegments';
24494
24495         }
24496
24497         LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
24498
24499                 constructor: LineSegments,
24500
24501                 isLineSegments: true
24502
24503         } );
24504
24505         /**
24506          * @author mgreter / http://github.com/mgreter
24507          */
24508
24509         function LineLoop( geometry, material ) {
24510
24511                 Line.call( this, geometry, material );
24512
24513                 this.type = 'LineLoop';
24514
24515         }
24516
24517         LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
24518
24519                 constructor: LineLoop,
24520
24521                 isLineLoop: true,
24522
24523         } );
24524
24525         /**
24526          * @author mrdoob / http://mrdoob.com/
24527          * @author alteredq / http://alteredqualia.com/
24528          *
24529          * parameters = {
24530          *  color: <hex>,
24531          *  opacity: <float>,
24532          *  map: new THREE.Texture( <Image> ),
24533          *
24534          *  size: <float>,
24535          *  sizeAttenuation: <bool>
24536          * }
24537          */
24538
24539         function PointsMaterial( parameters ) {
24540
24541                 Material.call( this );
24542
24543                 this.type = 'PointsMaterial';
24544
24545                 this.color = new Color( 0xffffff );
24546
24547                 this.map = null;
24548
24549                 this.size = 1;
24550                 this.sizeAttenuation = true;
24551
24552                 this.lights = false;
24553
24554                 this.setValues( parameters );
24555
24556         }
24557
24558         PointsMaterial.prototype = Object.create( Material.prototype );
24559         PointsMaterial.prototype.constructor = PointsMaterial;
24560
24561         PointsMaterial.prototype.isPointsMaterial = true;
24562
24563         PointsMaterial.prototype.copy = function ( source ) {
24564
24565                 Material.prototype.copy.call( this, source );
24566
24567                 this.color.copy( source.color );
24568
24569                 this.map = source.map;
24570
24571                 this.size = source.size;
24572                 this.sizeAttenuation = source.sizeAttenuation;
24573
24574                 return this;
24575
24576         };
24577
24578         /**
24579          * @author alteredq / http://alteredqualia.com/
24580          */
24581
24582         function Points( geometry, material ) {
24583
24584                 Object3D.call( this );
24585
24586                 this.type = 'Points';
24587
24588                 this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
24589                 this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } );
24590
24591         }
24592
24593         Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
24594
24595                 constructor: Points,
24596
24597                 isPoints: true,
24598
24599                 raycast: ( function () {
24600
24601                         var inverseMatrix = new Matrix4();
24602                         var ray = new Ray();
24603                         var sphere = new Sphere();
24604
24605                         return function raycast( raycaster, intersects ) {
24606
24607                                 var object = this;
24608                                 var geometry = this.geometry;
24609                                 var matrixWorld = this.matrixWorld;
24610                                 var threshold = raycaster.params.Points.threshold;
24611
24612                                 // Checking boundingSphere distance to ray
24613
24614                                 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
24615
24616                                 sphere.copy( geometry.boundingSphere );
24617                                 sphere.applyMatrix4( matrixWorld );
24618                                 sphere.radius += threshold;
24619
24620                                 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
24621
24622                                 //
24623
24624                                 inverseMatrix.getInverse( matrixWorld );
24625                                 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
24626
24627                                 var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
24628                                 var localThresholdSq = localThreshold * localThreshold;
24629                                 var position = new Vector3();
24630
24631                                 function testPoint( point, index ) {
24632
24633                                         var rayPointDistanceSq = ray.distanceSqToPoint( point );
24634
24635                                         if ( rayPointDistanceSq < localThresholdSq ) {
24636
24637                                                 var intersectPoint = ray.closestPointToPoint( point );
24638                                                 intersectPoint.applyMatrix4( matrixWorld );
24639
24640                                                 var distance = raycaster.ray.origin.distanceTo( intersectPoint );
24641
24642                                                 if ( distance < raycaster.near || distance > raycaster.far ) return;
24643
24644                                                 intersects.push( {
24645
24646                                                         distance: distance,
24647                                                         distanceToRay: Math.sqrt( rayPointDistanceSq ),
24648                                                         point: intersectPoint.clone(),
24649                                                         index: index,
24650                                                         face: null,
24651                                                         object: object
24652
24653                                                 } );
24654
24655                                         }
24656
24657                                 }
24658
24659                                 if ( geometry.isBufferGeometry ) {
24660
24661                                         var index = geometry.index;
24662                                         var attributes = geometry.attributes;
24663                                         var positions = attributes.position.array;
24664
24665                                         if ( index !== null ) {
24666
24667                                                 var indices = index.array;
24668
24669                                                 for ( var i = 0, il = indices.length; i < il; i ++ ) {
24670
24671                                                         var a = indices[ i ];
24672
24673                                                         position.fromArray( positions, a * 3 );
24674
24675                                                         testPoint( position, a );
24676
24677                                                 }
24678
24679                                         } else {
24680
24681                                                 for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
24682
24683                                                         position.fromArray( positions, i * 3 );
24684
24685                                                         testPoint( position, i );
24686
24687                                                 }
24688
24689                                         }
24690
24691                                 } else {
24692
24693                                         var vertices = geometry.vertices;
24694
24695                                         for ( var i = 0, l = vertices.length; i < l; i ++ ) {
24696
24697                                                 testPoint( vertices[ i ], i );
24698
24699                                         }
24700
24701                                 }
24702
24703                         };
24704
24705                 }() ),
24706
24707                 clone: function () {
24708
24709                         return new this.constructor( this.geometry, this.material ).copy( this );
24710
24711                 }
24712
24713         } );
24714
24715         /**
24716          * @author mrdoob / http://mrdoob.com/
24717          */
24718
24719         function Group() {
24720
24721                 Object3D.call( this );
24722
24723                 this.type = 'Group';
24724
24725         }
24726
24727         Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
24728
24729                 constructor: Group
24730
24731         } );
24732
24733         /**
24734          * @author mrdoob / http://mrdoob.com/
24735          */
24736
24737         function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
24738
24739                 Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
24740
24741                 this.generateMipmaps = false;
24742
24743                 var scope = this;
24744
24745                 function update() {
24746
24747                         requestAnimationFrame( update );
24748
24749                         if ( video.readyState >= video.HAVE_CURRENT_DATA ) {
24750
24751                                 scope.needsUpdate = true;
24752
24753                         }
24754
24755                 }
24756
24757                 update();
24758
24759         }
24760
24761         VideoTexture.prototype = Object.create( Texture.prototype );
24762         VideoTexture.prototype.constructor = VideoTexture;
24763
24764         /**
24765          * @author alteredq / http://alteredqualia.com/
24766          */
24767
24768         function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
24769
24770                 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
24771
24772                 this.image = { width: width, height: height };
24773                 this.mipmaps = mipmaps;
24774
24775                 // no flipping for cube textures
24776                 // (also flipping doesn't work for compressed textures )
24777
24778                 this.flipY = false;
24779
24780                 // can't generate mipmaps for compressed textures
24781                 // mips must be embedded in DDS files
24782
24783                 this.generateMipmaps = false;
24784
24785         }
24786
24787         CompressedTexture.prototype = Object.create( Texture.prototype );
24788         CompressedTexture.prototype.constructor = CompressedTexture;
24789
24790         CompressedTexture.prototype.isCompressedTexture = true;
24791
24792         /**
24793          * @author Matt DesLauriers / @mattdesl
24794          * @author atix / arthursilber.de
24795          */
24796
24797         function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
24798
24799                 format = format !== undefined ? format : DepthFormat;
24800
24801                 if ( format !== DepthFormat && format !== DepthStencilFormat ) {
24802
24803                         throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
24804
24805                 }
24806
24807                 if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
24808                 if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
24809
24810                 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
24811
24812                 this.image = { width: width, height: height };
24813
24814                 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
24815                 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
24816
24817                 this.flipY = false;
24818                 this.generateMipmaps    = false;
24819
24820         }
24821
24822         DepthTexture.prototype = Object.create( Texture.prototype );
24823         DepthTexture.prototype.constructor = DepthTexture;
24824         DepthTexture.prototype.isDepthTexture = true;
24825
24826         /**
24827          * @author mrdoob / http://mrdoob.com/
24828          * @author Mugen87 / https://github.com/Mugen87
24829          */
24830
24831         function WireframeGeometry( geometry ) {
24832
24833                 BufferGeometry.call( this );
24834
24835                 this.type = 'WireframeGeometry';
24836
24837                 // buffer
24838
24839                 var vertices = [];
24840
24841                 // helper variables
24842
24843                 var i, j, l, o, ol;
24844                 var edge = [ 0, 0 ], edges = {}, e, edge1, edge2;
24845                 var key, keys = [ 'a', 'b', 'c' ];
24846                 var vertex;
24847
24848                 // different logic for Geometry and BufferGeometry
24849
24850                 if ( geometry && geometry.isGeometry ) {
24851
24852                         // create a data structure that contains all edges without duplicates
24853
24854                         var faces = geometry.faces;
24855
24856                         for ( i = 0, l = faces.length; i < l; i ++ ) {
24857
24858                                 var face = faces[ i ];
24859
24860                                 for ( j = 0; j < 3; j ++ ) {
24861
24862                                         edge1 = face[ keys[ j ] ];
24863                                         edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
24864                                         edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
24865                                         edge[ 1 ] = Math.max( edge1, edge2 );
24866
24867                                         key = edge[ 0 ] + ',' + edge[ 1 ];
24868
24869                                         if ( edges[ key ] === undefined ) {
24870
24871                                                 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
24872
24873                                         }
24874
24875                                 }
24876
24877                         }
24878
24879                         // generate vertices
24880
24881                         for ( key in edges ) {
24882
24883                                 e = edges[ key ];
24884
24885                                 vertex = geometry.vertices[ e.index1 ];
24886                                 vertices.push( vertex.x, vertex.y, vertex.z );
24887
24888                                 vertex = geometry.vertices[ e.index2 ];
24889                                 vertices.push( vertex.x, vertex.y, vertex.z );
24890
24891                         }
24892
24893                 } else if ( geometry && geometry.isBufferGeometry ) {
24894
24895                         var position, indices, groups;
24896                         var group, start, count;
24897                         var index1, index2;
24898
24899                         vertex = new Vector3();
24900
24901                         if ( geometry.index !== null ) {
24902
24903                                 // indexed BufferGeometry
24904
24905                                 position = geometry.attributes.position;
24906                                 indices = geometry.index;
24907                                 groups = geometry.groups;
24908
24909                                 if ( groups.length === 0 ) {
24910
24911                                         groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
24912
24913                                 }
24914
24915                                 // create a data structure that contains all eges without duplicates
24916
24917                                 for ( o = 0, ol = groups.length; o < ol; ++ o ) {
24918
24919                                         group = groups[ o ];
24920
24921                                         start = group.start;
24922                                         count = group.count;
24923
24924                                         for ( i = start, l = ( start + count ); i < l; i += 3 ) {
24925
24926                                                 for ( j = 0; j < 3; j ++ ) {
24927
24928                                                         edge1 = indices.getX( i + j );
24929                                                         edge2 = indices.getX( i + ( j + 1 ) % 3 );
24930                                                         edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
24931                                                         edge[ 1 ] = Math.max( edge1, edge2 );
24932
24933                                                         key = edge[ 0 ] + ',' + edge[ 1 ];
24934
24935                                                         if ( edges[ key ] === undefined ) {
24936
24937                                                                 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
24938
24939                                                         }
24940
24941                                                 }
24942
24943                                         }
24944
24945                                 }
24946
24947                                 // generate vertices
24948
24949                                 for ( key in edges ) {
24950
24951                                         e = edges[ key ];
24952
24953                                         vertex.fromBufferAttribute( position, e.index1 );
24954                                         vertices.push( vertex.x, vertex.y, vertex.z );
24955
24956                                         vertex.fromBufferAttribute( position, e.index2 );
24957                                         vertices.push( vertex.x, vertex.y, vertex.z );
24958
24959                                 }
24960
24961                         } else {
24962
24963                                 // non-indexed BufferGeometry
24964
24965                                 position = geometry.attributes.position;
24966
24967                                 for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
24968
24969                                         for ( j = 0; j < 3; j ++ ) {
24970
24971                                                 // three edges per triangle, an edge is represented as (index1, index2)
24972                                                 // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
24973
24974                                                 index1 = 3 * i + j;
24975                                                 vertex.fromBufferAttribute( position, index1 );
24976                                                 vertices.push( vertex.x, vertex.y, vertex.z );
24977
24978                                                 index2 = 3 * i + ( ( j + 1 ) % 3 );
24979                                                 vertex.fromBufferAttribute( position, index2 );
24980                                                 vertices.push( vertex.x, vertex.y, vertex.z );
24981
24982                                         }
24983
24984                                 }
24985
24986                         }
24987
24988                 }
24989
24990                 // build geometry
24991
24992                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
24993
24994         }
24995
24996         WireframeGeometry.prototype = Object.create( BufferGeometry.prototype );
24997         WireframeGeometry.prototype.constructor = WireframeGeometry;
24998
24999         /**
25000          * @author zz85 / https://github.com/zz85
25001          * @author Mugen87 / https://github.com/Mugen87
25002          *
25003          * Parametric Surfaces Geometry
25004          * based on the brilliant article by @prideout http://prideout.net/blog/?p=44
25005          */
25006
25007         // ParametricGeometry
25008
25009         function ParametricGeometry( func, slices, stacks ) {
25010
25011                 Geometry.call( this );
25012
25013                 this.type = 'ParametricGeometry';
25014
25015                 this.parameters = {
25016                         func: func,
25017                         slices: slices,
25018                         stacks: stacks
25019                 };
25020
25021                 this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
25022                 this.mergeVertices();
25023
25024         }
25025
25026         ParametricGeometry.prototype = Object.create( Geometry.prototype );
25027         ParametricGeometry.prototype.constructor = ParametricGeometry;
25028
25029         // ParametricBufferGeometry
25030
25031         function ParametricBufferGeometry( func, slices, stacks ) {
25032
25033                 BufferGeometry.call( this );
25034
25035                 this.type = 'ParametricBufferGeometry';
25036
25037                 this.parameters = {
25038                         func: func,
25039                         slices: slices,
25040                         stacks: stacks
25041                 };
25042
25043                 // buffers
25044
25045                 var indices = [];
25046                 var vertices = [];
25047                 var normals = [];
25048                 var uvs = [];
25049
25050                 var EPS = 0.00001;
25051
25052                 var normal = new Vector3();
25053
25054                 var p0 = new Vector3(), p1 = new Vector3();
25055                 var pu = new Vector3(), pv = new Vector3();
25056
25057                 var i, j;
25058
25059                 // generate vertices, normals and uvs
25060
25061                 var sliceCount = slices + 1;
25062
25063                 for ( i = 0; i <= stacks; i ++ ) {
25064
25065                         var v = i / stacks;
25066
25067                         for ( j = 0; j <= slices; j ++ ) {
25068
25069                                 var u = j / slices;
25070
25071                                 // vertex
25072
25073                                 p0 = func( u, v, p0 );
25074                                 vertices.push( p0.x, p0.y, p0.z );
25075
25076                                 // normal
25077
25078                                 // approximate tangent vectors via finite differences
25079
25080                                 if ( u - EPS >= 0 ) {
25081
25082                                         p1 = func( u - EPS, v, p1 );
25083                                         pu.subVectors( p0, p1 );
25084
25085                                 } else {
25086
25087                                         p1 = func( u + EPS, v, p1 );
25088                                         pu.subVectors( p1, p0 );
25089
25090                                 }
25091
25092                                 if ( v - EPS >= 0 ) {
25093
25094                                         p1 = func( u, v - EPS, p1 );
25095                                         pv.subVectors( p0, p1 );
25096
25097                                 } else {
25098
25099                                         p1 = func( u, v + EPS, p1 );
25100                                         pv.subVectors( p1, p0 );
25101
25102                                 }
25103
25104                                 // cross product of tangent vectors returns surface normal
25105
25106                                 normal.crossVectors( pu, pv ).normalize();
25107                                 normals.push( normal.x, normal.y, normal.z );
25108
25109                                 // uv
25110
25111                                 uvs.push( u, v );
25112
25113                         }
25114
25115                 }
25116
25117                 // generate indices
25118
25119                 for ( i = 0; i < stacks; i ++ ) {
25120
25121                         for ( j = 0; j < slices; j ++ ) {
25122
25123                                 var a = i * sliceCount + j;
25124                                 var b = i * sliceCount + j + 1;
25125                                 var c = ( i + 1 ) * sliceCount + j + 1;
25126                                 var d = ( i + 1 ) * sliceCount + j;
25127
25128                                 // faces one and two
25129
25130                                 indices.push( a, b, d );
25131                                 indices.push( b, c, d );
25132
25133                         }
25134
25135                 }
25136
25137                 // build geometry
25138
25139                 this.setIndex( indices );
25140                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
25141                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
25142                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
25143
25144         }
25145
25146         ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
25147         ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
25148
25149         /**
25150          * @author clockworkgeek / https://github.com/clockworkgeek
25151          * @author timothypratley / https://github.com/timothypratley
25152          * @author WestLangley / http://github.com/WestLangley
25153          * @author Mugen87 / https://github.com/Mugen87
25154          */
25155
25156         // PolyhedronGeometry
25157
25158         function PolyhedronGeometry( vertices, indices, radius, detail ) {
25159
25160                 Geometry.call( this );
25161
25162                 this.type = 'PolyhedronGeometry';
25163
25164                 this.parameters = {
25165                         vertices: vertices,
25166                         indices: indices,
25167                         radius: radius,
25168                         detail: detail
25169                 };
25170
25171                 this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
25172                 this.mergeVertices();
25173
25174         }
25175
25176         PolyhedronGeometry.prototype = Object.create( Geometry.prototype );
25177         PolyhedronGeometry.prototype.constructor = PolyhedronGeometry;
25178
25179         // PolyhedronBufferGeometry
25180
25181         function PolyhedronBufferGeometry( vertices, indices, radius, detail ) {
25182
25183                 BufferGeometry.call( this );
25184
25185                 this.type = 'PolyhedronBufferGeometry';
25186
25187                 this.parameters = {
25188                         vertices: vertices,
25189                         indices: indices,
25190                         radius: radius,
25191                         detail: detail
25192                 };
25193
25194                 radius = radius || 1;
25195                 detail = detail || 0;
25196
25197                 // default buffer data
25198
25199                 var vertexBuffer = [];
25200                 var uvBuffer = [];
25201
25202                 // the subdivision creates the vertex buffer data
25203
25204                 subdivide( detail );
25205
25206                 // all vertices should lie on a conceptual sphere with a given radius
25207
25208                 appplyRadius( radius );
25209
25210                 // finally, create the uv data
25211
25212                 generateUVs();
25213
25214                 // build non-indexed geometry
25215
25216                 this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
25217                 this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
25218                 this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
25219
25220                 if ( detail === 0 ) {
25221
25222                         this.computeVertexNormals(); // flat normals
25223
25224                 } else {
25225
25226                         this.normalizeNormals(); // smooth normals
25227
25228                 }
25229
25230                 // helper functions
25231
25232                 function subdivide( detail ) {
25233
25234                         var a = new Vector3();
25235                         var b = new Vector3();
25236                         var c = new Vector3();
25237
25238                         // iterate over all faces and apply a subdivison with the given detail value
25239
25240                         for ( var i = 0; i < indices.length; i += 3 ) {
25241
25242                                 // get the vertices of the face
25243
25244                                 getVertexByIndex( indices[ i + 0 ], a );
25245                                 getVertexByIndex( indices[ i + 1 ], b );
25246                                 getVertexByIndex( indices[ i + 2 ], c );
25247
25248                                 // perform subdivision
25249
25250                                 subdivideFace( a, b, c, detail );
25251
25252                         }
25253
25254                 }
25255
25256                 function subdivideFace( a, b, c, detail ) {
25257
25258                         var cols = Math.pow( 2, detail );
25259
25260                         // we use this multidimensional array as a data structure for creating the subdivision
25261
25262                         var v = [];
25263
25264                         var i, j;
25265
25266                         // construct all of the vertices for this subdivision
25267
25268                         for ( i = 0; i <= cols; i ++ ) {
25269
25270                                 v[ i ] = [];
25271
25272                                 var aj = a.clone().lerp( c, i / cols );
25273                                 var bj = b.clone().lerp( c, i / cols );
25274
25275                                 var rows = cols - i;
25276
25277                                 for ( j = 0; j <= rows; j ++ ) {
25278
25279                                         if ( j === 0 && i === cols ) {
25280
25281                                                 v[ i ][ j ] = aj;
25282
25283                                         } else {
25284
25285                                                 v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
25286
25287                                         }
25288
25289                                 }
25290
25291                         }
25292
25293                         // construct all of the faces
25294
25295                         for ( i = 0; i < cols; i ++ ) {
25296
25297                                 for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
25298
25299                                         var k = Math.floor( j / 2 );
25300
25301                                         if ( j % 2 === 0 ) {
25302
25303                                                 pushVertex( v[ i ][ k + 1 ] );
25304                                                 pushVertex( v[ i + 1 ][ k ] );
25305                                                 pushVertex( v[ i ][ k ] );
25306
25307                                         } else {
25308
25309                                                 pushVertex( v[ i ][ k + 1 ] );
25310                                                 pushVertex( v[ i + 1 ][ k + 1 ] );
25311                                                 pushVertex( v[ i + 1 ][ k ] );
25312
25313                                         }
25314
25315                                 }
25316
25317                         }
25318
25319                 }
25320
25321                 function appplyRadius( radius ) {
25322
25323                         var vertex = new Vector3();
25324
25325                         // iterate over the entire buffer and apply the radius to each vertex
25326
25327                         for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
25328
25329                                 vertex.x = vertexBuffer[ i + 0 ];
25330                                 vertex.y = vertexBuffer[ i + 1 ];
25331                                 vertex.z = vertexBuffer[ i + 2 ];
25332
25333                                 vertex.normalize().multiplyScalar( radius );
25334
25335                                 vertexBuffer[ i + 0 ] = vertex.x;
25336                                 vertexBuffer[ i + 1 ] = vertex.y;
25337                                 vertexBuffer[ i + 2 ] = vertex.z;
25338
25339                         }
25340
25341                 }
25342
25343                 function generateUVs() {
25344
25345                         var vertex = new Vector3();
25346
25347                         for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
25348
25349                                 vertex.x = vertexBuffer[ i + 0 ];
25350                                 vertex.y = vertexBuffer[ i + 1 ];
25351                                 vertex.z = vertexBuffer[ i + 2 ];
25352
25353                                 var u = azimuth( vertex ) / 2 / Math.PI + 0.5;
25354                                 var v = inclination( vertex ) / Math.PI + 0.5;
25355                                 uvBuffer.push( u, 1 - v );
25356
25357                         }
25358
25359                         correctUVs();
25360
25361                         correctSeam();
25362
25363                 }
25364
25365                 function correctSeam() {
25366
25367                         // handle case when face straddles the seam, see #3269
25368
25369                         for ( var i = 0; i < uvBuffer.length; i += 6 ) {
25370
25371                                 // uv data of a single face
25372
25373                                 var x0 = uvBuffer[ i + 0 ];
25374                                 var x1 = uvBuffer[ i + 2 ];
25375                                 var x2 = uvBuffer[ i + 4 ];
25376
25377                                 var max = Math.max( x0, x1, x2 );
25378                                 var min = Math.min( x0, x1, x2 );
25379
25380                                 // 0.9 is somewhat arbitrary
25381
25382                                 if ( max > 0.9 && min < 0.1 ) {
25383
25384                                         if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
25385                                         if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
25386                                         if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
25387
25388                                 }
25389
25390                         }
25391
25392                 }
25393
25394                 function pushVertex( vertex ) {
25395
25396                         vertexBuffer.push( vertex.x, vertex.y, vertex.z );
25397
25398                 }
25399
25400                 function getVertexByIndex( index, vertex ) {
25401
25402                         var stride = index * 3;
25403
25404                         vertex.x = vertices[ stride + 0 ];
25405                         vertex.y = vertices[ stride + 1 ];
25406                         vertex.z = vertices[ stride + 2 ];
25407
25408                 }
25409
25410                 function correctUVs() {
25411
25412                         var a = new Vector3();
25413                         var b = new Vector3();
25414                         var c = new Vector3();
25415
25416                         var centroid = new Vector3();
25417
25418                         var uvA = new Vector2();
25419                         var uvB = new Vector2();
25420                         var uvC = new Vector2();
25421
25422                         for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
25423
25424                                 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
25425                                 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
25426                                 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
25427
25428                                 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
25429                                 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
25430                                 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
25431
25432                                 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
25433
25434                                 var azi = azimuth( centroid );
25435
25436                                 correctUV( uvA, j + 0, a, azi );
25437                                 correctUV( uvB, j + 2, b, azi );
25438                                 correctUV( uvC, j + 4, c, azi );
25439
25440                         }
25441
25442                 }
25443
25444                 function correctUV( uv, stride, vector, azimuth ) {
25445
25446                         if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
25447
25448                                 uvBuffer[ stride ] = uv.x - 1;
25449
25450                         }
25451
25452                         if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
25453
25454                                 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
25455
25456                         }
25457
25458                 }
25459
25460                 // Angle around the Y axis, counter-clockwise when looking from above.
25461
25462                 function azimuth( vector ) {
25463
25464                         return Math.atan2( vector.z, - vector.x );
25465
25466                 }
25467
25468
25469                 // Angle above the XZ plane.
25470
25471                 function inclination( vector ) {
25472
25473                         return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
25474
25475                 }
25476
25477         }
25478
25479         PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
25480         PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;
25481
25482         /**
25483          * @author timothypratley / https://github.com/timothypratley
25484          * @author Mugen87 / https://github.com/Mugen87
25485          */
25486
25487         // TetrahedronGeometry
25488
25489         function TetrahedronGeometry( radius, detail ) {
25490
25491                 Geometry.call( this );
25492
25493                 this.type = 'TetrahedronGeometry';
25494
25495                 this.parameters = {
25496                         radius: radius,
25497                         detail: detail
25498                 };
25499
25500                 this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
25501                 this.mergeVertices();
25502
25503         }
25504
25505         TetrahedronGeometry.prototype = Object.create( Geometry.prototype );
25506         TetrahedronGeometry.prototype.constructor = TetrahedronGeometry;
25507
25508         // TetrahedronBufferGeometry
25509
25510         function TetrahedronBufferGeometry( radius, detail ) {
25511
25512                 var vertices = [
25513                         1,  1,  1,   - 1, - 1,  1,   - 1,  1, - 1,    1, - 1, - 1
25514                 ];
25515
25516                 var indices = [
25517                         2,  1,  0,    0,  3,  2,    1,  3,  0,    2,  3,  1
25518                 ];
25519
25520                 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
25521
25522                 this.type = 'TetrahedronBufferGeometry';
25523
25524                 this.parameters = {
25525                         radius: radius,
25526                         detail: detail
25527                 };
25528
25529         }
25530
25531         TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
25532         TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;
25533
25534         /**
25535          * @author timothypratley / https://github.com/timothypratley
25536          * @author Mugen87 / https://github.com/Mugen87
25537          */
25538
25539         // OctahedronGeometry
25540
25541         function OctahedronGeometry( radius, detail ) {
25542
25543                 Geometry.call( this );
25544
25545                 this.type = 'OctahedronGeometry';
25546
25547                 this.parameters = {
25548                         radius: radius,
25549                         detail: detail
25550                 };
25551
25552                 this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
25553                 this.mergeVertices();
25554
25555         }
25556
25557         OctahedronGeometry.prototype = Object.create( Geometry.prototype );
25558         OctahedronGeometry.prototype.constructor = OctahedronGeometry;
25559
25560         // OctahedronBufferGeometry
25561
25562         function OctahedronBufferGeometry( radius, detail ) {
25563
25564                 var vertices = [
25565                         1, 0, 0,   - 1, 0, 0,    0, 1, 0,    0, - 1, 0,    0, 0, 1,    0, 0, - 1
25566                 ];
25567
25568                 var indices = [
25569                         0, 2, 4,    0, 4, 3,    0, 3, 5,    0, 5, 2,    1, 2, 5,    1, 5, 3,    1, 3, 4,    1, 4, 2
25570                 ];
25571
25572                 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
25573
25574                 this.type = 'OctahedronBufferGeometry';
25575
25576                 this.parameters = {
25577                         radius: radius,
25578                         detail: detail
25579                 };
25580
25581         }
25582
25583         OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
25584         OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;
25585
25586         /**
25587          * @author timothypratley / https://github.com/timothypratley
25588          * @author Mugen87 / https://github.com/Mugen87
25589          */
25590
25591         // IcosahedronGeometry
25592
25593         function IcosahedronGeometry( radius, detail ) {
25594
25595                 Geometry.call( this );
25596
25597                 this.type = 'IcosahedronGeometry';
25598
25599                 this.parameters = {
25600                         radius: radius,
25601                         detail: detail
25602                 };
25603
25604                 this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
25605                 this.mergeVertices();
25606
25607         }
25608
25609         IcosahedronGeometry.prototype = Object.create( Geometry.prototype );
25610         IcosahedronGeometry.prototype.constructor = IcosahedronGeometry;
25611
25612         // IcosahedronBufferGeometry
25613
25614         function IcosahedronBufferGeometry( radius, detail ) {
25615
25616                 var t = ( 1 + Math.sqrt( 5 ) ) / 2;
25617
25618                 var vertices = [
25619                         - 1,  t,  0,    1,  t,  0,   - 1, - t,  0,    1, - t,  0,
25620                          0, - 1,  t,    0,  1,  t,    0, - 1, - t,    0,  1, - t,
25621                          t,  0, - 1,    t,  0,  1,   - t,  0, - 1,   - t,  0,  1
25622                 ];
25623
25624                 var indices = [
25625                          0, 11,  5,    0,  5,  1,    0,  1,  7,    0,  7, 10,    0, 10, 11,
25626                          1,  5,  9,    5, 11,  4,   11, 10,  2,   10,  7,  6,    7,  1,  8,
25627                          3,  9,  4,    3,  4,  2,    3,  2,  6,    3,  6,  8,    3,  8,  9,
25628                          4,  9,  5,    2,  4, 11,    6,  2, 10,    8,  6,  7,    9,  8,  1
25629                 ];
25630
25631                 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
25632
25633                 this.type = 'IcosahedronBufferGeometry';
25634
25635                 this.parameters = {
25636                         radius: radius,
25637                         detail: detail
25638                 };
25639
25640         }
25641
25642         IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
25643         IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;
25644
25645         /**
25646          * @author Abe Pazos / https://hamoid.com
25647          * @author Mugen87 / https://github.com/Mugen87
25648          */
25649
25650         // DodecahedronGeometry
25651
25652         function DodecahedronGeometry( radius, detail ) {
25653
25654                 Geometry.call( this );
25655
25656                 this.type = 'DodecahedronGeometry';
25657
25658                 this.parameters = {
25659                         radius: radius,
25660                         detail: detail
25661                 };
25662
25663                 this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
25664                 this.mergeVertices();
25665
25666         }
25667
25668         DodecahedronGeometry.prototype = Object.create( Geometry.prototype );
25669         DodecahedronGeometry.prototype.constructor = DodecahedronGeometry;
25670
25671         // DodecahedronBufferGeometry
25672
25673         function DodecahedronBufferGeometry( radius, detail ) {
25674
25675                 var t = ( 1 + Math.sqrt( 5 ) ) / 2;
25676                 var r = 1 / t;
25677
25678                 var vertices = [
25679
25680                         // (±1, ±1, ±1)
25681                         - 1, - 1, - 1,    - 1, - 1,  1,
25682                         - 1,  1, - 1,    - 1,  1,  1,
25683                           1, - 1, - 1,     1, - 1,  1,
25684                           1,  1, - 1,     1,  1,  1,
25685
25686                         // (0, ±1/φ, ±φ)
25687                          0, - r, - t,     0, - r,  t,
25688                          0,  r, - t,     0,  r,  t,
25689
25690                         // (±1/φ, ±φ, 0)
25691                         - r, - t,  0,    - r,  t,  0,
25692                          r, - t,  0,     r,  t,  0,
25693
25694                         // (±φ, 0, ±1/φ)
25695                         - t,  0, - r,     t,  0, - r,
25696                         - t,  0,  r,     t,  0,  r
25697                 ];
25698
25699                 var indices = [
25700                          3, 11,  7,      3,  7, 15,      3, 15, 13,
25701                          7, 19, 17,      7, 17,  6,      7,  6, 15,
25702                         17,  4,  8,     17,  8, 10,     17, 10,  6,
25703                          8,  0, 16,      8, 16,  2,      8,  2, 10,
25704                          0, 12,  1,      0,  1, 18,      0, 18, 16,
25705                          6, 10,  2,      6,  2, 13,      6, 13, 15,
25706                          2, 16, 18,      2, 18,  3,      2,  3, 13,
25707                         18,  1,  9,     18,  9, 11,     18, 11,  3,
25708                          4, 14, 12,      4, 12,  0,      4,  0,  8,
25709                         11,  9,  5,     11,  5, 19,     11, 19,  7,
25710                         19,  5, 14,     19, 14,  4,     19,  4, 17,
25711                          1, 12, 14,      1, 14,  5,      1,  5,  9
25712                 ];
25713
25714                 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
25715
25716                 this.type = 'DodecahedronBufferGeometry';
25717
25718                 this.parameters = {
25719                         radius: radius,
25720                         detail: detail
25721                 };
25722
25723         }
25724
25725         DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
25726         DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;
25727
25728         /**
25729          * @author oosmoxiecode / https://github.com/oosmoxiecode
25730          * @author WestLangley / https://github.com/WestLangley
25731          * @author zz85 / https://github.com/zz85
25732          * @author miningold / https://github.com/miningold
25733          * @author jonobr1 / https://github.com/jonobr1
25734          * @author Mugen87 / https://github.com/Mugen87
25735          *
25736          */
25737
25738         // TubeGeometry
25739
25740         function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) {
25741
25742                 Geometry.call( this );
25743
25744                 this.type = 'TubeGeometry';
25745
25746                 this.parameters = {
25747                         path: path,
25748                         tubularSegments: tubularSegments,
25749                         radius: radius,
25750                         radialSegments: radialSegments,
25751                         closed: closed
25752                 };
25753
25754                 if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
25755
25756                 var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
25757
25758                 // expose internals
25759
25760                 this.tangents = bufferGeometry.tangents;
25761                 this.normals = bufferGeometry.normals;
25762                 this.binormals = bufferGeometry.binormals;
25763
25764                 // create geometry
25765
25766                 this.fromBufferGeometry( bufferGeometry );
25767                 this.mergeVertices();
25768
25769         }
25770
25771         TubeGeometry.prototype = Object.create( Geometry.prototype );
25772         TubeGeometry.prototype.constructor = TubeGeometry;
25773
25774         // TubeBufferGeometry
25775
25776         function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {
25777
25778                 BufferGeometry.call( this );
25779
25780                 this.type = 'TubeBufferGeometry';
25781
25782                 this.parameters = {
25783                         path: path,
25784                         tubularSegments: tubularSegments,
25785                         radius: radius,
25786                         radialSegments: radialSegments,
25787                         closed: closed
25788                 };
25789
25790                 tubularSegments = tubularSegments || 64;
25791                 radius = radius || 1;
25792                 radialSegments = radialSegments || 8;
25793                 closed = closed || false;
25794
25795                 var frames = path.computeFrenetFrames( tubularSegments, closed );
25796
25797                 // expose internals
25798
25799                 this.tangents = frames.tangents;
25800                 this.normals = frames.normals;
25801                 this.binormals = frames.binormals;
25802
25803                 // helper variables
25804
25805                 var vertex = new Vector3();
25806                 var normal = new Vector3();
25807                 var uv = new Vector2();
25808
25809                 var i, j;
25810
25811                 // buffer
25812
25813                 var vertices = [];
25814                 var normals = [];
25815                 var uvs = [];
25816                 var indices = [];
25817
25818                 // create buffer data
25819
25820                 generateBufferData();
25821
25822                 // build geometry
25823
25824                 this.setIndex( indices );
25825                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
25826                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
25827                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
25828
25829                 // functions
25830
25831                 function generateBufferData() {
25832
25833                         for ( i = 0; i < tubularSegments; i ++ ) {
25834
25835                                 generateSegment( i );
25836
25837                         }
25838
25839                         // if the geometry is not closed, generate the last row of vertices and normals
25840                         // at the regular position on the given path
25841                         //
25842                         // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
25843
25844                         generateSegment( ( closed === false ) ? tubularSegments : 0 );
25845
25846                         // uvs are generated in a separate function.
25847                         // this makes it easy compute correct values for closed geometries
25848
25849                         generateUVs();
25850
25851                         // finally create faces
25852
25853                         generateIndices();
25854
25855                 }
25856
25857                 function generateSegment( i ) {
25858
25859                         // we use getPointAt to sample evenly distributed points from the given path
25860
25861                         var P = path.getPointAt( i / tubularSegments );
25862
25863                         // retrieve corresponding normal and binormal
25864
25865                         var N = frames.normals[ i ];
25866                         var B = frames.binormals[ i ];
25867
25868                         // generate normals and vertices for the current segment
25869
25870                         for ( j = 0; j <= radialSegments; j ++ ) {
25871
25872                                 var v = j / radialSegments * Math.PI * 2;
25873
25874                                 var sin =   Math.sin( v );
25875                                 var cos = - Math.cos( v );
25876
25877                                 // normal
25878
25879                                 normal.x = ( cos * N.x + sin * B.x );
25880                                 normal.y = ( cos * N.y + sin * B.y );
25881                                 normal.z = ( cos * N.z + sin * B.z );
25882                                 normal.normalize();
25883
25884                                 normals.push( normal.x, normal.y, normal.z );
25885
25886                                 // vertex
25887
25888                                 vertex.x = P.x + radius * normal.x;
25889                                 vertex.y = P.y + radius * normal.y;
25890                                 vertex.z = P.z + radius * normal.z;
25891
25892                                 vertices.push( vertex.x, vertex.y, vertex.z );
25893
25894                         }
25895
25896                 }
25897
25898                 function generateIndices() {
25899
25900                         for ( j = 1; j <= tubularSegments; j ++ ) {
25901
25902                                 for ( i = 1; i <= radialSegments; i ++ ) {
25903
25904                                         var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
25905                                         var b = ( radialSegments + 1 ) * j + ( i - 1 );
25906                                         var c = ( radialSegments + 1 ) * j + i;
25907                                         var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
25908
25909                                         // faces
25910
25911                                         indices.push( a, b, d );
25912                                         indices.push( b, c, d );
25913
25914                                 }
25915
25916                         }
25917
25918                 }
25919
25920                 function generateUVs() {
25921
25922                         for ( i = 0; i <= tubularSegments; i ++ ) {
25923
25924                                 for ( j = 0; j <= radialSegments; j ++ ) {
25925
25926                                         uv.x = i / tubularSegments;
25927                                         uv.y = j / radialSegments;
25928
25929                                         uvs.push( uv.x, uv.y );
25930
25931                                 }
25932
25933                         }
25934
25935                 }
25936
25937         }
25938
25939         TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
25940         TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
25941
25942         /**
25943          * @author oosmoxiecode
25944          * @author Mugen87 / https://github.com/Mugen87
25945          *
25946          * based on http://www.blackpawn.com/texts/pqtorus/
25947          */
25948
25949         // TorusKnotGeometry
25950
25951         function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
25952
25953                 Geometry.call( this );
25954
25955                 this.type = 'TorusKnotGeometry';
25956
25957                 this.parameters = {
25958                         radius: radius,
25959                         tube: tube,
25960                         tubularSegments: tubularSegments,
25961                         radialSegments: radialSegments,
25962                         p: p,
25963                         q: q
25964                 };
25965
25966                 if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
25967
25968                 this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
25969                 this.mergeVertices();
25970
25971         }
25972
25973         TorusKnotGeometry.prototype = Object.create( Geometry.prototype );
25974         TorusKnotGeometry.prototype.constructor = TorusKnotGeometry;
25975
25976         // TorusKnotBufferGeometry
25977
25978         function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) {
25979
25980                 BufferGeometry.call( this );
25981
25982                 this.type = 'TorusKnotBufferGeometry';
25983
25984                 this.parameters = {
25985                         radius: radius,
25986                         tube: tube,
25987                         tubularSegments: tubularSegments,
25988                         radialSegments: radialSegments,
25989                         p: p,
25990                         q: q
25991                 };
25992
25993                 radius = radius || 100;
25994                 tube = tube || 40;
25995                 tubularSegments = Math.floor( tubularSegments ) || 64;
25996                 radialSegments = Math.floor( radialSegments ) || 8;
25997                 p = p || 2;
25998                 q = q || 3;
25999
26000                 // buffers
26001
26002                 var indices = [];
26003                 var vertices = [];
26004                 var normals = [];
26005                 var uvs = [];
26006
26007                 // helper variables
26008
26009                 var i, j;
26010
26011                 var vertex = new Vector3();
26012                 var normal = new Vector3();
26013
26014                 var P1 = new Vector3();
26015                 var P2 = new Vector3();
26016
26017                 var B = new Vector3();
26018                 var T = new Vector3();
26019                 var N = new Vector3();
26020
26021                 // generate vertices, normals and uvs
26022
26023                 for ( i = 0; i <= tubularSegments; ++ i ) {
26024
26025                         // the radian "u" is used to calculate the position on the torus curve of the current tubular segement
26026
26027                         var u = i / tubularSegments * p * Math.PI * 2;
26028
26029                         // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
26030                         // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
26031
26032                         calculatePositionOnCurve( u, p, q, radius, P1 );
26033                         calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
26034
26035                         // calculate orthonormal basis
26036
26037                         T.subVectors( P2, P1 );
26038                         N.addVectors( P2, P1 );
26039                         B.crossVectors( T, N );
26040                         N.crossVectors( B, T );
26041
26042                         // normalize B, N. T can be ignored, we don't use it
26043
26044                         B.normalize();
26045                         N.normalize();
26046
26047                         for ( j = 0; j <= radialSegments; ++ j ) {
26048
26049                                 // now calculate the vertices. they are nothing more than an extrusion of the torus curve.
26050                                 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
26051
26052                                 var v = j / radialSegments * Math.PI * 2;
26053                                 var cx = - tube * Math.cos( v );
26054                                 var cy = tube * Math.sin( v );
26055
26056                                 // now calculate the final vertex position.
26057                                 // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
26058
26059                                 vertex.x = P1.x + ( cx * N.x + cy * B.x );
26060                                 vertex.y = P1.y + ( cx * N.y + cy * B.y );
26061                                 vertex.z = P1.z + ( cx * N.z + cy * B.z );
26062
26063                                 vertices.push( vertex.x, vertex.y, vertex.z );
26064
26065                                 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
26066
26067                                 normal.subVectors( vertex, P1 ).normalize();
26068
26069                                 normals.push( normal.x, normal.y, normal.z );
26070
26071                                 // uv
26072
26073                                 uvs.push( i / tubularSegments );
26074                                 uvs.push( j / radialSegments );
26075
26076                         }
26077
26078                 }
26079
26080                 // generate indices
26081
26082                 for ( j = 1; j <= tubularSegments; j ++ ) {
26083
26084                         for ( i = 1; i <= radialSegments; i ++ ) {
26085
26086                                 // indices
26087
26088                                 var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
26089                                 var b = ( radialSegments + 1 ) * j + ( i - 1 );
26090                                 var c = ( radialSegments + 1 ) * j + i;
26091                                 var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
26092
26093                                 // faces
26094
26095                                 indices.push( a, b, d );
26096                                 indices.push( b, c, d );
26097
26098                         }
26099
26100                 }
26101
26102                 // build geometry
26103
26104                 this.setIndex( indices );
26105                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
26106                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
26107                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
26108
26109                 // this function calculates the current position on the torus curve
26110
26111                 function calculatePositionOnCurve( u, p, q, radius, position ) {
26112
26113                         var cu = Math.cos( u );
26114                         var su = Math.sin( u );
26115                         var quOverP = q / p * u;
26116                         var cs = Math.cos( quOverP );
26117
26118                         position.x = radius * ( 2 + cs ) * 0.5 * cu;
26119                         position.y = radius * ( 2 + cs ) * su * 0.5;
26120                         position.z = radius * Math.sin( quOverP ) * 0.5;
26121
26122                 }
26123
26124         }
26125
26126         TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
26127         TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;
26128
26129         /**
26130          * @author oosmoxiecode
26131          * @author mrdoob / http://mrdoob.com/
26132          * @author Mugen87 / https://github.com/Mugen87
26133          */
26134
26135         // TorusGeometry
26136
26137         function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
26138
26139                 Geometry.call( this );
26140
26141                 this.type = 'TorusGeometry';
26142
26143                 this.parameters = {
26144                         radius: radius,
26145                         tube: tube,
26146                         radialSegments: radialSegments,
26147                         tubularSegments: tubularSegments,
26148                         arc: arc
26149                 };
26150
26151                 this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
26152                 this.mergeVertices();
26153
26154         }
26155
26156         TorusGeometry.prototype = Object.create( Geometry.prototype );
26157         TorusGeometry.prototype.constructor = TorusGeometry;
26158
26159         // TorusBufferGeometry
26160
26161         function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
26162
26163                 BufferGeometry.call( this );
26164
26165                 this.type = 'TorusBufferGeometry';
26166
26167                 this.parameters = {
26168                         radius: radius,
26169                         tube: tube,
26170                         radialSegments: radialSegments,
26171                         tubularSegments: tubularSegments,
26172                         arc: arc
26173                 };
26174
26175                 radius = radius || 100;
26176                 tube = tube || 40;
26177                 radialSegments = Math.floor( radialSegments ) || 8;
26178                 tubularSegments = Math.floor( tubularSegments ) || 6;
26179                 arc = arc || Math.PI * 2;
26180
26181                 // buffers
26182
26183                 var indices = [];
26184                 var vertices = [];
26185                 var normals = [];
26186                 var uvs = [];
26187
26188                 // helper variables
26189
26190                 var center = new Vector3();
26191                 var vertex = new Vector3();
26192                 var normal = new Vector3();
26193
26194                 var j, i;
26195
26196                 // generate vertices, normals and uvs
26197
26198                 for ( j = 0; j <= radialSegments; j ++ ) {
26199
26200                         for ( i = 0; i <= tubularSegments; i ++ ) {
26201
26202                                 var u = i / tubularSegments * arc;
26203                                 var v = j / radialSegments * Math.PI * 2;
26204
26205                                 // vertex
26206
26207                                 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
26208                                 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
26209                                 vertex.z = tube * Math.sin( v );
26210
26211                                 vertices.push( vertex.x, vertex.y, vertex.z );
26212
26213                                 // normal
26214
26215                                 center.x = radius * Math.cos( u );
26216                                 center.y = radius * Math.sin( u );
26217                                 normal.subVectors( vertex, center ).normalize();
26218
26219                                 normals.push( normal.x, normal.y, normal.z );
26220
26221                                 // uv
26222
26223                                 uvs.push( i / tubularSegments );
26224                                 uvs.push( j / radialSegments );
26225
26226                         }
26227
26228                 }
26229
26230                 // generate indices
26231
26232                 for ( j = 1; j <= radialSegments; j ++ ) {
26233
26234                         for ( i = 1; i <= tubularSegments; i ++ ) {
26235
26236                                 // indices
26237
26238                                 var a = ( tubularSegments + 1 ) * j + i - 1;
26239                                 var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
26240                                 var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
26241                                 var d = ( tubularSegments + 1 ) * j + i;
26242
26243                                 // faces
26244
26245                                 indices.push( a, b, d );
26246                                 indices.push( b, c, d );
26247
26248                         }
26249
26250                 }
26251
26252                 // build geometry
26253
26254                 this.setIndex( indices );
26255                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
26256                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
26257                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
26258
26259         }
26260
26261         TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
26262         TorusBufferGeometry.prototype.constructor = TorusBufferGeometry;
26263
26264         /**
26265          * @author zz85 / http://www.lab4games.net/zz85/blog
26266          */
26267
26268         var ShapeUtils = {
26269
26270                 // calculate area of the contour polygon
26271
26272                 area: function ( contour ) {
26273
26274                         var n = contour.length;
26275                         var a = 0.0;
26276
26277                         for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
26278
26279                                 a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
26280
26281                         }
26282
26283                         return a * 0.5;
26284
26285                 },
26286
26287                 triangulate: ( function () {
26288
26289                         /**
26290                          * This code is a quick port of code written in C++ which was submitted to
26291                          * flipcode.com by John W. Ratcliff  // July 22, 2000
26292                          * See original code and more information here:
26293                          * http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml
26294                          *
26295                          * ported to actionscript by Zevan Rosser
26296                          * www.actionsnippet.com
26297                          *
26298                          * ported to javascript by Joshua Koo
26299                          * http://www.lab4games.net/zz85/blog
26300                          *
26301                          */
26302
26303                         function snip( contour, u, v, w, n, verts ) {
26304
26305                                 var p;
26306                                 var ax, ay, bx, by;
26307                                 var cx, cy, px, py;
26308
26309                                 ax = contour[ verts[ u ] ].x;
26310                                 ay = contour[ verts[ u ] ].y;
26311
26312                                 bx = contour[ verts[ v ] ].x;
26313                                 by = contour[ verts[ v ] ].y;
26314
26315                                 cx = contour[ verts[ w ] ].x;
26316                                 cy = contour[ verts[ w ] ].y;
26317
26318                                 if ( ( bx - ax ) * ( cy - ay ) - ( by - ay ) * ( cx - ax ) <= 0 ) return false;
26319
26320                                 var aX, aY, bX, bY, cX, cY;
26321                                 var apx, apy, bpx, bpy, cpx, cpy;
26322                                 var cCROSSap, bCROSScp, aCROSSbp;
26323
26324                                 aX = cx - bx;  aY = cy - by;
26325                                 bX = ax - cx;  bY = ay - cy;
26326                                 cX = bx - ax;  cY = by - ay;
26327
26328                                 for ( p = 0; p < n; p ++ ) {
26329
26330                                         px = contour[ verts[ p ] ].x;
26331                                         py = contour[ verts[ p ] ].y;
26332
26333                                         if ( ( ( px === ax ) && ( py === ay ) ) ||
26334                                                  ( ( px === bx ) && ( py === by ) ) ||
26335                                                  ( ( px === cx ) && ( py === cy ) ) )   continue;
26336
26337                                         apx = px - ax;  apy = py - ay;
26338                                         bpx = px - bx;  bpy = py - by;
26339                                         cpx = px - cx;  cpy = py - cy;
26340
26341                                         // see if p is inside triangle abc
26342
26343                                         aCROSSbp = aX * bpy - aY * bpx;
26344                                         cCROSSap = cX * apy - cY * apx;
26345                                         bCROSScp = bX * cpy - bY * cpx;
26346
26347                                         if ( ( aCROSSbp >= - Number.EPSILON ) && ( bCROSScp >= - Number.EPSILON ) && ( cCROSSap >= - Number.EPSILON ) ) return false;
26348
26349                                 }
26350
26351                                 return true;
26352
26353                         }
26354
26355                         // takes in an contour array and returns
26356
26357                         return function triangulate( contour, indices ) {
26358
26359                                 var n = contour.length;
26360
26361                                 if ( n < 3 ) return null;
26362
26363                                 var result = [],
26364                                         verts = [],
26365                                         vertIndices = [];
26366
26367                                 /* we want a counter-clockwise polygon in verts */
26368
26369                                 var u, v, w;
26370
26371                                 if ( ShapeUtils.area( contour ) > 0.0 ) {
26372
26373                                         for ( v = 0; v < n; v ++ ) verts[ v ] = v;
26374
26375                                 } else {
26376
26377                                         for ( v = 0; v < n; v ++ ) verts[ v ] = ( n - 1 ) - v;
26378
26379                                 }
26380
26381                                 var nv = n;
26382
26383                                 /*  remove nv - 2 vertices, creating 1 triangle every time */
26384
26385                                 var count = 2 * nv;   /* error detection */
26386
26387                                 for ( v = nv - 1; nv > 2; ) {
26388
26389                                         /* if we loop, it is probably a non-simple polygon */
26390
26391                                         if ( ( count -- ) <= 0 ) {
26392
26393                                                 //** Triangulate: ERROR - probable bad polygon!
26394
26395                                                 //throw ( "Warning, unable to triangulate polygon!" );
26396                                                 //return null;
26397                                                 // Sometimes warning is fine, especially polygons are triangulated in reverse.
26398                                                 console.warn( 'THREE.ShapeUtils: Unable to triangulate polygon! in triangulate()' );
26399
26400                                                 if ( indices ) return vertIndices;
26401                                                 return result;
26402
26403                                         }
26404
26405                                         /* three consecutive vertices in current polygon, <u,v,w> */
26406
26407                                         u = v;          if ( nv <= u ) u = 0;     /* previous */
26408                                         v = u + 1;  if ( nv <= v ) v = 0;     /* new v    */
26409                                         w = v + 1;  if ( nv <= w ) w = 0;     /* next     */
26410
26411                                         if ( snip( contour, u, v, w, nv, verts ) ) {
26412
26413                                                 var a, b, c, s, t;
26414
26415                                                 /* true names of the vertices */
26416
26417                                                 a = verts[ u ];
26418                                                 b = verts[ v ];
26419                                                 c = verts[ w ];
26420
26421                                                 /* output Triangle */
26422
26423                                                 result.push( [ contour[ a ],
26424                                                         contour[ b ],
26425                                                         contour[ c ] ] );
26426
26427
26428                                                 vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] );
26429
26430                                                 /* remove v from the remaining polygon */
26431
26432                                                 for ( s = v, t = v + 1; t < nv; s ++, t ++ ) {
26433
26434                                                         verts[ s ] = verts[ t ];
26435
26436                                                 }
26437
26438                                                 nv --;
26439
26440                                                 /* reset error detection counter */
26441
26442                                                 count = 2 * nv;
26443
26444                                         }
26445
26446                                 }
26447
26448                                 if ( indices ) return vertIndices;
26449                                 return result;
26450
26451                         };
26452
26453                 } )(),
26454
26455                 triangulateShape: function ( contour, holes ) {
26456
26457                         function removeDupEndPts(points) {
26458
26459                                 var l = points.length;
26460
26461                                 if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
26462
26463                                         points.pop();
26464
26465                                 }
26466
26467                         }
26468
26469                         removeDupEndPts( contour );
26470                         holes.forEach( removeDupEndPts );
26471
26472                         function point_in_segment_2D_colin( inSegPt1, inSegPt2, inOtherPt ) {
26473
26474                                 // inOtherPt needs to be collinear to the inSegment
26475                                 if ( inSegPt1.x !== inSegPt2.x ) {
26476
26477                                         if ( inSegPt1.x < inSegPt2.x ) {
26478
26479                                                 return  ( ( inSegPt1.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt2.x ) );
26480
26481                                         } else {
26482
26483                                                 return  ( ( inSegPt2.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt1.x ) );
26484
26485                                         }
26486
26487                                 } else {
26488
26489                                         if ( inSegPt1.y < inSegPt2.y ) {
26490
26491                                                 return  ( ( inSegPt1.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt2.y ) );
26492
26493                                         } else {
26494
26495                                                 return  ( ( inSegPt2.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt1.y ) );
26496
26497                                         }
26498
26499                                 }
26500
26501                         }
26502
26503                         function intersect_segments_2D( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1, inSeg2Pt2, inExcludeAdjacentSegs ) {
26504
26505                                 var seg1dx = inSeg1Pt2.x - inSeg1Pt1.x,   seg1dy = inSeg1Pt2.y - inSeg1Pt1.y;
26506                                 var seg2dx = inSeg2Pt2.x - inSeg2Pt1.x,   seg2dy = inSeg2Pt2.y - inSeg2Pt1.y;
26507
26508                                 var seg1seg2dx = inSeg1Pt1.x - inSeg2Pt1.x;
26509                                 var seg1seg2dy = inSeg1Pt1.y - inSeg2Pt1.y;
26510
26511                                 var limit               = seg1dy * seg2dx - seg1dx * seg2dy;
26512                                 var perpSeg1    = seg1dy * seg1seg2dx - seg1dx * seg1seg2dy;
26513
26514                                 if ( Math.abs( limit ) > Number.EPSILON ) {
26515
26516                                         // not parallel
26517
26518                                         var perpSeg2;
26519                                         if ( limit > 0 ) {
26520
26521                                                 if ( ( perpSeg1 < 0 ) || ( perpSeg1 > limit ) )                 return [];
26522                                                 perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
26523                                                 if ( ( perpSeg2 < 0 ) || ( perpSeg2 > limit ) )                 return [];
26524
26525                                         } else {
26526
26527                                                 if ( ( perpSeg1 > 0 ) || ( perpSeg1 < limit ) )                 return [];
26528                                                 perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
26529                                                 if ( ( perpSeg2 > 0 ) || ( perpSeg2 < limit ) )                 return [];
26530
26531                                         }
26532
26533                                         // i.e. to reduce rounding errors
26534                                         // intersection at endpoint of segment#1?
26535                                         if ( perpSeg2 === 0 ) {
26536
26537                                                 if ( ( inExcludeAdjacentSegs ) &&
26538                                                          ( ( perpSeg1 === 0 ) || ( perpSeg1 === limit ) ) )             return [];
26539                                                 return [ inSeg1Pt1 ];
26540
26541                                         }
26542                                         if ( perpSeg2 === limit ) {
26543
26544                                                 if ( ( inExcludeAdjacentSegs ) &&
26545                                                          ( ( perpSeg1 === 0 ) || ( perpSeg1 === limit ) ) )             return [];
26546                                                 return [ inSeg1Pt2 ];
26547
26548                                         }
26549                                         // intersection at endpoint of segment#2?
26550                                         if ( perpSeg1 === 0 )           return [ inSeg2Pt1 ];
26551                                         if ( perpSeg1 === limit )       return [ inSeg2Pt2 ];
26552
26553                                         // return real intersection point
26554                                         var factorSeg1 = perpSeg2 / limit;
26555                                         return  [ { x: inSeg1Pt1.x + factorSeg1 * seg1dx,
26556                                                                 y: inSeg1Pt1.y + factorSeg1 * seg1dy } ];
26557
26558                                 } else {
26559
26560                                         // parallel or collinear
26561                                         if ( ( perpSeg1 !== 0 ) ||
26562                                                  ( seg2dy * seg1seg2dx !== seg2dx * seg1seg2dy ) )                      return [];
26563
26564                                         // they are collinear or degenerate
26565                                         var seg1Pt = ( ( seg1dx === 0 ) && ( seg1dy === 0 ) );  // segment1 is just a point?
26566                                         var seg2Pt = ( ( seg2dx === 0 ) && ( seg2dy === 0 ) );  // segment2 is just a point?
26567                                         // both segments are points
26568                                         if ( seg1Pt && seg2Pt ) {
26569
26570                                                 if ( ( inSeg1Pt1.x !== inSeg2Pt1.x ) ||
26571                                                          ( inSeg1Pt1.y !== inSeg2Pt1.y ) )              return [];      // they are distinct  points
26572                                                 return [ inSeg1Pt1 ];                                                           // they are the same point
26573
26574                                         }
26575                                         // segment#1  is a single point
26576                                         if ( seg1Pt ) {
26577
26578                                                 if ( ! point_in_segment_2D_colin( inSeg2Pt1, inSeg2Pt2, inSeg1Pt1 ) )           return [];              // but not in segment#2
26579                                                 return [ inSeg1Pt1 ];
26580
26581                                         }
26582                                         // segment#2  is a single point
26583                                         if ( seg2Pt ) {
26584
26585                                                 if ( ! point_in_segment_2D_colin( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1 ) )           return [];              // but not in segment#1
26586                                                 return [ inSeg2Pt1 ];
26587
26588                                         }
26589
26590                                         // they are collinear segments, which might overlap
26591                                         var seg1min, seg1max, seg1minVal, seg1maxVal;
26592                                         var seg2min, seg2max, seg2minVal, seg2maxVal;
26593                                         if ( seg1dx !== 0 ) {
26594
26595                                                 // the segments are NOT on a vertical line
26596                                                 if ( inSeg1Pt1.x < inSeg1Pt2.x ) {
26597
26598                                                         seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.x;
26599                                                         seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.x;
26600
26601                                                 } else {
26602
26603                                                         seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.x;
26604                                                         seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.x;
26605
26606                                                 }
26607                                                 if ( inSeg2Pt1.x < inSeg2Pt2.x ) {
26608
26609                                                         seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.x;
26610                                                         seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.x;
26611
26612                                                 } else {
26613
26614                                                         seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.x;
26615                                                         seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.x;
26616
26617                                                 }
26618
26619                                         } else {
26620
26621                                                 // the segments are on a vertical line
26622                                                 if ( inSeg1Pt1.y < inSeg1Pt2.y ) {
26623
26624                                                         seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.y;
26625                                                         seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.y;
26626
26627                                                 } else {
26628
26629                                                         seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.y;
26630                                                         seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.y;
26631
26632                                                 }
26633                                                 if ( inSeg2Pt1.y < inSeg2Pt2.y ) {
26634
26635                                                         seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.y;
26636                                                         seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.y;
26637
26638                                                 } else {
26639
26640                                                         seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.y;
26641                                                         seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.y;
26642
26643                                                 }
26644
26645                                         }
26646                                         if ( seg1minVal <= seg2minVal ) {
26647
26648                                                 if ( seg1maxVal <  seg2minVal ) return [];
26649                                                 if ( seg1maxVal === seg2minVal )        {
26650
26651                                                         if ( inExcludeAdjacentSegs )            return [];
26652                                                         return [ seg2min ];
26653
26654                                                 }
26655                                                 if ( seg1maxVal <= seg2maxVal ) return [ seg2min, seg1max ];
26656                                                 return  [ seg2min, seg2max ];
26657
26658                                         } else {
26659
26660                                                 if ( seg1minVal >  seg2maxVal ) return [];
26661                                                 if ( seg1minVal === seg2maxVal )        {
26662
26663                                                         if ( inExcludeAdjacentSegs )            return [];
26664                                                         return [ seg1min ];
26665
26666                                                 }
26667                                                 if ( seg1maxVal <= seg2maxVal ) return [ seg1min, seg1max ];
26668                                                 return  [ seg1min, seg2max ];
26669
26670                                         }
26671
26672                                 }
26673
26674                         }
26675
26676                         function isPointInsideAngle( inVertex, inLegFromPt, inLegToPt, inOtherPt ) {
26677
26678                                 // The order of legs is important
26679
26680                                 // translation of all points, so that Vertex is at (0,0)
26681                                 var legFromPtX  = inLegFromPt.x - inVertex.x,  legFromPtY       = inLegFromPt.y - inVertex.y;
26682                                 var legToPtX    = inLegToPt.x   - inVertex.x,  legToPtY         = inLegToPt.y   - inVertex.y;
26683                                 var otherPtX    = inOtherPt.x   - inVertex.x,  otherPtY         = inOtherPt.y   - inVertex.y;
26684
26685                                 // main angle >0: < 180 deg.; 0: 180 deg.; <0: > 180 deg.
26686                                 var from2toAngle        = legFromPtX * legToPtY - legFromPtY * legToPtX;
26687                                 var from2otherAngle     = legFromPtX * otherPtY - legFromPtY * otherPtX;
26688
26689                                 if ( Math.abs( from2toAngle ) > Number.EPSILON ) {
26690
26691                                         // angle != 180 deg.
26692
26693                                         var other2toAngle               = otherPtX * legToPtY - otherPtY * legToPtX;
26694                                         // console.log( "from2to: " + from2toAngle + ", from2other: " + from2otherAngle + ", other2to: " + other2toAngle );
26695
26696                                         if ( from2toAngle > 0 ) {
26697
26698                                                 // main angle < 180 deg.
26699                                                 return  ( ( from2otherAngle >= 0 ) && ( other2toAngle >= 0 ) );
26700
26701                                         } else {
26702
26703                                                 // main angle > 180 deg.
26704                                                 return  ( ( from2otherAngle >= 0 ) || ( other2toAngle >= 0 ) );
26705
26706                                         }
26707
26708                                 } else {
26709
26710                                         // angle == 180 deg.
26711                                         // console.log( "from2to: 180 deg., from2other: " + from2otherAngle  );
26712                                         return  ( from2otherAngle > 0 );
26713
26714                                 }
26715
26716                         }
26717
26718
26719                         function removeHoles( contour, holes ) {
26720
26721                                 var shape = contour.concat(); // work on this shape
26722                                 var hole;
26723
26724                                 function isCutLineInsideAngles( inShapeIdx, inHoleIdx ) {
26725
26726                                         // Check if hole point lies within angle around shape point
26727                                         var lastShapeIdx = shape.length - 1;
26728
26729                                         var prevShapeIdx = inShapeIdx - 1;
26730                                         if ( prevShapeIdx < 0 )                 prevShapeIdx = lastShapeIdx;
26731
26732                                         var nextShapeIdx = inShapeIdx + 1;
26733                                         if ( nextShapeIdx > lastShapeIdx )      nextShapeIdx = 0;
26734
26735                                         var insideAngle = isPointInsideAngle( shape[ inShapeIdx ], shape[ prevShapeIdx ], shape[ nextShapeIdx ], hole[ inHoleIdx ] );
26736                                         if ( ! insideAngle ) {
26737
26738                                                 // console.log( "Vertex (Shape): " + inShapeIdx + ", Point: " + hole[inHoleIdx].x + "/" + hole[inHoleIdx].y );
26739                                                 return  false;
26740
26741                                         }
26742
26743                                         // Check if shape point lies within angle around hole point
26744                                         var lastHoleIdx = hole.length - 1;
26745
26746                                         var prevHoleIdx = inHoleIdx - 1;
26747                                         if ( prevHoleIdx < 0 )                  prevHoleIdx = lastHoleIdx;
26748
26749                                         var nextHoleIdx = inHoleIdx + 1;
26750                                         if ( nextHoleIdx > lastHoleIdx )        nextHoleIdx = 0;
26751
26752                                         insideAngle = isPointInsideAngle( hole[ inHoleIdx ], hole[ prevHoleIdx ], hole[ nextHoleIdx ], shape[ inShapeIdx ] );
26753                                         if ( ! insideAngle ) {
26754
26755                                                 // console.log( "Vertex (Hole): " + inHoleIdx + ", Point: " + shape[inShapeIdx].x + "/" + shape[inShapeIdx].y );
26756                                                 return  false;
26757
26758                                         }
26759
26760                                         return  true;
26761
26762                                 }
26763
26764                                 function intersectsShapeEdge( inShapePt, inHolePt ) {
26765
26766                                         // checks for intersections with shape edges
26767                                         var sIdx, nextIdx, intersection;
26768                                         for ( sIdx = 0; sIdx < shape.length; sIdx ++ ) {
26769
26770                                                 nextIdx = sIdx + 1; nextIdx %= shape.length;
26771                                                 intersection = intersect_segments_2D( inShapePt, inHolePt, shape[ sIdx ], shape[ nextIdx ], true );
26772                                                 if ( intersection.length > 0 )          return  true;
26773
26774                                         }
26775
26776                                         return  false;
26777
26778                                 }
26779
26780                                 var indepHoles = [];
26781
26782                                 function intersectsHoleEdge( inShapePt, inHolePt ) {
26783
26784                                         // checks for intersections with hole edges
26785                                         var ihIdx, chkHole,
26786                                                 hIdx, nextIdx, intersection;
26787                                         for ( ihIdx = 0; ihIdx < indepHoles.length; ihIdx ++ ) {
26788
26789                                                 chkHole = holes[ indepHoles[ ihIdx ] ];
26790                                                 for ( hIdx = 0; hIdx < chkHole.length; hIdx ++ ) {
26791
26792                                                         nextIdx = hIdx + 1; nextIdx %= chkHole.length;
26793                                                         intersection = intersect_segments_2D( inShapePt, inHolePt, chkHole[ hIdx ], chkHole[ nextIdx ], true );
26794                                                         if ( intersection.length > 0 )          return  true;
26795
26796                                                 }
26797
26798                                         }
26799                                         return  false;
26800
26801                                 }
26802
26803                                 var holeIndex, shapeIndex,
26804                                         shapePt, holePt,
26805                                         holeIdx, cutKey, failedCuts = [],
26806                                         tmpShape1, tmpShape2,
26807                                         tmpHole1, tmpHole2;
26808
26809                                 for ( var h = 0, hl = holes.length; h < hl; h ++ ) {
26810
26811                                         indepHoles.push( h );
26812
26813                                 }
26814
26815                                 var minShapeIndex = 0;
26816                                 var counter = indepHoles.length * 2;
26817                                 while ( indepHoles.length > 0 ) {
26818
26819                                         counter --;
26820                                         if ( counter < 0 ) {
26821
26822                                                 console.log( 'THREE.ShapeUtils: Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!' );
26823                                                 break;
26824
26825                                         }
26826
26827                                         // search for shape-vertex and hole-vertex,
26828                                         // which can be connected without intersections
26829                                         for ( shapeIndex = minShapeIndex; shapeIndex < shape.length; shapeIndex ++ ) {
26830
26831                                                 shapePt = shape[ shapeIndex ];
26832                                                 holeIndex       = - 1;
26833
26834                                                 // search for hole which can be reached without intersections
26835                                                 for ( var h = 0; h < indepHoles.length; h ++ ) {
26836
26837                                                         holeIdx = indepHoles[ h ];
26838
26839                                                         // prevent multiple checks
26840                                                         cutKey = shapePt.x + ':' + shapePt.y + ':' + holeIdx;
26841                                                         if ( failedCuts[ cutKey ] !== undefined )                       continue;
26842
26843                                                         hole = holes[ holeIdx ];
26844                                                         for ( var h2 = 0; h2 < hole.length; h2 ++ ) {
26845
26846                                                                 holePt = hole[ h2 ];
26847                                                                 if ( ! isCutLineInsideAngles( shapeIndex, h2 ) )                continue;
26848                                                                 if ( intersectsShapeEdge( shapePt, holePt ) )           continue;
26849                                                                 if ( intersectsHoleEdge( shapePt, holePt ) )            continue;
26850
26851                                                                 holeIndex = h2;
26852                                                                 indepHoles.splice( h, 1 );
26853
26854                                                                 tmpShape1 = shape.slice( 0, shapeIndex + 1 );
26855                                                                 tmpShape2 = shape.slice( shapeIndex );
26856                                                                 tmpHole1 = hole.slice( holeIndex );
26857                                                                 tmpHole2 = hole.slice( 0, holeIndex + 1 );
26858
26859                                                                 shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
26860
26861                                                                 minShapeIndex = shapeIndex;
26862
26863                                                                 // Debug only, to show the selected cuts
26864                                                                 // glob_CutLines.push( [ shapePt, holePt ] );
26865
26866                                                                 break;
26867
26868                                                         }
26869                                                         if ( holeIndex >= 0 )   break;          // hole-vertex found
26870
26871                                                         failedCuts[ cutKey ] = true;                    // remember failure
26872
26873                                                 }
26874                                                 if ( holeIndex >= 0 )   break;          // hole-vertex found
26875
26876                                         }
26877
26878                                 }
26879
26880                                 return shape;                   /* shape with no holes */
26881
26882                         }
26883
26884
26885                         var i, il, f, face,
26886                                 key, index,
26887                                 allPointsMap = {};
26888
26889                         // To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first.
26890
26891                         var allpoints = contour.concat();
26892
26893                         for ( var h = 0, hl = holes.length; h < hl; h ++ ) {
26894
26895                                 Array.prototype.push.apply( allpoints, holes[ h ] );
26896
26897                         }
26898
26899                         //console.log( "allpoints",allpoints, allpoints.length );
26900
26901                         // prepare all points map
26902
26903                         for ( i = 0, il = allpoints.length; i < il; i ++ ) {
26904
26905                                 key = allpoints[ i ].x + ':' + allpoints[ i ].y;
26906
26907                                 if ( allPointsMap[ key ] !== undefined ) {
26908
26909                                         console.warn( 'THREE.ShapeUtils: Duplicate point', key, i );
26910
26911                                 }
26912
26913                                 allPointsMap[ key ] = i;
26914
26915                         }
26916
26917                         // remove holes by cutting paths to holes and adding them to the shape
26918                         var shapeWithoutHoles = removeHoles( contour, holes );
26919
26920                         var triangles = ShapeUtils.triangulate( shapeWithoutHoles, false ); // True returns indices for points of spooled shape
26921                         //console.log( "triangles",triangles, triangles.length );
26922
26923                         // check all face vertices against all points map
26924
26925                         for ( i = 0, il = triangles.length; i < il; i ++ ) {
26926
26927                                 face = triangles[ i ];
26928
26929                                 for ( f = 0; f < 3; f ++ ) {
26930
26931                                         key = face[ f ].x + ':' + face[ f ].y;
26932
26933                                         index = allPointsMap[ key ];
26934
26935                                         if ( index !== undefined ) {
26936
26937                                                 face[ f ] = index;
26938
26939                                         }
26940
26941                                 }
26942
26943                         }
26944
26945                         return triangles.concat();
26946
26947                 },
26948
26949                 isClockWise: function ( pts ) {
26950
26951                         return ShapeUtils.area( pts ) < 0;
26952
26953                 }
26954
26955         };
26956
26957         /**
26958          * @author zz85 / http://www.lab4games.net/zz85/blog
26959          *
26960          * Creates extruded geometry from a path shape.
26961          *
26962          * parameters = {
26963          *
26964          *  curveSegments: <int>, // number of points on the curves
26965          *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
26966          *  amount: <int>, // Depth to extrude the shape
26967          *
26968          *  bevelEnabled: <bool>, // turn on bevel
26969          *  bevelThickness: <float>, // how deep into the original shape bevel goes
26970          *  bevelSize: <float>, // how far from shape outline is bevel
26971          *  bevelSegments: <int>, // number of bevel layers
26972          *
26973          *  extrudePath: <THREE.Curve> // curve to extrude shape along
26974          *  frames: <Object> // containing arrays of tangents, normals, binormals
26975          *
26976          *  UVGenerator: <Object> // object that provides UV generator functions
26977          *
26978          * }
26979          */
26980
26981         // ExtrudeGeometry
26982
26983         function ExtrudeGeometry( shapes, options ) {
26984
26985                 Geometry.call( this );
26986
26987                 this.type = 'ExtrudeGeometry';
26988
26989                 this.parameters = {
26990                         shapes: shapes,
26991                         options: options
26992                 };
26993
26994                 this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
26995                 this.mergeVertices();
26996
26997         }
26998
26999         ExtrudeGeometry.prototype = Object.create( Geometry.prototype );
27000         ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
27001
27002         // ExtrudeBufferGeometry
27003
27004         function ExtrudeBufferGeometry( shapes, options ) {
27005
27006                 if ( typeof ( shapes ) === "undefined" ) {
27007
27008                         return;
27009
27010                 }
27011
27012                 BufferGeometry.call( this );
27013
27014                 this.type = 'ExtrudeBufferGeometry';
27015
27016                 shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
27017
27018                 this.addShapeList( shapes, options );
27019
27020                 this.computeVertexNormals();
27021
27022                 // can't really use automatic vertex normals
27023                 // as then front and back sides get smoothed too
27024                 // should do separate smoothing just for sides
27025
27026                 //this.computeVertexNormals();
27027
27028                 //console.log( "took", ( Date.now() - startTime ) );
27029
27030         }
27031
27032         ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
27033         ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
27034
27035         ExtrudeBufferGeometry.prototype.getArrays = function () {
27036
27037                 var positionAttribute = this.getAttribute( "position" );
27038                 var verticesArray = positionAttribute ? Array.prototype.slice.call( positionAttribute.array ) : [];
27039
27040                 var uvAttribute = this.getAttribute( "uv" );
27041                 var uvArray = uvAttribute ? Array.prototype.slice.call( uvAttribute.array ) : [];
27042
27043                 var IndexAttribute = this.index;
27044                 var indicesArray = IndexAttribute ? Array.prototype.slice.call( IndexAttribute.array ) : [];
27045
27046                 return {
27047                         position: verticesArray,
27048                         uv: uvArray,
27049                         index: indicesArray
27050                 };
27051
27052         };
27053
27054         ExtrudeBufferGeometry.prototype.addShapeList = function ( shapes, options ) {
27055
27056                 var sl = shapes.length;
27057                 options.arrays = this.getArrays();
27058
27059                 for ( var s = 0; s < sl; s ++ ) {
27060
27061                         var shape = shapes[ s ];
27062                         this.addShape( shape, options );
27063
27064                 }
27065
27066                 this.setIndex( options.arrays.index );
27067                 this.addAttribute( 'position', new Float32BufferAttribute( options.arrays.position, 3 ) );
27068                 this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) );
27069
27070         };
27071
27072         ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) {
27073
27074                 var arrays = options.arrays ? options.arrays : this.getArrays();
27075                 var verticesArray = arrays.position;
27076                 var indicesArray = arrays.index;
27077                 var uvArray = arrays.uv;
27078
27079                 var placeholder = [];
27080
27081
27082                 var amount = options.amount !== undefined ? options.amount : 100;
27083
27084                 var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
27085                 var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8
27086                 var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
27087
27088                 var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
27089
27090                 var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
27091
27092                 var steps = options.steps !== undefined ? options.steps : 1;
27093
27094                 var extrudePath = options.extrudePath;
27095                 var extrudePts, extrudeByPath = false;
27096
27097                 // Use default WorldUVGenerator if no UV generators are specified.
27098                 var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : ExtrudeGeometry.WorldUVGenerator;
27099
27100                 var splineTube, binormal, normal, position2;
27101                 if ( extrudePath ) {
27102
27103                         extrudePts = extrudePath.getSpacedPoints( steps );
27104
27105                         extrudeByPath = true;
27106                         bevelEnabled = false; // bevels not supported for path extrusion
27107
27108                         // SETUP TNB variables
27109
27110                         // TODO1 - have a .isClosed in spline?
27111
27112                         splineTube = options.frames !== undefined ? options.frames : extrudePath.computeFrenetFrames( steps, false );
27113
27114                         // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
27115
27116                         binormal = new Vector3();
27117                         normal = new Vector3();
27118                         position2 = new Vector3();
27119
27120                 }
27121
27122                 // Safeguards if bevels are not enabled
27123
27124                 if ( ! bevelEnabled ) {
27125
27126                         bevelSegments = 0;
27127                         bevelThickness = 0;
27128                         bevelSize = 0;
27129
27130                 }
27131
27132                 // Variables initialization
27133
27134                 var ahole, h, hl; // looping of holes
27135                 var scope = this;
27136
27137                 var shapePoints = shape.extractPoints( curveSegments );
27138
27139                 var vertices = shapePoints.shape;
27140                 var holes = shapePoints.holes;
27141
27142                 var reverse = ! ShapeUtils.isClockWise( vertices );
27143
27144                 if ( reverse ) {
27145
27146                         vertices = vertices.reverse();
27147
27148                         // Maybe we should also check if holes are in the opposite direction, just to be safe ...
27149
27150                         for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27151
27152                                 ahole = holes[ h ];
27153
27154                                 if ( ShapeUtils.isClockWise( ahole ) ) {
27155
27156                                         holes[ h ] = ahole.reverse();
27157
27158                                 }
27159
27160                         }
27161
27162                 }
27163
27164
27165                 var faces = ShapeUtils.triangulateShape( vertices, holes );
27166
27167                 /* Vertices */
27168
27169                 var contour = vertices; // vertices has all points but contour has only points of circumference
27170
27171                 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27172
27173                         ahole = holes[ h ];
27174
27175                         vertices = vertices.concat( ahole );
27176
27177                 }
27178
27179
27180                 function scalePt2( pt, vec, size ) {
27181
27182                         if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
27183
27184                         return vec.clone().multiplyScalar( size ).add( pt );
27185
27186                 }
27187
27188                 var b, bs, t, z,
27189                         vert, vlen = vertices.length,
27190                         face, flen = faces.length;
27191
27192
27193                 // Find directions for point movement
27194
27195
27196                 function getBevelVec( inPt, inPrev, inNext ) {
27197
27198                         // computes for inPt the corresponding point inPt' on a new contour
27199                         //   shifted by 1 unit (length of normalized vector) to the left
27200                         // if we walk along contour clockwise, this new contour is outside the old one
27201                         //
27202                         // inPt' is the intersection of the two lines parallel to the two
27203                         //  adjacent edges of inPt at a distance of 1 unit on the left side.
27204
27205                         var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
27206
27207                         // good reading for geometry algorithms (here: line-line intersection)
27208                         // http://geomalgorithms.com/a05-_intersect-1.html
27209
27210                         var v_prev_x = inPt.x - inPrev.x,
27211                                 v_prev_y = inPt.y - inPrev.y;
27212                         var v_next_x = inNext.x - inPt.x,
27213                                 v_next_y = inNext.y - inPt.y;
27214
27215                         var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
27216
27217                         // check for collinear edges
27218                         var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
27219
27220                         if ( Math.abs( collinear0 ) > Number.EPSILON ) {
27221
27222                                 // not collinear
27223
27224                                 // length of vectors for normalizing
27225
27226                                 var v_prev_len = Math.sqrt( v_prev_lensq );
27227                                 var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
27228
27229                                 // shift adjacent points by unit vectors to the left
27230
27231                                 var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
27232                                 var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
27233
27234                                 var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
27235                                 var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
27236
27237                                 // scaling factor for v_prev to intersection point
27238
27239                                 var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
27240                                                 ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
27241                                         ( v_prev_x * v_next_y - v_prev_y * v_next_x );
27242
27243                                 // vector from inPt to intersection point
27244
27245                                 v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
27246                                 v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
27247
27248                                 // Don't normalize!, otherwise sharp corners become ugly
27249                                 //  but prevent crazy spikes
27250                                 var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
27251                                 if ( v_trans_lensq <= 2 ) {
27252
27253                                         return new Vector2( v_trans_x, v_trans_y );
27254
27255                                 } else {
27256
27257                                         shrink_by = Math.sqrt( v_trans_lensq / 2 );
27258
27259                                 }
27260
27261                         } else {
27262
27263                                 // handle special case of collinear edges
27264
27265                                 var direction_eq = false; // assumes: opposite
27266                                 if ( v_prev_x > Number.EPSILON ) {
27267
27268                                         if ( v_next_x > Number.EPSILON ) {
27269
27270                                                 direction_eq = true;
27271
27272                                         }
27273
27274                                 } else {
27275
27276                                         if ( v_prev_x < - Number.EPSILON ) {
27277
27278                                                 if ( v_next_x < - Number.EPSILON ) {
27279
27280                                                         direction_eq = true;
27281
27282                                                 }
27283
27284                                         } else {
27285
27286                                                 if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
27287
27288                                                         direction_eq = true;
27289
27290                                                 }
27291
27292                                         }
27293
27294                                 }
27295
27296                                 if ( direction_eq ) {
27297
27298                                         // console.log("Warning: lines are a straight sequence");
27299                                         v_trans_x = - v_prev_y;
27300                                         v_trans_y = v_prev_x;
27301                                         shrink_by = Math.sqrt( v_prev_lensq );
27302
27303                                 } else {
27304
27305                                         // console.log("Warning: lines are a straight spike");
27306                                         v_trans_x = v_prev_x;
27307                                         v_trans_y = v_prev_y;
27308                                         shrink_by = Math.sqrt( v_prev_lensq / 2 );
27309
27310                                 }
27311
27312                         }
27313
27314                         return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
27315
27316                 }
27317
27318
27319                 var contourMovements = [];
27320
27321                 for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
27322
27323                         if ( j === il ) j = 0;
27324                         if ( k === il ) k = 0;
27325
27326                         //  (j)---(i)---(k)
27327                         // console.log('i,j,k', i, j , k)
27328
27329                         contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
27330
27331                 }
27332
27333                 var holesMovements = [],
27334                         oneHoleMovements, verticesMovements = contourMovements.concat();
27335
27336                 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27337
27338                         ahole = holes[ h ];
27339
27340                         oneHoleMovements = [];
27341
27342                         for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
27343
27344                                 if ( j === il ) j = 0;
27345                                 if ( k === il ) k = 0;
27346
27347                                 //  (j)---(i)---(k)
27348                                 oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
27349
27350                         }
27351
27352                         holesMovements.push( oneHoleMovements );
27353                         verticesMovements = verticesMovements.concat( oneHoleMovements );
27354
27355                 }
27356
27357
27358                 // Loop bevelSegments, 1 for the front, 1 for the back
27359
27360                 for ( b = 0; b < bevelSegments; b ++ ) {
27361
27362                         //for ( b = bevelSegments; b > 0; b -- ) {
27363
27364                         t = b / bevelSegments;
27365                         z = bevelThickness * Math.cos( t * Math.PI / 2 );
27366                         bs = bevelSize * Math.sin( t * Math.PI / 2 );
27367
27368                         // contract shape
27369
27370                         for ( i = 0, il = contour.length; i < il; i ++ ) {
27371
27372                                 vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
27373
27374                                 v( vert.x, vert.y, - z );
27375
27376                         }
27377
27378                         // expand holes
27379
27380                         for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27381
27382                                 ahole = holes[ h ];
27383                                 oneHoleMovements = holesMovements[ h ];
27384
27385                                 for ( i = 0, il = ahole.length; i < il; i ++ ) {
27386
27387                                         vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
27388
27389                                         v( vert.x, vert.y, - z );
27390
27391                                 }
27392
27393                         }
27394
27395                 }
27396
27397                 bs = bevelSize;
27398
27399                 // Back facing vertices
27400
27401                 for ( i = 0; i < vlen; i ++ ) {
27402
27403                         vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
27404
27405                         if ( ! extrudeByPath ) {
27406
27407                                 v( vert.x, vert.y, 0 );
27408
27409                         } else {
27410
27411                                 // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
27412
27413                                 normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
27414                                 binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
27415
27416                                 position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
27417
27418                                 v( position2.x, position2.y, position2.z );
27419
27420                         }
27421
27422                 }
27423
27424                 // Add stepped vertices...
27425                 // Including front facing vertices
27426
27427                 var s;
27428
27429                 for ( s = 1; s <= steps; s ++ ) {
27430
27431                         for ( i = 0; i < vlen; i ++ ) {
27432
27433                                 vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
27434
27435                                 if ( ! extrudeByPath ) {
27436
27437                                         v( vert.x, vert.y, amount / steps * s );
27438
27439                                 } else {
27440
27441                                         // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
27442
27443                                         normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
27444                                         binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
27445
27446                                         position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
27447
27448                                         v( position2.x, position2.y, position2.z );
27449
27450                                 }
27451
27452                         }
27453
27454                 }
27455
27456
27457                 // Add bevel segments planes
27458
27459                 //for ( b = 1; b <= bevelSegments; b ++ ) {
27460                 for ( b = bevelSegments - 1; b >= 0; b -- ) {
27461
27462                         t = b / bevelSegments;
27463                         z = bevelThickness * Math.cos( t * Math.PI / 2 );
27464                         bs = bevelSize * Math.sin( t * Math.PI / 2 );
27465
27466                         // contract shape
27467
27468                         for ( i = 0, il = contour.length; i < il; i ++ ) {
27469
27470                                 vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
27471                                 v( vert.x, vert.y, amount + z );
27472
27473                         }
27474
27475                         // expand holes
27476
27477                         for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27478
27479                                 ahole = holes[ h ];
27480                                 oneHoleMovements = holesMovements[ h ];
27481
27482                                 for ( i = 0, il = ahole.length; i < il; i ++ ) {
27483
27484                                         vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
27485
27486                                         if ( ! extrudeByPath ) {
27487
27488                                                 v( vert.x, vert.y, amount + z );
27489
27490                                         } else {
27491
27492                                                 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
27493
27494                                         }
27495
27496                                 }
27497
27498                         }
27499
27500                 }
27501
27502                 /* Faces */
27503
27504                 // Top and bottom faces
27505
27506                 buildLidFaces();
27507
27508                 // Sides faces
27509
27510                 buildSideFaces();
27511
27512
27513                 /////  Internal functions
27514
27515                 function buildLidFaces() {
27516
27517                         var start = verticesArray.length/3;
27518
27519                         if ( bevelEnabled ) {
27520
27521                                 var layer = 0; // steps + 1
27522                                 var offset = vlen * layer;
27523
27524                                 // Bottom faces
27525
27526                                 for ( i = 0; i < flen; i ++ ) {
27527
27528                                         face = faces[ i ];
27529                                         f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
27530
27531                                 }
27532
27533                                 layer = steps + bevelSegments * 2;
27534                                 offset = vlen * layer;
27535
27536                                 // Top faces
27537
27538                                 for ( i = 0; i < flen; i ++ ) {
27539
27540                                         face = faces[ i ];
27541                                         f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
27542
27543                                 }
27544
27545                         } else {
27546
27547                                 // Bottom faces
27548
27549                                 for ( i = 0; i < flen; i ++ ) {
27550
27551                                         face = faces[ i ];
27552                                         f3( face[ 2 ], face[ 1 ], face[ 0 ] );
27553
27554                                 }
27555
27556                                 // Top faces
27557
27558                                 for ( i = 0; i < flen; i ++ ) {
27559
27560                                         face = faces[ i ];
27561                                         f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
27562
27563                                 }
27564
27565                         }
27566
27567                         scope.addGroup( start, verticesArray.length/3 -start, options.material !== undefined ? options.material : 0);
27568
27569                 }
27570
27571                 // Create faces for the z-sides of the shape
27572
27573                 function buildSideFaces() {
27574
27575                         var start = verticesArray.length/3;
27576                         var layeroffset = 0;
27577                         sidewalls( contour, layeroffset );
27578                         layeroffset += contour.length;
27579
27580                         for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27581
27582                                 ahole = holes[ h ];
27583                                 sidewalls( ahole, layeroffset );
27584
27585                                 //, true
27586                                 layeroffset += ahole.length;
27587
27588                         }
27589
27590
27591                         scope.addGroup( start, verticesArray.length/3 -start, options.extrudeMaterial !== undefined ? options.extrudeMaterial : 1);
27592
27593
27594                 }
27595
27596                 function sidewalls( contour, layeroffset ) {
27597
27598                         var j, k;
27599                         i = contour.length;
27600
27601                         while ( -- i >= 0 ) {
27602
27603                                 j = i;
27604                                 k = i - 1;
27605                                 if ( k < 0 ) k = contour.length - 1;
27606
27607                                 //console.log('b', i,j, i-1, k,vertices.length);
27608
27609                                 var s = 0,
27610                                         sl = steps + bevelSegments * 2;
27611
27612                                 for ( s = 0; s < sl; s ++ ) {
27613
27614                                         var slen1 = vlen * s;
27615                                         var slen2 = vlen * ( s + 1 );
27616
27617                                         var a = layeroffset + j + slen1,
27618                                                 b = layeroffset + k + slen1,
27619                                                 c = layeroffset + k + slen2,
27620                                                 d = layeroffset + j + slen2;
27621
27622                                         f4( a, b, c, d, contour, s, sl, j, k );
27623
27624                                 }
27625
27626                         }
27627
27628                 }
27629
27630                 function v( x, y, z ) {
27631
27632                         placeholder.push( x );
27633                         placeholder.push( y );
27634                         placeholder.push( z );
27635
27636                 }
27637
27638
27639                 function f3( a, b, c ) {
27640
27641                         addVertex( a );
27642                         addVertex( b );
27643                         addVertex( c );
27644
27645                         var nextIndex = verticesArray.length / 3;
27646                         var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
27647
27648                         addUV( uvs[ 0 ] );
27649                         addUV( uvs[ 1 ] );
27650                         addUV( uvs[ 2 ] );
27651
27652                 }
27653
27654                 function f4( a, b, c, d, wallContour, stepIndex, stepsLength, contourIndex1, contourIndex2 ) {
27655
27656                         addVertex( a );
27657                         addVertex( b );
27658                         addVertex( d );
27659
27660                         addVertex( b );
27661                         addVertex( c );
27662                         addVertex( d );
27663
27664
27665                         var nextIndex = verticesArray.length / 3;
27666                         var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
27667
27668                         addUV( uvs[ 0 ] );
27669                         addUV( uvs[ 1 ] );
27670                         addUV( uvs[ 3 ] );
27671
27672                         addUV( uvs[ 1 ] );
27673                         addUV( uvs[ 2 ] );
27674                         addUV( uvs[ 3 ] );
27675
27676                 }
27677
27678                 function addVertex( index ) {
27679
27680                         indicesArray.push( verticesArray.length / 3 );
27681                         verticesArray.push( placeholder[ index * 3 + 0 ] );
27682                         verticesArray.push( placeholder[ index * 3 + 1 ] );
27683                         verticesArray.push( placeholder[ index * 3 + 2 ] );
27684
27685                 }
27686
27687
27688                 function addUV( vector2 ) {
27689
27690                         uvArray.push( vector2.x );
27691                         uvArray.push( vector2.y );
27692
27693                 }
27694
27695                 if ( ! options.arrays ) {
27696
27697                         this.setIndex( indicesArray );
27698                         this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
27699                         this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) );
27700
27701                 }
27702
27703         };
27704
27705         ExtrudeGeometry.WorldUVGenerator = {
27706
27707                 generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
27708
27709                         var a_x = vertices[ indexA * 3 ];
27710                         var a_y = vertices[ indexA * 3 + 1 ];
27711                         var b_x = vertices[ indexB * 3 ];
27712                         var b_y = vertices[ indexB * 3 + 1 ];
27713                         var c_x = vertices[ indexC * 3 ];
27714                         var c_y = vertices[ indexC * 3 + 1 ];
27715
27716                         return [
27717                                 new Vector2( a_x, a_y ),
27718                                 new Vector2( b_x, b_y ),
27719                                 new Vector2( c_x, c_y )
27720                         ];
27721
27722                 },
27723
27724                 generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
27725
27726                         var a_x = vertices[ indexA * 3 ];
27727                         var a_y = vertices[ indexA * 3 + 1 ];
27728                         var a_z = vertices[ indexA * 3 + 2 ];
27729                         var b_x = vertices[ indexB * 3 ];
27730                         var b_y = vertices[ indexB * 3 + 1 ];
27731                         var b_z = vertices[ indexB * 3 + 2 ];
27732                         var c_x = vertices[ indexC * 3 ];
27733                         var c_y = vertices[ indexC * 3 + 1 ];
27734                         var c_z = vertices[ indexC * 3 + 2 ];
27735                         var d_x = vertices[ indexD * 3 ];
27736                         var d_y = vertices[ indexD * 3 + 1 ];
27737                         var d_z = vertices[ indexD * 3 + 2 ];
27738
27739                         if ( Math.abs( a_y - b_y ) < 0.01 ) {
27740
27741                                 return [
27742                                         new Vector2( a_x, 1 - a_z ),
27743                                         new Vector2( b_x, 1 - b_z ),
27744                                         new Vector2( c_x, 1 - c_z ),
27745                                         new Vector2( d_x, 1 - d_z )
27746                                 ];
27747
27748                         } else {
27749
27750                                 return [
27751                                         new Vector2( a_y, 1 - a_z ),
27752                                         new Vector2( b_y, 1 - b_z ),
27753                                         new Vector2( c_y, 1 - c_z ),
27754                                         new Vector2( d_y, 1 - d_z )
27755                                 ];
27756
27757                         }
27758
27759                 }
27760         };
27761
27762         /**
27763          * @author zz85 / http://www.lab4games.net/zz85/blog
27764          * @author alteredq / http://alteredqualia.com/
27765          *
27766          * Text = 3D Text
27767          *
27768          * parameters = {
27769          *  font: <THREE.Font>, // font
27770          *
27771          *  size: <float>, // size of the text
27772          *  height: <float>, // thickness to extrude text
27773          *  curveSegments: <int>, // number of points on the curves
27774          *
27775          *  bevelEnabled: <bool>, // turn on bevel
27776          *  bevelThickness: <float>, // how deep into text bevel goes
27777          *  bevelSize: <float> // how far from text outline is bevel
27778          * }
27779          */
27780
27781         // TextGeometry
27782
27783         function TextGeometry(  text, parameters ) {
27784
27785                 Geometry.call( this );
27786
27787                 this.type = 'TextGeometry';
27788
27789                 this.parameters = {
27790                         text: text,
27791                         parameters: parameters
27792                 };
27793
27794                 this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
27795                 this.mergeVertices();
27796
27797         }
27798
27799         TextGeometry.prototype = Object.create( Geometry.prototype );
27800         TextGeometry.prototype.constructor = TextGeometry;
27801
27802         // TextBufferGeometry
27803
27804         function TextBufferGeometry( text, parameters ) {
27805
27806                 parameters = parameters || {};
27807
27808                 var font = parameters.font;
27809
27810                 if ( ! ( font && font.isFont ) ) {
27811
27812                         console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
27813                         return new Geometry();
27814
27815                 }
27816
27817                 var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments );
27818
27819                 // translate parameters to ExtrudeGeometry API
27820
27821                 parameters.amount = parameters.height !== undefined ? parameters.height : 50;
27822
27823                 // defaults
27824
27825                 if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
27826                 if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
27827                 if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
27828
27829                 ExtrudeBufferGeometry.call( this, shapes, parameters );
27830
27831                 this.type = 'TextBufferGeometry';
27832
27833         }
27834
27835         TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype );
27836         TextBufferGeometry.prototype.constructor = TextBufferGeometry;
27837
27838         /**
27839          * @author mrdoob / http://mrdoob.com/
27840          * @author benaadams / https://twitter.com/ben_a_adams
27841          * @author Mugen87 / https://github.com/Mugen87
27842          */
27843
27844         // SphereGeometry
27845
27846         function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
27847
27848                 Geometry.call( this );
27849
27850                 this.type = 'SphereGeometry';
27851
27852                 this.parameters = {
27853                         radius: radius,
27854                         widthSegments: widthSegments,
27855                         heightSegments: heightSegments,
27856                         phiStart: phiStart,
27857                         phiLength: phiLength,
27858                         thetaStart: thetaStart,
27859                         thetaLength: thetaLength
27860                 };
27861
27862                 this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
27863                 this.mergeVertices();
27864
27865         }
27866
27867         SphereGeometry.prototype = Object.create( Geometry.prototype );
27868         SphereGeometry.prototype.constructor = SphereGeometry;
27869
27870         // SphereBufferGeometry
27871
27872         function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
27873
27874                 BufferGeometry.call( this );
27875
27876                 this.type = 'SphereBufferGeometry';
27877
27878                 this.parameters = {
27879                         radius: radius,
27880                         widthSegments: widthSegments,
27881                         heightSegments: heightSegments,
27882                         phiStart: phiStart,
27883                         phiLength: phiLength,
27884                         thetaStart: thetaStart,
27885                         thetaLength: thetaLength
27886                 };
27887
27888                 radius = radius || 50;
27889
27890                 widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
27891                 heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
27892
27893                 phiStart = phiStart !== undefined ? phiStart : 0;
27894                 phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
27895
27896                 thetaStart = thetaStart !== undefined ? thetaStart : 0;
27897                 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
27898
27899                 var thetaEnd = thetaStart + thetaLength;
27900
27901                 var ix, iy;
27902
27903                 var index = 0;
27904                 var grid = [];
27905
27906                 var vertex = new Vector3();
27907                 var normal = new Vector3();
27908
27909                 // buffers
27910
27911                 var indices = [];
27912                 var vertices = [];
27913                 var normals = [];
27914                 var uvs = [];
27915
27916                 // generate vertices, normals and uvs
27917
27918                 for ( iy = 0; iy <= heightSegments; iy ++ ) {
27919
27920                         var verticesRow = [];
27921
27922                         var v = iy / heightSegments;
27923
27924                         for ( ix = 0; ix <= widthSegments; ix ++ ) {
27925
27926                                 var u = ix / widthSegments;
27927
27928                                 // vertex
27929
27930                                 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
27931                                 vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
27932                                 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
27933
27934                                 vertices.push( vertex.x, vertex.y, vertex.z );
27935
27936                                 // normal
27937
27938                                 normal.set( vertex.x, vertex.y, vertex.z ).normalize();
27939                                 normals.push( normal.x, normal.y, normal.z );
27940
27941                                 // uv
27942
27943                                 uvs.push( u, 1 - v );
27944
27945                                 verticesRow.push( index ++ );
27946
27947                         }
27948
27949                         grid.push( verticesRow );
27950
27951                 }
27952
27953                 // indices
27954
27955                 for ( iy = 0; iy < heightSegments; iy ++ ) {
27956
27957                         for ( ix = 0; ix < widthSegments; ix ++ ) {
27958
27959                                 var a = grid[ iy ][ ix + 1 ];
27960                                 var b = grid[ iy ][ ix ];
27961                                 var c = grid[ iy + 1 ][ ix ];
27962                                 var d = grid[ iy + 1 ][ ix + 1 ];
27963
27964                                 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
27965                                 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
27966
27967                         }
27968
27969                 }
27970
27971                 // build geometry
27972
27973                 this.setIndex( indices );
27974                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
27975                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
27976                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
27977
27978         }
27979
27980         SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
27981         SphereBufferGeometry.prototype.constructor = SphereBufferGeometry;
27982
27983         /**
27984          * @author Kaleb Murphy
27985          * @author Mugen87 / https://github.com/Mugen87
27986          */
27987
27988         // RingGeometry
27989
27990         function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
27991
27992                 Geometry.call( this );
27993
27994                 this.type = 'RingGeometry';
27995
27996                 this.parameters = {
27997                         innerRadius: innerRadius,
27998                         outerRadius: outerRadius,
27999                         thetaSegments: thetaSegments,
28000                         phiSegments: phiSegments,
28001                         thetaStart: thetaStart,
28002                         thetaLength: thetaLength
28003                 };
28004
28005                 this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
28006                 this.mergeVertices();
28007
28008         }
28009
28010         RingGeometry.prototype = Object.create( Geometry.prototype );
28011         RingGeometry.prototype.constructor = RingGeometry;
28012
28013         // RingBufferGeometry
28014
28015         function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
28016
28017                 BufferGeometry.call( this );
28018
28019                 this.type = 'RingBufferGeometry';
28020
28021                 this.parameters = {
28022                         innerRadius: innerRadius,
28023                         outerRadius: outerRadius,
28024                         thetaSegments: thetaSegments,
28025                         phiSegments: phiSegments,
28026                         thetaStart: thetaStart,
28027                         thetaLength: thetaLength
28028                 };
28029
28030                 innerRadius = innerRadius || 20;
28031                 outerRadius = outerRadius || 50;
28032
28033                 thetaStart = thetaStart !== undefined ? thetaStart : 0;
28034                 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
28035
28036                 thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
28037                 phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;
28038
28039                 // buffers
28040
28041                 var indices = [];
28042                 var vertices = [];
28043                 var normals = [];
28044                 var uvs = [];
28045
28046                 // some helper variables
28047
28048                 var segment;
28049                 var radius = innerRadius;
28050                 var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
28051                 var vertex = new Vector3();
28052                 var uv = new Vector2();
28053                 var j, i;
28054
28055                 // generate vertices, normals and uvs
28056
28057                 for ( j = 0; j <= phiSegments; j ++ ) {
28058
28059                         for ( i = 0; i <= thetaSegments; i ++ ) {
28060
28061                                 // values are generate from the inside of the ring to the outside
28062
28063                                 segment = thetaStart + i / thetaSegments * thetaLength;
28064
28065                                 // vertex
28066
28067                                 vertex.x = radius * Math.cos( segment );
28068                                 vertex.y = radius * Math.sin( segment );
28069
28070                                 vertices.push( vertex.x, vertex.y, vertex.z );
28071
28072                                 // normal
28073
28074                                 normals.push( 0, 0, 1 );
28075
28076                                 // uv
28077
28078                                 uv.x = ( vertex.x / outerRadius + 1 ) / 2;
28079                                 uv.y = ( vertex.y / outerRadius + 1 ) / 2;
28080
28081                                 uvs.push( uv.x, uv.y );
28082
28083                         }
28084
28085                         // increase the radius for next row of vertices
28086
28087                         radius += radiusStep;
28088
28089                 }
28090
28091                 // indices
28092
28093                 for ( j = 0; j < phiSegments; j ++ ) {
28094
28095                         var thetaSegmentLevel = j * ( thetaSegments + 1 );
28096
28097                         for ( i = 0; i < thetaSegments; i ++ ) {
28098
28099                                 segment = i + thetaSegmentLevel;
28100
28101                                 var a = segment;
28102                                 var b = segment + thetaSegments + 1;
28103                                 var c = segment + thetaSegments + 2;
28104                                 var d = segment + 1;
28105
28106                                 // faces
28107
28108                                 indices.push( a, b, d );
28109                                 indices.push( b, c, d );
28110
28111                         }
28112
28113                 }
28114
28115                 // build geometry
28116
28117                 this.setIndex( indices );
28118                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28119                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28120                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28121
28122         }
28123
28124         RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28125         RingBufferGeometry.prototype.constructor = RingBufferGeometry;
28126
28127         /**
28128          * @author astrodud / http://astrodud.isgreat.org/
28129          * @author zz85 / https://github.com/zz85
28130          * @author bhouston / http://clara.io
28131          * @author Mugen87 / https://github.com/Mugen87
28132          */
28133
28134         // LatheGeometry
28135
28136         function LatheGeometry( points, segments, phiStart, phiLength ) {
28137
28138                 Geometry.call( this );
28139
28140                 this.type = 'LatheGeometry';
28141
28142                 this.parameters = {
28143                         points: points,
28144                         segments: segments,
28145                         phiStart: phiStart,
28146                         phiLength: phiLength
28147                 };
28148
28149                 this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
28150                 this.mergeVertices();
28151
28152         }
28153
28154         LatheGeometry.prototype = Object.create( Geometry.prototype );
28155         LatheGeometry.prototype.constructor = LatheGeometry;
28156
28157         // LatheBufferGeometry
28158
28159         function LatheBufferGeometry( points, segments, phiStart, phiLength ) {
28160
28161                 BufferGeometry.call( this );
28162
28163                 this.type = 'LatheBufferGeometry';
28164
28165                 this.parameters = {
28166                         points: points,
28167                         segments: segments,
28168                         phiStart: phiStart,
28169                         phiLength: phiLength
28170                 };
28171
28172                 segments = Math.floor( segments ) || 12;
28173                 phiStart = phiStart || 0;
28174                 phiLength = phiLength || Math.PI * 2;
28175
28176                 // clamp phiLength so it's in range of [ 0, 2PI ]
28177
28178                 phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 );
28179
28180
28181                 // buffers
28182
28183                 var indices = [];
28184                 var vertices = [];
28185                 var uvs = [];
28186
28187                 // helper variables
28188
28189                 var base;
28190                 var inverseSegments = 1.0 / segments;
28191                 var vertex = new Vector3();
28192                 var uv = new Vector2();
28193                 var i, j;
28194
28195                 // generate vertices and uvs
28196
28197                 for ( i = 0; i <= segments; i ++ ) {
28198
28199                         var phi = phiStart + i * inverseSegments * phiLength;
28200
28201                         var sin = Math.sin( phi );
28202                         var cos = Math.cos( phi );
28203
28204                         for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
28205
28206                                 // vertex
28207
28208                                 vertex.x = points[ j ].x * sin;
28209                                 vertex.y = points[ j ].y;
28210                                 vertex.z = points[ j ].x * cos;
28211
28212                                 vertices.push( vertex.x, vertex.y, vertex.z );
28213
28214                                 // uv
28215
28216                                 uv.x = i / segments;
28217                                 uv.y = j / ( points.length - 1 );
28218
28219                                 uvs.push( uv.x, uv.y );
28220
28221
28222                         }
28223
28224                 }
28225
28226                 // indices
28227
28228                 for ( i = 0; i < segments; i ++ ) {
28229
28230                         for ( j = 0; j < ( points.length - 1 ); j ++ ) {
28231
28232                                 base = j + i * points.length;
28233
28234                                 var a = base;
28235                                 var b = base + points.length;
28236                                 var c = base + points.length + 1;
28237                                 var d = base + 1;
28238
28239                                 // faces
28240
28241                                 indices.push( a, b, d );
28242                                 indices.push( b, c, d );
28243
28244                         }
28245
28246                 }
28247
28248                 // build geometry
28249
28250                 this.setIndex( indices );
28251                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28252                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28253
28254                 // generate normals
28255
28256                 this.computeVertexNormals();
28257
28258                 // if the geometry is closed, we need to average the normals along the seam.
28259                 // because the corresponding vertices are identical (but still have different UVs).
28260
28261                 if ( phiLength === Math.PI * 2 ) {
28262
28263                         var normals = this.attributes.normal.array;
28264                         var n1 = new Vector3();
28265                         var n2 = new Vector3();
28266                         var n = new Vector3();
28267
28268                         // this is the buffer offset for the last line of vertices
28269
28270                         base = segments * points.length * 3;
28271
28272                         for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
28273
28274                                 // select the normal of the vertex in the first line
28275
28276                                 n1.x = normals[ j + 0 ];
28277                                 n1.y = normals[ j + 1 ];
28278                                 n1.z = normals[ j + 2 ];
28279
28280                                 // select the normal of the vertex in the last line
28281
28282                                 n2.x = normals[ base + j + 0 ];
28283                                 n2.y = normals[ base + j + 1 ];
28284                                 n2.z = normals[ base + j + 2 ];
28285
28286                                 // average normals
28287
28288                                 n.addVectors( n1, n2 ).normalize();
28289
28290                                 // assign the new values to both normals
28291
28292                                 normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
28293                                 normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
28294                                 normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
28295
28296                         }
28297
28298                 }
28299
28300         }
28301
28302         LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28303         LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
28304
28305         /**
28306          * @author jonobr1 / http://jonobr1.com
28307          * @author Mugen87 / https://github.com/Mugen87
28308          */
28309
28310         // ShapeGeometry
28311
28312         function ShapeGeometry( shapes, curveSegments ) {
28313
28314                 Geometry.call( this );
28315
28316                 this.type = 'ShapeGeometry';
28317
28318                 if ( typeof curveSegments === 'object' ) {
28319
28320                         console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
28321
28322                         curveSegments = curveSegments.curveSegments;
28323
28324                 }
28325
28326                 this.parameters = {
28327                         shapes: shapes,
28328                         curveSegments: curveSegments
28329                 };
28330
28331                 this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
28332                 this.mergeVertices();
28333
28334         }
28335
28336         ShapeGeometry.prototype = Object.create( Geometry.prototype );
28337         ShapeGeometry.prototype.constructor = ShapeGeometry;
28338
28339         // ShapeBufferGeometry
28340
28341         function ShapeBufferGeometry( shapes, curveSegments ) {
28342
28343                 BufferGeometry.call( this );
28344
28345                 this.type = 'ShapeBufferGeometry';
28346
28347                 this.parameters = {
28348                         shapes: shapes,
28349                         curveSegments: curveSegments
28350                 };
28351
28352                 curveSegments = curveSegments || 12;
28353
28354                 // buffers
28355
28356                 var indices = [];
28357                 var vertices = [];
28358                 var normals = [];
28359                 var uvs = [];
28360
28361                 // helper variables
28362
28363                 var groupStart = 0;
28364                 var groupCount = 0;
28365
28366                 // allow single and array values for "shapes" parameter
28367
28368                 if ( Array.isArray( shapes ) === false ) {
28369
28370                         addShape( shapes );
28371
28372                 } else {
28373
28374                         for ( var i = 0; i < shapes.length; i ++ ) {
28375
28376                                 addShape( shapes[ i ] );
28377
28378                                 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
28379
28380                                 groupStart += groupCount;
28381                                 groupCount = 0;
28382
28383                         }
28384
28385                 }
28386
28387                 // build geometry
28388
28389                 this.setIndex( indices );
28390                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28391                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28392                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28393
28394
28395                 // helper functions
28396
28397                 function addShape( shape ) {
28398
28399                         var i, l, shapeHole;
28400
28401                         var indexOffset = vertices.length / 3;
28402                         var points = shape.extractPoints( curveSegments );
28403
28404                         var shapeVertices = points.shape;
28405                         var shapeHoles = points.holes;
28406
28407                         // check direction of vertices
28408
28409                         if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
28410
28411                                 shapeVertices = shapeVertices.reverse();
28412
28413                                 // also check if holes are in the opposite direction
28414
28415                                 for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
28416
28417                                         shapeHole = shapeHoles[ i ];
28418
28419                                         if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
28420
28421                                                 shapeHoles[ i ] = shapeHole.reverse();
28422
28423                                         }
28424
28425                                 }
28426
28427                         }
28428
28429                         var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
28430
28431                         // join vertices of inner and outer paths to a single array
28432
28433                         for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
28434
28435                                 shapeHole = shapeHoles[ i ];
28436                                 shapeVertices = shapeVertices.concat( shapeHole );
28437
28438                         }
28439
28440                         // vertices, normals, uvs
28441
28442                         for ( i = 0, l = shapeVertices.length; i < l; i ++ ) {
28443
28444                                 var vertex = shapeVertices[ i ];
28445
28446                                 vertices.push( vertex.x, vertex.y, 0 );
28447                                 normals.push( 0, 0, 1 );
28448                                 uvs.push( vertex.x, vertex.y ); // world uvs
28449
28450                         }
28451
28452                         // incides
28453
28454                         for ( i = 0, l = faces.length; i < l; i ++ ) {
28455
28456                                 var face = faces[ i ];
28457
28458                                 var a = face[ 0 ] + indexOffset;
28459                                 var b = face[ 1 ] + indexOffset;
28460                                 var c = face[ 2 ] + indexOffset;
28461
28462                                 indices.push( a, b, c );
28463                                 groupCount += 3;
28464
28465                         }
28466
28467                 }
28468
28469         }
28470
28471         ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28472         ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;
28473
28474         /**
28475          * @author WestLangley / http://github.com/WestLangley
28476          * @author Mugen87 / https://github.com/Mugen87
28477          */
28478
28479         function EdgesGeometry( geometry, thresholdAngle ) {
28480
28481                 BufferGeometry.call( this );
28482
28483                 this.type = 'EdgesGeometry';
28484
28485                 this.parameters = {
28486                         thresholdAngle: thresholdAngle
28487                 };
28488
28489                 thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
28490
28491                 // buffer
28492
28493                 var vertices = [];
28494
28495                 // helper variables
28496
28497                 var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle );
28498                 var edge = [ 0, 0 ], edges = {}, edge1, edge2;
28499                 var key, keys = [ 'a', 'b', 'c' ];
28500
28501                 // prepare source geometry
28502
28503                 var geometry2;
28504
28505                 if ( geometry.isBufferGeometry ) {
28506
28507                         geometry2 = new Geometry();
28508                         geometry2.fromBufferGeometry( geometry );
28509
28510                 } else {
28511
28512                         geometry2 = geometry.clone();
28513
28514                 }
28515
28516                 geometry2.mergeVertices();
28517                 geometry2.computeFaceNormals();
28518
28519                 var sourceVertices = geometry2.vertices;
28520                 var faces = geometry2.faces;
28521
28522                 // now create a data structure where each entry represents an edge with its adjoining faces
28523
28524                 for ( var i = 0, l = faces.length; i < l; i ++ ) {
28525
28526                         var face = faces[ i ];
28527
28528                         for ( var j = 0; j < 3; j ++ ) {
28529
28530                                 edge1 = face[ keys[ j ] ];
28531                                 edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
28532                                 edge[ 0 ] = Math.min( edge1, edge2 );
28533                                 edge[ 1 ] = Math.max( edge1, edge2 );
28534
28535                                 key = edge[ 0 ] + ',' + edge[ 1 ];
28536
28537                                 if ( edges[ key ] === undefined ) {
28538
28539                                         edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined };
28540
28541                                 } else {
28542
28543                                         edges[ key ].face2 = i;
28544
28545                                 }
28546
28547                         }
28548
28549                 }
28550
28551                 // generate vertices
28552
28553                 for ( key in edges ) {
28554
28555                         var e = edges[ key ];
28556
28557                         // an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree.
28558
28559                         if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {
28560
28561                                 var vertex = sourceVertices[ e.index1 ];
28562                                 vertices.push( vertex.x, vertex.y, vertex.z );
28563
28564                                 vertex = sourceVertices[ e.index2 ];
28565                                 vertices.push( vertex.x, vertex.y, vertex.z );
28566
28567                         }
28568
28569                 }
28570
28571                 // build geometry
28572
28573                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28574
28575         }
28576
28577         EdgesGeometry.prototype = Object.create( BufferGeometry.prototype );
28578         EdgesGeometry.prototype.constructor = EdgesGeometry;
28579
28580         /**
28581          * @author mrdoob / http://mrdoob.com/
28582          * @author Mugen87 / https://github.com/Mugen87
28583          */
28584
28585         // CylinderGeometry
28586
28587         function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
28588
28589                 Geometry.call( this );
28590
28591                 this.type = 'CylinderGeometry';
28592
28593                 this.parameters = {
28594                         radiusTop: radiusTop,
28595                         radiusBottom: radiusBottom,
28596                         height: height,
28597                         radialSegments: radialSegments,
28598                         heightSegments: heightSegments,
28599                         openEnded: openEnded,
28600                         thetaStart: thetaStart,
28601                         thetaLength: thetaLength
28602                 };
28603
28604                 this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
28605                 this.mergeVertices();
28606
28607         }
28608
28609         CylinderGeometry.prototype = Object.create( Geometry.prototype );
28610         CylinderGeometry.prototype.constructor = CylinderGeometry;
28611
28612         // CylinderBufferGeometry
28613
28614         function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
28615
28616                 BufferGeometry.call( this );
28617
28618                 this.type = 'CylinderBufferGeometry';
28619
28620                 this.parameters = {
28621                         radiusTop: radiusTop,
28622                         radiusBottom: radiusBottom,
28623                         height: height,
28624                         radialSegments: radialSegments,
28625                         heightSegments: heightSegments,
28626                         openEnded: openEnded,
28627                         thetaStart: thetaStart,
28628                         thetaLength: thetaLength
28629                 };
28630
28631                 var scope = this;
28632
28633                 radiusTop = radiusTop !== undefined ? radiusTop : 20;
28634                 radiusBottom = radiusBottom !== undefined ? radiusBottom : 20;
28635                 height = height !== undefined ? height : 100;
28636
28637                 radialSegments = Math.floor( radialSegments ) || 8;
28638                 heightSegments = Math.floor( heightSegments ) || 1;
28639
28640                 openEnded = openEnded !== undefined ? openEnded : false;
28641                 thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
28642                 thetaLength = thetaLength !== undefined ? thetaLength : 2.0 * Math.PI;
28643
28644                 // buffers
28645
28646                 var indices = [];
28647                 var vertices = [];
28648                 var normals = [];
28649                 var uvs = [];
28650
28651                 // helper variables
28652
28653                 var index = 0;
28654                 var indexArray = [];
28655                 var halfHeight = height / 2;
28656                 var groupStart = 0;
28657
28658                 // generate geometry
28659
28660                 generateTorso();
28661
28662                 if ( openEnded === false ) {
28663
28664                         if ( radiusTop > 0 ) generateCap( true );
28665                         if ( radiusBottom > 0 ) generateCap( false );
28666
28667                 }
28668
28669                 // build geometry
28670
28671                 this.setIndex( indices );
28672                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28673                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28674                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28675
28676                 function generateTorso() {
28677
28678                         var x, y;
28679                         var normal = new Vector3();
28680                         var vertex = new Vector3();
28681
28682                         var groupCount = 0;
28683
28684                         // this will be used to calculate the normal
28685                         var slope = ( radiusBottom - radiusTop ) / height;
28686
28687                         // generate vertices, normals and uvs
28688
28689                         for ( y = 0; y <= heightSegments; y ++ ) {
28690
28691                                 var indexRow = [];
28692
28693                                 var v = y / heightSegments;
28694
28695                                 // calculate the radius of the current row
28696
28697                                 var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
28698
28699                                 for ( x = 0; x <= radialSegments; x ++ ) {
28700
28701                                         var u = x / radialSegments;
28702
28703                                         var theta = u * thetaLength + thetaStart;
28704
28705                                         var sinTheta = Math.sin( theta );
28706                                         var cosTheta = Math.cos( theta );
28707
28708                                         // vertex
28709
28710                                         vertex.x = radius * sinTheta;
28711                                         vertex.y = - v * height + halfHeight;
28712                                         vertex.z = radius * cosTheta;
28713                                         vertices.push( vertex.x, vertex.y, vertex.z );
28714
28715                                         // normal
28716
28717                                         normal.set( sinTheta, slope, cosTheta ).normalize();
28718                                         normals.push( normal.x, normal.y, normal.z );
28719
28720                                         // uv
28721
28722                                         uvs.push( u, 1 - v );
28723
28724                                         // save index of vertex in respective row
28725
28726                                         indexRow.push( index ++ );
28727
28728                                 }
28729
28730                                 // now save vertices of the row in our index array
28731
28732                                 indexArray.push( indexRow );
28733
28734                         }
28735
28736                         // generate indices
28737
28738                         for ( x = 0; x < radialSegments; x ++ ) {
28739
28740                                 for ( y = 0; y < heightSegments; y ++ ) {
28741
28742                                         // we use the index array to access the correct indices
28743
28744                                         var a = indexArray[ y ][ x ];
28745                                         var b = indexArray[ y + 1 ][ x ];
28746                                         var c = indexArray[ y + 1 ][ x + 1 ];
28747                                         var d = indexArray[ y ][ x + 1 ];
28748
28749                                         // faces
28750
28751                                         indices.push( a, b, d );
28752                                         indices.push( b, c, d );
28753
28754                                         // update group counter
28755
28756                                         groupCount += 6;
28757
28758                                 }
28759
28760                         }
28761
28762                         // add a group to the geometry. this will ensure multi material support
28763
28764                         scope.addGroup( groupStart, groupCount, 0 );
28765
28766                         // calculate new start value for groups
28767
28768                         groupStart += groupCount;
28769
28770                 }
28771
28772                 function generateCap( top ) {
28773
28774                         var x, centerIndexStart, centerIndexEnd;
28775
28776                         var uv = new Vector2();
28777                         var vertex = new Vector3();
28778
28779                         var groupCount = 0;
28780
28781                         var radius = ( top === true ) ? radiusTop : radiusBottom;
28782                         var sign = ( top === true ) ? 1 : - 1;
28783
28784                         // save the index of the first center vertex
28785                         centerIndexStart = index;
28786
28787                         // first we generate the center vertex data of the cap.
28788                         // because the geometry needs one set of uvs per face,
28789                         // we must generate a center vertex per face/segment
28790
28791                         for ( x = 1; x <= radialSegments; x ++ ) {
28792
28793                                 // vertex
28794
28795                                 vertices.push( 0, halfHeight * sign, 0 );
28796
28797                                 // normal
28798
28799                                 normals.push( 0, sign, 0 );
28800
28801                                 // uv
28802
28803                                 uvs.push( 0.5, 0.5 );
28804
28805                                 // increase index
28806
28807                                 index ++;
28808
28809                         }
28810
28811                         // save the index of the last center vertex
28812
28813                         centerIndexEnd = index;
28814
28815                         // now we generate the surrounding vertices, normals and uvs
28816
28817                         for ( x = 0; x <= radialSegments; x ++ ) {
28818
28819                                 var u = x / radialSegments;
28820                                 var theta = u * thetaLength + thetaStart;
28821
28822                                 var cosTheta = Math.cos( theta );
28823                                 var sinTheta = Math.sin( theta );
28824
28825                                 // vertex
28826
28827                                 vertex.x = radius * sinTheta;
28828                                 vertex.y = halfHeight * sign;
28829                                 vertex.z = radius * cosTheta;
28830                                 vertices.push( vertex.x, vertex.y, vertex.z );
28831
28832                                 // normal
28833
28834                                 normals.push( 0, sign, 0 );
28835
28836                                 // uv
28837
28838                                 uv.x = ( cosTheta * 0.5 ) + 0.5;
28839                                 uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
28840                                 uvs.push( uv.x, uv.y );
28841
28842                                 // increase index
28843
28844                                 index ++;
28845
28846                         }
28847
28848                         // generate indices
28849
28850                         for ( x = 0; x < radialSegments; x ++ ) {
28851
28852                                 var c = centerIndexStart + x;
28853                                 var i = centerIndexEnd + x;
28854
28855                                 if ( top === true ) {
28856
28857                                         // face top
28858
28859                                         indices.push( i, i + 1, c );
28860
28861                                 } else {
28862
28863                                         // face bottom
28864
28865                                         indices.push( i + 1, i, c );
28866
28867                                 }
28868
28869                                 groupCount += 3;
28870
28871                         }
28872
28873                         // add a group to the geometry. this will ensure multi material support
28874
28875                         scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
28876
28877                         // calculate new start value for groups
28878
28879                         groupStart += groupCount;
28880
28881                 }
28882
28883         }
28884
28885         CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28886         CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;
28887
28888         /**
28889          * @author abelnation / http://github.com/abelnation
28890          */
28891
28892         // ConeGeometry
28893
28894         function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
28895
28896                 CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
28897
28898                 this.type = 'ConeGeometry';
28899
28900                 this.parameters = {
28901                         radius: radius,
28902                         height: height,
28903                         radialSegments: radialSegments,
28904                         heightSegments: heightSegments,
28905                         openEnded: openEnded,
28906                         thetaStart: thetaStart,
28907                         thetaLength: thetaLength
28908                 };
28909
28910         }
28911
28912         ConeGeometry.prototype = Object.create( CylinderGeometry.prototype );
28913         ConeGeometry.prototype.constructor = ConeGeometry;
28914
28915         // ConeBufferGeometry
28916
28917         function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
28918
28919                 CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
28920
28921                 this.type = 'ConeBufferGeometry';
28922
28923                 this.parameters = {
28924                         radius: radius,
28925                         height: height,
28926                         radialSegments: radialSegments,
28927                         heightSegments: heightSegments,
28928                         openEnded: openEnded,
28929                         thetaStart: thetaStart,
28930                         thetaLength: thetaLength
28931                 };
28932
28933         }
28934
28935         ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype );
28936         ConeBufferGeometry.prototype.constructor = ConeBufferGeometry;
28937
28938         /**
28939          * @author benaadams / https://twitter.com/ben_a_adams
28940          * @author Mugen87 / https://github.com/Mugen87
28941          * @author hughes
28942          */
28943
28944         // CircleGeometry
28945
28946         function CircleGeometry( radius, segments, thetaStart, thetaLength ) {
28947
28948                 Geometry.call( this );
28949
28950                 this.type = 'CircleGeometry';
28951
28952                 this.parameters = {
28953                         radius: radius,
28954                         segments: segments,
28955                         thetaStart: thetaStart,
28956                         thetaLength: thetaLength
28957                 };
28958
28959                 this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
28960                 this.mergeVertices();
28961
28962         }
28963
28964         CircleGeometry.prototype = Object.create( Geometry.prototype );
28965         CircleGeometry.prototype.constructor = CircleGeometry;
28966
28967         // CircleBufferGeometry
28968
28969         function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) {
28970
28971                 BufferGeometry.call( this );
28972
28973                 this.type = 'CircleBufferGeometry';
28974
28975                 this.parameters = {
28976                         radius: radius,
28977                         segments: segments,
28978                         thetaStart: thetaStart,
28979                         thetaLength: thetaLength
28980                 };
28981
28982                 radius = radius || 50;
28983                 segments = segments !== undefined ? Math.max( 3, segments ) : 8;
28984
28985                 thetaStart = thetaStart !== undefined ? thetaStart : 0;
28986                 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
28987
28988                 // buffers
28989
28990                 var indices = [];
28991                 var vertices = [];
28992                 var normals = [];
28993                 var uvs = [];
28994
28995                 // helper variables
28996
28997                 var i, s;
28998                 var vertex = new Vector3();
28999                 var uv = new Vector2();
29000
29001                 // center point
29002
29003                 vertices.push( 0, 0, 0 );
29004                 normals.push( 0, 0, 1 );
29005                 uvs.push( 0.5, 0.5 );
29006
29007                 for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {
29008
29009                         var segment = thetaStart + s / segments * thetaLength;
29010
29011                         // vertex
29012
29013                         vertex.x = radius * Math.cos( segment );
29014                         vertex.y = radius * Math.sin( segment );
29015
29016                         vertices.push( vertex.x, vertex.y, vertex.z );
29017
29018                         // normal
29019
29020                         normals.push( 0, 0, 1 );
29021
29022                         // uvs
29023
29024                         uv.x = ( vertices[ i ] / radius + 1 ) / 2;
29025                         uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
29026
29027                         uvs.push( uv.x, uv.y );
29028
29029                 }
29030
29031                 // indices
29032
29033                 for ( i = 1; i <= segments; i ++ ) {
29034
29035                         indices.push( i, i + 1, 0 );
29036
29037                 }
29038
29039                 // build geometry
29040
29041                 this.setIndex( indices );
29042                 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29043                 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29044                 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29045
29046         }
29047
29048         CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29049         CircleBufferGeometry.prototype.constructor = CircleBufferGeometry;
29050
29051
29052
29053         var Geometries = Object.freeze({
29054                 WireframeGeometry: WireframeGeometry,
29055                 ParametricGeometry: ParametricGeometry,
29056                 ParametricBufferGeometry: ParametricBufferGeometry,
29057                 TetrahedronGeometry: TetrahedronGeometry,
29058                 TetrahedronBufferGeometry: TetrahedronBufferGeometry,
29059                 OctahedronGeometry: OctahedronGeometry,
29060                 OctahedronBufferGeometry: OctahedronBufferGeometry,
29061                 IcosahedronGeometry: IcosahedronGeometry,
29062                 IcosahedronBufferGeometry: IcosahedronBufferGeometry,
29063                 DodecahedronGeometry: DodecahedronGeometry,
29064                 DodecahedronBufferGeometry: DodecahedronBufferGeometry,
29065                 PolyhedronGeometry: PolyhedronGeometry,
29066                 PolyhedronBufferGeometry: PolyhedronBufferGeometry,
29067                 TubeGeometry: TubeGeometry,
29068                 TubeBufferGeometry: TubeBufferGeometry,
29069                 TorusKnotGeometry: TorusKnotGeometry,
29070                 TorusKnotBufferGeometry: TorusKnotBufferGeometry,
29071                 TorusGeometry: TorusGeometry,
29072                 TorusBufferGeometry: TorusBufferGeometry,
29073                 TextGeometry: TextGeometry,
29074                 TextBufferGeometry: TextBufferGeometry,
29075                 SphereGeometry: SphereGeometry,
29076                 SphereBufferGeometry: SphereBufferGeometry,
29077                 RingGeometry: RingGeometry,
29078                 RingBufferGeometry: RingBufferGeometry,
29079                 PlaneGeometry: PlaneGeometry,
29080                 PlaneBufferGeometry: PlaneBufferGeometry,
29081                 LatheGeometry: LatheGeometry,
29082                 LatheBufferGeometry: LatheBufferGeometry,
29083                 ShapeGeometry: ShapeGeometry,
29084                 ShapeBufferGeometry: ShapeBufferGeometry,
29085                 ExtrudeGeometry: ExtrudeGeometry,
29086                 ExtrudeBufferGeometry: ExtrudeBufferGeometry,
29087                 EdgesGeometry: EdgesGeometry,
29088                 ConeGeometry: ConeGeometry,
29089                 ConeBufferGeometry: ConeBufferGeometry,
29090                 CylinderGeometry: CylinderGeometry,
29091                 CylinderBufferGeometry: CylinderBufferGeometry,
29092                 CircleGeometry: CircleGeometry,
29093                 CircleBufferGeometry: CircleBufferGeometry,
29094                 BoxGeometry: BoxGeometry,
29095                 BoxBufferGeometry: BoxBufferGeometry
29096         });
29097
29098         /**
29099          * @author mrdoob / http://mrdoob.com/
29100          *
29101          * parameters = {
29102          *  color: <THREE.Color>,
29103          *  opacity: <float>
29104          * }
29105          */
29106
29107         function ShadowMaterial( parameters ) {
29108
29109                 Material.call( this );
29110
29111                 this.type = 'ShadowMaterial';
29112
29113                 this.color = new Color( 0x000000 );
29114                 this.opacity = 1.0;
29115
29116                 this.lights = true;
29117                 this.transparent = true;
29118
29119                 this.setValues( parameters );
29120
29121         }
29122
29123         ShadowMaterial.prototype = Object.create( Material.prototype );
29124         ShadowMaterial.prototype.constructor = ShadowMaterial;
29125
29126         ShadowMaterial.prototype.isShadowMaterial = true;
29127
29128         /**
29129          * @author mrdoob / http://mrdoob.com/
29130          */
29131
29132         function RawShaderMaterial( parameters ) {
29133
29134                 ShaderMaterial.call( this, parameters );
29135
29136                 this.type = 'RawShaderMaterial';
29137
29138         }
29139
29140         RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
29141         RawShaderMaterial.prototype.constructor = RawShaderMaterial;
29142
29143         RawShaderMaterial.prototype.isRawShaderMaterial = true;
29144
29145         /**
29146          * @author WestLangley / http://github.com/WestLangley
29147          *
29148          * parameters = {
29149          *  color: <hex>,
29150          *  roughness: <float>,
29151          *  metalness: <float>,
29152          *  opacity: <float>,
29153          *
29154          *  map: new THREE.Texture( <Image> ),
29155          *
29156          *  lightMap: new THREE.Texture( <Image> ),
29157          *  lightMapIntensity: <float>
29158          *
29159          *  aoMap: new THREE.Texture( <Image> ),
29160          *  aoMapIntensity: <float>
29161          *
29162          *  emissive: <hex>,
29163          *  emissiveIntensity: <float>
29164          *  emissiveMap: new THREE.Texture( <Image> ),
29165          *
29166          *  bumpMap: new THREE.Texture( <Image> ),
29167          *  bumpScale: <float>,
29168          *
29169          *  normalMap: new THREE.Texture( <Image> ),
29170          *  normalScale: <Vector2>,
29171          *
29172          *  displacementMap: new THREE.Texture( <Image> ),
29173          *  displacementScale: <float>,
29174          *  displacementBias: <float>,
29175          *
29176          *  roughnessMap: new THREE.Texture( <Image> ),
29177          *
29178          *  metalnessMap: new THREE.Texture( <Image> ),
29179          *
29180          *  alphaMap: new THREE.Texture( <Image> ),
29181          *
29182          *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
29183          *  envMapIntensity: <float>
29184          *
29185          *  refractionRatio: <float>,
29186          *
29187          *  wireframe: <boolean>,
29188          *  wireframeLinewidth: <float>,
29189          *
29190          *  skinning: <bool>,
29191          *  morphTargets: <bool>,
29192          *  morphNormals: <bool>
29193          * }
29194          */
29195
29196         function MeshStandardMaterial( parameters ) {
29197
29198                 Material.call( this );
29199
29200                 this.defines = { 'STANDARD': '' };
29201
29202                 this.type = 'MeshStandardMaterial';
29203
29204                 this.color = new Color( 0xffffff ); // diffuse
29205                 this.roughness = 0.5;
29206                 this.metalness = 0.5;
29207
29208                 this.map = null;
29209
29210                 this.lightMap = null;
29211                 this.lightMapIntensity = 1.0;
29212
29213                 this.aoMap = null;
29214                 this.aoMapIntensity = 1.0;
29215
29216                 this.emissive = new Color( 0x000000 );
29217                 this.emissiveIntensity = 1.0;
29218                 this.emissiveMap = null;
29219
29220                 this.bumpMap = null;
29221                 this.bumpScale = 1;
29222
29223                 this.normalMap = null;
29224                 this.normalScale = new Vector2( 1, 1 );
29225
29226                 this.displacementMap = null;
29227                 this.displacementScale = 1;
29228                 this.displacementBias = 0;
29229
29230                 this.roughnessMap = null;
29231
29232                 this.metalnessMap = null;
29233
29234                 this.alphaMap = null;
29235
29236                 this.envMap = null;
29237                 this.envMapIntensity = 1.0;
29238
29239                 this.refractionRatio = 0.98;
29240
29241                 this.wireframe = false;
29242                 this.wireframeLinewidth = 1;
29243                 this.wireframeLinecap = 'round';
29244                 this.wireframeLinejoin = 'round';
29245
29246                 this.skinning = false;
29247                 this.morphTargets = false;
29248                 this.morphNormals = false;
29249
29250                 this.setValues( parameters );
29251
29252         }
29253
29254         MeshStandardMaterial.prototype = Object.create( Material.prototype );
29255         MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
29256
29257         MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
29258
29259         MeshStandardMaterial.prototype.copy = function ( source ) {
29260
29261                 Material.prototype.copy.call( this, source );
29262
29263                 this.defines = { 'STANDARD': '' };
29264
29265                 this.color.copy( source.color );
29266                 this.roughness = source.roughness;
29267                 this.metalness = source.metalness;
29268
29269                 this.map = source.map;
29270
29271                 this.lightMap = source.lightMap;
29272                 this.lightMapIntensity = source.lightMapIntensity;
29273
29274                 this.aoMap = source.aoMap;
29275                 this.aoMapIntensity = source.aoMapIntensity;
29276
29277                 this.emissive.copy( source.emissive );
29278                 this.emissiveMap = source.emissiveMap;
29279                 this.emissiveIntensity = source.emissiveIntensity;
29280
29281                 this.bumpMap = source.bumpMap;
29282                 this.bumpScale = source.bumpScale;
29283
29284                 this.normalMap = source.normalMap;
29285                 this.normalScale.copy( source.normalScale );
29286
29287                 this.displacementMap = source.displacementMap;
29288                 this.displacementScale = source.displacementScale;
29289                 this.displacementBias = source.displacementBias;
29290
29291                 this.roughnessMap = source.roughnessMap;
29292
29293                 this.metalnessMap = source.metalnessMap;
29294
29295                 this.alphaMap = source.alphaMap;
29296
29297                 this.envMap = source.envMap;
29298                 this.envMapIntensity = source.envMapIntensity;
29299
29300                 this.refractionRatio = source.refractionRatio;
29301
29302                 this.wireframe = source.wireframe;
29303                 this.wireframeLinewidth = source.wireframeLinewidth;
29304                 this.wireframeLinecap = source.wireframeLinecap;
29305                 this.wireframeLinejoin = source.wireframeLinejoin;
29306
29307                 this.skinning = source.skinning;
29308                 this.morphTargets = source.morphTargets;
29309                 this.morphNormals = source.morphNormals;
29310
29311                 return this;
29312
29313         };
29314
29315         /**
29316          * @author WestLangley / http://github.com/WestLangley
29317          *
29318          * parameters = {
29319          *  reflectivity: <float>
29320          * }
29321          */
29322
29323         function MeshPhysicalMaterial( parameters ) {
29324
29325                 MeshStandardMaterial.call( this );
29326
29327                 this.defines = { 'PHYSICAL': '' };
29328
29329                 this.type = 'MeshPhysicalMaterial';
29330
29331                 this.reflectivity = 0.5; // maps to F0 = 0.04
29332
29333                 this.clearCoat = 0.0;
29334                 this.clearCoatRoughness = 0.0;
29335
29336                 this.setValues( parameters );
29337
29338         }
29339
29340         MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
29341         MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
29342
29343         MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
29344
29345         MeshPhysicalMaterial.prototype.copy = function ( source ) {
29346
29347                 MeshStandardMaterial.prototype.copy.call( this, source );
29348
29349                 this.defines = { 'PHYSICAL': '' };
29350
29351                 this.reflectivity = source.reflectivity;
29352
29353                 this.clearCoat = source.clearCoat;
29354                 this.clearCoatRoughness = source.clearCoatRoughness;
29355
29356                 return this;
29357
29358         };
29359
29360         /**
29361          * @author mrdoob / http://mrdoob.com/
29362          * @author alteredq / http://alteredqualia.com/
29363          *
29364          * parameters = {
29365          *  color: <hex>,
29366          *  specular: <hex>,
29367          *  shininess: <float>,
29368          *  opacity: <float>,
29369          *
29370          *  map: new THREE.Texture( <Image> ),
29371          *
29372          *  lightMap: new THREE.Texture( <Image> ),
29373          *  lightMapIntensity: <float>
29374          *
29375          *  aoMap: new THREE.Texture( <Image> ),
29376          *  aoMapIntensity: <float>
29377          *
29378          *  emissive: <hex>,
29379          *  emissiveIntensity: <float>
29380          *  emissiveMap: new THREE.Texture( <Image> ),
29381          *
29382          *  bumpMap: new THREE.Texture( <Image> ),
29383          *  bumpScale: <float>,
29384          *
29385          *  normalMap: new THREE.Texture( <Image> ),
29386          *  normalScale: <Vector2>,
29387          *
29388          *  displacementMap: new THREE.Texture( <Image> ),
29389          *  displacementScale: <float>,
29390          *  displacementBias: <float>,
29391          *
29392          *  specularMap: new THREE.Texture( <Image> ),
29393          *
29394          *  alphaMap: new THREE.Texture( <Image> ),
29395          *
29396          *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
29397          *  combine: THREE.Multiply,
29398          *  reflectivity: <float>,
29399          *  refractionRatio: <float>,
29400          *
29401          *  wireframe: <boolean>,
29402          *  wireframeLinewidth: <float>,
29403          *
29404          *  skinning: <bool>,
29405          *  morphTargets: <bool>,
29406          *  morphNormals: <bool>
29407          * }
29408          */
29409
29410         function MeshPhongMaterial( parameters ) {
29411
29412                 Material.call( this );
29413
29414                 this.type = 'MeshPhongMaterial';
29415
29416                 this.color = new Color( 0xffffff ); // diffuse
29417                 this.specular = new Color( 0x111111 );
29418                 this.shininess = 30;
29419
29420                 this.map = null;
29421
29422                 this.lightMap = null;
29423                 this.lightMapIntensity = 1.0;
29424
29425                 this.aoMap = null;
29426                 this.aoMapIntensity = 1.0;
29427
29428                 this.emissive = new Color( 0x000000 );
29429                 this.emissiveIntensity = 1.0;
29430                 this.emissiveMap = null;
29431
29432                 this.bumpMap = null;
29433                 this.bumpScale = 1;
29434
29435                 this.normalMap = null;
29436                 this.normalScale = new Vector2( 1, 1 );
29437
29438                 this.displacementMap = null;
29439                 this.displacementScale = 1;
29440                 this.displacementBias = 0;
29441
29442                 this.specularMap = null;
29443
29444                 this.alphaMap = null;
29445
29446                 this.envMap = null;
29447                 this.combine = MultiplyOperation;
29448                 this.reflectivity = 1;
29449                 this.refractionRatio = 0.98;
29450
29451                 this.wireframe = false;
29452                 this.wireframeLinewidth = 1;
29453                 this.wireframeLinecap = 'round';
29454                 this.wireframeLinejoin = 'round';
29455
29456                 this.skinning = false;
29457                 this.morphTargets = false;
29458                 this.morphNormals = false;
29459
29460                 this.setValues( parameters );
29461
29462         }
29463
29464         MeshPhongMaterial.prototype = Object.create( Material.prototype );
29465         MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
29466
29467         MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
29468
29469         MeshPhongMaterial.prototype.copy = function ( source ) {
29470
29471                 Material.prototype.copy.call( this, source );
29472
29473                 this.color.copy( source.color );
29474                 this.specular.copy( source.specular );
29475                 this.shininess = source.shininess;
29476
29477                 this.map = source.map;
29478
29479                 this.lightMap = source.lightMap;
29480                 this.lightMapIntensity = source.lightMapIntensity;
29481
29482                 this.aoMap = source.aoMap;
29483                 this.aoMapIntensity = source.aoMapIntensity;
29484
29485                 this.emissive.copy( source.emissive );
29486                 this.emissiveMap = source.emissiveMap;
29487                 this.emissiveIntensity = source.emissiveIntensity;
29488
29489                 this.bumpMap = source.bumpMap;
29490                 this.bumpScale = source.bumpScale;
29491
29492                 this.normalMap = source.normalMap;
29493                 this.normalScale.copy( source.normalScale );
29494
29495                 this.displacementMap = source.displacementMap;
29496                 this.displacementScale = source.displacementScale;
29497                 this.displacementBias = source.displacementBias;
29498
29499                 this.specularMap = source.specularMap;
29500
29501                 this.alphaMap = source.alphaMap;
29502
29503                 this.envMap = source.envMap;
29504                 this.combine = source.combine;
29505                 this.reflectivity = source.reflectivity;
29506                 this.refractionRatio = source.refractionRatio;
29507
29508                 this.wireframe = source.wireframe;
29509                 this.wireframeLinewidth = source.wireframeLinewidth;
29510                 this.wireframeLinecap = source.wireframeLinecap;
29511                 this.wireframeLinejoin = source.wireframeLinejoin;
29512
29513                 this.skinning = source.skinning;
29514                 this.morphTargets = source.morphTargets;
29515                 this.morphNormals = source.morphNormals;
29516
29517                 return this;
29518
29519         };
29520
29521         /**
29522          * @author takahirox / http://github.com/takahirox
29523          *
29524          * parameters = {
29525          *  gradientMap: new THREE.Texture( <Image> )
29526          * }
29527          */
29528
29529         function MeshToonMaterial( parameters ) {
29530
29531                 MeshPhongMaterial.call( this );
29532
29533                 this.defines = { 'TOON': '' };
29534
29535                 this.type = 'MeshToonMaterial';
29536
29537                 this.gradientMap = null;
29538
29539                 this.setValues( parameters );
29540
29541         }
29542
29543         MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype );
29544         MeshToonMaterial.prototype.constructor = MeshToonMaterial;
29545
29546         MeshToonMaterial.prototype.isMeshToonMaterial = true;
29547
29548         MeshToonMaterial.prototype.copy = function ( source ) {
29549
29550                 MeshPhongMaterial.prototype.copy.call( this, source );
29551
29552                 this.gradientMap = source.gradientMap;
29553
29554                 return this;
29555
29556         };
29557
29558         /**
29559          * @author mrdoob / http://mrdoob.com/
29560          * @author WestLangley / http://github.com/WestLangley
29561          *
29562          * parameters = {
29563          *  opacity: <float>,
29564          *
29565          *  bumpMap: new THREE.Texture( <Image> ),
29566          *  bumpScale: <float>,
29567          *
29568          *  normalMap: new THREE.Texture( <Image> ),
29569          *  normalScale: <Vector2>,
29570          *
29571          *  displacementMap: new THREE.Texture( <Image> ),
29572          *  displacementScale: <float>,
29573          *  displacementBias: <float>,
29574          *
29575          *  wireframe: <boolean>,
29576          *  wireframeLinewidth: <float>
29577          *
29578          *  skinning: <bool>,
29579          *  morphTargets: <bool>,
29580          *  morphNormals: <bool>
29581          * }
29582          */
29583
29584         function MeshNormalMaterial( parameters ) {
29585
29586                 Material.call( this );
29587
29588                 this.type = 'MeshNormalMaterial';
29589
29590                 this.bumpMap = null;
29591                 this.bumpScale = 1;
29592
29593                 this.normalMap = null;
29594                 this.normalScale = new Vector2( 1, 1 );
29595
29596                 this.displacementMap = null;
29597                 this.displacementScale = 1;
29598                 this.displacementBias = 0;
29599
29600                 this.wireframe = false;
29601                 this.wireframeLinewidth = 1;
29602
29603                 this.fog = false;
29604                 this.lights = false;
29605
29606                 this.skinning = false;
29607                 this.morphTargets = false;
29608                 this.morphNormals = false;
29609
29610                 this.setValues( parameters );
29611
29612         }
29613
29614         MeshNormalMaterial.prototype = Object.create( Material.prototype );
29615         MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
29616
29617         MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
29618
29619         MeshNormalMaterial.prototype.copy = function ( source ) {
29620
29621                 Material.prototype.copy.call( this, source );
29622
29623                 this.bumpMap = source.bumpMap;
29624                 this.bumpScale = source.bumpScale;
29625
29626                 this.normalMap = source.normalMap;
29627                 this.normalScale.copy( source.normalScale );
29628
29629                 this.displacementMap = source.displacementMap;
29630                 this.displacementScale = source.displacementScale;
29631                 this.displacementBias = source.displacementBias;
29632
29633                 this.wireframe = source.wireframe;
29634                 this.wireframeLinewidth = source.wireframeLinewidth;
29635
29636                 this.skinning = source.skinning;
29637                 this.morphTargets = source.morphTargets;
29638                 this.morphNormals = source.morphNormals;
29639
29640                 return this;
29641
29642         };
29643
29644         /**
29645          * @author mrdoob / http://mrdoob.com/
29646          * @author alteredq / http://alteredqualia.com/
29647          *
29648          * parameters = {
29649          *  color: <hex>,
29650          *  opacity: <float>,
29651          *
29652          *  map: new THREE.Texture( <Image> ),
29653          *
29654          *  lightMap: new THREE.Texture( <Image> ),
29655          *  lightMapIntensity: <float>
29656          *
29657          *  aoMap: new THREE.Texture( <Image> ),
29658          *  aoMapIntensity: <float>
29659          *
29660          *  emissive: <hex>,
29661          *  emissiveIntensity: <float>
29662          *  emissiveMap: new THREE.Texture( <Image> ),
29663          *
29664          *  specularMap: new THREE.Texture( <Image> ),
29665          *
29666          *  alphaMap: new THREE.Texture( <Image> ),
29667          *
29668          *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
29669          *  combine: THREE.Multiply,
29670          *  reflectivity: <float>,
29671          *  refractionRatio: <float>,
29672          *
29673          *  wireframe: <boolean>,
29674          *  wireframeLinewidth: <float>,
29675          *
29676          *  skinning: <bool>,
29677          *  morphTargets: <bool>,
29678          *  morphNormals: <bool>
29679          * }
29680          */
29681
29682         function MeshLambertMaterial( parameters ) {
29683
29684                 Material.call( this );
29685
29686                 this.type = 'MeshLambertMaterial';
29687
29688                 this.color = new Color( 0xffffff ); // diffuse
29689
29690                 this.map = null;
29691
29692                 this.lightMap = null;
29693                 this.lightMapIntensity = 1.0;
29694
29695                 this.aoMap = null;
29696                 this.aoMapIntensity = 1.0;
29697
29698                 this.emissive = new Color( 0x000000 );
29699                 this.emissiveIntensity = 1.0;
29700                 this.emissiveMap = null;
29701
29702                 this.specularMap = null;
29703
29704                 this.alphaMap = null;
29705
29706                 this.envMap = null;
29707                 this.combine = MultiplyOperation;
29708                 this.reflectivity = 1;
29709                 this.refractionRatio = 0.98;
29710
29711                 this.wireframe = false;
29712                 this.wireframeLinewidth = 1;
29713                 this.wireframeLinecap = 'round';
29714                 this.wireframeLinejoin = 'round';
29715
29716                 this.skinning = false;
29717                 this.morphTargets = false;
29718                 this.morphNormals = false;
29719
29720                 this.setValues( parameters );
29721
29722         }
29723
29724         MeshLambertMaterial.prototype = Object.create( Material.prototype );
29725         MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
29726
29727         MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
29728
29729         MeshLambertMaterial.prototype.copy = function ( source ) {
29730
29731                 Material.prototype.copy.call( this, source );
29732
29733                 this.color.copy( source.color );
29734
29735                 this.map = source.map;
29736
29737                 this.lightMap = source.lightMap;
29738                 this.lightMapIntensity = source.lightMapIntensity;
29739
29740                 this.aoMap = source.aoMap;
29741                 this.aoMapIntensity = source.aoMapIntensity;
29742
29743                 this.emissive.copy( source.emissive );
29744                 this.emissiveMap = source.emissiveMap;
29745                 this.emissiveIntensity = source.emissiveIntensity;
29746
29747                 this.specularMap = source.specularMap;
29748
29749                 this.alphaMap = source.alphaMap;
29750
29751                 this.envMap = source.envMap;
29752                 this.combine = source.combine;
29753                 this.reflectivity = source.reflectivity;
29754                 this.refractionRatio = source.refractionRatio;
29755
29756                 this.wireframe = source.wireframe;
29757                 this.wireframeLinewidth = source.wireframeLinewidth;
29758                 this.wireframeLinecap = source.wireframeLinecap;
29759                 this.wireframeLinejoin = source.wireframeLinejoin;
29760
29761                 this.skinning = source.skinning;
29762                 this.morphTargets = source.morphTargets;
29763                 this.morphNormals = source.morphNormals;
29764
29765                 return this;
29766
29767         };
29768
29769         /**
29770          * @author alteredq / http://alteredqualia.com/
29771          *
29772          * parameters = {
29773          *  color: <hex>,
29774          *  opacity: <float>,
29775          *
29776          *  linewidth: <float>,
29777          *
29778          *  scale: <float>,
29779          *  dashSize: <float>,
29780          *  gapSize: <float>
29781          * }
29782          */
29783
29784         function LineDashedMaterial( parameters ) {
29785
29786                 LineBasicMaterial.call( this );
29787
29788                 this.type = 'LineDashedMaterial';
29789
29790                 this.scale = 1;
29791                 this.dashSize = 3;
29792                 this.gapSize = 1;
29793
29794                 this.setValues( parameters );
29795
29796         }
29797
29798         LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
29799         LineDashedMaterial.prototype.constructor = LineDashedMaterial;
29800
29801         LineDashedMaterial.prototype.isLineDashedMaterial = true;
29802
29803         LineDashedMaterial.prototype.copy = function ( source ) {
29804
29805                 LineBasicMaterial.prototype.copy.call( this, source );
29806
29807                 this.scale = source.scale;
29808                 this.dashSize = source.dashSize;
29809                 this.gapSize = source.gapSize;
29810
29811                 return this;
29812
29813         };
29814
29815
29816
29817         var Materials = Object.freeze({
29818                 ShadowMaterial: ShadowMaterial,
29819                 SpriteMaterial: SpriteMaterial,
29820                 RawShaderMaterial: RawShaderMaterial,
29821                 ShaderMaterial: ShaderMaterial,
29822                 PointsMaterial: PointsMaterial,
29823                 MeshPhysicalMaterial: MeshPhysicalMaterial,
29824                 MeshStandardMaterial: MeshStandardMaterial,
29825                 MeshPhongMaterial: MeshPhongMaterial,
29826                 MeshToonMaterial: MeshToonMaterial,
29827                 MeshNormalMaterial: MeshNormalMaterial,
29828                 MeshLambertMaterial: MeshLambertMaterial,
29829                 MeshDepthMaterial: MeshDepthMaterial,
29830                 MeshDistanceMaterial: MeshDistanceMaterial,
29831                 MeshBasicMaterial: MeshBasicMaterial,
29832                 LineDashedMaterial: LineDashedMaterial,
29833                 LineBasicMaterial: LineBasicMaterial,
29834                 Material: Material
29835         });
29836
29837         /**
29838          * @author mrdoob / http://mrdoob.com/
29839          */
29840
29841         var Cache = {
29842
29843                 enabled: false,
29844
29845                 files: {},
29846
29847                 add: function ( key, file ) {
29848
29849                         if ( this.enabled === false ) return;
29850
29851                         // console.log( 'THREE.Cache', 'Adding key:', key );
29852
29853                         this.files[ key ] = file;
29854
29855                 },
29856
29857                 get: function ( key ) {
29858
29859                         if ( this.enabled === false ) return;
29860
29861                         // console.log( 'THREE.Cache', 'Checking key:', key );
29862
29863                         return this.files[ key ];
29864
29865                 },
29866
29867                 remove: function ( key ) {
29868
29869                         delete this.files[ key ];
29870
29871                 },
29872
29873                 clear: function () {
29874
29875                         this.files = {};
29876
29877                 }
29878
29879         };
29880
29881         /**
29882          * @author mrdoob / http://mrdoob.com/
29883          */
29884
29885         function LoadingManager( onLoad, onProgress, onError ) {
29886
29887                 var scope = this;
29888
29889                 var isLoading = false, itemsLoaded = 0, itemsTotal = 0;
29890
29891                 this.onStart = undefined;
29892                 this.onLoad = onLoad;
29893                 this.onProgress = onProgress;
29894                 this.onError = onError;
29895
29896                 this.itemStart = function ( url ) {
29897
29898                         itemsTotal ++;
29899
29900                         if ( isLoading === false ) {
29901
29902                                 if ( scope.onStart !== undefined ) {
29903
29904                                         scope.onStart( url, itemsLoaded, itemsTotal );
29905
29906                                 }
29907
29908                         }
29909
29910                         isLoading = true;
29911
29912                 };
29913
29914                 this.itemEnd = function ( url ) {
29915
29916                         itemsLoaded ++;
29917
29918                         if ( scope.onProgress !== undefined ) {
29919
29920                                 scope.onProgress( url, itemsLoaded, itemsTotal );
29921
29922                         }
29923
29924                         if ( itemsLoaded === itemsTotal ) {
29925
29926                                 isLoading = false;
29927
29928                                 if ( scope.onLoad !== undefined ) {
29929
29930                                         scope.onLoad();
29931
29932                                 }
29933
29934                         }
29935
29936                 };
29937
29938                 this.itemError = function ( url ) {
29939
29940                         if ( scope.onError !== undefined ) {
29941
29942                                 scope.onError( url );
29943
29944                         }
29945
29946                 };
29947
29948         }
29949
29950         var DefaultLoadingManager = new LoadingManager();
29951
29952         /**
29953          * @author mrdoob / http://mrdoob.com/
29954          */
29955
29956         function FileLoader( manager ) {
29957
29958                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
29959
29960         }
29961
29962         Object.assign( FileLoader.prototype, {
29963
29964                 load: function ( url, onLoad, onProgress, onError ) {
29965
29966                         if ( url === undefined ) url = '';
29967
29968                         if ( this.path !== undefined ) url = this.path + url;
29969
29970                         var scope = this;
29971
29972                         var cached = Cache.get( url );
29973
29974                         if ( cached !== undefined ) {
29975
29976                                 scope.manager.itemStart( url );
29977
29978                                 setTimeout( function () {
29979
29980                                         if ( onLoad ) onLoad( cached );
29981
29982                                         scope.manager.itemEnd( url );
29983
29984                                 }, 0 );
29985
29986                                 return cached;
29987
29988                         }
29989
29990                         // Check for data: URI
29991                         var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
29992                         var dataUriRegexResult = url.match( dataUriRegex );
29993
29994                         // Safari can not handle Data URIs through XMLHttpRequest so process manually
29995                         if ( dataUriRegexResult ) {
29996
29997                                 var mimeType = dataUriRegexResult[ 1 ];
29998                                 var isBase64 = !! dataUriRegexResult[ 2 ];
29999                                 var data = dataUriRegexResult[ 3 ];
30000
30001                                 data = window.decodeURIComponent( data );
30002
30003                                 if ( isBase64 ) data = window.atob( data );
30004
30005                                 try {
30006
30007                                         var response;
30008                                         var responseType = ( this.responseType || '' ).toLowerCase();
30009
30010                                         switch ( responseType ) {
30011
30012                                                 case 'arraybuffer':
30013                                                 case 'blob':
30014
30015                                                         response = new ArrayBuffer( data.length );
30016
30017                                                         var view = new Uint8Array( response );
30018
30019                                                         for ( var i = 0; i < data.length; i ++ ) {
30020
30021                                                                 view[ i ] = data.charCodeAt( i );
30022
30023                                                         }
30024
30025                                                         if ( responseType === 'blob' ) {
30026
30027                                                                 response = new Blob( [ response ], { type: mimeType } );
30028
30029                                                         }
30030
30031                                                         break;
30032
30033                                                 case 'document':
30034
30035                                                         var parser = new DOMParser();
30036                                                         response = parser.parseFromString( data, mimeType );
30037
30038                                                         break;
30039
30040                                                 case 'json':
30041
30042                                                         response = JSON.parse( data );
30043
30044                                                         break;
30045
30046                                                 default: // 'text' or other
30047
30048                                                         response = data;
30049
30050                                                         break;
30051
30052                                         }
30053
30054                                         // Wait for next browser tick
30055                                         window.setTimeout( function () {
30056
30057                                                 if ( onLoad ) onLoad( response );
30058
30059                                                 scope.manager.itemEnd( url );
30060
30061                                         }, 0 );
30062
30063                                 } catch ( error ) {
30064
30065                                         // Wait for next browser tick
30066                                         window.setTimeout( function () {
30067
30068                                                 if ( onError ) onError( error );
30069
30070                                                 scope.manager.itemEnd( url );
30071                                                 scope.manager.itemError( url );
30072
30073                                         }, 0 );
30074
30075                                 }
30076
30077                         } else {
30078
30079                                 var request = new XMLHttpRequest();
30080                                 request.open( 'GET', url, true );
30081
30082                                 request.addEventListener( 'load', function ( event ) {
30083
30084                                         var response = event.target.response;
30085
30086                                         Cache.add( url, response );
30087
30088                                         if ( this.status === 200 ) {
30089
30090                                                 if ( onLoad ) onLoad( response );
30091
30092                                                 scope.manager.itemEnd( url );
30093
30094                                         } else if ( this.status === 0 ) {
30095
30096                                                 // Some browsers return HTTP Status 0 when using non-http protocol
30097                                                 // e.g. 'file://' or 'data://'. Handle as success.
30098
30099                                                 console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
30100
30101                                                 if ( onLoad ) onLoad( response );
30102
30103                                                 scope.manager.itemEnd( url );
30104
30105                                         } else {
30106
30107                                                 if ( onError ) onError( event );
30108
30109                                                 scope.manager.itemEnd( url );
30110                                                 scope.manager.itemError( url );
30111
30112                                         }
30113
30114                                 }, false );
30115
30116                                 if ( onProgress !== undefined ) {
30117
30118                                         request.addEventListener( 'progress', function ( event ) {
30119
30120                                                 onProgress( event );
30121
30122                                         }, false );
30123
30124                                 }
30125
30126                                 request.addEventListener( 'error', function ( event ) {
30127
30128                                         if ( onError ) onError( event );
30129
30130                                         scope.manager.itemEnd( url );
30131                                         scope.manager.itemError( url );
30132
30133                                 }, false );
30134
30135                                 if ( this.responseType !== undefined ) request.responseType = this.responseType;
30136                                 if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
30137
30138                                 if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
30139
30140                                 for ( var header in this.requestHeader ) {
30141
30142                                         request.setRequestHeader( header, this.requestHeader[ header ] );
30143
30144                                 }
30145
30146                                 request.send( null );
30147
30148                         }
30149
30150                         scope.manager.itemStart( url );
30151
30152                         return request;
30153
30154                 },
30155
30156                 setPath: function ( value ) {
30157
30158                         this.path = value;
30159                         return this;
30160
30161                 },
30162
30163                 setResponseType: function ( value ) {
30164
30165                         this.responseType = value;
30166                         return this;
30167
30168                 },
30169
30170                 setWithCredentials: function ( value ) {
30171
30172                         this.withCredentials = value;
30173                         return this;
30174
30175                 },
30176
30177                 setMimeType: function ( value ) {
30178
30179                         this.mimeType = value;
30180                         return this;
30181
30182                 },
30183
30184                 setRequestHeader: function ( value ) {
30185
30186                         this.requestHeader = value;
30187                         return this;
30188
30189                 }
30190
30191         } );
30192
30193         /**
30194          * @author mrdoob / http://mrdoob.com/
30195          *
30196          * Abstract Base class to block based textures loader (dds, pvr, ...)
30197          */
30198
30199         function CompressedTextureLoader( manager ) {
30200
30201                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
30202
30203                 // override in sub classes
30204                 this._parser = null;
30205
30206         }
30207
30208         Object.assign( CompressedTextureLoader.prototype, {
30209
30210                 load: function ( url, onLoad, onProgress, onError ) {
30211
30212                         var scope = this;
30213
30214                         var images = [];
30215
30216                         var texture = new CompressedTexture();
30217                         texture.image = images;
30218
30219                         var loader = new FileLoader( this.manager );
30220                         loader.setPath( this.path );
30221                         loader.setResponseType( 'arraybuffer' );
30222
30223                         function loadTexture( i ) {
30224
30225                                 loader.load( url[ i ], function ( buffer ) {
30226
30227                                         var texDatas = scope._parser( buffer, true );
30228
30229                                         images[ i ] = {
30230                                                 width: texDatas.width,
30231                                                 height: texDatas.height,
30232                                                 format: texDatas.format,
30233                                                 mipmaps: texDatas.mipmaps
30234                                         };
30235
30236                                         loaded += 1;
30237
30238                                         if ( loaded === 6 ) {
30239
30240                                                 if ( texDatas.mipmapCount === 1 )
30241                                                         texture.minFilter = LinearFilter;
30242
30243                                                 texture.format = texDatas.format;
30244                                                 texture.needsUpdate = true;
30245
30246                                                 if ( onLoad ) onLoad( texture );
30247
30248                                         }
30249
30250                                 }, onProgress, onError );
30251
30252                         }
30253
30254                         if ( Array.isArray( url ) ) {
30255
30256                                 var loaded = 0;
30257
30258                                 for ( var i = 0, il = url.length; i < il; ++ i ) {
30259
30260                                         loadTexture( i );
30261
30262                                 }
30263
30264                         } else {
30265
30266                                 // compressed cubemap texture stored in a single DDS file
30267
30268                                 loader.load( url, function ( buffer ) {
30269
30270                                         var texDatas = scope._parser( buffer, true );
30271
30272                                         if ( texDatas.isCubemap ) {
30273
30274                                                 var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
30275
30276                                                 for ( var f = 0; f < faces; f ++ ) {
30277
30278                                                         images[ f ] = { mipmaps : [] };
30279
30280                                                         for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
30281
30282                                                                 images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
30283                                                                 images[ f ].format = texDatas.format;
30284                                                                 images[ f ].width = texDatas.width;
30285                                                                 images[ f ].height = texDatas.height;
30286
30287                                                         }
30288
30289                                                 }
30290
30291                                         } else {
30292
30293                                                 texture.image.width = texDatas.width;
30294                                                 texture.image.height = texDatas.height;
30295                                                 texture.mipmaps = texDatas.mipmaps;
30296
30297                                         }
30298
30299                                         if ( texDatas.mipmapCount === 1 ) {
30300
30301                                                 texture.minFilter = LinearFilter;
30302
30303                                         }
30304
30305                                         texture.format = texDatas.format;
30306                                         texture.needsUpdate = true;
30307
30308                                         if ( onLoad ) onLoad( texture );
30309
30310                                 }, onProgress, onError );
30311
30312                         }
30313
30314                         return texture;
30315
30316                 },
30317
30318                 setPath: function ( value ) {
30319
30320                         this.path = value;
30321                         return this;
30322
30323                 }
30324
30325         } );
30326
30327         /**
30328          * @author Nikos M. / https://github.com/foo123/
30329          *
30330          * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
30331          */
30332
30333         function DataTextureLoader( manager ) {
30334
30335                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
30336
30337                 // override in sub classes
30338                 this._parser = null;
30339
30340         }
30341
30342         Object.assign( DataTextureLoader.prototype, {
30343
30344                 load: function ( url, onLoad, onProgress, onError ) {
30345
30346                         var scope = this;
30347
30348                         var texture = new DataTexture();
30349
30350                         var loader = new FileLoader( this.manager );
30351                         loader.setResponseType( 'arraybuffer' );
30352
30353                         loader.load( url, function ( buffer ) {
30354
30355                                 var texData = scope._parser( buffer );
30356
30357                                 if ( ! texData ) return;
30358
30359                                 if ( undefined !== texData.image ) {
30360
30361                                         texture.image = texData.image;
30362
30363                                 } else if ( undefined !== texData.data ) {
30364
30365                                         texture.image.width = texData.width;
30366                                         texture.image.height = texData.height;
30367                                         texture.image.data = texData.data;
30368
30369                                 }
30370
30371                                 texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping;
30372                                 texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping;
30373
30374                                 texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter;
30375                                 texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter;
30376
30377                                 texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
30378
30379                                 if ( undefined !== texData.format ) {
30380
30381                                         texture.format = texData.format;
30382
30383                                 }
30384                                 if ( undefined !== texData.type ) {
30385
30386                                         texture.type = texData.type;
30387
30388                                 }
30389
30390                                 if ( undefined !== texData.mipmaps ) {
30391
30392                                         texture.mipmaps = texData.mipmaps;
30393
30394                                 }
30395
30396                                 if ( 1 === texData.mipmapCount ) {
30397
30398                                         texture.minFilter = LinearFilter;
30399
30400                                 }
30401
30402                                 texture.needsUpdate = true;
30403
30404                                 if ( onLoad ) onLoad( texture, texData );
30405
30406                         }, onProgress, onError );
30407
30408
30409                         return texture;
30410
30411                 }
30412
30413         } );
30414
30415         /**
30416          * @author mrdoob / http://mrdoob.com/
30417          */
30418
30419         function ImageLoader( manager ) {
30420
30421                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
30422
30423         }
30424
30425         Object.assign( ImageLoader.prototype, {
30426
30427                 crossOrigin: 'Anonymous',
30428
30429                 load: function ( url, onLoad, onProgress, onError ) {
30430
30431                         if ( url === undefined ) url = '';
30432
30433                         if ( this.path !== undefined ) url = this.path + url;
30434
30435                         var scope = this;
30436
30437                         var cached = Cache.get( url );
30438
30439                         if ( cached !== undefined ) {
30440
30441                                 scope.manager.itemStart( url );
30442
30443                                 setTimeout( function () {
30444
30445                                         if ( onLoad ) onLoad( cached );
30446
30447                                         scope.manager.itemEnd( url );
30448
30449                                 }, 0 );
30450
30451                                 return cached;
30452
30453                         }
30454
30455                         var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
30456
30457                         image.addEventListener( 'load', function () {
30458
30459                                 Cache.add( url, this );
30460
30461                                 if ( onLoad ) onLoad( this );
30462
30463                                 scope.manager.itemEnd( url );
30464
30465                         }, false );
30466
30467                         /*
30468                         image.addEventListener( 'progress', function ( event ) {
30469
30470                                 if ( onProgress ) onProgress( event );
30471
30472                         }, false );
30473                         */
30474
30475                         image.addEventListener( 'error', function ( event ) {
30476
30477                                 if ( onError ) onError( event );
30478
30479                                 scope.manager.itemEnd( url );
30480                                 scope.manager.itemError( url );
30481
30482                         }, false );
30483
30484                         if ( url.substr( 0, 5 ) !== 'data:' ) {
30485
30486                                 if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
30487
30488                         }
30489
30490                         scope.manager.itemStart( url );
30491
30492                         image.src = url;
30493
30494                         return image;
30495
30496                 },
30497
30498                 setCrossOrigin: function ( value ) {
30499
30500                         this.crossOrigin = value;
30501                         return this;
30502
30503                 },
30504
30505                 setPath: function ( value ) {
30506
30507                         this.path = value;
30508                         return this;
30509
30510                 }
30511
30512         } );
30513
30514         /**
30515          * @author mrdoob / http://mrdoob.com/
30516          */
30517
30518         function CubeTextureLoader( manager ) {
30519
30520                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
30521
30522         }
30523
30524         Object.assign( CubeTextureLoader.prototype, {
30525
30526                 crossOrigin: 'Anonymous',
30527
30528                 load: function ( urls, onLoad, onProgress, onError ) {
30529
30530                         var texture = new CubeTexture();
30531
30532                         var loader = new ImageLoader( this.manager );
30533                         loader.setCrossOrigin( this.crossOrigin );
30534                         loader.setPath( this.path );
30535
30536                         var loaded = 0;
30537
30538                         function loadTexture( i ) {
30539
30540                                 loader.load( urls[ i ], function ( image ) {
30541
30542                                         texture.images[ i ] = image;
30543
30544                                         loaded ++;
30545
30546                                         if ( loaded === 6 ) {
30547
30548                                                 texture.needsUpdate = true;
30549
30550                                                 if ( onLoad ) onLoad( texture );
30551
30552                                         }
30553
30554                                 }, undefined, onError );
30555
30556                         }
30557
30558                         for ( var i = 0; i < urls.length; ++ i ) {
30559
30560                                 loadTexture( i );
30561
30562                         }
30563
30564                         return texture;
30565
30566                 },
30567
30568                 setCrossOrigin: function ( value ) {
30569
30570                         this.crossOrigin = value;
30571                         return this;
30572
30573                 },
30574
30575                 setPath: function ( value ) {
30576
30577                         this.path = value;
30578                         return this;
30579
30580                 }
30581
30582         } );
30583
30584         /**
30585          * @author mrdoob / http://mrdoob.com/
30586          */
30587
30588         function TextureLoader( manager ) {
30589
30590                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
30591
30592         }
30593
30594         Object.assign( TextureLoader.prototype, {
30595
30596                 crossOrigin: 'Anonymous',
30597
30598                 load: function ( url, onLoad, onProgress, onError ) {
30599
30600                         var loader = new ImageLoader( this.manager );
30601                         loader.setCrossOrigin( this.crossOrigin );
30602                         loader.setPath( this.path );
30603
30604                         var texture = new Texture();
30605                         texture.image = loader.load( url, function () {
30606
30607                                 // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
30608                                 var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
30609
30610                                 texture.format = isJPEG ? RGBFormat : RGBAFormat;
30611                                 texture.needsUpdate = true;
30612
30613                                 if ( onLoad !== undefined ) {
30614
30615                                         onLoad( texture );
30616
30617                                 }
30618
30619                         }, onProgress, onError );
30620
30621                         return texture;
30622
30623                 },
30624
30625                 setCrossOrigin: function ( value ) {
30626
30627                         this.crossOrigin = value;
30628                         return this;
30629
30630                 },
30631
30632                 setPath: function ( value ) {
30633
30634                         this.path = value;
30635                         return this;
30636
30637                 }
30638
30639         } );
30640
30641         /**
30642          * @author mrdoob / http://mrdoob.com/
30643          * @author alteredq / http://alteredqualia.com/
30644          */
30645
30646         function Light( color, intensity ) {
30647
30648                 Object3D.call( this );
30649
30650                 this.type = 'Light';
30651
30652                 this.color = new Color( color );
30653                 this.intensity = intensity !== undefined ? intensity : 1;
30654
30655                 this.receiveShadow = undefined;
30656
30657         }
30658
30659         Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
30660
30661                 constructor: Light,
30662
30663                 isLight: true,
30664
30665                 copy: function ( source ) {
30666
30667                         Object3D.prototype.copy.call( this, source );
30668
30669                         this.color.copy( source.color );
30670                         this.intensity = source.intensity;
30671
30672                         return this;
30673
30674                 },
30675
30676                 toJSON: function ( meta ) {
30677
30678                         var data = Object3D.prototype.toJSON.call( this, meta );
30679
30680                         data.object.color = this.color.getHex();
30681                         data.object.intensity = this.intensity;
30682
30683                         if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
30684
30685                         if ( this.distance !== undefined ) data.object.distance = this.distance;
30686                         if ( this.angle !== undefined ) data.object.angle = this.angle;
30687                         if ( this.decay !== undefined ) data.object.decay = this.decay;
30688                         if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
30689
30690                         if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
30691
30692                         return data;
30693
30694                 }
30695
30696         } );
30697
30698         /**
30699          * @author alteredq / http://alteredqualia.com/
30700          */
30701
30702         function HemisphereLight( skyColor, groundColor, intensity ) {
30703
30704                 Light.call( this, skyColor, intensity );
30705
30706                 this.type = 'HemisphereLight';
30707
30708                 this.castShadow = undefined;
30709
30710                 this.position.copy( Object3D.DefaultUp );
30711                 this.updateMatrix();
30712
30713                 this.groundColor = new Color( groundColor );
30714
30715         }
30716
30717         HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
30718
30719                 constructor: HemisphereLight,
30720
30721                 isHemisphereLight: true,
30722
30723                 copy: function ( source ) {
30724
30725                         Light.prototype.copy.call( this, source );
30726
30727                         this.groundColor.copy( source.groundColor );
30728
30729                         return this;
30730
30731                 }
30732
30733         } );
30734
30735         /**
30736          * @author mrdoob / http://mrdoob.com/
30737          */
30738
30739         function LightShadow( camera ) {
30740
30741                 this.camera = camera;
30742
30743                 this.bias = 0;
30744                 this.radius = 1;
30745
30746                 this.mapSize = new Vector2( 512, 512 );
30747
30748                 this.map = null;
30749                 this.matrix = new Matrix4();
30750
30751         }
30752
30753         Object.assign( LightShadow.prototype, {
30754
30755                 copy: function ( source ) {
30756
30757                         this.camera = source.camera.clone();
30758
30759                         this.bias = source.bias;
30760                         this.radius = source.radius;
30761
30762                         this.mapSize.copy( source.mapSize );
30763
30764                         return this;
30765
30766                 },
30767
30768                 clone: function () {
30769
30770                         return new this.constructor().copy( this );
30771
30772                 },
30773
30774                 toJSON: function () {
30775
30776                         var object = {};
30777
30778                         if ( this.bias !== 0 ) object.bias = this.bias;
30779                         if ( this.radius !== 1 ) object.radius = this.radius;
30780                         if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
30781
30782                         object.camera = this.camera.toJSON( false ).object;
30783                         delete object.camera.matrix;
30784
30785                         return object;
30786
30787                 }
30788
30789         } );
30790
30791         /**
30792          * @author mrdoob / http://mrdoob.com/
30793          */
30794
30795         function SpotLightShadow() {
30796
30797                 LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
30798
30799         }
30800
30801         SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
30802
30803                 constructor: SpotLightShadow,
30804
30805                 isSpotLightShadow: true,
30806
30807                 update: function ( light ) {
30808
30809                         var camera = this.camera;
30810
30811                         var fov = _Math.RAD2DEG * 2 * light.angle;
30812                         var aspect = this.mapSize.width / this.mapSize.height;
30813                         var far = light.distance || camera.far;
30814
30815                         if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
30816
30817                                 camera.fov = fov;
30818                                 camera.aspect = aspect;
30819                                 camera.far = far;
30820                                 camera.updateProjectionMatrix();
30821
30822                         }
30823
30824                 }
30825
30826         } );
30827
30828         /**
30829          * @author alteredq / http://alteredqualia.com/
30830          */
30831
30832         function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
30833
30834                 Light.call( this, color, intensity );
30835
30836                 this.type = 'SpotLight';
30837
30838                 this.position.copy( Object3D.DefaultUp );
30839                 this.updateMatrix();
30840
30841                 this.target = new Object3D();
30842
30843                 Object.defineProperty( this, 'power', {
30844                         get: function () {
30845                                 // intensity = power per solid angle.
30846                                 // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
30847                                 return this.intensity * Math.PI;
30848                         },
30849                         set: function ( power ) {
30850                                 // intensity = power per solid angle.
30851                                 // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
30852                                 this.intensity = power / Math.PI;
30853                         }
30854                 } );
30855
30856                 this.distance = ( distance !== undefined ) ? distance : 0;
30857                 this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
30858                 this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
30859                 this.decay = ( decay !== undefined ) ? decay : 1;       // for physically correct lights, should be 2.
30860
30861                 this.shadow = new SpotLightShadow();
30862
30863         }
30864
30865         SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
30866
30867                 constructor: SpotLight,
30868
30869                 isSpotLight: true,
30870
30871                 copy: function ( source ) {
30872
30873                         Light.prototype.copy.call( this, source );
30874
30875                         this.distance = source.distance;
30876                         this.angle = source.angle;
30877                         this.penumbra = source.penumbra;
30878                         this.decay = source.decay;
30879
30880                         this.target = source.target.clone();
30881
30882                         this.shadow = source.shadow.clone();
30883
30884                         return this;
30885
30886                 }
30887
30888         } );
30889
30890         /**
30891          * @author mrdoob / http://mrdoob.com/
30892          */
30893
30894
30895         function PointLight( color, intensity, distance, decay ) {
30896
30897                 Light.call( this, color, intensity );
30898
30899                 this.type = 'PointLight';
30900
30901                 Object.defineProperty( this, 'power', {
30902                         get: function () {
30903                                 // intensity = power per solid angle.
30904                                 // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
30905                                 return this.intensity * 4 * Math.PI;
30906
30907                         },
30908                         set: function ( power ) {
30909                                 // intensity = power per solid angle.
30910                                 // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
30911                                 this.intensity = power / ( 4 * Math.PI );
30912                         }
30913                 } );
30914
30915                 this.distance = ( distance !== undefined ) ? distance : 0;
30916                 this.decay = ( decay !== undefined ) ? decay : 1;       // for physically correct lights, should be 2.
30917
30918                 this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
30919
30920         }
30921
30922         PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
30923
30924                 constructor: PointLight,
30925
30926                 isPointLight: true,
30927
30928                 copy: function ( source ) {
30929
30930                         Light.prototype.copy.call( this, source );
30931
30932                         this.distance = source.distance;
30933                         this.decay = source.decay;
30934
30935                         this.shadow = source.shadow.clone();
30936
30937                         return this;
30938
30939                 }
30940
30941         } );
30942
30943         /**
30944          * @author mrdoob / http://mrdoob.com/
30945          */
30946
30947         function DirectionalLightShadow( ) {
30948
30949                 LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
30950
30951         }
30952
30953         DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
30954
30955                 constructor: DirectionalLightShadow
30956
30957         } );
30958
30959         /**
30960          * @author mrdoob / http://mrdoob.com/
30961          * @author alteredq / http://alteredqualia.com/
30962          */
30963
30964         function DirectionalLight( color, intensity ) {
30965
30966                 Light.call( this, color, intensity );
30967
30968                 this.type = 'DirectionalLight';
30969
30970                 this.position.copy( Object3D.DefaultUp );
30971                 this.updateMatrix();
30972
30973                 this.target = new Object3D();
30974
30975                 this.shadow = new DirectionalLightShadow();
30976
30977         }
30978
30979         DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
30980
30981                 constructor: DirectionalLight,
30982
30983                 isDirectionalLight: true,
30984
30985                 copy: function ( source ) {
30986
30987                         Light.prototype.copy.call( this, source );
30988
30989                         this.target = source.target.clone();
30990
30991                         this.shadow = source.shadow.clone();
30992
30993                         return this;
30994
30995                 }
30996
30997         } );
30998
30999         /**
31000          * @author mrdoob / http://mrdoob.com/
31001          */
31002
31003         function AmbientLight( color, intensity ) {
31004
31005                 Light.call( this, color, intensity );
31006
31007                 this.type = 'AmbientLight';
31008
31009                 this.castShadow = undefined;
31010
31011         }
31012
31013         AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
31014
31015                 constructor: AmbientLight,
31016
31017                 isAmbientLight: true
31018
31019         } );
31020
31021         /**
31022          * @author abelnation / http://github.com/abelnation
31023          */
31024
31025         function RectAreaLight( color, intensity, width, height ) {
31026
31027                 Light.call( this, color, intensity );
31028
31029                 this.type = 'RectAreaLight';
31030
31031                 this.position.set( 0, 1, 0 );
31032                 this.updateMatrix();
31033
31034                 this.width = ( width !== undefined ) ? width : 10;
31035                 this.height = ( height !== undefined ) ? height : 10;
31036
31037                 // TODO (abelnation): distance/decay
31038
31039                 // TODO (abelnation): update method for RectAreaLight to update transform to lookat target
31040
31041                 // TODO (abelnation): shadows
31042
31043         }
31044
31045         // TODO (abelnation): RectAreaLight update when light shape is changed
31046         RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
31047
31048                 constructor: RectAreaLight,
31049
31050                 isRectAreaLight: true,
31051
31052                 copy: function ( source ) {
31053
31054                         Light.prototype.copy.call( this, source );
31055
31056                         this.width = source.width;
31057                         this.height = source.height;
31058
31059                         return this;
31060
31061                 },
31062
31063                 toJSON: function ( meta ) {
31064
31065                         var data = Light.prototype.toJSON.call( this, meta );
31066
31067                         data.object.width = this.width;
31068                         data.object.height = this.height;
31069
31070                         return data;
31071
31072                 }
31073
31074         } );
31075
31076         /**
31077          * @author tschw
31078          * @author Ben Houston / http://clara.io/
31079          * @author David Sarno / http://lighthaus.us/
31080          */
31081
31082         var AnimationUtils = {
31083
31084                 // same as Array.prototype.slice, but also works on typed arrays
31085                 arraySlice: function ( array, from, to ) {
31086
31087                         if ( AnimationUtils.isTypedArray( array ) ) {
31088
31089                                 // in ios9 array.subarray(from, undefined) will return empty array
31090                                 // but array.subarray(from) or array.subarray(from, len) is correct
31091                                 return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
31092
31093                         }
31094
31095                         return array.slice( from, to );
31096
31097                 },
31098
31099                 // converts an array to a specific type
31100                 convertArray: function ( array, type, forceClone ) {
31101
31102                         if ( ! array || // let 'undefined' and 'null' pass
31103                                         ! forceClone && array.constructor === type ) return array;
31104
31105                         if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
31106
31107                                 return new type( array ); // create typed array
31108
31109                         }
31110
31111                         return Array.prototype.slice.call( array ); // create Array
31112
31113                 },
31114
31115                 isTypedArray: function ( object ) {
31116
31117                         return ArrayBuffer.isView( object ) &&
31118                                         ! ( object instanceof DataView );
31119
31120                 },
31121
31122                 // returns an array by which times and values can be sorted
31123                 getKeyframeOrder: function ( times ) {
31124
31125                         function compareTime( i, j ) {
31126
31127                                 return times[ i ] - times[ j ];
31128
31129                         }
31130
31131                         var n = times.length;
31132                         var result = new Array( n );
31133                         for ( var i = 0; i !== n; ++ i ) result[ i ] = i;
31134
31135                         result.sort( compareTime );
31136
31137                         return result;
31138
31139                 },
31140
31141                 // uses the array previously returned by 'getKeyframeOrder' to sort data
31142                 sortedArray: function ( values, stride, order ) {
31143
31144                         var nValues = values.length;
31145                         var result = new values.constructor( nValues );
31146
31147                         for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
31148
31149                                 var srcOffset = order[ i ] * stride;
31150
31151                                 for ( var j = 0; j !== stride; ++ j ) {
31152
31153                                         result[ dstOffset ++ ] = values[ srcOffset + j ];
31154
31155                                 }
31156
31157                         }
31158
31159                         return result;
31160
31161                 },
31162
31163                 // function for parsing AOS keyframe formats
31164                 flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
31165
31166                         var i = 1, key = jsonKeys[ 0 ];
31167
31168                         while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
31169
31170                                 key = jsonKeys[ i ++ ];
31171
31172                         }
31173
31174                         if ( key === undefined ) return; // no data
31175
31176                         var value = key[ valuePropertyName ];
31177                         if ( value === undefined ) return; // no data
31178
31179                         if ( Array.isArray( value ) ) {
31180
31181                                 do {
31182
31183                                         value = key[ valuePropertyName ];
31184
31185                                         if ( value !== undefined ) {
31186
31187                                                 times.push( key.time );
31188                                                 values.push.apply( values, value ); // push all elements
31189
31190                                         }
31191
31192                                         key = jsonKeys[ i ++ ];
31193
31194                                 } while ( key !== undefined );
31195
31196                         } else if ( value.toArray !== undefined ) {
31197
31198                                 // ...assume THREE.Math-ish
31199
31200                                 do {
31201
31202                                         value = key[ valuePropertyName ];
31203
31204                                         if ( value !== undefined ) {
31205
31206                                                 times.push( key.time );
31207                                                 value.toArray( values, values.length );
31208
31209                                         }
31210
31211                                         key = jsonKeys[ i ++ ];
31212
31213                                 } while ( key !== undefined );
31214
31215                         } else {
31216
31217                                 // otherwise push as-is
31218
31219                                 do {
31220
31221                                         value = key[ valuePropertyName ];
31222
31223                                         if ( value !== undefined ) {
31224
31225                                                 times.push( key.time );
31226                                                 values.push( value );
31227
31228                                         }
31229
31230                                         key = jsonKeys[ i ++ ];
31231
31232                                 } while ( key !== undefined );
31233
31234                         }
31235
31236                 }
31237
31238         };
31239
31240         /**
31241          * Abstract base class of interpolants over parametric samples.
31242          *
31243          * The parameter domain is one dimensional, typically the time or a path
31244          * along a curve defined by the data.
31245          *
31246          * The sample values can have any dimensionality and derived classes may
31247          * apply special interpretations to the data.
31248          *
31249          * This class provides the interval seek in a Template Method, deferring
31250          * the actual interpolation to derived classes.
31251          *
31252          * Time complexity is O(1) for linear access crossing at most two points
31253          * and O(log N) for random access, where N is the number of positions.
31254          *
31255          * References:
31256          *
31257          *              http://www.oodesign.com/template-method-pattern.html
31258          *
31259          * @author tschw
31260          */
31261
31262         function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
31263
31264                 this.parameterPositions = parameterPositions;
31265                 this._cachedIndex = 0;
31266
31267                 this.resultBuffer = resultBuffer !== undefined ?
31268                                 resultBuffer : new sampleValues.constructor( sampleSize );
31269                 this.sampleValues = sampleValues;
31270                 this.valueSize = sampleSize;
31271
31272         }
31273
31274         Object.assign( Interpolant.prototype, {
31275
31276                 evaluate: function( t ) {
31277
31278                         var pp = this.parameterPositions,
31279                                 i1 = this._cachedIndex,
31280
31281                                 t1 = pp[   i1   ],
31282                                 t0 = pp[ i1 - 1 ];
31283
31284                         validate_interval: {
31285
31286                                 seek: {
31287
31288                                         var right;
31289
31290                                         linear_scan: {
31291                                                 //- See http://jsperf.com/comparison-to-undefined/3
31292                                                 //- slower code:
31293                                                 //-
31294                                                 //-                             if ( t >= t1 || t1 === undefined ) {
31295                                                 forward_scan: if ( ! ( t < t1 ) ) {
31296
31297                                                         for ( var giveUpAt = i1 + 2; ;) {
31298
31299                                                                 if ( t1 === undefined ) {
31300
31301                                                                         if ( t < t0 ) break forward_scan;
31302
31303                                                                         // after end
31304
31305                                                                         i1 = pp.length;
31306                                                                         this._cachedIndex = i1;
31307                                                                         return this.afterEnd_( i1 - 1, t, t0 );
31308
31309                                                                 }
31310
31311                                                                 if ( i1 === giveUpAt ) break; // this loop
31312
31313                                                                 t0 = t1;
31314                                                                 t1 = pp[ ++ i1 ];
31315
31316                                                                 if ( t < t1 ) {
31317
31318                                                                         // we have arrived at the sought interval
31319                                                                         break seek;
31320
31321                                                                 }
31322
31323                                                         }
31324
31325                                                         // prepare binary search on the right side of the index
31326                                                         right = pp.length;
31327                                                         break linear_scan;
31328
31329                                                 }
31330
31331                                                 //- slower code:
31332                                                 //-                                     if ( t < t0 || t0 === undefined ) {
31333                                                 if ( ! ( t >= t0 ) ) {
31334
31335                                                         // looping?
31336
31337                                                         var t1global = pp[ 1 ];
31338
31339                                                         if ( t < t1global ) {
31340
31341                                                                 i1 = 2; // + 1, using the scan for the details
31342                                                                 t0 = t1global;
31343
31344                                                         }
31345
31346                                                         // linear reverse scan
31347
31348                                                         for ( var giveUpAt = i1 - 2; ;) {
31349
31350                                                                 if ( t0 === undefined ) {
31351
31352                                                                         // before start
31353
31354                                                                         this._cachedIndex = 0;
31355                                                                         return this.beforeStart_( 0, t, t1 );
31356
31357                                                                 }
31358
31359                                                                 if ( i1 === giveUpAt ) break; // this loop
31360
31361                                                                 t1 = t0;
31362                                                                 t0 = pp[ -- i1 - 1 ];
31363
31364                                                                 if ( t >= t0 ) {
31365
31366                                                                         // we have arrived at the sought interval
31367                                                                         break seek;
31368
31369                                                                 }
31370
31371                                                         }
31372
31373                                                         // prepare binary search on the left side of the index
31374                                                         right = i1;
31375                                                         i1 = 0;
31376                                                         break linear_scan;
31377
31378                                                 }
31379
31380                                                 // the interval is valid
31381
31382                                                 break validate_interval;
31383
31384                                         } // linear scan
31385
31386                                         // binary search
31387
31388                                         while ( i1 < right ) {
31389
31390                                                 var mid = ( i1 + right ) >>> 1;
31391
31392                                                 if ( t < pp[ mid ] ) {
31393
31394                                                         right = mid;
31395
31396                                                 } else {
31397
31398                                                         i1 = mid + 1;
31399
31400                                                 }
31401
31402                                         }
31403
31404                                         t1 = pp[   i1   ];
31405                                         t0 = pp[ i1 - 1 ];
31406
31407                                         // check boundary cases, again
31408
31409                                         if ( t0 === undefined ) {
31410
31411                                                 this._cachedIndex = 0;
31412                                                 return this.beforeStart_( 0, t, t1 );
31413
31414                                         }
31415
31416                                         if ( t1 === undefined ) {
31417
31418                                                 i1 = pp.length;
31419                                                 this._cachedIndex = i1;
31420                                                 return this.afterEnd_( i1 - 1, t0, t );
31421
31422                                         }
31423
31424                                 } // seek
31425
31426                                 this._cachedIndex = i1;
31427
31428                                 this.intervalChanged_( i1, t0, t1 );
31429
31430                         } // validate_interval
31431
31432                         return this.interpolate_( i1, t0, t, t1 );
31433
31434                 },
31435
31436                 settings: null, // optional, subclass-specific settings structure
31437                 // Note: The indirection allows central control of many interpolants.
31438
31439                 // --- Protected interface
31440
31441                 DefaultSettings_: {},
31442
31443                 getSettings_: function() {
31444
31445                         return this.settings || this.DefaultSettings_;
31446
31447                 },
31448
31449                 copySampleValue_: function( index ) {
31450
31451                         // copies a sample value to the result buffer
31452
31453                         var result = this.resultBuffer,
31454                                 values = this.sampleValues,
31455                                 stride = this.valueSize,
31456                                 offset = index * stride;
31457
31458                         for ( var i = 0; i !== stride; ++ i ) {
31459
31460                                 result[ i ] = values[ offset + i ];
31461
31462                         }
31463
31464                         return result;
31465
31466                 },
31467
31468                 // Template methods for derived classes:
31469
31470                 interpolate_: function( i1, t0, t, t1 ) {
31471
31472                         throw new Error( "call to abstract method" );
31473                         // implementations shall return this.resultBuffer
31474
31475                 },
31476
31477                 intervalChanged_: function( i1, t0, t1 ) {
31478
31479                         // empty
31480
31481                 }
31482
31483         } );
31484
31485         //!\ DECLARE ALIAS AFTER assign prototype !
31486         Object.assign( Interpolant.prototype, {
31487
31488                 //( 0, t, t0 ), returns this.resultBuffer
31489                 beforeStart_: Interpolant.prototype.copySampleValue_,
31490
31491                 //( N-1, tN-1, t ), returns this.resultBuffer
31492                 afterEnd_: Interpolant.prototype.copySampleValue_,
31493
31494         } );
31495
31496         /**
31497          * Fast and simple cubic spline interpolant.
31498          *
31499          * It was derived from a Hermitian construction setting the first derivative
31500          * at each sample position to the linear slope between neighboring positions
31501          * over their parameter interval.
31502          *
31503          * @author tschw
31504          */
31505
31506         function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
31507
31508                 Interpolant.call(
31509                                 this, parameterPositions, sampleValues, sampleSize, resultBuffer );
31510
31511                 this._weightPrev = -0;
31512                 this._offsetPrev = -0;
31513                 this._weightNext = -0;
31514                 this._offsetNext = -0;
31515
31516         }
31517
31518         CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
31519
31520                 constructor: CubicInterpolant,
31521
31522                 DefaultSettings_: {
31523
31524                         endingStart:    ZeroCurvatureEnding,
31525                         endingEnd:              ZeroCurvatureEnding
31526
31527                 },
31528
31529                 intervalChanged_: function( i1, t0, t1 ) {
31530
31531                         var pp = this.parameterPositions,
31532                                 iPrev = i1 - 2,
31533                                 iNext = i1 + 1,
31534
31535                                 tPrev = pp[ iPrev ],
31536                                 tNext = pp[ iNext ];
31537
31538                         if ( tPrev === undefined ) {
31539
31540                                 switch ( this.getSettings_().endingStart ) {
31541
31542                                         case ZeroSlopeEnding:
31543
31544                                                 // f'(t0) = 0
31545                                                 iPrev = i1;
31546                                                 tPrev = 2 * t0 - t1;
31547
31548                                                 break;
31549
31550                                         case WrapAroundEnding:
31551
31552                                                 // use the other end of the curve
31553                                                 iPrev = pp.length - 2;
31554                                                 tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
31555
31556                                                 break;
31557
31558                                         default: // ZeroCurvatureEnding
31559
31560                                                 // f''(t0) = 0 a.k.a. Natural Spline
31561                                                 iPrev = i1;
31562                                                 tPrev = t1;
31563
31564                                 }
31565
31566                         }
31567
31568                         if ( tNext === undefined ) {
31569
31570                                 switch ( this.getSettings_().endingEnd ) {
31571
31572                                         case ZeroSlopeEnding:
31573
31574                                                 // f'(tN) = 0
31575                                                 iNext = i1;
31576                                                 tNext = 2 * t1 - t0;
31577
31578                                                 break;
31579
31580                                         case WrapAroundEnding:
31581
31582                                                 // use the other end of the curve
31583                                                 iNext = 1;
31584                                                 tNext = t1 + pp[ 1 ] - pp[ 0 ];
31585
31586                                                 break;
31587
31588                                         default: // ZeroCurvatureEnding
31589
31590                                                 // f''(tN) = 0, a.k.a. Natural Spline
31591                                                 iNext = i1 - 1;
31592                                                 tNext = t0;
31593
31594                                 }
31595
31596                         }
31597
31598                         var halfDt = ( t1 - t0 ) * 0.5,
31599                                 stride = this.valueSize;
31600
31601                         this._weightPrev = halfDt / ( t0 - tPrev );
31602                         this._weightNext = halfDt / ( tNext - t1 );
31603                         this._offsetPrev = iPrev * stride;
31604                         this._offsetNext = iNext * stride;
31605
31606                 },
31607
31608                 interpolate_: function( i1, t0, t, t1 ) {
31609
31610                         var result = this.resultBuffer,
31611                                 values = this.sampleValues,
31612                                 stride = this.valueSize,
31613
31614                                 o1 = i1 * stride,               o0 = o1 - stride,
31615                                 oP = this._offsetPrev,  oN = this._offsetNext,
31616                                 wP = this._weightPrev,  wN = this._weightNext,
31617
31618                                 p = ( t - t0 ) / ( t1 - t0 ),
31619                                 pp = p * p,
31620                                 ppp = pp * p;
31621
31622                         // evaluate polynomials
31623
31624                         var sP =     - wP   * ppp   +         2 * wP    * pp    -          wP   * p;
31625                         var s0 = ( 1 + wP ) * ppp   + (-1.5 - 2 * wP )  * pp    + ( -0.5 + wP ) * p     + 1;
31626                         var s1 = (-1 - wN ) * ppp   + ( 1.5 +   wN   )  * pp    +    0.5        * p;
31627                         var sN =       wN   * ppp   -           wN      * pp;
31628
31629                         // combine data linearly
31630
31631                         for ( var i = 0; i !== stride; ++ i ) {
31632
31633                                 result[ i ] =
31634                                                 sP * values[ oP + i ] +
31635                                                 s0 * values[ o0 + i ] +
31636                                                 s1 * values[ o1 + i ] +
31637                                                 sN * values[ oN + i ];
31638
31639                         }
31640
31641                         return result;
31642
31643                 }
31644
31645         } );
31646
31647         /**
31648          * @author tschw
31649          */
31650
31651         function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
31652
31653                 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
31654
31655         }
31656
31657         LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
31658
31659                 constructor: LinearInterpolant,
31660
31661                 interpolate_: function( i1, t0, t, t1 ) {
31662
31663                         var result = this.resultBuffer,
31664                                 values = this.sampleValues,
31665                                 stride = this.valueSize,
31666
31667                                 offset1 = i1 * stride,
31668                                 offset0 = offset1 - stride,
31669
31670                                 weight1 = ( t - t0 ) / ( t1 - t0 ),
31671                                 weight0 = 1 - weight1;
31672
31673                         for ( var i = 0; i !== stride; ++ i ) {
31674
31675                                 result[ i ] =
31676                                                 values[ offset0 + i ] * weight0 +
31677                                                 values[ offset1 + i ] * weight1;
31678
31679                         }
31680
31681                         return result;
31682
31683                 }
31684
31685         } );
31686
31687         /**
31688          *
31689          * Interpolant that evaluates to the sample value at the position preceeding
31690          * the parameter.
31691          *
31692          * @author tschw
31693          */
31694
31695         function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
31696
31697                 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
31698
31699         }
31700
31701         DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
31702
31703                 constructor: DiscreteInterpolant,
31704
31705                 interpolate_: function( i1, t0, t, t1 ) {
31706
31707                         return this.copySampleValue_( i1 - 1 );
31708
31709                 }
31710
31711         } );
31712
31713         var KeyframeTrackPrototype;
31714
31715         KeyframeTrackPrototype = {
31716
31717                 TimeBufferType: Float32Array,
31718                 ValueBufferType: Float32Array,
31719
31720                 DefaultInterpolation: InterpolateLinear,
31721
31722                 InterpolantFactoryMethodDiscrete: function ( result ) {
31723
31724                         return new DiscreteInterpolant(
31725                                         this.times, this.values, this.getValueSize(), result );
31726
31727                 },
31728
31729                 InterpolantFactoryMethodLinear: function ( result ) {
31730
31731                         return new LinearInterpolant(
31732                                         this.times, this.values, this.getValueSize(), result );
31733
31734                 },
31735
31736                 InterpolantFactoryMethodSmooth: function ( result ) {
31737
31738                         return new CubicInterpolant(
31739                                         this.times, this.values, this.getValueSize(), result );
31740
31741                 },
31742
31743                 setInterpolation: function ( interpolation ) {
31744
31745                         var factoryMethod;
31746
31747                         switch ( interpolation ) {
31748
31749                                 case InterpolateDiscrete:
31750
31751                                         factoryMethod = this.InterpolantFactoryMethodDiscrete;
31752
31753                                         break;
31754
31755                                 case InterpolateLinear:
31756
31757                                         factoryMethod = this.InterpolantFactoryMethodLinear;
31758
31759                                         break;
31760
31761                                 case InterpolateSmooth:
31762
31763                                         factoryMethod = this.InterpolantFactoryMethodSmooth;
31764
31765                                         break;
31766
31767                         }
31768
31769                         if ( factoryMethod === undefined ) {
31770
31771                                 var message = "unsupported interpolation for " +
31772                                                 this.ValueTypeName + " keyframe track named " + this.name;
31773
31774                                 if ( this.createInterpolant === undefined ) {
31775
31776                                         // fall back to default, unless the default itself is messed up
31777                                         if ( interpolation !== this.DefaultInterpolation ) {
31778
31779                                                 this.setInterpolation( this.DefaultInterpolation );
31780
31781                                         } else {
31782
31783                                                 throw new Error( message ); // fatal, in this case
31784
31785                                         }
31786
31787                                 }
31788
31789                                 console.warn( 'THREE.KeyframeTrackPrototype:', message );
31790                                 return;
31791
31792                         }
31793
31794                         this.createInterpolant = factoryMethod;
31795
31796                 },
31797
31798                 getInterpolation: function () {
31799
31800                         switch ( this.createInterpolant ) {
31801
31802                                 case this.InterpolantFactoryMethodDiscrete:
31803
31804                                         return InterpolateDiscrete;
31805
31806                                 case this.InterpolantFactoryMethodLinear:
31807
31808                                         return InterpolateLinear;
31809
31810                                 case this.InterpolantFactoryMethodSmooth:
31811
31812                                         return InterpolateSmooth;
31813
31814                         }
31815
31816                 },
31817
31818                 getValueSize: function () {
31819
31820                         return this.values.length / this.times.length;
31821
31822                 },
31823
31824                 // move all keyframes either forwards or backwards in time
31825                 shift: function ( timeOffset ) {
31826
31827                         if ( timeOffset !== 0.0 ) {
31828
31829                                 var times = this.times;
31830
31831                                 for ( var i = 0, n = times.length; i !== n; ++ i ) {
31832
31833                                         times[ i ] += timeOffset;
31834
31835                                 }
31836
31837                         }
31838
31839                         return this;
31840
31841                 },
31842
31843                 // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
31844                 scale: function ( timeScale ) {
31845
31846                         if ( timeScale !== 1.0 ) {
31847
31848                                 var times = this.times;
31849
31850                                 for ( var i = 0, n = times.length; i !== n; ++ i ) {
31851
31852                                         times[ i ] *= timeScale;
31853
31854                                 }
31855
31856                         }
31857
31858                         return this;
31859
31860                 },
31861
31862                 // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
31863                 // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
31864                 trim: function ( startTime, endTime ) {
31865
31866                         var times = this.times,
31867                                 nKeys = times.length,
31868                                 from = 0,
31869                                 to = nKeys - 1;
31870
31871                         while ( from !== nKeys && times[ from ] < startTime ) ++ from;
31872                         while ( to !== - 1 && times[ to ] > endTime ) -- to;
31873
31874                         ++ to; // inclusive -> exclusive bound
31875
31876                         if ( from !== 0 || to !== nKeys ) {
31877
31878                                 // empty tracks are forbidden, so keep at least one keyframe
31879                                 if ( from >= to ) to = Math.max( to, 1 ), from = to - 1;
31880
31881                                 var stride = this.getValueSize();
31882                                 this.times = AnimationUtils.arraySlice( times, from, to );
31883                                 this.values = AnimationUtils.
31884                                                 arraySlice( this.values, from * stride, to * stride );
31885
31886                         }
31887
31888                         return this;
31889
31890                 },
31891
31892                 // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
31893                 validate: function () {
31894
31895                         var valid = true;
31896
31897                         var valueSize = this.getValueSize();
31898                         if ( valueSize - Math.floor( valueSize ) !== 0 ) {
31899
31900                                 console.error( 'THREE.KeyframeTrackPrototype: Invalid value size in track.', this );
31901                                 valid = false;
31902
31903                         }
31904
31905                         var times = this.times,
31906                                 values = this.values,
31907
31908                                 nKeys = times.length;
31909
31910                         if ( nKeys === 0 ) {
31911
31912                                 console.error( 'THREE.KeyframeTrackPrototype: Track is empty.', this );
31913                                 valid = false;
31914
31915                         }
31916
31917                         var prevTime = null;
31918
31919                         for ( var i = 0; i !== nKeys; i ++ ) {
31920
31921                                 var currTime = times[ i ];
31922
31923                                 if ( typeof currTime === 'number' && isNaN( currTime ) ) {
31924
31925                                         console.error( 'THREE.KeyframeTrackPrototype: Time is not a valid number.', this, i, currTime );
31926                                         valid = false;
31927                                         break;
31928
31929                                 }
31930
31931                                 if ( prevTime !== null && prevTime > currTime ) {
31932
31933                                         console.error( 'THREE.KeyframeTrackPrototype: Out of order keys.', this, i, currTime, prevTime );
31934                                         valid = false;
31935                                         break;
31936
31937                                 }
31938
31939                                 prevTime = currTime;
31940
31941                         }
31942
31943                         if ( values !== undefined ) {
31944
31945                                 if ( AnimationUtils.isTypedArray( values ) ) {
31946
31947                                         for ( var i = 0, n = values.length; i !== n; ++ i ) {
31948
31949                                                 var value = values[ i ];
31950
31951                                                 if ( isNaN( value ) ) {
31952
31953                                                         console.error( 'THREE.KeyframeTrackPrototype: Value is not a valid number.', this, i, value );
31954                                                         valid = false;
31955                                                         break;
31956
31957                                                 }
31958
31959                                         }
31960
31961                                 }
31962
31963                         }
31964
31965                         return valid;
31966
31967                 },
31968
31969                 // removes equivalent sequential keys as common in morph target sequences
31970                 // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
31971                 optimize: function () {
31972
31973                         var times = this.times,
31974                                 values = this.values,
31975                                 stride = this.getValueSize(),
31976
31977                                 smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
31978
31979                                 writeIndex = 1,
31980                                 lastIndex = times.length - 1;
31981
31982                         for ( var i = 1; i < lastIndex; ++ i ) {
31983
31984                                 var keep = false;
31985
31986                                 var time = times[ i ];
31987                                 var timeNext = times[ i + 1 ];
31988
31989                                 // remove adjacent keyframes scheduled at the same time
31990
31991                                 if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
31992
31993                                         if ( ! smoothInterpolation ) {
31994
31995                                                 // remove unnecessary keyframes same as their neighbors
31996
31997                                                 var offset = i * stride,
31998                                                         offsetP = offset - stride,
31999                                                         offsetN = offset + stride;
32000
32001                                                 for ( var j = 0; j !== stride; ++ j ) {
32002
32003                                                         var value = values[ offset + j ];
32004
32005                                                         if ( value !== values[ offsetP + j ] ||
32006                                                                         value !== values[ offsetN + j ] ) {
32007
32008                                                                 keep = true;
32009                                                                 break;
32010
32011                                                         }
32012
32013                                                 }
32014
32015                                         } else keep = true;
32016
32017                                 }
32018
32019                                 // in-place compaction
32020
32021                                 if ( keep ) {
32022
32023                                         if ( i !== writeIndex ) {
32024
32025                                                 times[ writeIndex ] = times[ i ];
32026
32027                                                 var readOffset = i * stride,
32028                                                         writeOffset = writeIndex * stride;
32029
32030                                                 for ( var j = 0; j !== stride; ++ j )
32031
32032                                                         values[ writeOffset + j ] = values[ readOffset + j ];
32033
32034                                         }
32035
32036                                         ++ writeIndex;
32037
32038                                 }
32039
32040                         }
32041
32042                         // flush last keyframe (compaction looks ahead)
32043
32044                         if ( lastIndex > 0 ) {
32045
32046                                 times[ writeIndex ] = times[ lastIndex ];
32047
32048                                 for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j )
32049
32050                                         values[ writeOffset + j ] = values[ readOffset + j ];
32051
32052                                 ++ writeIndex;
32053
32054                         }
32055
32056                         if ( writeIndex !== times.length ) {
32057
32058                                 this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
32059                                 this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
32060
32061                         }
32062
32063                         return this;
32064
32065                 }
32066
32067         };
32068
32069         function KeyframeTrackConstructor( name, times, values, interpolation ) {
32070
32071                 if ( name === undefined ) throw new Error( "track name is undefined" );
32072
32073                 if ( times === undefined || times.length === 0 ) {
32074
32075                         throw new Error( "no keyframes in track named " + name );
32076
32077                 }
32078
32079                 this.name = name;
32080
32081                 this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
32082                 this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
32083
32084                 this.setInterpolation( interpolation || this.DefaultInterpolation );
32085
32086                 this.validate();
32087                 this.optimize();
32088
32089         }
32090
32091         /**
32092          *
32093          * A Track of vectored keyframe values.
32094          *
32095          *
32096          * @author Ben Houston / http://clara.io/
32097          * @author David Sarno / http://lighthaus.us/
32098          * @author tschw
32099          */
32100
32101         function VectorKeyframeTrack( name, times, values, interpolation ) {
32102
32103                 KeyframeTrackConstructor.call( this, name, times, values, interpolation );
32104
32105         }
32106
32107         VectorKeyframeTrack.prototype =
32108                         Object.assign( Object.create( KeyframeTrackPrototype ), {
32109
32110                 constructor: VectorKeyframeTrack,
32111
32112                 ValueTypeName: 'vector'
32113
32114                 // ValueBufferType is inherited
32115
32116                 // DefaultInterpolation is inherited
32117
32118         } );
32119
32120         /**
32121          * Spherical linear unit quaternion interpolant.
32122          *
32123          * @author tschw
32124          */
32125
32126         function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
32127
32128                 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
32129
32130         }
32131
32132         QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
32133
32134                 constructor: QuaternionLinearInterpolant,
32135
32136                 interpolate_: function( i1, t0, t, t1 ) {
32137
32138                         var result = this.resultBuffer,
32139                                 values = this.sampleValues,
32140                                 stride = this.valueSize,
32141
32142                                 offset = i1 * stride,
32143
32144                                 alpha = ( t - t0 ) / ( t1 - t0 );
32145
32146                         for ( var end = offset + stride; offset !== end; offset += 4 ) {
32147
32148                                 Quaternion.slerpFlat( result, 0,
32149                                                 values, offset - stride, values, offset, alpha );
32150
32151                         }
32152
32153                         return result;
32154
32155                 }
32156
32157         } );
32158
32159         /**
32160          *
32161          * A Track of quaternion keyframe values.
32162          *
32163          * @author Ben Houston / http://clara.io/
32164          * @author David Sarno / http://lighthaus.us/
32165          * @author tschw
32166          */
32167
32168         function QuaternionKeyframeTrack( name, times, values, interpolation ) {
32169
32170                 KeyframeTrackConstructor.call( this, name, times, values, interpolation );
32171
32172         }
32173
32174         QuaternionKeyframeTrack.prototype =
32175                         Object.assign( Object.create( KeyframeTrackPrototype ), {
32176
32177                 constructor: QuaternionKeyframeTrack,
32178
32179                 ValueTypeName: 'quaternion',
32180
32181                 // ValueBufferType is inherited
32182
32183                 DefaultInterpolation: InterpolateLinear,
32184
32185                 InterpolantFactoryMethodLinear: function( result ) {
32186
32187                         return new QuaternionLinearInterpolant(
32188                                         this.times, this.values, this.getValueSize(), result );
32189
32190                 },
32191
32192                 InterpolantFactoryMethodSmooth: undefined // not yet implemented
32193
32194         } );
32195
32196         /**
32197          *
32198          * A Track of numeric keyframe values.
32199          *
32200          * @author Ben Houston / http://clara.io/
32201          * @author David Sarno / http://lighthaus.us/
32202          * @author tschw
32203          */
32204
32205         function NumberKeyframeTrack( name, times, values, interpolation ) {
32206
32207                 KeyframeTrackConstructor.call( this, name, times, values, interpolation );
32208
32209         }
32210
32211         NumberKeyframeTrack.prototype =
32212                         Object.assign( Object.create( KeyframeTrackPrototype ), {
32213
32214                 constructor: NumberKeyframeTrack,
32215
32216                 ValueTypeName: 'number'
32217
32218                 // ValueBufferType is inherited
32219
32220                 // DefaultInterpolation is inherited
32221
32222         } );
32223
32224         /**
32225          *
32226          * A Track that interpolates Strings
32227          *
32228          *
32229          * @author Ben Houston / http://clara.io/
32230          * @author David Sarno / http://lighthaus.us/
32231          * @author tschw
32232          */
32233
32234         function StringKeyframeTrack( name, times, values, interpolation ) {
32235
32236                 KeyframeTrackConstructor.call( this, name, times, values, interpolation );
32237
32238         }
32239
32240         StringKeyframeTrack.prototype =
32241                         Object.assign( Object.create( KeyframeTrackPrototype ), {
32242
32243                 constructor: StringKeyframeTrack,
32244
32245                 ValueTypeName: 'string',
32246                 ValueBufferType: Array,
32247
32248                 DefaultInterpolation: InterpolateDiscrete,
32249
32250                 InterpolantFactoryMethodLinear: undefined,
32251
32252                 InterpolantFactoryMethodSmooth: undefined
32253
32254         } );
32255
32256         /**
32257          *
32258          * A Track of Boolean keyframe values.
32259          *
32260          *
32261          * @author Ben Houston / http://clara.io/
32262          * @author David Sarno / http://lighthaus.us/
32263          * @author tschw
32264          */
32265
32266         function BooleanKeyframeTrack( name, times, values ) {
32267
32268                 KeyframeTrackConstructor.call( this, name, times, values );
32269
32270         }
32271
32272         BooleanKeyframeTrack.prototype =
32273                         Object.assign( Object.create( KeyframeTrackPrototype ), {
32274
32275                 constructor: BooleanKeyframeTrack,
32276
32277                 ValueTypeName: 'bool',
32278                 ValueBufferType: Array,
32279
32280                 DefaultInterpolation: InterpolateDiscrete,
32281
32282                 InterpolantFactoryMethodLinear: undefined,
32283                 InterpolantFactoryMethodSmooth: undefined
32284
32285                 // Note: Actually this track could have a optimized / compressed
32286                 // representation of a single value and a custom interpolant that
32287                 // computes "firstValue ^ isOdd( index )".
32288
32289         } );
32290
32291         /**
32292          *
32293          * A Track of keyframe values that represent color.
32294          *
32295          *
32296          * @author Ben Houston / http://clara.io/
32297          * @author David Sarno / http://lighthaus.us/
32298          * @author tschw
32299          */
32300
32301         function ColorKeyframeTrack( name, times, values, interpolation ) {
32302
32303                 KeyframeTrackConstructor.call( this, name, times, values, interpolation );
32304
32305         }
32306
32307         ColorKeyframeTrack.prototype =
32308                         Object.assign( Object.create( KeyframeTrackPrototype ), {
32309
32310                 constructor: ColorKeyframeTrack,
32311
32312                 ValueTypeName: 'color'
32313
32314                 // ValueBufferType is inherited
32315
32316                 // DefaultInterpolation is inherited
32317
32318
32319                 // Note: Very basic implementation and nothing special yet.
32320                 // However, this is the place for color space parameterization.
32321
32322         } );
32323
32324         /**
32325          *
32326          * A timed sequence of keyframes for a specific property.
32327          *
32328          *
32329          * @author Ben Houston / http://clara.io/
32330          * @author David Sarno / http://lighthaus.us/
32331          * @author tschw
32332          */
32333
32334         function KeyframeTrack( name, times, values, interpolation ) {
32335
32336                 KeyframeTrackConstructor.apply( this, arguments );
32337
32338         }
32339
32340         KeyframeTrack.prototype = KeyframeTrackPrototype;
32341         KeyframeTrackPrototype.constructor = KeyframeTrack;
32342
32343         // Static methods:
32344
32345         Object.assign( KeyframeTrack, {
32346
32347                 // Serialization (in static context, because of constructor invocation
32348                 // and automatic invocation of .toJSON):
32349
32350                 parse: function( json ) {
32351
32352                         if( json.type === undefined ) {
32353
32354                                 throw new Error( "track type undefined, can not parse" );
32355
32356                         }
32357
32358                         var trackType = KeyframeTrack._getTrackTypeForValueTypeName( json.type );
32359
32360                         if ( json.times === undefined ) {
32361
32362                                 var times = [], values = [];
32363
32364                                 AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
32365
32366                                 json.times = times;
32367                                 json.values = values;
32368
32369                         }
32370
32371                         // derived classes can define a static parse method
32372                         if ( trackType.parse !== undefined ) {
32373
32374                                 return trackType.parse( json );
32375
32376                         } else {
32377
32378                                 // by default, we assume a constructor compatible with the base
32379                                 return new trackType(
32380                                                 json.name, json.times, json.values, json.interpolation );
32381
32382                         }
32383
32384                 },
32385
32386                 toJSON: function( track ) {
32387
32388                         var trackType = track.constructor;
32389
32390                         var json;
32391
32392                         // derived classes can define a static toJSON method
32393                         if ( trackType.toJSON !== undefined ) {
32394
32395                                 json = trackType.toJSON( track );
32396
32397                         } else {
32398
32399                                 // by default, we assume the data can be serialized as-is
32400                                 json = {
32401
32402                                         'name': track.name,
32403                                         'times': AnimationUtils.convertArray( track.times, Array ),
32404                                         'values': AnimationUtils.convertArray( track.values, Array )
32405
32406                                 };
32407
32408                                 var interpolation = track.getInterpolation();
32409
32410                                 if ( interpolation !== track.DefaultInterpolation ) {
32411
32412                                         json.interpolation = interpolation;
32413
32414                                 }
32415
32416                         }
32417
32418                         json.type = track.ValueTypeName; // mandatory
32419
32420                         return json;
32421
32422                 },
32423
32424                 _getTrackTypeForValueTypeName: function( typeName ) {
32425
32426                         switch( typeName.toLowerCase() ) {
32427
32428                                 case "scalar":
32429                                 case "double":
32430                                 case "float":
32431                                 case "number":
32432                                 case "integer":
32433
32434                                         return NumberKeyframeTrack;
32435
32436                                 case "vector":
32437                                 case "vector2":
32438                                 case "vector3":
32439                                 case "vector4":
32440
32441                                         return VectorKeyframeTrack;
32442
32443                                 case "color":
32444
32445                                         return ColorKeyframeTrack;
32446
32447                                 case "quaternion":
32448
32449                                         return QuaternionKeyframeTrack;
32450
32451                                 case "bool":
32452                                 case "boolean":
32453
32454                                         return BooleanKeyframeTrack;
32455
32456                                 case "string":
32457
32458                                         return StringKeyframeTrack;
32459
32460                         }
32461
32462                         throw new Error( "Unsupported typeName: " + typeName );
32463
32464                 }
32465
32466         } );
32467
32468         /**
32469          *
32470          * Reusable set of Tracks that represent an animation.
32471          *
32472          * @author Ben Houston / http://clara.io/
32473          * @author David Sarno / http://lighthaus.us/
32474          */
32475
32476         function AnimationClip( name, duration, tracks ) {
32477
32478                 this.name = name;
32479                 this.tracks = tracks;
32480                 this.duration = ( duration !== undefined ) ? duration : - 1;
32481
32482                 this.uuid = _Math.generateUUID();
32483
32484                 // this means it should figure out its duration by scanning the tracks
32485                 if ( this.duration < 0 ) {
32486
32487                         this.resetDuration();
32488
32489                 }
32490
32491                 this.optimize();
32492
32493         }
32494
32495         Object.assign( AnimationClip, {
32496
32497                 parse: function ( json ) {
32498
32499                         var tracks = [],
32500                                 jsonTracks = json.tracks,
32501                                 frameTime = 1.0 / ( json.fps || 1.0 );
32502
32503                         for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) {
32504
32505                                 tracks.push( KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) );
32506
32507                         }
32508
32509                         return new AnimationClip( json.name, json.duration, tracks );
32510
32511                 },
32512
32513                 toJSON: function ( clip ) {
32514
32515                         var tracks = [],
32516                                 clipTracks = clip.tracks;
32517
32518                         var json = {
32519
32520                                 'name': clip.name,
32521                                 'duration': clip.duration,
32522                                 'tracks': tracks
32523
32524                         };
32525
32526                         for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) {
32527
32528                                 tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
32529
32530                         }
32531
32532                         return json;
32533
32534                 },
32535
32536                 CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
32537
32538                         var numMorphTargets = morphTargetSequence.length;
32539                         var tracks = [];
32540
32541                         for ( var i = 0; i < numMorphTargets; i ++ ) {
32542
32543                                 var times = [];
32544                                 var values = [];
32545
32546                                 times.push(
32547                                                 ( i + numMorphTargets - 1 ) % numMorphTargets,
32548                                                 i,
32549                                                 ( i + 1 ) % numMorphTargets );
32550
32551                                 values.push( 0, 1, 0 );
32552
32553                                 var order = AnimationUtils.getKeyframeOrder( times );
32554                                 times = AnimationUtils.sortedArray( times, 1, order );
32555                                 values = AnimationUtils.sortedArray( values, 1, order );
32556
32557                                 // if there is a key at the first frame, duplicate it as the
32558                                 // last frame as well for perfect loop.
32559                                 if ( ! noLoop && times[ 0 ] === 0 ) {
32560
32561                                         times.push( numMorphTargets );
32562                                         values.push( values[ 0 ] );
32563
32564                                 }
32565
32566                                 tracks.push(
32567                                                 new NumberKeyframeTrack(
32568                                                         '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
32569                                                         times, values
32570                                                 ).scale( 1.0 / fps ) );
32571
32572                         }
32573
32574                         return new AnimationClip( name, - 1, tracks );
32575
32576                 },
32577
32578                 findByName: function ( objectOrClipArray, name ) {
32579
32580                         var clipArray = objectOrClipArray;
32581
32582                         if ( ! Array.isArray( objectOrClipArray ) ) {
32583
32584                                 var o = objectOrClipArray;
32585                                 clipArray = o.geometry && o.geometry.animations || o.animations;
32586
32587                         }
32588
32589                         for ( var i = 0; i < clipArray.length; i ++ ) {
32590
32591                                 if ( clipArray[ i ].name === name ) {
32592
32593                                         return clipArray[ i ];
32594
32595                                 }
32596
32597                         }
32598
32599                         return null;
32600
32601                 },
32602
32603                 CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
32604
32605                         var animationToMorphTargets = {};
32606
32607                         // tested with https://regex101.com/ on trick sequences
32608                         // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
32609                         var pattern = /^([\w-]*?)([\d]+)$/;
32610
32611                         // sort morph target names into animation groups based
32612                         // patterns like Walk_001, Walk_002, Run_001, Run_002
32613                         for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
32614
32615                                 var morphTarget = morphTargets[ i ];
32616                                 var parts = morphTarget.name.match( pattern );
32617
32618                                 if ( parts && parts.length > 1 ) {
32619
32620                                         var name = parts[ 1 ];
32621
32622                                         var animationMorphTargets = animationToMorphTargets[ name ];
32623                                         if ( ! animationMorphTargets ) {
32624
32625                                                 animationToMorphTargets[ name ] = animationMorphTargets = [];
32626
32627                                         }
32628
32629                                         animationMorphTargets.push( morphTarget );
32630
32631                                 }
32632
32633                         }
32634
32635                         var clips = [];
32636
32637                         for ( var name in animationToMorphTargets ) {
32638
32639                                 clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
32640
32641                         }
32642
32643                         return clips;
32644
32645                 },
32646
32647                 // parse the animation.hierarchy format
32648                 parseAnimation: function ( animation, bones ) {
32649
32650                         if ( ! animation ) {
32651
32652                                 console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
32653                                 return null;
32654
32655                         }
32656
32657                         var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
32658
32659                                 // only return track if there are actually keys.
32660                                 if ( animationKeys.length !== 0 ) {
32661
32662                                         var times = [];
32663                                         var values = [];
32664
32665                                         AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
32666
32667                                         // empty keys are filtered out, so check again
32668                                         if ( times.length !== 0 ) {
32669
32670                                                 destTracks.push( new trackType( trackName, times, values ) );
32671
32672                                         }
32673
32674                                 }
32675
32676                         };
32677
32678                         var tracks = [];
32679
32680                         var clipName = animation.name || 'default';
32681                         // automatic length determination in AnimationClip.
32682                         var duration = animation.length || - 1;
32683                         var fps = animation.fps || 30;
32684
32685                         var hierarchyTracks = animation.hierarchy || [];
32686
32687                         for ( var h = 0; h < hierarchyTracks.length; h ++ ) {
32688
32689                                 var animationKeys = hierarchyTracks[ h ].keys;
32690
32691                                 // skip empty tracks
32692                                 if ( ! animationKeys || animationKeys.length === 0 ) continue;
32693
32694                                 // process morph targets
32695                                 if ( animationKeys[ 0 ].morphTargets ) {
32696
32697                                         // figure out all morph targets used in this track
32698                                         var morphTargetNames = {};
32699
32700                                         for ( var k = 0; k < animationKeys.length; k ++ ) {
32701
32702                                                 if ( animationKeys[ k ].morphTargets ) {
32703
32704                                                         for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
32705
32706                                                                 morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
32707
32708                                                         }
32709
32710                                                 }
32711
32712                                         }
32713
32714                                         // create a track for each morph target with all zero
32715                                         // morphTargetInfluences except for the keys in which
32716                                         // the morphTarget is named.
32717                                         for ( var morphTargetName in morphTargetNames ) {
32718
32719                                                 var times = [];
32720                                                 var values = [];
32721
32722                                                 for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
32723
32724                                                         var animationKey = animationKeys[ k ];
32725
32726                                                         times.push( animationKey.time );
32727                                                         values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
32728
32729                                                 }
32730
32731                                                 tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
32732
32733                                         }
32734
32735                                         duration = morphTargetNames.length * ( fps || 1.0 );
32736
32737                                 } else {
32738
32739                                         // ...assume skeletal animation
32740
32741                                         var boneName = '.bones[' + bones[ h ].name + ']';
32742
32743                                         addNonemptyTrack(
32744                                                         VectorKeyframeTrack, boneName + '.position',
32745                                                         animationKeys, 'pos', tracks );
32746
32747                                         addNonemptyTrack(
32748                                                         QuaternionKeyframeTrack, boneName + '.quaternion',
32749                                                         animationKeys, 'rot', tracks );
32750
32751                                         addNonemptyTrack(
32752                                                         VectorKeyframeTrack, boneName + '.scale',
32753                                                         animationKeys, 'scl', tracks );
32754
32755                                 }
32756
32757                         }
32758
32759                         if ( tracks.length === 0 ) {
32760
32761                                 return null;
32762
32763                         }
32764
32765                         var clip = new AnimationClip( clipName, duration, tracks );
32766
32767                         return clip;
32768
32769                 }
32770
32771         } );
32772
32773         Object.assign( AnimationClip.prototype, {
32774
32775                 resetDuration: function () {
32776
32777                         var tracks = this.tracks, duration = 0;
32778
32779                         for ( var i = 0, n = tracks.length; i !== n; ++ i ) {
32780
32781                                 var track = this.tracks[ i ];
32782
32783                                 duration = Math.max( duration, track.times[ track.times.length - 1 ] );
32784
32785                         }
32786
32787                         this.duration = duration;
32788
32789                 },
32790
32791                 trim: function () {
32792
32793                         for ( var i = 0; i < this.tracks.length; i ++ ) {
32794
32795                                 this.tracks[ i ].trim( 0, this.duration );
32796
32797                         }
32798
32799                         return this;
32800
32801                 },
32802
32803                 optimize: function () {
32804
32805                         for ( var i = 0; i < this.tracks.length; i ++ ) {
32806
32807                                 this.tracks[ i ].optimize();
32808
32809                         }
32810
32811                         return this;
32812
32813                 }
32814
32815         } );
32816
32817         /**
32818          * @author mrdoob / http://mrdoob.com/
32819          */
32820
32821         function MaterialLoader( manager ) {
32822
32823                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
32824                 this.textures = {};
32825
32826         }
32827
32828         Object.assign( MaterialLoader.prototype, {
32829
32830                 load: function ( url, onLoad, onProgress, onError ) {
32831
32832                         var scope = this;
32833
32834                         var loader = new FileLoader( scope.manager );
32835                         loader.load( url, function ( text ) {
32836
32837                                 onLoad( scope.parse( JSON.parse( text ) ) );
32838
32839                         }, onProgress, onError );
32840
32841                 },
32842
32843                 setTextures: function ( value ) {
32844
32845                         this.textures = value;
32846
32847                 },
32848
32849                 parse: function ( json ) {
32850
32851                         var textures = this.textures;
32852
32853                         function getTexture( name ) {
32854
32855                                 if ( textures[ name ] === undefined ) {
32856
32857                                         console.warn( 'THREE.MaterialLoader: Undefined texture', name );
32858
32859                                 }
32860
32861                                 return textures[ name ];
32862
32863                         }
32864
32865                         var material = new Materials[ json.type ]();
32866
32867                         if ( json.uuid !== undefined ) material.uuid = json.uuid;
32868                         if ( json.name !== undefined ) material.name = json.name;
32869                         if ( json.color !== undefined ) material.color.setHex( json.color );
32870                         if ( json.roughness !== undefined ) material.roughness = json.roughness;
32871                         if ( json.metalness !== undefined ) material.metalness = json.metalness;
32872                         if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
32873                         if ( json.specular !== undefined ) material.specular.setHex( json.specular );
32874                         if ( json.shininess !== undefined ) material.shininess = json.shininess;
32875                         if ( json.clearCoat !== undefined ) material.clearCoat = json.clearCoat;
32876                         if ( json.clearCoatRoughness !== undefined ) material.clearCoatRoughness = json.clearCoatRoughness;
32877                         if ( json.uniforms !== undefined ) material.uniforms = json.uniforms;
32878                         if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
32879                         if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
32880                         if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
32881                         if ( json.fog !== undefined ) material.fog = json.fog;
32882                         if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
32883                         if ( json.blending !== undefined ) material.blending = json.blending;
32884                         if ( json.side !== undefined ) material.side = json.side;
32885                         if ( json.opacity !== undefined ) material.opacity = json.opacity;
32886                         if ( json.transparent !== undefined ) material.transparent = json.transparent;
32887                         if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
32888                         if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
32889                         if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
32890                         if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
32891                         if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
32892                         if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
32893                         if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
32894                         if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
32895
32896                         if ( json.skinning !== undefined ) material.skinning = json.skinning;
32897                         if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
32898                         if ( json.dithering !== undefined ) material.dithering = json.dithering;
32899
32900                         if ( json.visible !== undefined ) material.visible = json.visible;
32901                         if ( json.userData !== undefined ) material.userData = json.userData;
32902
32903                         // Deprecated
32904
32905                         if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
32906
32907                         // for PointsMaterial
32908
32909                         if ( json.size !== undefined ) material.size = json.size;
32910                         if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
32911
32912                         // maps
32913
32914                         if ( json.map !== undefined ) material.map = getTexture( json.map );
32915
32916                         if ( json.alphaMap !== undefined ) {
32917
32918                                 material.alphaMap = getTexture( json.alphaMap );
32919                                 material.transparent = true;
32920
32921                         }
32922
32923                         if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
32924                         if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
32925
32926                         if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
32927                         if ( json.normalScale !== undefined ) {
32928
32929                                 var normalScale = json.normalScale;
32930
32931                                 if ( Array.isArray( normalScale ) === false ) {
32932
32933                                         // Blender exporter used to export a scalar. See #7459
32934
32935                                         normalScale = [ normalScale, normalScale ];
32936
32937                                 }
32938
32939                                 material.normalScale = new Vector2().fromArray( normalScale );
32940
32941                         }
32942
32943                         if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
32944                         if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
32945                         if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
32946
32947                         if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
32948                         if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
32949
32950                         if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
32951                         if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
32952
32953                         if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
32954
32955                         if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
32956
32957                         if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
32958
32959                         if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
32960                         if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
32961
32962                         if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
32963                         if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
32964
32965                         if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
32966
32967                         return material;
32968
32969                 }
32970
32971         } );
32972
32973         /**
32974          * @author mrdoob / http://mrdoob.com/
32975          */
32976
32977         function BufferGeometryLoader( manager ) {
32978
32979                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
32980
32981         }
32982
32983         Object.assign( BufferGeometryLoader.prototype, {
32984
32985                 load: function ( url, onLoad, onProgress, onError ) {
32986
32987                         var scope = this;
32988
32989                         var loader = new FileLoader( scope.manager );
32990                         loader.load( url, function ( text ) {
32991
32992                                 onLoad( scope.parse( JSON.parse( text ) ) );
32993
32994                         }, onProgress, onError );
32995
32996                 },
32997
32998                 parse: function ( json ) {
32999
33000                         var geometry = new BufferGeometry();
33001
33002                         var index = json.data.index;
33003
33004                         if ( index !== undefined ) {
33005
33006                                 var typedArray = new TYPED_ARRAYS[ index.type ]( index.array );
33007                                 geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
33008
33009                         }
33010
33011                         var attributes = json.data.attributes;
33012
33013                         for ( var key in attributes ) {
33014
33015                                 var attribute = attributes[ key ];
33016                                 var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
33017
33018                                 geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) );
33019
33020                         }
33021
33022                         var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
33023
33024                         if ( groups !== undefined ) {
33025
33026                                 for ( var i = 0, n = groups.length; i !== n; ++ i ) {
33027
33028                                         var group = groups[ i ];
33029
33030                                         geometry.addGroup( group.start, group.count, group.materialIndex );
33031
33032                                 }
33033
33034                         }
33035
33036                         var boundingSphere = json.data.boundingSphere;
33037
33038                         if ( boundingSphere !== undefined ) {
33039
33040                                 var center = new Vector3();
33041
33042                                 if ( boundingSphere.center !== undefined ) {
33043
33044                                         center.fromArray( boundingSphere.center );
33045
33046                                 }
33047
33048                                 geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
33049
33050                         }
33051
33052                         return geometry;
33053
33054                 }
33055
33056         } );
33057
33058         var TYPED_ARRAYS = {
33059                 Int8Array: Int8Array,
33060                 Uint8Array: Uint8Array,
33061                 // Workaround for IE11 pre KB2929437. See #11440
33062                 Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
33063                 Int16Array: Int16Array,
33064                 Uint16Array: Uint16Array,
33065                 Int32Array: Int32Array,
33066                 Uint32Array: Uint32Array,
33067                 Float32Array: Float32Array,
33068                 Float64Array: Float64Array
33069         };
33070
33071         /**
33072          * @author alteredq / http://alteredqualia.com/
33073          */
33074
33075         function Loader() {
33076
33077                 this.onLoadStart = function () {};
33078                 this.onLoadProgress = function () {};
33079                 this.onLoadComplete = function () {};
33080
33081         }
33082
33083         Loader.Handlers = {
33084
33085                 handlers: [],
33086
33087                 add: function ( regex, loader ) {
33088
33089                         this.handlers.push( regex, loader );
33090
33091                 },
33092
33093                 get: function ( file ) {
33094
33095                         var handlers = this.handlers;
33096
33097                         for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
33098
33099                                 var regex = handlers[ i ];
33100                                 var loader = handlers[ i + 1 ];
33101
33102                                 if ( regex.test( file ) ) {
33103
33104                                         return loader;
33105
33106                                 }
33107
33108                         }
33109
33110                         return null;
33111
33112                 }
33113
33114         };
33115
33116         Object.assign( Loader.prototype, {
33117
33118                 crossOrigin: undefined,
33119
33120                 extractUrlBase: function ( url ) {
33121
33122                         var parts = url.split( '/' );
33123
33124                         if ( parts.length === 1 ) return './';
33125
33126                         parts.pop();
33127
33128                         return parts.join( '/' ) + '/';
33129
33130                 },
33131
33132                 initMaterials: function ( materials, texturePath, crossOrigin ) {
33133
33134                         var array = [];
33135
33136                         for ( var i = 0; i < materials.length; ++ i ) {
33137
33138                                 array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
33139
33140                         }
33141
33142                         return array;
33143
33144                 },
33145
33146                 createMaterial: ( function () {
33147
33148                         var BlendingMode = {
33149                                 NoBlending: NoBlending,
33150                                 NormalBlending: NormalBlending,
33151                                 AdditiveBlending: AdditiveBlending,
33152                                 SubtractiveBlending: SubtractiveBlending,
33153                                 MultiplyBlending: MultiplyBlending,
33154                                 CustomBlending: CustomBlending
33155                         };
33156
33157                         var color = new Color();
33158                         var textureLoader = new TextureLoader();
33159                         var materialLoader = new MaterialLoader();
33160
33161                         return function createMaterial( m, texturePath, crossOrigin ) {
33162
33163                                 // convert from old material format
33164
33165                                 var textures = {};
33166
33167                                 function loadTexture( path, repeat, offset, wrap, anisotropy ) {
33168
33169                                         var fullPath = texturePath + path;
33170                                         var loader = Loader.Handlers.get( fullPath );
33171
33172                                         var texture;
33173
33174                                         if ( loader !== null ) {
33175
33176                                                 texture = loader.load( fullPath );
33177
33178                                         } else {
33179
33180                                                 textureLoader.setCrossOrigin( crossOrigin );
33181                                                 texture = textureLoader.load( fullPath );
33182
33183                                         }
33184
33185                                         if ( repeat !== undefined ) {
33186
33187                                                 texture.repeat.fromArray( repeat );
33188
33189                                                 if ( repeat[ 0 ] !== 1 ) texture.wrapS = RepeatWrapping;
33190                                                 if ( repeat[ 1 ] !== 1 ) texture.wrapT = RepeatWrapping;
33191
33192                                         }
33193
33194                                         if ( offset !== undefined ) {
33195
33196                                                 texture.offset.fromArray( offset );
33197
33198                                         }
33199
33200                                         if ( wrap !== undefined ) {
33201
33202                                                 if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = RepeatWrapping;
33203                                                 if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = MirroredRepeatWrapping;
33204
33205                                                 if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = RepeatWrapping;
33206                                                 if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = MirroredRepeatWrapping;
33207
33208                                         }
33209
33210                                         if ( anisotropy !== undefined ) {
33211
33212                                                 texture.anisotropy = anisotropy;
33213
33214                                         }
33215
33216                                         var uuid = _Math.generateUUID();
33217
33218                                         textures[ uuid ] = texture;
33219
33220                                         return uuid;
33221
33222                                 }
33223
33224                                 //
33225
33226                                 var json = {
33227                                         uuid: _Math.generateUUID(),
33228                                         type: 'MeshLambertMaterial'
33229                                 };
33230
33231                                 for ( var name in m ) {
33232
33233                                         var value = m[ name ];
33234
33235                                         switch ( name ) {
33236
33237                                                 case 'DbgColor':
33238                                                 case 'DbgIndex':
33239                                                 case 'opticalDensity':
33240                                                 case 'illumination':
33241                                                         break;
33242                                                 case 'DbgName':
33243                                                         json.name = value;
33244                                                         break;
33245                                                 case 'blending':
33246                                                         json.blending = BlendingMode[ value ];
33247                                                         break;
33248                                                 case 'colorAmbient':
33249                                                 case 'mapAmbient':
33250                                                         console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' );
33251                                                         break;
33252                                                 case 'colorDiffuse':
33253                                                         json.color = color.fromArray( value ).getHex();
33254                                                         break;
33255                                                 case 'colorSpecular':
33256                                                         json.specular = color.fromArray( value ).getHex();
33257                                                         break;
33258                                                 case 'colorEmissive':
33259                                                         json.emissive = color.fromArray( value ).getHex();
33260                                                         break;
33261                                                 case 'specularCoef':
33262                                                         json.shininess = value;
33263                                                         break;
33264                                                 case 'shading':
33265                                                         if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
33266                                                         if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
33267                                                         if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial';
33268                                                         break;
33269                                                 case 'mapDiffuse':
33270                                                         json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
33271                                                         break;
33272                                                 case 'mapDiffuseRepeat':
33273                                                 case 'mapDiffuseOffset':
33274                                                 case 'mapDiffuseWrap':
33275                                                 case 'mapDiffuseAnisotropy':
33276                                                         break;
33277                                                 case 'mapEmissive':
33278                                                         json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy );
33279                                                         break;
33280                                                 case 'mapEmissiveRepeat':
33281                                                 case 'mapEmissiveOffset':
33282                                                 case 'mapEmissiveWrap':
33283                                                 case 'mapEmissiveAnisotropy':
33284                                                         break;
33285                                                 case 'mapLight':
33286                                                         json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
33287                                                         break;
33288                                                 case 'mapLightRepeat':
33289                                                 case 'mapLightOffset':
33290                                                 case 'mapLightWrap':
33291                                                 case 'mapLightAnisotropy':
33292                                                         break;
33293                                                 case 'mapAO':
33294                                                         json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
33295                                                         break;
33296                                                 case 'mapAORepeat':
33297                                                 case 'mapAOOffset':
33298                                                 case 'mapAOWrap':
33299                                                 case 'mapAOAnisotropy':
33300                                                         break;
33301                                                 case 'mapBump':
33302                                                         json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
33303                                                         break;
33304                                                 case 'mapBumpScale':
33305                                                         json.bumpScale = value;
33306                                                         break;
33307                                                 case 'mapBumpRepeat':
33308                                                 case 'mapBumpOffset':
33309                                                 case 'mapBumpWrap':
33310                                                 case 'mapBumpAnisotropy':
33311                                                         break;
33312                                                 case 'mapNormal':
33313                                                         json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
33314                                                         break;
33315                                                 case 'mapNormalFactor':
33316                                                         json.normalScale = [ value, value ];
33317                                                         break;
33318                                                 case 'mapNormalRepeat':
33319                                                 case 'mapNormalOffset':
33320                                                 case 'mapNormalWrap':
33321                                                 case 'mapNormalAnisotropy':
33322                                                         break;
33323                                                 case 'mapSpecular':
33324                                                         json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
33325                                                         break;
33326                                                 case 'mapSpecularRepeat':
33327                                                 case 'mapSpecularOffset':
33328                                                 case 'mapSpecularWrap':
33329                                                 case 'mapSpecularAnisotropy':
33330                                                         break;
33331                                                 case 'mapMetalness':
33332                                                         json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy );
33333                                                         break;
33334                                                 case 'mapMetalnessRepeat':
33335                                                 case 'mapMetalnessOffset':
33336                                                 case 'mapMetalnessWrap':
33337                                                 case 'mapMetalnessAnisotropy':
33338                                                         break;
33339                                                 case 'mapRoughness':
33340                                                         json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy );
33341                                                         break;
33342                                                 case 'mapRoughnessRepeat':
33343                                                 case 'mapRoughnessOffset':
33344                                                 case 'mapRoughnessWrap':
33345                                                 case 'mapRoughnessAnisotropy':
33346                                                         break;
33347                                                 case 'mapAlpha':
33348                                                         json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
33349                                                         break;
33350                                                 case 'mapAlphaRepeat':
33351                                                 case 'mapAlphaOffset':
33352                                                 case 'mapAlphaWrap':
33353                                                 case 'mapAlphaAnisotropy':
33354                                                         break;
33355                                                 case 'flipSided':
33356                                                         json.side = BackSide;
33357                                                         break;
33358                                                 case 'doubleSided':
33359                                                         json.side = DoubleSide;
33360                                                         break;
33361                                                 case 'transparency':
33362                                                         console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' );
33363                                                         json.opacity = value;
33364                                                         break;
33365                                                 case 'depthTest':
33366                                                 case 'depthWrite':
33367                                                 case 'colorWrite':
33368                                                 case 'opacity':
33369                                                 case 'reflectivity':
33370                                                 case 'transparent':
33371                                                 case 'visible':
33372                                                 case 'wireframe':
33373                                                         json[ name ] = value;
33374                                                         break;
33375                                                 case 'vertexColors':
33376                                                         if ( value === true ) json.vertexColors = VertexColors;
33377                                                         if ( value === 'face' ) json.vertexColors = FaceColors;
33378                                                         break;
33379                                                 default:
33380                                                         console.error( 'THREE.Loader.createMaterial: Unsupported', name, value );
33381                                                         break;
33382
33383                                         }
33384
33385                                 }
33386
33387                                 if ( json.type === 'MeshBasicMaterial' ) delete json.emissive;
33388                                 if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
33389
33390                                 if ( json.opacity < 1 ) json.transparent = true;
33391
33392                                 materialLoader.setTextures( textures );
33393
33394                                 return materialLoader.parse( json );
33395
33396                         };
33397
33398                 } )()
33399
33400         } );
33401
33402         /**
33403          * @author mrdoob / http://mrdoob.com/
33404          * @author alteredq / http://alteredqualia.com/
33405          */
33406
33407         function JSONLoader( manager ) {
33408
33409                 if ( typeof manager === 'boolean' ) {
33410
33411                         console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
33412                         manager = undefined;
33413
33414                 }
33415
33416                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
33417
33418                 this.withCredentials = false;
33419
33420         }
33421
33422         Object.assign( JSONLoader.prototype, {
33423
33424                 load: function ( url, onLoad, onProgress, onError ) {
33425
33426                         var scope = this;
33427
33428                         var texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : Loader.prototype.extractUrlBase( url );
33429
33430                         var loader = new FileLoader( this.manager );
33431                         loader.setWithCredentials( this.withCredentials );
33432                         loader.load( url, function ( text ) {
33433
33434                                 var json = JSON.parse( text );
33435                                 var metadata = json.metadata;
33436
33437                                 if ( metadata !== undefined ) {
33438
33439                                         var type = metadata.type;
33440
33441                                         if ( type !== undefined ) {
33442
33443                                                 if ( type.toLowerCase() === 'object' ) {
33444
33445                                                         console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
33446                                                         return;
33447
33448                                                 }
33449
33450                                                 if ( type.toLowerCase() === 'scene' ) {
33451
33452                                                         console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' );
33453                                                         return;
33454
33455                                                 }
33456
33457                                         }
33458
33459                                 }
33460
33461                                 var object = scope.parse( json, texturePath );
33462                                 onLoad( object.geometry, object.materials );
33463
33464                         }, onProgress, onError );
33465
33466                 },
33467
33468                 setTexturePath: function ( value ) {
33469
33470                         this.texturePath = value;
33471
33472                 },
33473
33474                 parse: ( function () {
33475
33476                         function parseModel( json, geometry ) {
33477
33478                                 function isBitSet( value, position ) {
33479
33480                                         return value & ( 1 << position );
33481
33482                                 }
33483
33484                                 var i, j, fi,
33485
33486                                         offset, zLength,
33487
33488                                         colorIndex, normalIndex, uvIndex, materialIndex,
33489
33490                                         type,
33491                                         isQuad,
33492                                         hasMaterial,
33493                                         hasFaceVertexUv,
33494                                         hasFaceNormal, hasFaceVertexNormal,
33495                                         hasFaceColor, hasFaceVertexColor,
33496
33497                                         vertex, face, faceA, faceB, hex, normal,
33498
33499                                         uvLayer, uv, u, v,
33500
33501                                         faces = json.faces,
33502                                         vertices = json.vertices,
33503                                         normals = json.normals,
33504                                         colors = json.colors,
33505
33506                                         scale = json.scale,
33507
33508                                         nUvLayers = 0;
33509
33510
33511                                 if ( json.uvs !== undefined ) {
33512
33513                                         // disregard empty arrays
33514
33515                                         for ( i = 0; i < json.uvs.length; i ++ ) {
33516
33517                                                 if ( json.uvs[ i ].length ) nUvLayers ++;
33518
33519                                         }
33520
33521                                         for ( i = 0; i < nUvLayers; i ++ ) {
33522
33523                                                 geometry.faceVertexUvs[ i ] = [];
33524
33525                                         }
33526
33527                                 }
33528
33529                                 offset = 0;
33530                                 zLength = vertices.length;
33531
33532                                 while ( offset < zLength ) {
33533
33534                                         vertex = new Vector3();
33535
33536                                         vertex.x = vertices[ offset ++ ] * scale;
33537                                         vertex.y = vertices[ offset ++ ] * scale;
33538                                         vertex.z = vertices[ offset ++ ] * scale;
33539
33540                                         geometry.vertices.push( vertex );
33541
33542                                 }
33543
33544                                 offset = 0;
33545                                 zLength = faces.length;
33546
33547                                 while ( offset < zLength ) {
33548
33549                                         type = faces[ offset ++ ];
33550
33551                                         isQuad = isBitSet( type, 0 );
33552                                         hasMaterial = isBitSet( type, 1 );
33553                                         hasFaceVertexUv = isBitSet( type, 3 );
33554                                         hasFaceNormal = isBitSet( type, 4 );
33555                                         hasFaceVertexNormal = isBitSet( type, 5 );
33556                                         hasFaceColor = isBitSet( type, 6 );
33557                                         hasFaceVertexColor = isBitSet( type, 7 );
33558
33559                                         // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
33560
33561                                         if ( isQuad ) {
33562
33563                                                 faceA = new Face3();
33564                                                 faceA.a = faces[ offset ];
33565                                                 faceA.b = faces[ offset + 1 ];
33566                                                 faceA.c = faces[ offset + 3 ];
33567
33568                                                 faceB = new Face3();
33569                                                 faceB.a = faces[ offset + 1 ];
33570                                                 faceB.b = faces[ offset + 2 ];
33571                                                 faceB.c = faces[ offset + 3 ];
33572
33573                                                 offset += 4;
33574
33575                                                 if ( hasMaterial ) {
33576
33577                                                         materialIndex = faces[ offset ++ ];
33578                                                         faceA.materialIndex = materialIndex;
33579                                                         faceB.materialIndex = materialIndex;
33580
33581                                                 }
33582
33583                                                 // to get face <=> uv index correspondence
33584
33585                                                 fi = geometry.faces.length;
33586
33587                                                 if ( hasFaceVertexUv ) {
33588
33589                                                         for ( i = 0; i < nUvLayers; i ++ ) {
33590
33591                                                                 uvLayer = json.uvs[ i ];
33592
33593                                                                 geometry.faceVertexUvs[ i ][ fi ] = [];
33594                                                                 geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
33595
33596                                                                 for ( j = 0; j < 4; j ++ ) {
33597
33598                                                                         uvIndex = faces[ offset ++ ];
33599
33600                                                                         u = uvLayer[ uvIndex * 2 ];
33601                                                                         v = uvLayer[ uvIndex * 2 + 1 ];
33602
33603                                                                         uv = new Vector2( u, v );
33604
33605                                                                         if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
33606                                                                         if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
33607
33608                                                                 }
33609
33610                                                         }
33611
33612                                                 }
33613
33614                                                 if ( hasFaceNormal ) {
33615
33616                                                         normalIndex = faces[ offset ++ ] * 3;
33617
33618                                                         faceA.normal.set(
33619                                                                 normals[ normalIndex ++ ],
33620                                                                 normals[ normalIndex ++ ],
33621                                                                 normals[ normalIndex ]
33622                                                         );
33623
33624                                                         faceB.normal.copy( faceA.normal );
33625
33626                                                 }
33627
33628                                                 if ( hasFaceVertexNormal ) {
33629
33630                                                         for ( i = 0; i < 4; i ++ ) {
33631
33632                                                                 normalIndex = faces[ offset ++ ] * 3;
33633
33634                                                                 normal = new Vector3(
33635                                                                         normals[ normalIndex ++ ],
33636                                                                         normals[ normalIndex ++ ],
33637                                                                         normals[ normalIndex ]
33638                                                                 );
33639
33640
33641                                                                 if ( i !== 2 ) faceA.vertexNormals.push( normal );
33642                                                                 if ( i !== 0 ) faceB.vertexNormals.push( normal );
33643
33644                                                         }
33645
33646                                                 }
33647
33648
33649                                                 if ( hasFaceColor ) {
33650
33651                                                         colorIndex = faces[ offset ++ ];
33652                                                         hex = colors[ colorIndex ];
33653
33654                                                         faceA.color.setHex( hex );
33655                                                         faceB.color.setHex( hex );
33656
33657                                                 }
33658
33659
33660                                                 if ( hasFaceVertexColor ) {
33661
33662                                                         for ( i = 0; i < 4; i ++ ) {
33663
33664                                                                 colorIndex = faces[ offset ++ ];
33665                                                                 hex = colors[ colorIndex ];
33666
33667                                                                 if ( i !== 2 ) faceA.vertexColors.push( new Color( hex ) );
33668                                                                 if ( i !== 0 ) faceB.vertexColors.push( new Color( hex ) );
33669
33670                                                         }
33671
33672                                                 }
33673
33674                                                 geometry.faces.push( faceA );
33675                                                 geometry.faces.push( faceB );
33676
33677                                         } else {
33678
33679                                                 face = new Face3();
33680                                                 face.a = faces[ offset ++ ];
33681                                                 face.b = faces[ offset ++ ];
33682                                                 face.c = faces[ offset ++ ];
33683
33684                                                 if ( hasMaterial ) {
33685
33686                                                         materialIndex = faces[ offset ++ ];
33687                                                         face.materialIndex = materialIndex;
33688
33689                                                 }
33690
33691                                                 // to get face <=> uv index correspondence
33692
33693                                                 fi = geometry.faces.length;
33694
33695                                                 if ( hasFaceVertexUv ) {
33696
33697                                                         for ( i = 0; i < nUvLayers; i ++ ) {
33698
33699                                                                 uvLayer = json.uvs[ i ];
33700
33701                                                                 geometry.faceVertexUvs[ i ][ fi ] = [];
33702
33703                                                                 for ( j = 0; j < 3; j ++ ) {
33704
33705                                                                         uvIndex = faces[ offset ++ ];
33706
33707                                                                         u = uvLayer[ uvIndex * 2 ];
33708                                                                         v = uvLayer[ uvIndex * 2 + 1 ];
33709
33710                                                                         uv = new Vector2( u, v );
33711
33712                                                                         geometry.faceVertexUvs[ i ][ fi ].push( uv );
33713
33714                                                                 }
33715
33716                                                         }
33717
33718                                                 }
33719
33720                                                 if ( hasFaceNormal ) {
33721
33722                                                         normalIndex = faces[ offset ++ ] * 3;
33723
33724                                                         face.normal.set(
33725                                                                 normals[ normalIndex ++ ],
33726                                                                 normals[ normalIndex ++ ],
33727                                                                 normals[ normalIndex ]
33728                                                         );
33729
33730                                                 }
33731
33732                                                 if ( hasFaceVertexNormal ) {
33733
33734                                                         for ( i = 0; i < 3; i ++ ) {
33735
33736                                                                 normalIndex = faces[ offset ++ ] * 3;
33737
33738                                                                 normal = new Vector3(
33739                                                                         normals[ normalIndex ++ ],
33740                                                                         normals[ normalIndex ++ ],
33741                                                                         normals[ normalIndex ]
33742                                                                 );
33743
33744                                                                 face.vertexNormals.push( normal );
33745
33746                                                         }
33747
33748                                                 }
33749
33750
33751                                                 if ( hasFaceColor ) {
33752
33753                                                         colorIndex = faces[ offset ++ ];
33754                                                         face.color.setHex( colors[ colorIndex ] );
33755
33756                                                 }
33757
33758
33759                                                 if ( hasFaceVertexColor ) {
33760
33761                                                         for ( i = 0; i < 3; i ++ ) {
33762
33763                                                                 colorIndex = faces[ offset ++ ];
33764                                                                 face.vertexColors.push( new Color( colors[ colorIndex ] ) );
33765
33766                                                         }
33767
33768                                                 }
33769
33770                                                 geometry.faces.push( face );
33771
33772                                         }
33773
33774                                 }
33775
33776                         }
33777
33778                         function parseSkin( json, geometry ) {
33779
33780                                 var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
33781
33782                                 if ( json.skinWeights ) {
33783
33784                                         for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
33785
33786                                                 var x = json.skinWeights[ i ];
33787                                                 var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
33788                                                 var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
33789                                                 var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
33790
33791                                                 geometry.skinWeights.push( new Vector4( x, y, z, w ) );
33792
33793                                         }
33794
33795                                 }
33796
33797                                 if ( json.skinIndices ) {
33798
33799                                         for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
33800
33801                                                 var a = json.skinIndices[ i ];
33802                                                 var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
33803                                                 var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
33804                                                 var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
33805
33806                                                 geometry.skinIndices.push( new Vector4( a, b, c, d ) );
33807
33808                                         }
33809
33810                                 }
33811
33812                                 geometry.bones = json.bones;
33813
33814                                 if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
33815
33816                                         console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
33817                                                 geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
33818
33819                                 }
33820
33821                         }
33822
33823                         function parseMorphing( json, geometry ) {
33824
33825                                 var scale = json.scale;
33826
33827                                 if ( json.morphTargets !== undefined ) {
33828
33829                                         for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
33830
33831                                                 geometry.morphTargets[ i ] = {};
33832                                                 geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
33833                                                 geometry.morphTargets[ i ].vertices = [];
33834
33835                                                 var dstVertices = geometry.morphTargets[ i ].vertices;
33836                                                 var srcVertices = json.morphTargets[ i ].vertices;
33837
33838                                                 for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
33839
33840                                                         var vertex = new Vector3();
33841                                                         vertex.x = srcVertices[ v ] * scale;
33842                                                         vertex.y = srcVertices[ v + 1 ] * scale;
33843                                                         vertex.z = srcVertices[ v + 2 ] * scale;
33844
33845                                                         dstVertices.push( vertex );
33846
33847                                                 }
33848
33849                                         }
33850
33851                                 }
33852
33853                                 if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
33854
33855                                         console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
33856
33857                                         var faces = geometry.faces;
33858                                         var morphColors = json.morphColors[ 0 ].colors;
33859
33860                                         for ( var i = 0, l = faces.length; i < l; i ++ ) {
33861
33862                                                 faces[ i ].color.fromArray( morphColors, i * 3 );
33863
33864                                         }
33865
33866                                 }
33867
33868                         }
33869
33870                         function parseAnimations( json, geometry ) {
33871
33872                                 var outputAnimations = [];
33873
33874                                 // parse old style Bone/Hierarchy animations
33875                                 var animations = [];
33876
33877                                 if ( json.animation !== undefined ) {
33878
33879                                         animations.push( json.animation );
33880
33881                                 }
33882
33883                                 if ( json.animations !== undefined ) {
33884
33885                                         if ( json.animations.length ) {
33886
33887                                                 animations = animations.concat( json.animations );
33888
33889                                         } else {
33890
33891                                                 animations.push( json.animations );
33892
33893                                         }
33894
33895                                 }
33896
33897                                 for ( var i = 0; i < animations.length; i ++ ) {
33898
33899                                         var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones );
33900                                         if ( clip ) outputAnimations.push( clip );
33901
33902                                 }
33903
33904                                 // parse implicit morph animations
33905                                 if ( geometry.morphTargets ) {
33906
33907                                         // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
33908                                         var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
33909                                         outputAnimations = outputAnimations.concat( morphAnimationClips );
33910
33911                                 }
33912
33913                                 if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
33914
33915                         }
33916
33917                         return function ( json, texturePath ) {
33918
33919                                 if ( json.data !== undefined ) {
33920
33921                                         // Geometry 4.0 spec
33922                                         json = json.data;
33923
33924                                 }
33925
33926                                 if ( json.scale !== undefined ) {
33927
33928                                         json.scale = 1.0 / json.scale;
33929
33930                                 } else {
33931
33932                                         json.scale = 1.0;
33933
33934                                 }
33935
33936                                 var geometry = new Geometry();
33937
33938                                 parseModel( json, geometry );
33939                                 parseSkin( json, geometry );
33940                                 parseMorphing( json, geometry );
33941                                 parseAnimations( json, geometry );
33942
33943                                 geometry.computeFaceNormals();
33944                                 geometry.computeBoundingSphere();
33945
33946                                 if ( json.materials === undefined || json.materials.length === 0 ) {
33947
33948                                         return { geometry: geometry };
33949
33950                                 } else {
33951
33952                                         var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin );
33953
33954                                         return { geometry: geometry, materials: materials };
33955
33956                                 }
33957
33958                         };
33959
33960                 } )()
33961
33962         } );
33963
33964         /**
33965          * @author mrdoob / http://mrdoob.com/
33966          */
33967
33968         function ObjectLoader( manager ) {
33969
33970                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
33971                 this.texturePath = '';
33972
33973         }
33974
33975         Object.assign( ObjectLoader.prototype, {
33976
33977                 load: function ( url, onLoad, onProgress, onError ) {
33978
33979                         if ( this.texturePath === '' ) {
33980
33981                                 this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
33982
33983                         }
33984
33985                         var scope = this;
33986
33987                         var loader = new FileLoader( scope.manager );
33988                         loader.load( url, function ( text ) {
33989
33990                                 var json = null;
33991
33992                                 try {
33993
33994                                         json = JSON.parse( text );
33995
33996                                 } catch ( error ) {
33997
33998                                         if ( onError !== undefined ) onError( error );
33999
34000                                         console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
34001
34002                                         return;
34003
34004                                 }
34005
34006                                 var metadata = json.metadata;
34007
34008                                 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
34009
34010                                         console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' );
34011                                         return;
34012
34013                                 }
34014
34015                                 scope.parse( json, onLoad );
34016
34017                         }, onProgress, onError );
34018
34019                 },
34020
34021                 setTexturePath: function ( value ) {
34022
34023                         this.texturePath = value;
34024
34025                 },
34026
34027                 setCrossOrigin: function ( value ) {
34028
34029                         this.crossOrigin = value;
34030
34031                 },
34032
34033                 parse: function ( json, onLoad ) {
34034
34035                         var geometries = this.parseGeometries( json.geometries );
34036
34037                         var images = this.parseImages( json.images, function () {
34038
34039                                 if ( onLoad !== undefined ) onLoad( object );
34040
34041                         } );
34042
34043                         var textures = this.parseTextures( json.textures, images );
34044                         var materials = this.parseMaterials( json.materials, textures );
34045
34046                         var object = this.parseObject( json.object, geometries, materials );
34047
34048                         if ( json.animations ) {
34049
34050                                 object.animations = this.parseAnimations( json.animations );
34051
34052                         }
34053
34054                         if ( json.images === undefined || json.images.length === 0 ) {
34055
34056                                 if ( onLoad !== undefined ) onLoad( object );
34057
34058                         }
34059
34060                         return object;
34061
34062                 },
34063
34064                 parseGeometries: function ( json ) {
34065
34066                         var geometries = {};
34067
34068                         if ( json !== undefined ) {
34069
34070                                 var geometryLoader = new JSONLoader();
34071                                 var bufferGeometryLoader = new BufferGeometryLoader();
34072
34073                                 for ( var i = 0, l = json.length; i < l; i ++ ) {
34074
34075                                         var geometry;
34076                                         var data = json[ i ];
34077
34078                                         switch ( data.type ) {
34079
34080                                                 case 'PlaneGeometry':
34081                                                 case 'PlaneBufferGeometry':
34082
34083                                                         geometry = new Geometries[ data.type ](
34084                                                                 data.width,
34085                                                                 data.height,
34086                                                                 data.widthSegments,
34087                                                                 data.heightSegments
34088                                                         );
34089
34090                                                         break;
34091
34092                                                 case 'BoxGeometry':
34093                                                 case 'BoxBufferGeometry':
34094                                                 case 'CubeGeometry': // backwards compatible
34095
34096                                                         geometry = new Geometries[ data.type ](
34097                                                                 data.width,
34098                                                                 data.height,
34099                                                                 data.depth,
34100                                                                 data.widthSegments,
34101                                                                 data.heightSegments,
34102                                                                 data.depthSegments
34103                                                         );
34104
34105                                                         break;
34106
34107                                                 case 'CircleGeometry':
34108                                                 case 'CircleBufferGeometry':
34109
34110                                                         geometry = new Geometries[ data.type ](
34111                                                                 data.radius,
34112                                                                 data.segments,
34113                                                                 data.thetaStart,
34114                                                                 data.thetaLength
34115                                                         );
34116
34117                                                         break;
34118
34119                                                 case 'CylinderGeometry':
34120                                                 case 'CylinderBufferGeometry':
34121
34122                                                         geometry = new Geometries[ data.type ](
34123                                                                 data.radiusTop,
34124                                                                 data.radiusBottom,
34125                                                                 data.height,
34126                                                                 data.radialSegments,
34127                                                                 data.heightSegments,
34128                                                                 data.openEnded,
34129                                                                 data.thetaStart,
34130                                                                 data.thetaLength
34131                                                         );
34132
34133                                                         break;
34134
34135                                                 case 'ConeGeometry':
34136                                                 case 'ConeBufferGeometry':
34137
34138                                                         geometry = new Geometries[ data.type ](
34139                                                                 data.radius,
34140                                                                 data.height,
34141                                                                 data.radialSegments,
34142                                                                 data.heightSegments,
34143                                                                 data.openEnded,
34144                                                                 data.thetaStart,
34145                                                                 data.thetaLength
34146                                                         );
34147
34148                                                         break;
34149
34150                                                 case 'SphereGeometry':
34151                                                 case 'SphereBufferGeometry':
34152
34153                                                         geometry = new Geometries[ data.type ](
34154                                                                 data.radius,
34155                                                                 data.widthSegments,
34156                                                                 data.heightSegments,
34157                                                                 data.phiStart,
34158                                                                 data.phiLength,
34159                                                                 data.thetaStart,
34160                                                                 data.thetaLength
34161                                                         );
34162
34163                                                         break;
34164
34165                                                 case 'DodecahedronGeometry':
34166                                                 case 'IcosahedronGeometry':
34167                                                 case 'OctahedronGeometry':
34168                                                 case 'TetrahedronGeometry':
34169
34170                                                         geometry = new Geometries[ data.type ](
34171                                                                 data.radius,
34172                                                                 data.detail
34173                                                         );
34174
34175                                                         break;
34176
34177                                                 case 'RingGeometry':
34178                                                 case 'RingBufferGeometry':
34179
34180                                                         geometry = new Geometries[ data.type ](
34181                                                                 data.innerRadius,
34182                                                                 data.outerRadius,
34183                                                                 data.thetaSegments,
34184                                                                 data.phiSegments,
34185                                                                 data.thetaStart,
34186                                                                 data.thetaLength
34187                                                         );
34188
34189                                                         break;
34190
34191                                                 case 'TorusGeometry':
34192                                                 case 'TorusBufferGeometry':
34193
34194                                                         geometry = new Geometries[ data.type ](
34195                                                                 data.radius,
34196                                                                 data.tube,
34197                                                                 data.radialSegments,
34198                                                                 data.tubularSegments,
34199                                                                 data.arc
34200                                                         );
34201
34202                                                         break;
34203
34204                                                 case 'TorusKnotGeometry':
34205                                                 case 'TorusKnotBufferGeometry':
34206
34207                                                         geometry = new Geometries[ data.type ](
34208                                                                 data.radius,
34209                                                                 data.tube,
34210                                                                 data.tubularSegments,
34211                                                                 data.radialSegments,
34212                                                                 data.p,
34213                                                                 data.q
34214                                                         );
34215
34216                                                         break;
34217
34218                                                 case 'LatheGeometry':
34219                                                 case 'LatheBufferGeometry':
34220
34221                                                         geometry = new Geometries[ data.type ](
34222                                                                 data.points,
34223                                                                 data.segments,
34224                                                                 data.phiStart,
34225                                                                 data.phiLength
34226                                                         );
34227
34228                                                         break;
34229
34230                                                 case 'BufferGeometry':
34231
34232                                                         geometry = bufferGeometryLoader.parse( data );
34233
34234                                                         break;
34235
34236                                                 case 'Geometry':
34237
34238                                                         geometry = geometryLoader.parse( data, this.texturePath ).geometry;
34239
34240                                                         break;
34241
34242                                                 default:
34243
34244                                                         console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
34245
34246                                                         continue;
34247
34248                                         }
34249
34250                                         geometry.uuid = data.uuid;
34251
34252                                         if ( data.name !== undefined ) geometry.name = data.name;
34253
34254                                         geometries[ data.uuid ] = geometry;
34255
34256                                 }
34257
34258                         }
34259
34260                         return geometries;
34261
34262                 },
34263
34264                 parseMaterials: function ( json, textures ) {
34265
34266                         var materials = {};
34267
34268                         if ( json !== undefined ) {
34269
34270                                 var loader = new MaterialLoader();
34271                                 loader.setTextures( textures );
34272
34273                                 for ( var i = 0, l = json.length; i < l; i ++ ) {
34274
34275                                         var data = json[ i ];
34276
34277                                         if ( data.type === 'MultiMaterial' ) {
34278
34279                                                 // Deprecated
34280
34281                                                 var array = [];
34282
34283                                                 for ( var j = 0; j < data.materials.length; j ++ ) {
34284
34285                                                         array.push( loader.parse( data.materials[ j ] ) );
34286
34287                                                 }
34288
34289                                                 materials[ data.uuid ] = array;
34290
34291                                         } else {
34292
34293                                                 materials[ data.uuid ] = loader.parse( data );
34294
34295                                         }
34296
34297                                 }
34298
34299                         }
34300
34301                         return materials;
34302
34303                 },
34304
34305                 parseAnimations: function ( json ) {
34306
34307                         var animations = [];
34308
34309                         for ( var i = 0; i < json.length; i ++ ) {
34310
34311                                 var clip = AnimationClip.parse( json[ i ] );
34312
34313                                 animations.push( clip );
34314
34315                         }
34316
34317                         return animations;
34318
34319                 },
34320
34321                 parseImages: function ( json, onLoad ) {
34322
34323                         var scope = this;
34324                         var images = {};
34325
34326                         function loadImage( url ) {
34327
34328                                 scope.manager.itemStart( url );
34329
34330                                 return loader.load( url, function () {
34331
34332                                         scope.manager.itemEnd( url );
34333
34334                                 }, undefined, function () {
34335
34336                                         scope.manager.itemEnd( url );
34337                                         scope.manager.itemError( url );
34338
34339                                 } );
34340
34341                         }
34342
34343                         if ( json !== undefined && json.length > 0 ) {
34344
34345                                 var manager = new LoadingManager( onLoad );
34346
34347                                 var loader = new ImageLoader( manager );
34348                                 loader.setCrossOrigin( this.crossOrigin );
34349
34350                                 for ( var i = 0, l = json.length; i < l; i ++ ) {
34351
34352                                         var image = json[ i ];
34353                                         var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
34354
34355                                         images[ image.uuid ] = loadImage( path );
34356
34357                                 }
34358
34359                         }
34360
34361                         return images;
34362
34363                 },
34364
34365                 parseTextures: function ( json, images ) {
34366
34367                         function parseConstant( value, type ) {
34368
34369                                 if ( typeof( value ) === 'number' ) return value;
34370
34371                                 console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
34372
34373                                 return type[ value ];
34374
34375                         }
34376
34377                         var textures = {};
34378
34379                         if ( json !== undefined ) {
34380
34381                                 for ( var i = 0, l = json.length; i < l; i ++ ) {
34382
34383                                         var data = json[ i ];
34384
34385                                         if ( data.image === undefined ) {
34386
34387                                                 console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
34388
34389                                         }
34390
34391                                         if ( images[ data.image ] === undefined ) {
34392
34393                                                 console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
34394
34395                                         }
34396
34397                                         var texture = new Texture( images[ data.image ] );
34398                                         texture.needsUpdate = true;
34399
34400                                         texture.uuid = data.uuid;
34401
34402                                         if ( data.name !== undefined ) texture.name = data.name;
34403
34404                                         if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
34405
34406                                         if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
34407                                         if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
34408                                         if ( data.wrap !== undefined ) {
34409
34410                                                 texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
34411                                                 texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
34412
34413                                         }
34414
34415                                         if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
34416                                         if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
34417                                         if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
34418
34419                                         if ( data.flipY !== undefined ) texture.flipY = data.flipY;
34420
34421                                         textures[ data.uuid ] = texture;
34422
34423                                 }
34424
34425                         }
34426
34427                         return textures;
34428
34429                 },
34430
34431                 parseObject: function () {
34432
34433                         var matrix = new Matrix4();
34434
34435                         return function parseObject( data, geometries, materials ) {
34436
34437                                 var object;
34438
34439                                 function getGeometry( name ) {
34440
34441                                         if ( geometries[ name ] === undefined ) {
34442
34443                                                 console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
34444
34445                                         }
34446
34447                                         return geometries[ name ];
34448
34449                                 }
34450
34451                                 function getMaterial( name ) {
34452
34453                                         if ( name === undefined ) return undefined;
34454
34455                                         if ( Array.isArray( name ) ) {
34456
34457                                                 var array = [];
34458
34459                                                 for ( var i = 0, l = name.length; i < l; i ++ ) {
34460
34461                                                         var uuid = name[ i ];
34462
34463                                                         if ( materials[ uuid ] === undefined ) {
34464
34465                                                                 console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
34466
34467                                                         }
34468
34469                                                         array.push( materials[ uuid ] );
34470
34471                                                 }
34472
34473                                                 return array;
34474
34475                                         }
34476
34477                                         if ( materials[ name ] === undefined ) {
34478
34479                                                 console.warn( 'THREE.ObjectLoader: Undefined material', name );
34480
34481                                         }
34482
34483                                         return materials[ name ];
34484
34485                                 }
34486
34487                                 switch ( data.type ) {
34488
34489                                         case 'Scene':
34490
34491                                                 object = new Scene();
34492
34493                                                 if ( data.background !== undefined ) {
34494
34495                                                         if ( Number.isInteger( data.background ) ) {
34496
34497                                                                 object.background = new Color( data.background );
34498
34499                                                         }
34500
34501                                                 }
34502
34503                                                 if ( data.fog !== undefined ) {
34504
34505                                                         if ( data.fog.type === 'Fog' ) {
34506
34507                                                                 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
34508
34509                                                         } else if ( data.fog.type === 'FogExp2' ) {
34510
34511                                                                 object.fog = new FogExp2( data.fog.color, data.fog.density );
34512
34513                                                         }
34514
34515                                                 }
34516
34517                                                 break;
34518
34519                                         case 'PerspectiveCamera':
34520
34521                                                 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
34522
34523                                                 if ( data.focus !== undefined ) object.focus = data.focus;
34524                                                 if ( data.zoom !== undefined ) object.zoom = data.zoom;
34525                                                 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
34526                                                 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
34527                                                 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
34528
34529                                                 break;
34530
34531                                         case 'OrthographicCamera':
34532
34533                                                 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
34534
34535                                                 break;
34536
34537                                         case 'AmbientLight':
34538
34539                                                 object = new AmbientLight( data.color, data.intensity );
34540
34541                                                 break;
34542
34543                                         case 'DirectionalLight':
34544
34545                                                 object = new DirectionalLight( data.color, data.intensity );
34546
34547                                                 break;
34548
34549                                         case 'PointLight':
34550
34551                                                 object = new PointLight( data.color, data.intensity, data.distance, data.decay );
34552
34553                                                 break;
34554
34555                                         case 'RectAreaLight':
34556
34557                                                 object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
34558
34559                                                 break;
34560
34561                                         case 'SpotLight':
34562
34563                                                 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
34564
34565                                                 break;
34566
34567                                         case 'HemisphereLight':
34568
34569                                                 object = new HemisphereLight( data.color, data.groundColor, data.intensity );
34570
34571                                                 break;
34572
34573                                         case 'SkinnedMesh':
34574
34575                                                 console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' );
34576
34577                                         case 'Mesh':
34578
34579                                                 var geometry = getGeometry( data.geometry );
34580                                                 var material = getMaterial( data.material );
34581
34582                                                 if ( geometry.bones && geometry.bones.length > 0 ) {
34583
34584                                                         object = new SkinnedMesh( geometry, material );
34585
34586                                                 } else {
34587
34588                                                         object = new Mesh( geometry, material );
34589
34590                                                 }
34591
34592                                                 break;
34593
34594                                         case 'LOD':
34595
34596                                                 object = new LOD();
34597
34598                                                 break;
34599
34600                                         case 'Line':
34601
34602                                                 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
34603
34604                                                 break;
34605
34606                                         case 'LineLoop':
34607
34608                                                 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
34609
34610                                                 break;
34611
34612                                         case 'LineSegments':
34613
34614                                                 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
34615
34616                                                 break;
34617
34618                                         case 'PointCloud':
34619                                         case 'Points':
34620
34621                                                 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
34622
34623                                                 break;
34624
34625                                         case 'Sprite':
34626
34627                                                 object = new Sprite( getMaterial( data.material ) );
34628
34629                                                 break;
34630
34631                                         case 'Group':
34632
34633                                                 object = new Group();
34634
34635                                                 break;
34636
34637                                         default:
34638
34639                                                 object = new Object3D();
34640
34641                                 }
34642
34643                                 object.uuid = data.uuid;
34644
34645                                 if ( data.name !== undefined ) object.name = data.name;
34646                                 if ( data.matrix !== undefined ) {
34647
34648                                         matrix.fromArray( data.matrix );
34649                                         matrix.decompose( object.position, object.quaternion, object.scale );
34650
34651                                 } else {
34652
34653                                         if ( data.position !== undefined ) object.position.fromArray( data.position );
34654                                         if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
34655                                         if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
34656                                         if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
34657
34658                                 }
34659
34660                                 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
34661                                 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
34662
34663                                 if ( data.shadow ) {
34664
34665                                         if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
34666                                         if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
34667                                         if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
34668                                         if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
34669
34670                                 }
34671
34672                                 if ( data.visible !== undefined ) object.visible = data.visible;
34673                                 if ( data.userData !== undefined ) object.userData = data.userData;
34674
34675                                 if ( data.children !== undefined ) {
34676
34677                                         var children = data.children;
34678
34679                                         for ( var  i = 0; i < children.length; i ++ ) {
34680
34681                                                 object.add( this.parseObject( children[ i ], geometries, materials ) );
34682
34683                                         }
34684
34685                                 }
34686
34687                                 if ( data.type === 'LOD' ) {
34688
34689                                         var levels = data.levels;
34690
34691                                         for ( var l = 0; l < levels.length; l ++ ) {
34692
34693                                                 var level = levels[ l ];
34694                                                 var child = object.getObjectByProperty( 'uuid', level.object );
34695
34696                                                 if ( child !== undefined ) {
34697
34698                                                         object.addLevel( child, level.distance );
34699
34700                                                 }
34701
34702                                         }
34703
34704                                 }
34705
34706                                 return object;
34707
34708                         };
34709
34710                 }()
34711
34712         } );
34713
34714         var TEXTURE_MAPPING = {
34715                 UVMapping: UVMapping,
34716                 CubeReflectionMapping: CubeReflectionMapping,
34717                 CubeRefractionMapping: CubeRefractionMapping,
34718                 EquirectangularReflectionMapping: EquirectangularReflectionMapping,
34719                 EquirectangularRefractionMapping: EquirectangularRefractionMapping,
34720                 SphericalReflectionMapping: SphericalReflectionMapping,
34721                 CubeUVReflectionMapping: CubeUVReflectionMapping,
34722                 CubeUVRefractionMapping: CubeUVRefractionMapping
34723         };
34724
34725         var TEXTURE_WRAPPING = {
34726                 RepeatWrapping: RepeatWrapping,
34727                 ClampToEdgeWrapping: ClampToEdgeWrapping,
34728                 MirroredRepeatWrapping: MirroredRepeatWrapping
34729         };
34730
34731         var TEXTURE_FILTER = {
34732                 NearestFilter: NearestFilter,
34733                 NearestMipMapNearestFilter: NearestMipMapNearestFilter,
34734                 NearestMipMapLinearFilter: NearestMipMapLinearFilter,
34735                 LinearFilter: LinearFilter,
34736                 LinearMipMapNearestFilter: LinearMipMapNearestFilter,
34737                 LinearMipMapLinearFilter: LinearMipMapLinearFilter
34738         };
34739
34740         /**
34741          * @author zz85 / http://www.lab4games.net/zz85/blog
34742          *
34743          * Bezier Curves formulas obtained from
34744          * http://en.wikipedia.org/wiki/Bézier_curve
34745          */
34746
34747         function CatmullRom( t, p0, p1, p2, p3 ) {
34748
34749                 var v0 = ( p2 - p0 ) * 0.5;
34750                 var v1 = ( p3 - p1 ) * 0.5;
34751                 var t2 = t * t;
34752                 var t3 = t * t2;
34753                 return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
34754
34755         }
34756
34757         //
34758
34759         function QuadraticBezierP0( t, p ) {
34760
34761                 var k = 1 - t;
34762                 return k * k * p;
34763
34764         }
34765
34766         function QuadraticBezierP1( t, p ) {
34767
34768                 return 2 * ( 1 - t ) * t * p;
34769
34770         }
34771
34772         function QuadraticBezierP2( t, p ) {
34773
34774                 return t * t * p;
34775
34776         }
34777
34778         function QuadraticBezier( t, p0, p1, p2 ) {
34779
34780                 return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
34781                         QuadraticBezierP2( t, p2 );
34782
34783         }
34784
34785         //
34786
34787         function CubicBezierP0( t, p ) {
34788
34789                 var k = 1 - t;
34790                 return k * k * k * p;
34791
34792         }
34793
34794         function CubicBezierP1( t, p ) {
34795
34796                 var k = 1 - t;
34797                 return 3 * k * k * t * p;
34798
34799         }
34800
34801         function CubicBezierP2( t, p ) {
34802
34803                 return 3 * ( 1 - t ) * t * t * p;
34804
34805         }
34806
34807         function CubicBezierP3( t, p ) {
34808
34809                 return t * t * t * p;
34810
34811         }
34812
34813         function CubicBezier( t, p0, p1, p2, p3 ) {
34814
34815                 return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
34816                         CubicBezierP3( t, p3 );
34817
34818         }
34819
34820         /**
34821          * @author zz85 / http://www.lab4games.net/zz85/blog
34822          * Extensible curve object
34823          *
34824          * Some common of curve methods:
34825          * .getPoint(t), getTangent(t)
34826          * .getPointAt(u), getTangentAt(u)
34827          * .getPoints(), .getSpacedPoints()
34828          * .getLength()
34829          * .updateArcLengths()
34830          *
34831          * This following curves inherit from THREE.Curve:
34832          *
34833          * -- 2D curves --
34834          * THREE.ArcCurve
34835          * THREE.CubicBezierCurve
34836          * THREE.EllipseCurve
34837          * THREE.LineCurve
34838          * THREE.QuadraticBezierCurve
34839          * THREE.SplineCurve
34840          *
34841          * -- 3D curves --
34842          * THREE.CatmullRomCurve3
34843          * THREE.CubicBezierCurve3
34844          * THREE.LineCurve3
34845          * THREE.QuadraticBezierCurve3
34846          *
34847          * A series of curves can be represented as a THREE.CurvePath.
34848          *
34849          **/
34850
34851         /**************************************************************
34852          *      Abstract Curve base class
34853          **************************************************************/
34854
34855         function Curve() {
34856
34857                 this.arcLengthDivisions = 200;
34858
34859         }
34860
34861         Object.assign( Curve.prototype, {
34862
34863                 // Virtual base class method to overwrite and implement in subclasses
34864                 //      - t [0 .. 1]
34865
34866                 getPoint: function () {
34867
34868                         console.warn( 'THREE.Curve: .getPoint() not implemented.' );
34869                         return null;
34870
34871                 },
34872
34873                 // Get point at relative position in curve according to arc length
34874                 // - u [0 .. 1]
34875
34876                 getPointAt: function ( u ) {
34877
34878                         var t = this.getUtoTmapping( u );
34879                         return this.getPoint( t );
34880
34881                 },
34882
34883                 // Get sequence of points using getPoint( t )
34884
34885                 getPoints: function ( divisions ) {
34886
34887                         if ( divisions === undefined ) divisions = 5;
34888
34889                         var points = [];
34890
34891                         for ( var d = 0; d <= divisions; d ++ ) {
34892
34893                                 points.push( this.getPoint( d / divisions ) );
34894
34895                         }
34896
34897                         return points;
34898
34899                 },
34900
34901                 // Get sequence of points using getPointAt( u )
34902
34903                 getSpacedPoints: function ( divisions ) {
34904
34905                         if ( divisions === undefined ) divisions = 5;
34906
34907                         var points = [];
34908
34909                         for ( var d = 0; d <= divisions; d ++ ) {
34910
34911                                 points.push( this.getPointAt( d / divisions ) );
34912
34913                         }
34914
34915                         return points;
34916
34917                 },
34918
34919                 // Get total curve arc length
34920
34921                 getLength: function () {
34922
34923                         var lengths = this.getLengths();
34924                         return lengths[ lengths.length - 1 ];
34925
34926                 },
34927
34928                 // Get list of cumulative segment lengths
34929
34930                 getLengths: function ( divisions ) {
34931
34932                         if ( divisions === undefined ) divisions = this.arcLengthDivisions;
34933
34934                         if ( this.cacheArcLengths &&
34935                                 ( this.cacheArcLengths.length === divisions + 1 ) &&
34936                                 ! this.needsUpdate ) {
34937
34938                                 return this.cacheArcLengths;
34939
34940                         }
34941
34942                         this.needsUpdate = false;
34943
34944                         var cache = [];
34945                         var current, last = this.getPoint( 0 );
34946                         var p, sum = 0;
34947
34948                         cache.push( 0 );
34949
34950                         for ( p = 1; p <= divisions; p ++ ) {
34951
34952                                 current = this.getPoint( p / divisions );
34953                                 sum += current.distanceTo( last );
34954                                 cache.push( sum );
34955                                 last = current;
34956
34957                         }
34958
34959                         this.cacheArcLengths = cache;
34960
34961                         return cache; // { sums: cache, sum: sum }; Sum is in the last element.
34962
34963                 },
34964
34965                 updateArcLengths: function () {
34966
34967                         this.needsUpdate = true;
34968                         this.getLengths();
34969
34970                 },
34971
34972                 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
34973
34974                 getUtoTmapping: function ( u, distance ) {
34975
34976                         var arcLengths = this.getLengths();
34977
34978                         var i = 0, il = arcLengths.length;
34979
34980                         var targetArcLength; // The targeted u distance value to get
34981
34982                         if ( distance ) {
34983
34984                                 targetArcLength = distance;
34985
34986                         } else {
34987
34988                                 targetArcLength = u * arcLengths[ il - 1 ];
34989
34990                         }
34991
34992                         // binary search for the index with largest value smaller than target u distance
34993
34994                         var low = 0, high = il - 1, comparison;
34995
34996                         while ( low <= high ) {
34997
34998                                 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
34999
35000                                 comparison = arcLengths[ i ] - targetArcLength;
35001
35002                                 if ( comparison < 0 ) {
35003
35004                                         low = i + 1;
35005
35006                                 } else if ( comparison > 0 ) {
35007
35008                                         high = i - 1;
35009
35010                                 } else {
35011
35012                                         high = i;
35013                                         break;
35014
35015                                         // DONE
35016
35017                                 }
35018
35019                         }
35020
35021                         i = high;
35022
35023                         if ( arcLengths[ i ] === targetArcLength ) {
35024
35025                                 return i / ( il - 1 );
35026
35027                         }
35028
35029                         // we could get finer grain at lengths, or use simple interpolation between two points
35030
35031                         var lengthBefore = arcLengths[ i ];
35032                         var lengthAfter = arcLengths[ i + 1 ];
35033
35034                         var segmentLength = lengthAfter - lengthBefore;
35035
35036                         // determine where we are between the 'before' and 'after' points
35037
35038                         var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
35039
35040                         // add that fractional amount to t
35041
35042                         var t = ( i + segmentFraction ) / ( il - 1 );
35043
35044                         return t;
35045
35046                 },
35047
35048                 // Returns a unit vector tangent at t
35049                 // In case any sub curve does not implement its tangent derivation,
35050                 // 2 points a small delta apart will be used to find its gradient
35051                 // which seems to give a reasonable approximation
35052
35053                 getTangent: function ( t ) {
35054
35055                         var delta = 0.0001;
35056                         var t1 = t - delta;
35057                         var t2 = t + delta;
35058
35059                         // Capping in case of danger
35060
35061                         if ( t1 < 0 ) t1 = 0;
35062                         if ( t2 > 1 ) t2 = 1;
35063
35064                         var pt1 = this.getPoint( t1 );
35065                         var pt2 = this.getPoint( t2 );
35066
35067                         var vec = pt2.clone().sub( pt1 );
35068                         return vec.normalize();
35069
35070                 },
35071
35072                 getTangentAt: function ( u ) {
35073
35074                         var t = this.getUtoTmapping( u );
35075                         return this.getTangent( t );
35076
35077                 },
35078
35079                 computeFrenetFrames: function ( segments, closed ) {
35080
35081                         // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
35082
35083                         var normal = new Vector3();
35084
35085                         var tangents = [];
35086                         var normals = [];
35087                         var binormals = [];
35088
35089                         var vec = new Vector3();
35090                         var mat = new Matrix4();
35091
35092                         var i, u, theta;
35093
35094                         // compute the tangent vectors for each segment on the curve
35095
35096                         for ( i = 0; i <= segments; i ++ ) {
35097
35098                                 u = i / segments;
35099
35100                                 tangents[ i ] = this.getTangentAt( u );
35101                                 tangents[ i ].normalize();
35102
35103                         }
35104
35105                         // select an initial normal vector perpendicular to the first tangent vector,
35106                         // and in the direction of the minimum tangent xyz component
35107
35108                         normals[ 0 ] = new Vector3();
35109                         binormals[ 0 ] = new Vector3();
35110                         var min = Number.MAX_VALUE;
35111                         var tx = Math.abs( tangents[ 0 ].x );
35112                         var ty = Math.abs( tangents[ 0 ].y );
35113                         var tz = Math.abs( tangents[ 0 ].z );
35114
35115                         if ( tx <= min ) {
35116
35117                                 min = tx;
35118                                 normal.set( 1, 0, 0 );
35119
35120                         }
35121
35122                         if ( ty <= min ) {
35123
35124                                 min = ty;
35125                                 normal.set( 0, 1, 0 );
35126
35127                         }
35128
35129                         if ( tz <= min ) {
35130
35131                                 normal.set( 0, 0, 1 );
35132
35133                         }
35134
35135                         vec.crossVectors( tangents[ 0 ], normal ).normalize();
35136
35137                         normals[ 0 ].crossVectors( tangents[ 0 ], vec );
35138                         binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
35139
35140
35141                         // compute the slowly-varying normal and binormal vectors for each segment on the curve
35142
35143                         for ( i = 1; i <= segments; i ++ ) {
35144
35145                                 normals[ i ] = normals[ i - 1 ].clone();
35146
35147                                 binormals[ i ] = binormals[ i - 1 ].clone();
35148
35149                                 vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
35150
35151                                 if ( vec.length() > Number.EPSILON ) {
35152
35153                                         vec.normalize();
35154
35155                                         theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
35156
35157                                         normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
35158
35159                                 }
35160
35161                                 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
35162
35163                         }
35164
35165                         // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
35166
35167                         if ( closed === true ) {
35168
35169                                 theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
35170                                 theta /= segments;
35171
35172                                 if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
35173
35174                                         theta = - theta;
35175
35176                                 }
35177
35178                                 for ( i = 1; i <= segments; i ++ ) {
35179
35180                                         // twist a little...
35181                                         normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
35182                                         binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
35183
35184                                 }
35185
35186                         }
35187
35188                         return {
35189                                 tangents: tangents,
35190                                 normals: normals,
35191                                 binormals: binormals
35192                         };
35193
35194                 }
35195
35196         } );
35197
35198         function LineCurve( v1, v2 ) {
35199
35200                 Curve.call( this );
35201
35202                 this.v1 = v1;
35203                 this.v2 = v2;
35204
35205         }
35206
35207         LineCurve.prototype = Object.create( Curve.prototype );
35208         LineCurve.prototype.constructor = LineCurve;
35209
35210         LineCurve.prototype.isLineCurve = true;
35211
35212         LineCurve.prototype.getPoint = function ( t ) {
35213
35214                 if ( t === 1 ) {
35215
35216                         return this.v2.clone();
35217
35218                 }
35219
35220                 var point = this.v2.clone().sub( this.v1 );
35221                 point.multiplyScalar( t ).add( this.v1 );
35222
35223                 return point;
35224
35225         };
35226
35227         // Line curve is linear, so we can overwrite default getPointAt
35228
35229         LineCurve.prototype.getPointAt = function ( u ) {
35230
35231                 return this.getPoint( u );
35232
35233         };
35234
35235         LineCurve.prototype.getTangent = function ( t ) {
35236
35237                 var tangent = this.v2.clone().sub( this.v1 );
35238
35239                 return tangent.normalize();
35240
35241         };
35242
35243         /**
35244          * @author zz85 / http://www.lab4games.net/zz85/blog
35245          *
35246          **/
35247
35248         /**************************************************************
35249          *      Curved Path - a curve path is simply a array of connected
35250          *  curves, but retains the api of a curve
35251          **************************************************************/
35252
35253         function CurvePath() {
35254
35255                 Curve.call( this );
35256
35257                 this.curves = [];
35258
35259                 this.autoClose = false; // Automatically closes the path
35260
35261         }
35262
35263         CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
35264
35265                 constructor: CurvePath,
35266
35267                 add: function ( curve ) {
35268
35269                         this.curves.push( curve );
35270
35271                 },
35272
35273                 closePath: function () {
35274
35275                         // Add a line curve if start and end of lines are not connected
35276                         var startPoint = this.curves[ 0 ].getPoint( 0 );
35277                         var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
35278
35279                         if ( ! startPoint.equals( endPoint ) ) {
35280
35281                                 this.curves.push( new LineCurve( endPoint, startPoint ) );
35282
35283                         }
35284
35285                 },
35286
35287                 // To get accurate point with reference to
35288                 // entire path distance at time t,
35289                 // following has to be done:
35290
35291                 // 1. Length of each sub path have to be known
35292                 // 2. Locate and identify type of curve
35293                 // 3. Get t for the curve
35294                 // 4. Return curve.getPointAt(t')
35295
35296                 getPoint: function ( t ) {
35297
35298                         var d = t * this.getLength();
35299                         var curveLengths = this.getCurveLengths();
35300                         var i = 0;
35301
35302                         // To think about boundaries points.
35303
35304                         while ( i < curveLengths.length ) {
35305
35306                                 if ( curveLengths[ i ] >= d ) {
35307
35308                                         var diff = curveLengths[ i ] - d;
35309                                         var curve = this.curves[ i ];
35310
35311                                         var segmentLength = curve.getLength();
35312                                         var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
35313
35314                                         return curve.getPointAt( u );
35315
35316                                 }
35317
35318                                 i ++;
35319
35320                         }
35321
35322                         return null;
35323
35324                         // loop where sum != 0, sum > d , sum+1 <d
35325
35326                 },
35327
35328                 // We cannot use the default THREE.Curve getPoint() with getLength() because in
35329                 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
35330                 // getPoint() depends on getLength
35331
35332                 getLength: function () {
35333
35334                         var lens = this.getCurveLengths();
35335                         return lens[ lens.length - 1 ];
35336
35337                 },
35338
35339                 // cacheLengths must be recalculated.
35340                 updateArcLengths: function () {
35341
35342                         this.needsUpdate = true;
35343                         this.cacheLengths = null;
35344                         this.getCurveLengths();
35345
35346                 },
35347
35348                 // Compute lengths and cache them
35349                 // We cannot overwrite getLengths() because UtoT mapping uses it.
35350
35351                 getCurveLengths: function () {
35352
35353                         // We use cache values if curves and cache array are same length
35354
35355                         if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
35356
35357                                 return this.cacheLengths;
35358
35359                         }
35360
35361                         // Get length of sub-curve
35362                         // Push sums into cached array
35363
35364                         var lengths = [], sums = 0;
35365
35366                         for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
35367
35368                                 sums += this.curves[ i ].getLength();
35369                                 lengths.push( sums );
35370
35371                         }
35372
35373                         this.cacheLengths = lengths;
35374
35375                         return lengths;
35376
35377                 },
35378
35379                 getSpacedPoints: function ( divisions ) {
35380
35381                         if ( divisions === undefined ) divisions = 40;
35382
35383                         var points = [];
35384
35385                         for ( var i = 0; i <= divisions; i ++ ) {
35386
35387                                 points.push( this.getPoint( i / divisions ) );
35388
35389                         }
35390
35391                         if ( this.autoClose ) {
35392
35393                                 points.push( points[ 0 ] );
35394
35395                         }
35396
35397                         return points;
35398
35399                 },
35400
35401                 getPoints: function ( divisions ) {
35402
35403                         divisions = divisions || 12;
35404
35405                         var points = [], last;
35406
35407                         for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) {
35408
35409                                 var curve = curves[ i ];
35410                                 var resolution = (curve && curve.isEllipseCurve) ? divisions * 2
35411                                         : (curve && curve.isLineCurve) ? 1
35412                                         : (curve && curve.isSplineCurve) ? divisions * curve.points.length
35413                                         : divisions;
35414
35415                                 var pts = curve.getPoints( resolution );
35416
35417                                 for ( var j = 0; j < pts.length; j++ ) {
35418
35419                                         var point = pts[ j ];
35420
35421                                         if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
35422
35423                                         points.push( point );
35424                                         last = point;
35425
35426                                 }
35427
35428                         }
35429
35430                         if ( this.autoClose && points.length > 1 && !points[ points.length - 1 ].equals( points[ 0 ] ) ) {
35431
35432                                 points.push( points[ 0 ] );
35433
35434                         }
35435
35436                         return points;
35437
35438                 },
35439
35440                 /**************************************************************
35441                  *      Create Geometries Helpers
35442                  **************************************************************/
35443
35444                 /// Generate geometry from path points (for Line or Points objects)
35445
35446                 createPointsGeometry: function ( divisions ) {
35447
35448                         var pts = this.getPoints( divisions );
35449                         return this.createGeometry( pts );
35450
35451                 },
35452
35453                 // Generate geometry from equidistant sampling along the path
35454
35455                 createSpacedPointsGeometry: function ( divisions ) {
35456
35457                         var pts = this.getSpacedPoints( divisions );
35458                         return this.createGeometry( pts );
35459
35460                 },
35461
35462                 createGeometry: function ( points ) {
35463
35464                         var geometry = new Geometry();
35465
35466                         for ( var i = 0, l = points.length; i < l; i ++ ) {
35467
35468                                 var point = points[ i ];
35469                                 geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
35470
35471                         }
35472
35473                         return geometry;
35474
35475                 }
35476
35477         } );
35478
35479         function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
35480
35481                 Curve.call( this );
35482
35483                 this.aX = aX;
35484                 this.aY = aY;
35485
35486                 this.xRadius = xRadius;
35487                 this.yRadius = yRadius;
35488
35489                 this.aStartAngle = aStartAngle;
35490                 this.aEndAngle = aEndAngle;
35491
35492                 this.aClockwise = aClockwise;
35493
35494                 this.aRotation = aRotation || 0;
35495
35496         }
35497
35498         EllipseCurve.prototype = Object.create( Curve.prototype );
35499         EllipseCurve.prototype.constructor = EllipseCurve;
35500
35501         EllipseCurve.prototype.isEllipseCurve = true;
35502
35503         EllipseCurve.prototype.getPoint = function ( t ) {
35504
35505                 var twoPi = Math.PI * 2;
35506                 var deltaAngle = this.aEndAngle - this.aStartAngle;
35507                 var samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
35508
35509                 // ensures that deltaAngle is 0 .. 2 PI
35510                 while ( deltaAngle < 0 ) deltaAngle += twoPi;
35511                 while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
35512
35513                 if ( deltaAngle < Number.EPSILON ) {
35514
35515                         if ( samePoints ) {
35516
35517                                 deltaAngle = 0;
35518
35519                         } else {
35520
35521                                 deltaAngle = twoPi;
35522
35523                         }
35524
35525                 }
35526
35527                 if ( this.aClockwise === true && ! samePoints ) {
35528
35529                         if ( deltaAngle === twoPi ) {
35530
35531                                 deltaAngle = - twoPi;
35532
35533                         } else {
35534
35535                                 deltaAngle = deltaAngle - twoPi;
35536
35537                         }
35538
35539                 }
35540
35541                 var angle = this.aStartAngle + t * deltaAngle;
35542                 var x = this.aX + this.xRadius * Math.cos( angle );
35543                 var y = this.aY + this.yRadius * Math.sin( angle );
35544
35545                 if ( this.aRotation !== 0 ) {
35546
35547                         var cos = Math.cos( this.aRotation );
35548                         var sin = Math.sin( this.aRotation );
35549
35550                         var tx = x - this.aX;
35551                         var ty = y - this.aY;
35552
35553                         // Rotate the point about the center of the ellipse.
35554                         x = tx * cos - ty * sin + this.aX;
35555                         y = tx * sin + ty * cos + this.aY;
35556
35557                 }
35558
35559                 return new Vector2( x, y );
35560
35561         };
35562
35563         function SplineCurve( points /* array of Vector2 */ ) {
35564
35565                 Curve.call( this );
35566
35567                 this.points = ( points === undefined ) ? [] : points;
35568
35569         }
35570
35571         SplineCurve.prototype = Object.create( Curve.prototype );
35572         SplineCurve.prototype.constructor = SplineCurve;
35573
35574         SplineCurve.prototype.isSplineCurve = true;
35575
35576         SplineCurve.prototype.getPoint = function ( t ) {
35577
35578                 var points = this.points;
35579                 var point = ( points.length - 1 ) * t;
35580
35581                 var intPoint = Math.floor( point );
35582                 var weight = point - intPoint;
35583
35584                 var point0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
35585                 var point1 = points[ intPoint ];
35586                 var point2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
35587                 var point3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
35588
35589                 return new Vector2(
35590                         CatmullRom( weight, point0.x, point1.x, point2.x, point3.x ),
35591                         CatmullRom( weight, point0.y, point1.y, point2.y, point3.y )
35592                 );
35593
35594         };
35595
35596         function CubicBezierCurve( v0, v1, v2, v3 ) {
35597
35598                 Curve.call( this );
35599
35600                 this.v0 = v0;
35601                 this.v1 = v1;
35602                 this.v2 = v2;
35603                 this.v3 = v3;
35604
35605         }
35606
35607         CubicBezierCurve.prototype = Object.create( Curve.prototype );
35608         CubicBezierCurve.prototype.constructor = CubicBezierCurve;
35609
35610         CubicBezierCurve.prototype.getPoint = function ( t ) {
35611
35612                 var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
35613
35614                 return new Vector2(
35615                         CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
35616                         CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
35617                 );
35618
35619         };
35620
35621         function QuadraticBezierCurve( v0, v1, v2 ) {
35622
35623                 Curve.call( this );
35624
35625                 this.v0 = v0;
35626                 this.v1 = v1;
35627                 this.v2 = v2;
35628
35629         }
35630
35631         QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
35632         QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
35633
35634         QuadraticBezierCurve.prototype.getPoint = function ( t ) {
35635
35636                 var v0 = this.v0, v1 = this.v1, v2 = this.v2;
35637
35638                 return new Vector2(
35639                         QuadraticBezier( t, v0.x, v1.x, v2.x ),
35640                         QuadraticBezier( t, v0.y, v1.y, v2.y )
35641                 );
35642
35643         };
35644
35645         var PathPrototype = Object.assign( Object.create( CurvePath.prototype ), {
35646
35647                 fromPoints: function ( vectors ) {
35648
35649                         this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
35650
35651                         for ( var i = 1, l = vectors.length; i < l; i ++ ) {
35652
35653                                 this.lineTo( vectors[ i ].x, vectors[ i ].y );
35654
35655                         }
35656
35657                 },
35658
35659                 moveTo: function ( x, y ) {
35660
35661                         this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
35662
35663                 },
35664
35665                 lineTo: function ( x, y ) {
35666
35667                         var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
35668                         this.curves.push( curve );
35669
35670                         this.currentPoint.set( x, y );
35671
35672                 },
35673
35674                 quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
35675
35676                         var curve = new QuadraticBezierCurve(
35677                                 this.currentPoint.clone(),
35678                                 new Vector2( aCPx, aCPy ),
35679                                 new Vector2( aX, aY )
35680                         );
35681
35682                         this.curves.push( curve );
35683
35684                         this.currentPoint.set( aX, aY );
35685
35686                 },
35687
35688                 bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
35689
35690                         var curve = new CubicBezierCurve(
35691                                 this.currentPoint.clone(),
35692                                 new Vector2( aCP1x, aCP1y ),
35693                                 new Vector2( aCP2x, aCP2y ),
35694                                 new Vector2( aX, aY )
35695                         );
35696
35697                         this.curves.push( curve );
35698
35699                         this.currentPoint.set( aX, aY );
35700
35701                 },
35702
35703                 splineThru: function ( pts /*Array of Vector*/ ) {
35704
35705                         var npts = [ this.currentPoint.clone() ].concat( pts );
35706
35707                         var curve = new SplineCurve( npts );
35708                         this.curves.push( curve );
35709
35710                         this.currentPoint.copy( pts[ pts.length - 1 ] );
35711
35712                 },
35713
35714                 arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
35715
35716                         var x0 = this.currentPoint.x;
35717                         var y0 = this.currentPoint.y;
35718
35719                         this.absarc( aX + x0, aY + y0, aRadius,
35720                                 aStartAngle, aEndAngle, aClockwise );
35721
35722                 },
35723
35724                 absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
35725
35726                         this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
35727
35728                 },
35729
35730                 ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
35731
35732                         var x0 = this.currentPoint.x;
35733                         var y0 = this.currentPoint.y;
35734
35735                         this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
35736
35737                 },
35738
35739                 absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
35740
35741                         var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
35742
35743                         if ( this.curves.length > 0 ) {
35744
35745                                 // if a previous curve is present, attempt to join
35746                                 var firstPoint = curve.getPoint( 0 );
35747
35748                                 if ( ! firstPoint.equals( this.currentPoint ) ) {
35749
35750                                         this.lineTo( firstPoint.x, firstPoint.y );
35751
35752                                 }
35753
35754                         }
35755
35756                         this.curves.push( curve );
35757
35758                         var lastPoint = curve.getPoint( 1 );
35759                         this.currentPoint.copy( lastPoint );
35760
35761                 }
35762
35763         } );
35764
35765         /**
35766          * @author zz85 / http://www.lab4games.net/zz85/blog
35767          * Creates free form 2d path using series of points, lines or curves.
35768          **/
35769
35770         function Path( points ) {
35771
35772                 CurvePath.call( this );
35773                 this.currentPoint = new Vector2();
35774
35775                 if ( points ) {
35776
35777                         this.fromPoints( points );
35778
35779                 }
35780
35781         }
35782
35783         Path.prototype = PathPrototype;
35784         PathPrototype.constructor = Path;
35785
35786         /**
35787          * @author zz85 / http://www.lab4games.net/zz85/blog
35788          * Defines a 2d shape plane using paths.
35789          **/
35790
35791         // STEP 1 Create a path.
35792         // STEP 2 Turn path into shape.
35793         // STEP 3 ExtrudeGeometry takes in Shape/Shapes
35794         // STEP 3a - Extract points from each shape, turn to vertices
35795         // STEP 3b - Triangulate each shape, add faces.
35796
35797         function Shape() {
35798
35799                 Path.apply( this, arguments );
35800
35801                 this.holes = [];
35802
35803         }
35804
35805         Shape.prototype = Object.assign( Object.create( PathPrototype ), {
35806
35807                 constructor: Shape,
35808
35809                 getPointsHoles: function ( divisions ) {
35810
35811                         var holesPts = [];
35812
35813                         for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
35814
35815                                 holesPts[ i ] = this.holes[ i ].getPoints( divisions );
35816
35817                         }
35818
35819                         return holesPts;
35820
35821                 },
35822
35823                 // Get points of shape and holes (keypoints based on segments parameter)
35824
35825                 extractAllPoints: function ( divisions ) {
35826
35827                         return {
35828
35829                                 shape: this.getPoints( divisions ),
35830                                 holes: this.getPointsHoles( divisions )
35831
35832                         };
35833
35834                 },
35835
35836                 extractPoints: function ( divisions ) {
35837
35838                         return this.extractAllPoints( divisions );
35839
35840                 }
35841
35842         } );
35843
35844         /**
35845          * @author zz85 / http://www.lab4games.net/zz85/blog
35846          * minimal class for proxing functions to Path. Replaces old "extractSubpaths()"
35847          **/
35848
35849         function ShapePath() {
35850
35851                 this.subPaths = [];
35852                 this.currentPath = null;
35853
35854         }
35855
35856         Object.assign( ShapePath.prototype, {
35857
35858                 moveTo: function ( x, y ) {
35859
35860                         this.currentPath = new Path();
35861                         this.subPaths.push( this.currentPath );
35862                         this.currentPath.moveTo( x, y );
35863
35864                 },
35865
35866                 lineTo: function ( x, y ) {
35867
35868                         this.currentPath.lineTo( x, y );
35869
35870                 },
35871
35872                 quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
35873
35874                         this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
35875
35876                 },
35877
35878                 bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
35879
35880                         this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
35881
35882                 },
35883
35884                 splineThru: function ( pts ) {
35885
35886                         this.currentPath.splineThru( pts );
35887
35888                 },
35889
35890                 toShapes: function ( isCCW, noHoles ) {
35891
35892                         function toShapesNoHoles( inSubpaths ) {
35893
35894                                 var shapes = [];
35895
35896                                 for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
35897
35898                                         var tmpPath = inSubpaths[ i ];
35899
35900                                         var tmpShape = new Shape();
35901                                         tmpShape.curves = tmpPath.curves;
35902
35903                                         shapes.push( tmpShape );
35904
35905                                 }
35906
35907                                 return shapes;
35908
35909                         }
35910
35911                         function isPointInsidePolygon( inPt, inPolygon ) {
35912
35913                                 var polyLen = inPolygon.length;
35914
35915                                 // inPt on polygon contour => immediate success    or
35916                                 // toggling of inside/outside at every single! intersection point of an edge
35917                                 //  with the horizontal line through inPt, left of inPt
35918                                 //  not counting lowerY endpoints of edges and whole edges on that line
35919                                 var inside = false;
35920                                 for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
35921
35922                                         var edgeLowPt  = inPolygon[ p ];
35923                                         var edgeHighPt = inPolygon[ q ];
35924
35925                                         var edgeDx = edgeHighPt.x - edgeLowPt.x;
35926                                         var edgeDy = edgeHighPt.y - edgeLowPt.y;
35927
35928                                         if ( Math.abs( edgeDy ) > Number.EPSILON ) {
35929
35930                                                 // not parallel
35931                                                 if ( edgeDy < 0 ) {
35932
35933                                                         edgeLowPt  = inPolygon[ q ]; edgeDx = - edgeDx;
35934                                                         edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
35935
35936                                                 }
35937                                                 if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) )            continue;
35938
35939                                                 if ( inPt.y === edgeLowPt.y ) {
35940
35941                                                         if ( inPt.x === edgeLowPt.x )           return  true;           // inPt is on contour ?
35942                                                         // continue;                            // no intersection or edgeLowPt => doesn't count !!!
35943
35944                                                 } else {
35945
35946                                                         var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
35947                                                         if ( perpEdge === 0 )                           return  true;           // inPt is on contour ?
35948                                                         if ( perpEdge < 0 )                             continue;
35949                                                         inside = ! inside;              // true intersection left of inPt
35950
35951                                                 }
35952
35953                                         } else {
35954
35955                                                 // parallel or collinear
35956                                                 if ( inPt.y !== edgeLowPt.y )           continue;                       // parallel
35957                                                 // edge lies on the same horizontal line as inPt
35958                                                 if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
35959                                                          ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )          return  true;   // inPt: Point on contour !
35960                                                 // continue;
35961
35962                                         }
35963
35964                                 }
35965
35966                                 return  inside;
35967
35968                         }
35969
35970                         var isClockWise = ShapeUtils.isClockWise;
35971
35972                         var subPaths = this.subPaths;
35973                         if ( subPaths.length === 0 ) return [];
35974
35975                         if ( noHoles === true ) return  toShapesNoHoles( subPaths );
35976
35977
35978                         var solid, tmpPath, tmpShape, shapes = [];
35979
35980                         if ( subPaths.length === 1 ) {
35981
35982                                 tmpPath = subPaths[ 0 ];
35983                                 tmpShape = new Shape();
35984                                 tmpShape.curves = tmpPath.curves;
35985                                 shapes.push( tmpShape );
35986                                 return shapes;
35987
35988                         }
35989
35990                         var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
35991                         holesFirst = isCCW ? ! holesFirst : holesFirst;
35992
35993                         // console.log("Holes first", holesFirst);
35994
35995                         var betterShapeHoles = [];
35996                         var newShapes = [];
35997                         var newShapeHoles = [];
35998                         var mainIdx = 0;
35999                         var tmpPoints;
36000
36001                         newShapes[ mainIdx ] = undefined;
36002                         newShapeHoles[ mainIdx ] = [];
36003
36004                         for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
36005
36006                                 tmpPath = subPaths[ i ];
36007                                 tmpPoints = tmpPath.getPoints();
36008                                 solid = isClockWise( tmpPoints );
36009                                 solid = isCCW ? ! solid : solid;
36010
36011                                 if ( solid ) {
36012
36013                                         if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )     mainIdx ++;
36014
36015                                         newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
36016                                         newShapes[ mainIdx ].s.curves = tmpPath.curves;
36017
36018                                         if ( holesFirst )       mainIdx ++;
36019                                         newShapeHoles[ mainIdx ] = [];
36020
36021                                         //console.log('cw', i);
36022
36023                                 } else {
36024
36025                                         newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
36026
36027                                         //console.log('ccw', i);
36028
36029                                 }
36030
36031                         }
36032
36033                         // only Holes? -> probably all Shapes with wrong orientation
36034                         if ( ! newShapes[ 0 ] ) return  toShapesNoHoles( subPaths );
36035
36036
36037                         if ( newShapes.length > 1 ) {
36038
36039                                 var ambiguous = false;
36040                                 var toChange = [];
36041
36042                                 for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
36043
36044                                         betterShapeHoles[ sIdx ] = [];
36045
36046                                 }
36047
36048                                 for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
36049
36050                                         var sho = newShapeHoles[ sIdx ];
36051
36052                                         for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
36053
36054                                                 var ho = sho[ hIdx ];
36055                                                 var hole_unassigned = true;
36056
36057                                                 for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
36058
36059                                                         if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
36060
36061                                                                 if ( sIdx !== s2Idx )   toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
36062                                                                 if ( hole_unassigned ) {
36063
36064                                                                         hole_unassigned = false;
36065                                                                         betterShapeHoles[ s2Idx ].push( ho );
36066
36067                                                                 } else {
36068
36069                                                                         ambiguous = true;
36070
36071                                                                 }
36072
36073                                                         }
36074
36075                                                 }
36076                                                 if ( hole_unassigned ) {
36077
36078                                                         betterShapeHoles[ sIdx ].push( ho );
36079
36080                                                 }
36081
36082                                         }
36083
36084                                 }
36085                                 // console.log("ambiguous: ", ambiguous);
36086                                 if ( toChange.length > 0 ) {
36087
36088                                         // console.log("to change: ", toChange);
36089                                         if ( ! ambiguous )      newShapeHoles = betterShapeHoles;
36090
36091                                 }
36092
36093                         }
36094
36095                         var tmpHoles;
36096
36097                         for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
36098
36099                                 tmpShape = newShapes[ i ].s;
36100                                 shapes.push( tmpShape );
36101                                 tmpHoles = newShapeHoles[ i ];
36102
36103                                 for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
36104
36105                                         tmpShape.holes.push( tmpHoles[ j ].h );
36106
36107                                 }
36108
36109                         }
36110
36111                         //console.log("shape", shapes);
36112
36113                         return shapes;
36114
36115                 }
36116
36117         } );
36118
36119         /**
36120          * @author zz85 / http://www.lab4games.net/zz85/blog
36121          * @author mrdoob / http://mrdoob.com/
36122          */
36123
36124         function Font( data ) {
36125
36126                 this.data = data;
36127
36128         }
36129
36130         Object.assign( Font.prototype, {
36131
36132                 isFont: true,
36133
36134                 generateShapes: function ( text, size, divisions ) {
36135
36136                         function createPaths( text ) {
36137
36138                                 var chars = String( text ).split( '' );
36139                                 var scale = size / data.resolution;
36140                                 var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
36141
36142                                 var offsetX = 0, offsetY = 0;
36143
36144                                 var paths = [];
36145
36146                                 for ( var i = 0; i < chars.length; i ++ ) {
36147
36148                                         var char = chars[ i ];
36149
36150                                         if ( char === '\n' ) {
36151
36152                                                 offsetX = 0;
36153                                                 offsetY -= line_height;
36154
36155                                         } else {
36156
36157                                                 var ret = createPath( char, scale, offsetX, offsetY );
36158                                                 offsetX += ret.offsetX;
36159                                                 paths.push( ret.path );
36160
36161                                         }
36162
36163                                 }
36164
36165                                 return paths;
36166
36167                         }
36168
36169                         function createPath( c, scale, offsetX, offsetY ) {
36170
36171                                 var glyph = data.glyphs[ c ] || data.glyphs[ '?' ];
36172
36173                                 if ( ! glyph ) return;
36174
36175                                 var path = new ShapePath();
36176
36177                                 var pts = [];
36178                                 var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
36179
36180                                 if ( glyph.o ) {
36181
36182                                         var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
36183
36184                                         for ( var i = 0, l = outline.length; i < l; ) {
36185
36186                                                 var action = outline[ i ++ ];
36187
36188                                                 switch ( action ) {
36189
36190                                                         case 'm': // moveTo
36191
36192                                                                 x = outline[ i ++ ] * scale + offsetX;
36193                                                                 y = outline[ i ++ ] * scale + offsetY;
36194
36195                                                                 path.moveTo( x, y );
36196
36197                                                                 break;
36198
36199                                                         case 'l': // lineTo
36200
36201                                                                 x = outline[ i ++ ] * scale + offsetX;
36202                                                                 y = outline[ i ++ ] * scale + offsetY;
36203
36204                                                                 path.lineTo( x, y );
36205
36206                                                                 break;
36207
36208                                                         case 'q': // quadraticCurveTo
36209
36210                                                                 cpx  = outline[ i ++ ] * scale + offsetX;
36211                                                                 cpy  = outline[ i ++ ] * scale + offsetY;
36212                                                                 cpx1 = outline[ i ++ ] * scale + offsetX;
36213                                                                 cpy1 = outline[ i ++ ] * scale + offsetY;
36214
36215                                                                 path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
36216
36217                                                                 laste = pts[ pts.length - 1 ];
36218
36219                                                                 if ( laste ) {
36220
36221                                                                         cpx0 = laste.x;
36222                                                                         cpy0 = laste.y;
36223
36224                                                                         for ( var i2 = 1; i2 <= divisions; i2 ++ ) {
36225
36226                                                                                 var t = i2 / divisions;
36227                                                                                 QuadraticBezier( t, cpx0, cpx1, cpx );
36228                                                                                 QuadraticBezier( t, cpy0, cpy1, cpy );
36229
36230                                                                         }
36231
36232                                                                 }
36233
36234                                                                 break;
36235
36236                                                         case 'b': // bezierCurveTo
36237
36238                                                                 cpx  = outline[ i ++ ] * scale + offsetX;
36239                                                                 cpy  = outline[ i ++ ] * scale + offsetY;
36240                                                                 cpx1 = outline[ i ++ ] * scale + offsetX;
36241                                                                 cpy1 = outline[ i ++ ] * scale + offsetY;
36242                                                                 cpx2 = outline[ i ++ ] * scale + offsetX;
36243                                                                 cpy2 = outline[ i ++ ] * scale + offsetY;
36244
36245                                                                 path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
36246
36247                                                                 laste = pts[ pts.length - 1 ];
36248
36249                                                                 if ( laste ) {
36250
36251                                                                         cpx0 = laste.x;
36252                                                                         cpy0 = laste.y;
36253
36254                                                                         for ( var i2 = 1; i2 <= divisions; i2 ++ ) {
36255
36256                                                                                 var t = i2 / divisions;
36257                                                                                 CubicBezier( t, cpx0, cpx1, cpx2, cpx );
36258                                                                                 CubicBezier( t, cpy0, cpy1, cpy2, cpy );
36259
36260                                                                         }
36261
36262                                                                 }
36263
36264                                                                 break;
36265
36266                                                 }
36267
36268                                         }
36269
36270                                 }
36271
36272                                 return { offsetX: glyph.ha * scale, path: path };
36273
36274                         }
36275
36276                         //
36277
36278                         if ( size === undefined ) size = 100;
36279                         if ( divisions === undefined ) divisions = 4;
36280
36281                         var data = this.data;
36282
36283                         var paths = createPaths( text );
36284                         var shapes = [];
36285
36286                         for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
36287
36288                                 Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
36289
36290                         }
36291
36292                         return shapes;
36293
36294                 }
36295
36296         } );
36297
36298         /**
36299          * @author mrdoob / http://mrdoob.com/
36300          */
36301
36302         function FontLoader( manager ) {
36303
36304                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
36305
36306         }
36307
36308         Object.assign( FontLoader.prototype, {
36309
36310                 load: function ( url, onLoad, onProgress, onError ) {
36311
36312                         var scope = this;
36313
36314                         var loader = new FileLoader( this.manager );
36315                         loader.load( url, function ( text ) {
36316
36317                                 var json;
36318
36319                                 try {
36320
36321                                         json = JSON.parse( text );
36322
36323                                 } catch ( e ) {
36324
36325                                         console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
36326                                         json = JSON.parse( text.substring( 65, text.length - 2 ) );
36327
36328                                 }
36329
36330                                 var font = scope.parse( json );
36331
36332                                 if ( onLoad ) onLoad( font );
36333
36334                         }, onProgress, onError );
36335
36336                 },
36337
36338                 parse: function ( json ) {
36339
36340                         return new Font( json );
36341
36342                 }
36343
36344         } );
36345
36346         var context;
36347
36348         var AudioContext = {
36349
36350                 getContext: function () {
36351
36352                         if ( context === undefined ) {
36353
36354                                 context = new ( window.AudioContext || window.webkitAudioContext )();
36355
36356                         }
36357
36358                         return context;
36359
36360                 },
36361
36362                 setContext: function ( value ) {
36363
36364                         context = value;
36365
36366                 }
36367
36368         };
36369
36370         /**
36371          * @author Reece Aaron Lecrivain / http://reecenotes.com/
36372          */
36373
36374         function AudioLoader( manager ) {
36375
36376                 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
36377
36378         }
36379
36380         Object.assign( AudioLoader.prototype, {
36381
36382                 load: function ( url, onLoad, onProgress, onError ) {
36383
36384                         var loader = new FileLoader( this.manager );
36385                         loader.setResponseType( 'arraybuffer' );
36386                         loader.load( url, function ( buffer ) {
36387
36388                                 var context = AudioContext.getContext();
36389
36390                                 context.decodeAudioData( buffer, function ( audioBuffer ) {
36391
36392                                         onLoad( audioBuffer );
36393
36394                                 } );
36395
36396                         }, onProgress, onError );
36397
36398                 }
36399
36400         } );
36401
36402         /**
36403          * @author mrdoob / http://mrdoob.com/
36404          */
36405
36406         function StereoCamera() {
36407
36408                 this.type = 'StereoCamera';
36409
36410                 this.aspect = 1;
36411
36412                 this.eyeSep = 0.064;
36413
36414                 this.cameraL = new PerspectiveCamera();
36415                 this.cameraL.layers.enable( 1 );
36416                 this.cameraL.matrixAutoUpdate = false;
36417
36418                 this.cameraR = new PerspectiveCamera();
36419                 this.cameraR.layers.enable( 2 );
36420                 this.cameraR.matrixAutoUpdate = false;
36421
36422         }
36423
36424         Object.assign( StereoCamera.prototype, {
36425
36426                 update: ( function () {
36427
36428                         var instance, focus, fov, aspect, near, far, zoom, eyeSep;
36429
36430                         var eyeRight = new Matrix4();
36431                         var eyeLeft = new Matrix4();
36432
36433                         return function update( camera ) {
36434
36435                                 var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov ||
36436                                                                                                         aspect !== camera.aspect * this.aspect || near !== camera.near ||
36437                                                                                                         far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep;
36438
36439                                 if ( needsUpdate ) {
36440
36441                                         instance = this;
36442                                         focus = camera.focus;
36443                                         fov = camera.fov;
36444                                         aspect = camera.aspect * this.aspect;
36445                                         near = camera.near;
36446                                         far = camera.far;
36447                                         zoom = camera.zoom;
36448
36449                                         // Off-axis stereoscopic effect based on
36450                                         // http://paulbourke.net/stereographics/stereorender/
36451
36452                                         var projectionMatrix = camera.projectionMatrix.clone();
36453                                         eyeSep = this.eyeSep / 2;
36454                                         var eyeSepOnProjection = eyeSep * near / focus;
36455                                         var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom;
36456                                         var xmin, xmax;
36457
36458                                         // translate xOffset
36459
36460                                         eyeLeft.elements[ 12 ] = - eyeSep;
36461                                         eyeRight.elements[ 12 ] = eyeSep;
36462
36463                                         // for left eye
36464
36465                                         xmin = - ymax * aspect + eyeSepOnProjection;
36466                                         xmax = ymax * aspect + eyeSepOnProjection;
36467
36468                                         projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
36469                                         projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
36470
36471                                         this.cameraL.projectionMatrix.copy( projectionMatrix );
36472
36473                                         // for right eye
36474
36475                                         xmin = - ymax * aspect - eyeSepOnProjection;
36476                                         xmax = ymax * aspect - eyeSepOnProjection;
36477
36478                                         projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
36479                                         projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
36480
36481                                         this.cameraR.projectionMatrix.copy( projectionMatrix );
36482
36483                                 }
36484
36485                                 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft );
36486                                 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight );
36487
36488                         };
36489
36490                 } )()
36491
36492         } );
36493
36494         /**
36495          * Camera for rendering cube maps
36496          *      - renders scene into axis-aligned cube
36497          *
36498          * @author alteredq / http://alteredqualia.com/
36499          */
36500
36501         function CubeCamera( near, far, cubeResolution ) {
36502
36503                 Object3D.call( this );
36504
36505                 this.type = 'CubeCamera';
36506
36507                 var fov = 90, aspect = 1;
36508
36509                 var cameraPX = new PerspectiveCamera( fov, aspect, near, far );
36510                 cameraPX.up.set( 0, - 1, 0 );
36511                 cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
36512                 this.add( cameraPX );
36513
36514                 var cameraNX = new PerspectiveCamera( fov, aspect, near, far );
36515                 cameraNX.up.set( 0, - 1, 0 );
36516                 cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
36517                 this.add( cameraNX );
36518
36519                 var cameraPY = new PerspectiveCamera( fov, aspect, near, far );
36520                 cameraPY.up.set( 0, 0, 1 );
36521                 cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
36522                 this.add( cameraPY );
36523
36524                 var cameraNY = new PerspectiveCamera( fov, aspect, near, far );
36525                 cameraNY.up.set( 0, 0, - 1 );
36526                 cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
36527                 this.add( cameraNY );
36528
36529                 var cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
36530                 cameraPZ.up.set( 0, - 1, 0 );
36531                 cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
36532                 this.add( cameraPZ );
36533
36534                 var cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
36535                 cameraNZ.up.set( 0, - 1, 0 );
36536                 cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
36537                 this.add( cameraNZ );
36538
36539                 var options = { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter };
36540
36541                 this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options );
36542                 this.renderTarget.texture.name = "CubeCamera";
36543
36544                 this.update = function ( renderer, scene ) {
36545
36546                         if ( this.parent === null ) this.updateMatrixWorld();
36547
36548                         var renderTarget = this.renderTarget;
36549                         var generateMipmaps = renderTarget.texture.generateMipmaps;
36550
36551                         renderTarget.texture.generateMipmaps = false;
36552
36553                         renderTarget.activeCubeFace = 0;
36554                         renderer.render( scene, cameraPX, renderTarget );
36555
36556                         renderTarget.activeCubeFace = 1;
36557                         renderer.render( scene, cameraNX, renderTarget );
36558
36559                         renderTarget.activeCubeFace = 2;
36560                         renderer.render( scene, cameraPY, renderTarget );
36561
36562                         renderTarget.activeCubeFace = 3;
36563                         renderer.render( scene, cameraNY, renderTarget );
36564
36565                         renderTarget.activeCubeFace = 4;
36566                         renderer.render( scene, cameraPZ, renderTarget );
36567
36568                         renderTarget.texture.generateMipmaps = generateMipmaps;
36569
36570                         renderTarget.activeCubeFace = 5;
36571                         renderer.render( scene, cameraNZ, renderTarget );
36572
36573                         renderer.setRenderTarget( null );
36574
36575                 };
36576
36577                 this.clear = function ( renderer, color, depth, stencil ) {
36578
36579                         var renderTarget = this.renderTarget;
36580
36581                         for ( var i = 0; i < 6; i ++ ) {
36582
36583                                 renderTarget.activeCubeFace = i;
36584                                 renderer.setRenderTarget( renderTarget );
36585
36586                                 renderer.clear( color, depth, stencil );
36587
36588                         }
36589
36590                         renderer.setRenderTarget( null );
36591
36592                 };
36593
36594         }
36595
36596         CubeCamera.prototype = Object.create( Object3D.prototype );
36597         CubeCamera.prototype.constructor = CubeCamera;
36598
36599         /**
36600          * @author mrdoob / http://mrdoob.com/
36601          */
36602
36603         function AudioListener() {
36604
36605                 Object3D.call( this );
36606
36607                 this.type = 'AudioListener';
36608
36609                 this.context = AudioContext.getContext();
36610
36611                 this.gain = this.context.createGain();
36612                 this.gain.connect( this.context.destination );
36613
36614                 this.filter = null;
36615
36616         }
36617
36618         AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {
36619
36620                 constructor: AudioListener,
36621
36622                 getInput: function () {
36623
36624                         return this.gain;
36625
36626                 },
36627
36628                 removeFilter: function ( ) {
36629
36630                         if ( this.filter !== null ) {
36631
36632                                 this.gain.disconnect( this.filter );
36633                                 this.filter.disconnect( this.context.destination );
36634                                 this.gain.connect( this.context.destination );
36635                                 this.filter = null;
36636
36637                         }
36638
36639                 },
36640
36641                 getFilter: function () {
36642
36643                         return this.filter;
36644
36645                 },
36646
36647                 setFilter: function ( value ) {
36648
36649                         if ( this.filter !== null ) {
36650
36651                                 this.gain.disconnect( this.filter );
36652                                 this.filter.disconnect( this.context.destination );
36653
36654                         } else {
36655
36656                                 this.gain.disconnect( this.context.destination );
36657
36658                         }
36659
36660                         this.filter = value;
36661                         this.gain.connect( this.filter );
36662                         this.filter.connect( this.context.destination );
36663
36664                 },
36665
36666                 getMasterVolume: function () {
36667
36668                         return this.gain.gain.value;
36669
36670                 },
36671
36672                 setMasterVolume: function ( value ) {
36673
36674                         this.gain.gain.value = value;
36675
36676                 },
36677
36678                 updateMatrixWorld: ( function () {
36679
36680                         var position = new Vector3();
36681                         var quaternion = new Quaternion();
36682                         var scale = new Vector3();
36683
36684                         var orientation = new Vector3();
36685
36686                         return function updateMatrixWorld( force ) {
36687
36688                                 Object3D.prototype.updateMatrixWorld.call( this, force );
36689
36690                                 var listener = this.context.listener;
36691                                 var up = this.up;
36692
36693                                 this.matrixWorld.decompose( position, quaternion, scale );
36694
36695                                 orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
36696
36697                                 if ( listener.positionX ) {
36698
36699                                         listener.positionX.setValueAtTime( position.x, this.context.currentTime );
36700                                         listener.positionY.setValueAtTime( position.y, this.context.currentTime );
36701                                         listener.positionZ.setValueAtTime( position.z, this.context.currentTime );
36702                                         listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime );
36703                                         listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime );
36704                                         listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime );
36705                                         listener.upX.setValueAtTime( up.x, this.context.currentTime );
36706                                         listener.upY.setValueAtTime( up.y, this.context.currentTime );
36707                                         listener.upZ.setValueAtTime( up.z, this.context.currentTime );
36708
36709                                 } else {
36710
36711                                         listener.setPosition( position.x, position.y, position.z );
36712                                         listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
36713
36714                                 }
36715
36716                         };
36717
36718                 } )()
36719
36720         } );
36721
36722         /**
36723          * @author mrdoob / http://mrdoob.com/
36724          * @author Reece Aaron Lecrivain / http://reecenotes.com/
36725          */
36726
36727         function Audio( listener ) {
36728
36729                 Object3D.call( this );
36730
36731                 this.type = 'Audio';
36732
36733                 this.context = listener.context;
36734
36735                 this.gain = this.context.createGain();
36736                 this.gain.connect( listener.getInput() );
36737
36738                 this.autoplay = false;
36739
36740                 this.buffer = null;
36741                 this.loop = false;
36742                 this.startTime = 0;
36743                 this.playbackRate = 1;
36744                 this.isPlaying = false;
36745                 this.hasPlaybackControl = true;
36746                 this.sourceType = 'empty';
36747
36748                 this.filters = [];
36749
36750         }
36751
36752         Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
36753
36754                 constructor: Audio,
36755
36756                 getOutput: function () {
36757
36758                         return this.gain;
36759
36760                 },
36761
36762                 setNodeSource: function ( audioNode ) {
36763
36764                         this.hasPlaybackControl = false;
36765                         this.sourceType = 'audioNode';
36766                         this.source = audioNode;
36767                         this.connect();
36768
36769                         return this;
36770
36771                 },
36772
36773                 setBuffer: function ( audioBuffer ) {
36774
36775                         this.buffer = audioBuffer;
36776                         this.sourceType = 'buffer';
36777
36778                         if ( this.autoplay ) this.play();
36779
36780                         return this;
36781
36782                 },
36783
36784                 play: function () {
36785
36786                         if ( this.isPlaying === true ) {
36787
36788                                 console.warn( 'THREE.Audio: Audio is already playing.' );
36789                                 return;
36790
36791                         }
36792
36793                         if ( this.hasPlaybackControl === false ) {
36794
36795                                 console.warn( 'THREE.Audio: this Audio has no playback control.' );
36796                                 return;
36797
36798                         }
36799
36800                         var source = this.context.createBufferSource();
36801
36802                         source.buffer = this.buffer;
36803                         source.loop = this.loop;
36804                         source.onended = this.onEnded.bind( this );
36805                         source.playbackRate.setValueAtTime( this.playbackRate, this.startTime );
36806                         source.start( 0, this.startTime );
36807
36808                         this.isPlaying = true;
36809
36810                         this.source = source;
36811
36812                         return this.connect();
36813
36814                 },
36815
36816                 pause: function () {
36817
36818                         if ( this.hasPlaybackControl === false ) {
36819
36820                                 console.warn( 'THREE.Audio: this Audio has no playback control.' );
36821                                 return;
36822
36823                         }
36824
36825                         this.source.stop();
36826                         this.startTime = this.context.currentTime;
36827                         this.isPlaying = false;
36828
36829                         return this;
36830
36831                 },
36832
36833                 stop: function () {
36834
36835                         if ( this.hasPlaybackControl === false ) {
36836
36837                                 console.warn( 'THREE.Audio: this Audio has no playback control.' );
36838                                 return;
36839
36840                         }
36841
36842                         this.source.stop();
36843                         this.startTime = 0;
36844                         this.isPlaying = false;
36845
36846                         return this;
36847
36848                 },
36849
36850                 connect: function () {
36851
36852                         if ( this.filters.length > 0 ) {
36853
36854                                 this.source.connect( this.filters[ 0 ] );
36855
36856                                 for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
36857
36858                                         this.filters[ i - 1 ].connect( this.filters[ i ] );
36859
36860                                 }
36861
36862                                 this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
36863
36864                         } else {
36865
36866                                 this.source.connect( this.getOutput() );
36867
36868                         }
36869
36870                         return this;
36871
36872                 },
36873
36874                 disconnect: function () {
36875
36876                         if ( this.filters.length > 0 ) {
36877
36878                                 this.source.disconnect( this.filters[ 0 ] );
36879
36880                                 for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
36881
36882                                         this.filters[ i - 1 ].disconnect( this.filters[ i ] );
36883
36884                                 }
36885
36886                                 this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
36887
36888                         } else {
36889
36890                                 this.source.disconnect( this.getOutput() );
36891
36892                         }
36893
36894                         return this;
36895
36896                 },
36897
36898                 getFilters: function () {
36899
36900                         return this.filters;
36901
36902                 },
36903
36904                 setFilters: function ( value ) {
36905
36906                         if ( ! value ) value = [];
36907
36908                         if ( this.isPlaying === true ) {
36909
36910                                 this.disconnect();
36911                                 this.filters = value;
36912                                 this.connect();
36913
36914                         } else {
36915
36916                                 this.filters = value;
36917
36918                         }
36919
36920                         return this;
36921
36922                 },
36923
36924                 getFilter: function () {
36925
36926                         return this.getFilters()[ 0 ];
36927
36928                 },
36929
36930                 setFilter: function ( filter ) {
36931
36932                         return this.setFilters( filter ? [ filter ] : [] );
36933
36934                 },
36935
36936                 setPlaybackRate: function ( value ) {
36937
36938                         if ( this.hasPlaybackControl === false ) {
36939
36940                                 console.warn( 'THREE.Audio: this Audio has no playback control.' );
36941                                 return;
36942
36943                         }
36944
36945                         this.playbackRate = value;
36946
36947                         if ( this.isPlaying === true ) {
36948
36949                                 this.source.playbackRate.setValueAtTime( this.playbackRate, this.context.currentTime );
36950
36951                         }
36952
36953                         return this;
36954
36955                 },
36956
36957                 getPlaybackRate: function () {
36958
36959                         return this.playbackRate;
36960
36961                 },
36962
36963                 onEnded: function () {
36964
36965                         this.isPlaying = false;
36966
36967                 },
36968
36969                 getLoop: function () {
36970
36971                         if ( this.hasPlaybackControl === false ) {
36972
36973                                 console.warn( 'THREE.Audio: this Audio has no playback control.' );
36974                                 return false;
36975
36976                         }
36977
36978                         return this.loop;
36979
36980                 },
36981
36982                 setLoop: function ( value ) {
36983
36984                         if ( this.hasPlaybackControl === false ) {
36985
36986                                 console.warn( 'THREE.Audio: this Audio has no playback control.' );
36987                                 return;
36988
36989                         }
36990
36991                         this.loop = value;
36992
36993                         if ( this.isPlaying === true ) {
36994
36995                                 this.source.loop = this.loop;
36996
36997                         }
36998
36999                         return this;
37000
37001                 },
37002
37003                 getVolume: function () {
37004
37005                         return this.gain.gain.value;
37006
37007                 },
37008
37009                 setVolume: function ( value ) {
37010
37011                         this.gain.gain.value = value;
37012
37013                         return this;
37014
37015                 }
37016
37017         } );
37018
37019         /**
37020          * @author mrdoob / http://mrdoob.com/
37021          */
37022
37023         function PositionalAudio( listener ) {
37024
37025                 Audio.call( this, listener );
37026
37027                 this.panner = this.context.createPanner();
37028                 this.panner.connect( this.gain );
37029
37030         }
37031
37032         PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {
37033
37034                 constructor: PositionalAudio,
37035
37036                 getOutput: function () {
37037
37038                         return this.panner;
37039
37040                 },
37041
37042                 getRefDistance: function () {
37043
37044                         return this.panner.refDistance;
37045
37046                 },
37047
37048                 setRefDistance: function ( value ) {
37049
37050                         this.panner.refDistance = value;
37051
37052                 },
37053
37054                 getRolloffFactor: function () {
37055
37056                         return this.panner.rolloffFactor;
37057
37058                 },
37059
37060                 setRolloffFactor: function ( value ) {
37061
37062                         this.panner.rolloffFactor = value;
37063
37064                 },
37065
37066                 getDistanceModel: function () {
37067
37068                         return this.panner.distanceModel;
37069
37070                 },
37071
37072                 setDistanceModel: function ( value ) {
37073
37074                         this.panner.distanceModel = value;
37075
37076                 },
37077
37078                 getMaxDistance: function () {
37079
37080                         return this.panner.maxDistance;
37081
37082                 },
37083
37084                 setMaxDistance: function ( value ) {
37085
37086                         this.panner.maxDistance = value;
37087
37088                 },
37089
37090                 updateMatrixWorld: ( function () {
37091
37092                         var position = new Vector3();
37093
37094                         return function updateMatrixWorld( force ) {
37095
37096                                 Object3D.prototype.updateMatrixWorld.call( this, force );
37097
37098                                 position.setFromMatrixPosition( this.matrixWorld );
37099
37100                                 this.panner.setPosition( position.x, position.y, position.z );
37101
37102                         };
37103
37104                 } )()
37105
37106
37107         } );
37108
37109         /**
37110          * @author mrdoob / http://mrdoob.com/
37111          */
37112
37113         function AudioAnalyser( audio, fftSize ) {
37114
37115                 this.analyser = audio.context.createAnalyser();
37116                 this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
37117
37118                 this.data = new Uint8Array( this.analyser.frequencyBinCount );
37119
37120                 audio.getOutput().connect( this.analyser );
37121
37122         }
37123
37124         Object.assign( AudioAnalyser.prototype, {
37125
37126                 getFrequencyData: function () {
37127
37128                         this.analyser.getByteFrequencyData( this.data );
37129
37130                         return this.data;
37131
37132                 },
37133
37134                 getAverageFrequency: function () {
37135
37136                         var value = 0, data = this.getFrequencyData();
37137
37138                         for ( var i = 0; i < data.length; i ++ ) {
37139
37140                                 value += data[ i ];
37141
37142                         }
37143
37144                         return value / data.length;
37145
37146                 }
37147
37148         } );
37149
37150         /**
37151          *
37152          * Buffered scene graph property that allows weighted accumulation.
37153          *
37154          *
37155          * @author Ben Houston / http://clara.io/
37156          * @author David Sarno / http://lighthaus.us/
37157          * @author tschw
37158          */
37159
37160         function PropertyMixer( binding, typeName, valueSize ) {
37161
37162                 this.binding = binding;
37163                 this.valueSize = valueSize;
37164
37165                 var bufferType = Float64Array,
37166                         mixFunction;
37167
37168                 switch ( typeName ) {
37169
37170                         case 'quaternion':
37171                                 mixFunction = this._slerp;
37172                                 break;
37173
37174                         case 'string':
37175                         case 'bool':
37176                                 bufferType = Array;
37177                                 mixFunction = this._select;
37178                                 break;
37179
37180                         default:
37181                                 mixFunction = this._lerp;
37182
37183                 }
37184
37185                 this.buffer = new bufferType( valueSize * 4 );
37186                 // layout: [ incoming | accu0 | accu1 | orig ]
37187                 //
37188                 // interpolators can use .buffer as their .result
37189                 // the data then goes to 'incoming'
37190                 //
37191                 // 'accu0' and 'accu1' are used frame-interleaved for
37192                 // the cumulative result and are compared to detect
37193                 // changes
37194                 //
37195                 // 'orig' stores the original state of the property
37196
37197                 this._mixBufferRegion = mixFunction;
37198
37199                 this.cumulativeWeight = 0;
37200
37201                 this.useCount = 0;
37202                 this.referenceCount = 0;
37203
37204         }
37205
37206         Object.assign( PropertyMixer.prototype, {
37207
37208                 // accumulate data in the 'incoming' region into 'accu<i>'
37209                 accumulate: function ( accuIndex, weight ) {
37210
37211                         // note: happily accumulating nothing when weight = 0, the caller knows
37212                         // the weight and shouldn't have made the call in the first place
37213
37214                         var buffer = this.buffer,
37215                                 stride = this.valueSize,
37216                                 offset = accuIndex * stride + stride,
37217
37218                                 currentWeight = this.cumulativeWeight;
37219
37220                         if ( currentWeight === 0 ) {
37221
37222                                 // accuN := incoming * weight
37223
37224                                 for ( var i = 0; i !== stride; ++ i ) {
37225
37226                                         buffer[ offset + i ] = buffer[ i ];
37227
37228                                 }
37229
37230                                 currentWeight = weight;
37231
37232                         } else {
37233
37234                                 // accuN := accuN + incoming * weight
37235
37236                                 currentWeight += weight;
37237                                 var mix = weight / currentWeight;
37238                                 this._mixBufferRegion( buffer, offset, 0, mix, stride );
37239
37240                         }
37241
37242                         this.cumulativeWeight = currentWeight;
37243
37244                 },
37245
37246                 // apply the state of 'accu<i>' to the binding when accus differ
37247                 apply: function ( accuIndex ) {
37248
37249                         var stride = this.valueSize,
37250                                 buffer = this.buffer,
37251                                 offset = accuIndex * stride + stride,
37252
37253                                 weight = this.cumulativeWeight,
37254
37255                                 binding = this.binding;
37256
37257                         this.cumulativeWeight = 0;
37258
37259                         if ( weight < 1 ) {
37260
37261                                 // accuN := accuN + original * ( 1 - cumulativeWeight )
37262
37263                                 var originalValueOffset = stride * 3;
37264
37265                                 this._mixBufferRegion(
37266                                         buffer, offset, originalValueOffset, 1 - weight, stride );
37267
37268                         }
37269
37270                         for ( var i = stride, e = stride + stride; i !== e; ++ i ) {
37271
37272                                 if ( buffer[ i ] !== buffer[ i + stride ] ) {
37273
37274                                         // value has changed -> update scene graph
37275
37276                                         binding.setValue( buffer, offset );
37277                                         break;
37278
37279                                 }
37280
37281                         }
37282
37283                 },
37284
37285                 // remember the state of the bound property and copy it to both accus
37286                 saveOriginalState: function () {
37287
37288                         var binding = this.binding;
37289
37290                         var buffer = this.buffer,
37291                                 stride = this.valueSize,
37292
37293                                 originalValueOffset = stride * 3;
37294
37295                         binding.getValue( buffer, originalValueOffset );
37296
37297                         // accu[0..1] := orig -- initially detect changes against the original
37298                         for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {
37299
37300                                 buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
37301
37302                         }
37303
37304                         this.cumulativeWeight = 0;
37305
37306                 },
37307
37308                 // apply the state previously taken via 'saveOriginalState' to the binding
37309                 restoreOriginalState: function () {
37310
37311                         var originalValueOffset = this.valueSize * 3;
37312                         this.binding.setValue( this.buffer, originalValueOffset );
37313
37314                 },
37315
37316
37317                 // mix functions
37318
37319                 _select: function ( buffer, dstOffset, srcOffset, t, stride ) {
37320
37321                         if ( t >= 0.5 ) {
37322
37323                                 for ( var i = 0; i !== stride; ++ i ) {
37324
37325                                         buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
37326
37327                                 }
37328
37329                         }
37330
37331                 },
37332
37333                 _slerp: function ( buffer, dstOffset, srcOffset, t ) {
37334
37335                         Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
37336
37337                 },
37338
37339                 _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
37340
37341                         var s = 1 - t;
37342
37343                         for ( var i = 0; i !== stride; ++ i ) {
37344
37345                                 var j = dstOffset + i;
37346
37347                                 buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
37348
37349                         }
37350
37351                 }
37352
37353         } );
37354
37355         /**
37356          *
37357          * A reference to a real property in the scene graph.
37358          *
37359          *
37360          * @author Ben Houston / http://clara.io/
37361          * @author David Sarno / http://lighthaus.us/
37362          * @author tschw
37363          */
37364
37365         function Composite( targetGroup, path, optionalParsedPath ) {
37366
37367                 var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
37368
37369                 this._targetGroup = targetGroup;
37370                 this._bindings = targetGroup.subscribe_( path, parsedPath );
37371
37372         }
37373
37374         Object.assign( Composite.prototype, {
37375
37376                 getValue: function ( array, offset ) {
37377
37378                         this.bind(); // bind all binding
37379
37380                         var firstValidIndex = this._targetGroup.nCachedObjects_,
37381                                 binding = this._bindings[ firstValidIndex ];
37382
37383                         // and only call .getValue on the first
37384                         if ( binding !== undefined ) binding.getValue( array, offset );
37385
37386                 },
37387
37388                 setValue: function ( array, offset ) {
37389
37390                         var bindings = this._bindings;
37391
37392                         for ( var i = this._targetGroup.nCachedObjects_,
37393                                           n = bindings.length; i !== n; ++ i ) {
37394
37395                                 bindings[ i ].setValue( array, offset );
37396
37397                         }
37398
37399                 },
37400
37401                 bind: function () {
37402
37403                         var bindings = this._bindings;
37404
37405                         for ( var i = this._targetGroup.nCachedObjects_,
37406                                           n = bindings.length; i !== n; ++ i ) {
37407
37408                                 bindings[ i ].bind();
37409
37410                         }
37411
37412                 },
37413
37414                 unbind: function () {
37415
37416                         var bindings = this._bindings;
37417
37418                         for ( var i = this._targetGroup.nCachedObjects_,
37419                                           n = bindings.length; i !== n; ++ i ) {
37420
37421                                 bindings[ i ].unbind();
37422
37423                         }
37424
37425                 }
37426
37427         } );
37428
37429
37430         function PropertyBinding( rootNode, path, parsedPath ) {
37431
37432                 this.path = path;
37433                 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
37434
37435                 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
37436
37437                 this.rootNode = rootNode;
37438
37439         }
37440
37441         Object.assign( PropertyBinding, {
37442
37443                 Composite: Composite,
37444
37445                 create: function ( root, path, parsedPath ) {
37446
37447                         if ( ! ( root && root.isAnimationObjectGroup ) ) {
37448
37449                                 return new PropertyBinding( root, path, parsedPath );
37450
37451                         } else {
37452
37453                                 return new PropertyBinding.Composite( root, path, parsedPath );
37454
37455                         }
37456
37457                 },
37458
37459                 /**
37460                  * Replaces spaces with underscores and removes unsupported characters from
37461                  * node names, to ensure compatibility with parseTrackName().
37462                  *
37463                  * @param  {string} name Node name to be sanitized.
37464                  * @return {string}
37465                  */
37466                 sanitizeNodeName: function ( name ) {
37467
37468                         return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' );
37469
37470                 },
37471
37472                 parseTrackName: function () {
37473
37474                         // Parent directories, delimited by '/' or ':'. Currently unused, but must
37475                         // be matched to parse the rest of the track name.
37476                         var directoryRe = /((?:[\w-]+[\/:])*)/;
37477
37478                         // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
37479                         var nodeRe = /([\w-\.]+)?/;
37480
37481                         // Object on target node, and accessor. Name may contain only word
37482                         // characters. Accessor may contain any character except closing bracket.
37483                         var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/;
37484
37485                         // Property and accessor. May contain only word characters. Accessor may
37486                         // contain any non-bracket characters.
37487                         var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/;
37488
37489                         var trackRe = new RegExp(''
37490                                 + '^'
37491                                 + directoryRe.source
37492                                 + nodeRe.source
37493                                 + objectRe.source
37494                                 + propertyRe.source
37495                                 + '$'
37496                         );
37497
37498                         var supportedObjectNames = [ 'material', 'materials', 'bones' ];
37499
37500                         return function ( trackName ) {
37501
37502                                         var matches = trackRe.exec( trackName );
37503
37504                                         if ( ! matches ) {
37505
37506                                                 throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
37507
37508                                         }
37509
37510                                         var results = {
37511                                                 // directoryName: matches[ 1 ], // (tschw) currently unused
37512                                                 nodeName: matches[ 2 ],
37513                                                 objectName: matches[ 3 ],
37514                                                 objectIndex: matches[ 4 ],
37515                                                 propertyName: matches[ 5 ],     // required
37516                                                 propertyIndex: matches[ 6 ]
37517                                         };
37518
37519                                         var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
37520
37521                                         if ( lastDot !== undefined && lastDot !== -1 ) {
37522
37523                                                 var objectName = results.nodeName.substring( lastDot + 1 );
37524
37525                                                 // Object names must be checked against a whitelist. Otherwise, there
37526                                                 // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
37527                                                 // 'bar' could be the objectName, or part of a nodeName (which can
37528                                                 // include '.' characters).
37529                                                 if ( supportedObjectNames.indexOf( objectName ) !== -1 ) {
37530
37531                                                         results.nodeName = results.nodeName.substring( 0, lastDot );
37532                                                         results.objectName = objectName;
37533
37534                                                 }
37535
37536                                         }
37537
37538                                         if ( results.propertyName === null || results.propertyName.length === 0 ) {
37539
37540                                                 throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
37541
37542                                         }
37543
37544                                         return results;
37545
37546                                 };
37547
37548                 }(),
37549
37550                 findNode: function ( root, nodeName ) {
37551
37552                         if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
37553
37554                                 return root;
37555
37556                         }
37557
37558                         // search into skeleton bones.
37559                         if ( root.skeleton ) {
37560
37561                                 var searchSkeleton = function ( skeleton ) {
37562
37563                                         for ( var i = 0; i < skeleton.bones.length; i ++ ) {
37564
37565                                                 var bone = skeleton.bones[ i ];
37566
37567                                                 if ( bone.name === nodeName ) {
37568
37569                                                         return bone;
37570
37571                                                 }
37572
37573                                         }
37574
37575                                         return null;
37576
37577                                 };
37578
37579                                 var bone = searchSkeleton( root.skeleton );
37580
37581                                 if ( bone ) {
37582
37583                                         return bone;
37584
37585                                 }
37586
37587                         }
37588
37589                         // search into node subtree.
37590                         if ( root.children ) {
37591
37592                                 var searchNodeSubtree = function ( children ) {
37593
37594                                         for ( var i = 0; i < children.length; i ++ ) {
37595
37596                                                 var childNode = children[ i ];
37597
37598                                                 if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
37599
37600                                                         return childNode;
37601
37602                                                 }
37603
37604                                                 var result = searchNodeSubtree( childNode.children );
37605
37606                                                 if ( result ) return result;
37607
37608                                         }
37609
37610                                         return null;
37611
37612                                 };
37613
37614                                 var subTreeNode = searchNodeSubtree( root.children );
37615
37616                                 if ( subTreeNode ) {
37617
37618                                         return subTreeNode;
37619
37620                                 }
37621
37622                         }
37623
37624                         return null;
37625
37626                 }
37627
37628         } );
37629
37630         Object.assign( PropertyBinding.prototype, { // prototype, continued
37631
37632                 // these are used to "bind" a nonexistent property
37633                 _getValue_unavailable: function () {},
37634                 _setValue_unavailable: function () {},
37635
37636                 BindingType: {
37637                         Direct: 0,
37638                         EntireArray: 1,
37639                         ArrayElement: 2,
37640                         HasFromToArray: 3
37641                 },
37642
37643                 Versioning: {
37644                         None: 0,
37645                         NeedsUpdate: 1,
37646                         MatrixWorldNeedsUpdate: 2
37647                 },
37648
37649                 GetterByBindingType: [
37650
37651                         function getValue_direct( buffer, offset ) {
37652
37653                                 buffer[ offset ] = this.node[ this.propertyName ];
37654
37655                         },
37656
37657                         function getValue_array( buffer, offset ) {
37658
37659                                 var source = this.resolvedProperty;
37660
37661                                 for ( var i = 0, n = source.length; i !== n; ++ i ) {
37662
37663                                         buffer[ offset ++ ] = source[ i ];
37664
37665                                 }
37666
37667                         },
37668
37669                         function getValue_arrayElement( buffer, offset ) {
37670
37671                                 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
37672
37673                         },
37674
37675                         function getValue_toArray( buffer, offset ) {
37676
37677                                 this.resolvedProperty.toArray( buffer, offset );
37678
37679                         }
37680
37681                 ],
37682
37683                 SetterByBindingTypeAndVersioning: [
37684
37685                         [
37686                                 // Direct
37687
37688                                 function setValue_direct( buffer, offset ) {
37689
37690                                         this.node[ this.propertyName ] = buffer[ offset ];
37691
37692                                 },
37693
37694                                 function setValue_direct_setNeedsUpdate( buffer, offset ) {
37695
37696                                         this.node[ this.propertyName ] = buffer[ offset ];
37697                                         this.targetObject.needsUpdate = true;
37698
37699                                 },
37700
37701                                 function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
37702
37703                                         this.node[ this.propertyName ] = buffer[ offset ];
37704                                         this.targetObject.matrixWorldNeedsUpdate = true;
37705
37706                                 }
37707
37708                         ], [
37709
37710                                 // EntireArray
37711
37712                                 function setValue_array( buffer, offset ) {
37713
37714                                         var dest = this.resolvedProperty;
37715
37716                                         for ( var i = 0, n = dest.length; i !== n; ++ i ) {
37717
37718                                                 dest[ i ] = buffer[ offset ++ ];
37719
37720                                         }
37721
37722                                 },
37723
37724                                 function setValue_array_setNeedsUpdate( buffer, offset ) {
37725
37726                                         var dest = this.resolvedProperty;
37727
37728                                         for ( var i = 0, n = dest.length; i !== n; ++ i ) {
37729
37730                                                 dest[ i ] = buffer[ offset ++ ];
37731
37732                                         }
37733
37734                                         this.targetObject.needsUpdate = true;
37735
37736                                 },
37737
37738                                 function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
37739
37740                                         var dest = this.resolvedProperty;
37741
37742                                         for ( var i = 0, n = dest.length; i !== n; ++ i ) {
37743
37744                                                 dest[ i ] = buffer[ offset ++ ];
37745
37746                                         }
37747
37748                                         this.targetObject.matrixWorldNeedsUpdate = true;
37749
37750                                 }
37751
37752                         ], [
37753
37754                                 // ArrayElement
37755
37756                                 function setValue_arrayElement( buffer, offset ) {
37757
37758                                         this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
37759
37760                                 },
37761
37762                                 function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
37763
37764                                         this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
37765                                         this.targetObject.needsUpdate = true;
37766
37767                                 },
37768
37769                                 function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
37770
37771                                         this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
37772                                         this.targetObject.matrixWorldNeedsUpdate = true;
37773
37774                                 }
37775
37776                         ], [
37777
37778                                 // HasToFromArray
37779
37780                                 function setValue_fromArray( buffer, offset ) {
37781
37782                                         this.resolvedProperty.fromArray( buffer, offset );
37783
37784                                 },
37785
37786                                 function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
37787
37788                                         this.resolvedProperty.fromArray( buffer, offset );
37789                                         this.targetObject.needsUpdate = true;
37790
37791                                 },
37792
37793                                 function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
37794
37795                                         this.resolvedProperty.fromArray( buffer, offset );
37796                                         this.targetObject.matrixWorldNeedsUpdate = true;
37797
37798                                 }
37799
37800                         ]
37801
37802                 ],
37803
37804                 getValue: function getValue_unbound( targetArray, offset ) {
37805
37806                         this.bind();
37807                         this.getValue( targetArray, offset );
37808
37809                         // Note: This class uses a State pattern on a per-method basis:
37810                         // 'bind' sets 'this.getValue' / 'setValue' and shadows the
37811                         // prototype version of these methods with one that represents
37812                         // the bound state. When the property is not found, the methods
37813                         // become no-ops.
37814
37815                 },
37816
37817                 setValue: function getValue_unbound( sourceArray, offset ) {
37818
37819                         this.bind();
37820                         this.setValue( sourceArray, offset );
37821
37822                 },
37823
37824                 // create getter / setter pair for a property in the scene graph
37825                 bind: function () {
37826
37827                         var targetObject = this.node,
37828                                 parsedPath = this.parsedPath,
37829
37830                                 objectName = parsedPath.objectName,
37831                                 propertyName = parsedPath.propertyName,
37832                                 propertyIndex = parsedPath.propertyIndex;
37833
37834                         if ( ! targetObject ) {
37835
37836                                 targetObject = PropertyBinding.findNode(
37837                                                 this.rootNode, parsedPath.nodeName ) || this.rootNode;
37838
37839                                 this.node = targetObject;
37840
37841                         }
37842
37843                         // set fail state so we can just 'return' on error
37844                         this.getValue = this._getValue_unavailable;
37845                         this.setValue = this._setValue_unavailable;
37846
37847                         // ensure there is a value node
37848                         if ( ! targetObject ) {
37849
37850                                 console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
37851                                 return;
37852
37853                         }
37854
37855                         if ( objectName ) {
37856
37857                                 var objectIndex = parsedPath.objectIndex;
37858
37859                                 // special cases were we need to reach deeper into the hierarchy to get the face materials....
37860                                 switch ( objectName ) {
37861
37862                                         case 'materials':
37863
37864                                                 if ( ! targetObject.material ) {
37865
37866                                                         console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
37867                                                         return;
37868
37869                                                 }
37870
37871                                                 if ( ! targetObject.material.materials ) {
37872
37873                                                         console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
37874                                                         return;
37875
37876                                                 }
37877
37878                                                 targetObject = targetObject.material.materials;
37879
37880                                                 break;
37881
37882                                         case 'bones':
37883
37884                                                 if ( ! targetObject.skeleton ) {
37885
37886                                                         console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
37887                                                         return;
37888
37889                                                 }
37890
37891                                                 // potential future optimization: skip this if propertyIndex is already an integer
37892                                                 // and convert the integer string to a true integer.
37893
37894                                                 targetObject = targetObject.skeleton.bones;
37895
37896                                                 // support resolving morphTarget names into indices.
37897                                                 for ( var i = 0; i < targetObject.length; i ++ ) {
37898
37899                                                         if ( targetObject[ i ].name === objectIndex ) {
37900
37901                                                                 objectIndex = i;
37902                                                                 break;
37903
37904                                                         }
37905
37906                                                 }
37907
37908                                                 break;
37909
37910                                         default:
37911
37912                                                 if ( targetObject[ objectName ] === undefined ) {
37913
37914                                                         console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
37915                                                         return;
37916
37917                                                 }
37918
37919                                                 targetObject = targetObject[ objectName ];
37920
37921                                 }
37922
37923
37924                                 if ( objectIndex !== undefined ) {
37925
37926                                         if ( targetObject[ objectIndex ] === undefined ) {
37927
37928                                                 console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
37929                                                 return;
37930
37931                                         }
37932
37933                                         targetObject = targetObject[ objectIndex ];
37934
37935                                 }
37936
37937                         }
37938
37939                         // resolve property
37940                         var nodeProperty = targetObject[ propertyName ];
37941
37942                         if ( nodeProperty === undefined ) {
37943
37944                                 var nodeName = parsedPath.nodeName;
37945
37946                                 console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
37947                                         '.' + propertyName + ' but it wasn\'t found.', targetObject );
37948                                 return;
37949
37950                         }
37951
37952                         // determine versioning scheme
37953                         var versioning = this.Versioning.None;
37954
37955                         if ( targetObject.needsUpdate !== undefined ) { // material
37956
37957                                 versioning = this.Versioning.NeedsUpdate;
37958                                 this.targetObject = targetObject;
37959
37960                         } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
37961
37962                                 versioning = this.Versioning.MatrixWorldNeedsUpdate;
37963                                 this.targetObject = targetObject;
37964
37965                         }
37966
37967                         // determine how the property gets bound
37968                         var bindingType = this.BindingType.Direct;
37969
37970                         if ( propertyIndex !== undefined ) {
37971
37972                                 // access a sub element of the property array (only primitives are supported right now)
37973
37974                                 if ( propertyName === "morphTargetInfluences" ) {
37975
37976                                         // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
37977
37978                                         // support resolving morphTarget names into indices.
37979                                         if ( ! targetObject.geometry ) {
37980
37981                                                 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
37982                                                 return;
37983
37984                                         }
37985
37986                                         if ( targetObject.geometry.isBufferGeometry ) {
37987
37988                                                 if ( ! targetObject.geometry.morphAttributes ) {
37989
37990                                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
37991                                                         return;
37992
37993                                                 }
37994
37995                                                 for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) {
37996
37997                                                         if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) {
37998
37999                                                                 propertyIndex = i;
38000                                                                 break;
38001
38002                                                         }
38003
38004                                                 }
38005
38006
38007                                         } else {
38008
38009                                                 if ( ! targetObject.geometry.morphTargets ) {
38010
38011                                                         console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this );
38012                                                         return;
38013
38014                                                 }
38015
38016                                                 for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {
38017
38018                                                         if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {
38019
38020                                                                 propertyIndex = i;
38021                                                                 break;
38022
38023                                                         }
38024
38025                                                 }
38026
38027                                         }
38028
38029                                 }
38030
38031                                 bindingType = this.BindingType.ArrayElement;
38032
38033                                 this.resolvedProperty = nodeProperty;
38034                                 this.propertyIndex = propertyIndex;
38035
38036                         } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
38037
38038                                 // must use copy for Object3D.Euler/Quaternion
38039
38040                                 bindingType = this.BindingType.HasFromToArray;
38041
38042                                 this.resolvedProperty = nodeProperty;
38043
38044                         } else if ( Array.isArray( nodeProperty ) ) {
38045
38046                                 bindingType = this.BindingType.EntireArray;
38047
38048                                 this.resolvedProperty = nodeProperty;
38049
38050                         } else {
38051
38052                                 this.propertyName = propertyName;
38053
38054                         }
38055
38056                         // select getter / setter
38057                         this.getValue = this.GetterByBindingType[ bindingType ];
38058                         this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
38059
38060                 },
38061
38062                 unbind: function () {
38063
38064                         this.node = null;
38065
38066                         // back to the prototype version of getValue / setValue
38067                         // note: avoiding to mutate the shape of 'this' via 'delete'
38068                         this.getValue = this._getValue_unbound;
38069                         this.setValue = this._setValue_unbound;
38070
38071                 }
38072
38073         } );
38074
38075         //!\ DECLARE ALIAS AFTER assign prototype !
38076         Object.assign( PropertyBinding.prototype, {
38077
38078                 // initial state of these methods that calls 'bind'
38079                 _getValue_unbound: PropertyBinding.prototype.getValue,
38080                 _setValue_unbound: PropertyBinding.prototype.setValue,
38081
38082         } );
38083
38084         /**
38085          *
38086          * A group of objects that receives a shared animation state.
38087          *
38088          * Usage:
38089          *
38090          *      -       Add objects you would otherwise pass as 'root' to the
38091          *              constructor or the .clipAction method of AnimationMixer.
38092          *
38093          *      -       Instead pass this object as 'root'.
38094          *
38095          *      -       You can also add and remove objects later when the mixer
38096          *              is running.
38097          *
38098          * Note:
38099          *
38100          *      Objects of this class appear as one object to the mixer,
38101          *      so cache control of the individual objects must be done
38102          *      on the group.
38103          *
38104          * Limitation:
38105          *
38106          *      -       The animated properties must be compatible among the
38107          *              all objects in the group.
38108          *
38109          *  -   A single property can either be controlled through a
38110          *      target group or directly, but not both.
38111          *
38112          * @author tschw
38113          */
38114
38115         function AnimationObjectGroup( var_args ) {
38116
38117                 this.uuid = _Math.generateUUID();
38118
38119                 // cached objects followed by the active ones
38120                 this._objects = Array.prototype.slice.call( arguments );
38121
38122                 this.nCachedObjects_ = 0;                       // threshold
38123                 // note: read by PropertyBinding.Composite
38124
38125                 var indices = {};
38126                 this._indicesByUUID = indices;          // for bookkeeping
38127
38128                 for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
38129
38130                         indices[ arguments[ i ].uuid ] = i;
38131
38132                 }
38133
38134                 this._paths = [];                                       // inside: string
38135                 this._parsedPaths = [];                         // inside: { we don't care, here }
38136                 this._bindings = [];                            // inside: Array< PropertyBinding >
38137                 this._bindingsIndicesByPath = {};       // inside: indices in these arrays
38138
38139                 var scope = this;
38140
38141                 this.stats = {
38142
38143                         objects: {
38144                                 get total() { return scope._objects.length; },
38145                                 get inUse() { return this.total - scope.nCachedObjects_; }
38146                         },
38147
38148                         get bindingsPerObject() { return scope._bindings.length; }
38149
38150                 };
38151
38152         }
38153
38154         Object.assign( AnimationObjectGroup.prototype, {
38155
38156                 isAnimationObjectGroup: true,
38157
38158                 add: function( var_args ) {
38159
38160                         var objects = this._objects,
38161                                 nObjects = objects.length,
38162                                 nCachedObjects = this.nCachedObjects_,
38163                                 indicesByUUID = this._indicesByUUID,
38164                                 paths = this._paths,
38165                                 parsedPaths = this._parsedPaths,
38166                                 bindings = this._bindings,
38167                                 nBindings = bindings.length;
38168
38169                         for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
38170
38171                                 var object = arguments[ i ],
38172                                         uuid = object.uuid,
38173                                         index = indicesByUUID[ uuid ],
38174                                         knownObject = undefined;
38175
38176                                 if ( index === undefined ) {
38177
38178                                         // unknown object -> add it to the ACTIVE region
38179
38180                                         index = nObjects ++;
38181                                         indicesByUUID[ uuid ] = index;
38182                                         objects.push( object );
38183
38184                                         // accounting is done, now do the same for all bindings
38185
38186                                         for ( var j = 0, m = nBindings; j !== m; ++ j ) {
38187
38188                                                 bindings[ j ].push(
38189                                                                 new PropertyBinding(
38190                                                                         object, paths[ j ], parsedPaths[ j ] ) );
38191
38192                                         }
38193
38194                                 } else if ( index < nCachedObjects ) {
38195
38196                                         knownObject = objects[ index ];
38197
38198                                         // move existing object to the ACTIVE region
38199
38200                                         var firstActiveIndex = -- nCachedObjects,
38201                                                 lastCachedObject = objects[ firstActiveIndex ];
38202
38203                                         indicesByUUID[ lastCachedObject.uuid ] = index;
38204                                         objects[ index ] = lastCachedObject;
38205
38206                                         indicesByUUID[ uuid ] = firstActiveIndex;
38207                                         objects[ firstActiveIndex ] = object;
38208
38209                                         // accounting is done, now do the same for all bindings
38210
38211                                         for ( var j = 0, m = nBindings; j !== m; ++ j ) {
38212
38213                                                 var bindingsForPath = bindings[ j ],
38214                                                         lastCached = bindingsForPath[ firstActiveIndex ],
38215                                                         binding = bindingsForPath[ index ];
38216
38217                                                 bindingsForPath[ index ] = lastCached;
38218
38219                                                 if ( binding === undefined ) {
38220
38221                                                         // since we do not bother to create new bindings
38222                                                         // for objects that are cached, the binding may
38223                                                         // or may not exist
38224
38225                                                         binding = new PropertyBinding(
38226                                                                         object, paths[ j ], parsedPaths[ j ] );
38227
38228                                                 }
38229
38230                                                 bindingsForPath[ firstActiveIndex ] = binding;
38231
38232                                         }
38233
38234                                 } else if ( objects[ index ] !== knownObject ) {
38235
38236                                         console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
38237                                                         'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
38238
38239                                 } // else the object is already where we want it to be
38240
38241                         } // for arguments
38242
38243                         this.nCachedObjects_ = nCachedObjects;
38244
38245                 },
38246
38247                 remove: function( var_args ) {
38248
38249                         var objects = this._objects,
38250                                 nCachedObjects = this.nCachedObjects_,
38251                                 indicesByUUID = this._indicesByUUID,
38252                                 bindings = this._bindings,
38253                                 nBindings = bindings.length;
38254
38255                         for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
38256
38257                                 var object = arguments[ i ],
38258                                         uuid = object.uuid,
38259                                         index = indicesByUUID[ uuid ];
38260
38261                                 if ( index !== undefined && index >= nCachedObjects ) {
38262
38263                                         // move existing object into the CACHED region
38264
38265                                         var lastCachedIndex = nCachedObjects ++,
38266                                                 firstActiveObject = objects[ lastCachedIndex ];
38267
38268                                         indicesByUUID[ firstActiveObject.uuid ] = index;
38269                                         objects[ index ] = firstActiveObject;
38270
38271                                         indicesByUUID[ uuid ] = lastCachedIndex;
38272                                         objects[ lastCachedIndex ] = object;
38273
38274                                         // accounting is done, now do the same for all bindings
38275
38276                                         for ( var j = 0, m = nBindings; j !== m; ++ j ) {
38277
38278                                                 var bindingsForPath = bindings[ j ],
38279                                                         firstActive = bindingsForPath[ lastCachedIndex ],
38280                                                         binding = bindingsForPath[ index ];
38281
38282                                                 bindingsForPath[ index ] = firstActive;
38283                                                 bindingsForPath[ lastCachedIndex ] = binding;
38284
38285                                         }
38286
38287                                 }
38288
38289                         } // for arguments
38290
38291                         this.nCachedObjects_ = nCachedObjects;
38292
38293                 },
38294
38295                 // remove & forget
38296                 uncache: function( var_args ) {
38297
38298                         var objects = this._objects,
38299                                 nObjects = objects.length,
38300                                 nCachedObjects = this.nCachedObjects_,
38301                                 indicesByUUID = this._indicesByUUID,
38302                                 bindings = this._bindings,
38303                                 nBindings = bindings.length;
38304
38305                         for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
38306
38307                                 var object = arguments[ i ],
38308                                         uuid = object.uuid,
38309                                         index = indicesByUUID[ uuid ];
38310
38311                                 if ( index !== undefined ) {
38312
38313                                         delete indicesByUUID[ uuid ];
38314
38315                                         if ( index < nCachedObjects ) {
38316
38317                                                 // object is cached, shrink the CACHED region
38318
38319                                                 var firstActiveIndex = -- nCachedObjects,
38320                                                         lastCachedObject = objects[ firstActiveIndex ],
38321                                                         lastIndex = -- nObjects,
38322                                                         lastObject = objects[ lastIndex ];
38323
38324                                                 // last cached object takes this object's place
38325                                                 indicesByUUID[ lastCachedObject.uuid ] = index;
38326                                                 objects[ index ] = lastCachedObject;
38327
38328                                                 // last object goes to the activated slot and pop
38329                                                 indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
38330                                                 objects[ firstActiveIndex ] = lastObject;
38331                                                 objects.pop();
38332
38333                                                 // accounting is done, now do the same for all bindings
38334
38335                                                 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
38336
38337                                                         var bindingsForPath = bindings[ j ],
38338                                                                 lastCached = bindingsForPath[ firstActiveIndex ],
38339                                                                 last = bindingsForPath[ lastIndex ];
38340
38341                                                         bindingsForPath[ index ] = lastCached;
38342                                                         bindingsForPath[ firstActiveIndex ] = last;
38343                                                         bindingsForPath.pop();
38344
38345                                                 }
38346
38347                                         } else {
38348
38349                                                 // object is active, just swap with the last and pop
38350
38351                                                 var lastIndex = -- nObjects,
38352                                                         lastObject = objects[ lastIndex ];
38353
38354                                                 indicesByUUID[ lastObject.uuid ] = index;
38355                                                 objects[ index ] = lastObject;
38356                                                 objects.pop();
38357
38358                                                 // accounting is done, now do the same for all bindings
38359
38360                                                 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
38361
38362                                                         var bindingsForPath = bindings[ j ];
38363
38364                                                         bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
38365                                                         bindingsForPath.pop();
38366
38367                                                 }
38368
38369                                         } // cached or active
38370
38371                                 } // if object is known
38372
38373                         } // for arguments
38374
38375                         this.nCachedObjects_ = nCachedObjects;
38376
38377                 },
38378
38379                 // Internal interface used by befriended PropertyBinding.Composite:
38380
38381                 subscribe_: function ( path, parsedPath ) {
38382
38383                         // returns an array of bindings for the given path that is changed
38384                         // according to the contained objects in the group
38385
38386                         var indicesByPath = this._bindingsIndicesByPath,
38387                                 index = indicesByPath[ path ],
38388                                 bindings = this._bindings;
38389
38390                         if ( index !== undefined ) return bindings[ index ];
38391
38392                         var paths = this._paths,
38393                                 parsedPaths = this._parsedPaths,
38394                                 objects = this._objects,
38395                                 nObjects = objects.length,
38396                                 nCachedObjects = this.nCachedObjects_,
38397                                 bindingsForPath = new Array( nObjects );
38398
38399                         index = bindings.length;
38400
38401                         indicesByPath[ path ] = index;
38402
38403                         paths.push( path );
38404                         parsedPaths.push( parsedPath );
38405                         bindings.push( bindingsForPath );
38406
38407                         for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
38408
38409                                 var object = objects[ i ];
38410                                 bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
38411
38412                         }
38413
38414                         return bindingsForPath;
38415
38416                 },
38417
38418                 unsubscribe_: function ( path ) {
38419
38420                         // tells the group to forget about a property path and no longer
38421                         // update the array previously obtained with 'subscribe_'
38422
38423                         var indicesByPath = this._bindingsIndicesByPath,
38424                                 index = indicesByPath[ path ];
38425
38426                         if ( index !== undefined ) {
38427
38428                                 var paths = this._paths,
38429                                         parsedPaths = this._parsedPaths,
38430                                         bindings = this._bindings,
38431                                         lastBindingsIndex = bindings.length - 1,
38432                                         lastBindings = bindings[ lastBindingsIndex ],
38433                                         lastBindingsPath = path[ lastBindingsIndex ];
38434
38435                                 indicesByPath[ lastBindingsPath ] = index;
38436
38437                                 bindings[ index ] = lastBindings;
38438                                 bindings.pop();
38439
38440                                 parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
38441                                 parsedPaths.pop();
38442
38443                                 paths[ index ] = paths[ lastBindingsIndex ];
38444                                 paths.pop();
38445
38446                         }
38447
38448                 }
38449
38450         } );
38451
38452         /**
38453          *
38454          * Action provided by AnimationMixer for scheduling clip playback on specific
38455          * objects.
38456          *
38457          * @author Ben Houston / http://clara.io/
38458          * @author David Sarno / http://lighthaus.us/
38459          * @author tschw
38460          *
38461          */
38462
38463         function AnimationAction( mixer, clip, localRoot ) {
38464
38465                 this._mixer = mixer;
38466                 this._clip = clip;
38467                 this._localRoot = localRoot || null;
38468
38469                 var tracks = clip.tracks,
38470                         nTracks = tracks.length,
38471                         interpolants = new Array( nTracks );
38472
38473                 var interpolantSettings = {
38474                                 endingStart:    ZeroCurvatureEnding,
38475                                 endingEnd:              ZeroCurvatureEnding
38476                 };
38477
38478                 for ( var i = 0; i !== nTracks; ++ i ) {
38479
38480                         var interpolant = tracks[ i ].createInterpolant( null );
38481                         interpolants[ i ] = interpolant;
38482                         interpolant.settings = interpolantSettings;
38483
38484                 }
38485
38486                 this._interpolantSettings = interpolantSettings;
38487
38488                 this._interpolants = interpolants;      // bound by the mixer
38489
38490                 // inside: PropertyMixer (managed by the mixer)
38491                 this._propertyBindings = new Array( nTracks );
38492
38493                 this._cacheIndex = null;                        // for the memory manager
38494                 this._byClipCacheIndex = null;          // for the memory manager
38495
38496                 this._timeScaleInterpolant = null;
38497                 this._weightInterpolant = null;
38498
38499                 this.loop = LoopRepeat;
38500                 this._loopCount = -1;
38501
38502                 // global mixer time when the action is to be started
38503                 // it's set back to 'null' upon start of the action
38504                 this._startTime = null;
38505
38506                 // scaled local time of the action
38507                 // gets clamped or wrapped to 0..clip.duration according to loop
38508                 this.time = 0;
38509
38510                 this.timeScale = 1;
38511                 this._effectiveTimeScale = 1;
38512
38513                 this.weight = 1;
38514                 this._effectiveWeight = 1;
38515
38516                 this.repetitions = Infinity;            // no. of repetitions when looping
38517
38518                 this.paused = false;                            // true -> zero effective time scale
38519                 this.enabled = true;                            // false -> zero effective weight
38520
38521                 this.clampWhenFinished  = false;        // keep feeding the last frame?
38522
38523                 this.zeroSlopeAtStart   = true;         // for smooth interpolation w/o separate
38524                 this.zeroSlopeAtEnd             = true;         // clips for start, loop and end
38525
38526         }
38527
38528         Object.assign( AnimationAction.prototype, {
38529
38530                 // State & Scheduling
38531
38532                 play: function() {
38533
38534                         this._mixer._activateAction( this );
38535
38536                         return this;
38537
38538                 },
38539
38540                 stop: function() {
38541
38542                         this._mixer._deactivateAction( this );
38543
38544                         return this.reset();
38545
38546                 },
38547
38548                 reset: function() {
38549
38550                         this.paused = false;
38551                         this.enabled = true;
38552
38553                         this.time = 0;                  // restart clip
38554                         this._loopCount = -1;   // forget previous loops
38555                         this._startTime = null; // forget scheduling
38556
38557                         return this.stopFading().stopWarping();
38558
38559                 },
38560
38561                 isRunning: function() {
38562
38563                         return this.enabled && ! this.paused && this.timeScale !== 0 &&
38564                                         this._startTime === null && this._mixer._isActiveAction( this );
38565
38566                 },
38567
38568                 // return true when play has been called
38569                 isScheduled: function() {
38570
38571                         return this._mixer._isActiveAction( this );
38572
38573                 },
38574
38575                 startAt: function( time ) {
38576
38577                         this._startTime = time;
38578
38579                         return this;
38580
38581                 },
38582
38583                 setLoop: function( mode, repetitions ) {
38584
38585                         this.loop = mode;
38586                         this.repetitions = repetitions;
38587
38588                         return this;
38589
38590                 },
38591
38592                 // Weight
38593
38594                 // set the weight stopping any scheduled fading
38595                 // although .enabled = false yields an effective weight of zero, this
38596                 // method does *not* change .enabled, because it would be confusing
38597                 setEffectiveWeight: function( weight ) {
38598
38599                         this.weight = weight;
38600
38601                         // note: same logic as when updated at runtime
38602                         this._effectiveWeight = this.enabled ? weight : 0;
38603
38604                         return this.stopFading();
38605
38606                 },
38607
38608                 // return the weight considering fading and .enabled
38609                 getEffectiveWeight: function() {
38610
38611                         return this._effectiveWeight;
38612
38613                 },
38614
38615                 fadeIn: function( duration ) {
38616
38617                         return this._scheduleFading( duration, 0, 1 );
38618
38619                 },
38620
38621                 fadeOut: function( duration ) {
38622
38623                         return this._scheduleFading( duration, 1, 0 );
38624
38625                 },
38626
38627                 crossFadeFrom: function( fadeOutAction, duration, warp ) {
38628
38629                         fadeOutAction.fadeOut( duration );
38630                         this.fadeIn( duration );
38631
38632                         if( warp ) {
38633
38634                                 var fadeInDuration = this._clip.duration,
38635                                         fadeOutDuration = fadeOutAction._clip.duration,
38636
38637                                         startEndRatio = fadeOutDuration / fadeInDuration,
38638                                         endStartRatio = fadeInDuration / fadeOutDuration;
38639
38640                                 fadeOutAction.warp( 1.0, startEndRatio, duration );
38641                                 this.warp( endStartRatio, 1.0, duration );
38642
38643                         }
38644
38645                         return this;
38646
38647                 },
38648
38649                 crossFadeTo: function( fadeInAction, duration, warp ) {
38650
38651                         return fadeInAction.crossFadeFrom( this, duration, warp );
38652
38653                 },
38654
38655                 stopFading: function() {
38656
38657                         var weightInterpolant = this._weightInterpolant;
38658
38659                         if ( weightInterpolant !== null ) {
38660
38661                                 this._weightInterpolant = null;
38662                                 this._mixer._takeBackControlInterpolant( weightInterpolant );
38663
38664                         }
38665
38666                         return this;
38667
38668                 },
38669
38670                 // Time Scale Control
38671
38672                 // set the time scale stopping any scheduled warping
38673                 // although .paused = true yields an effective time scale of zero, this
38674                 // method does *not* change .paused, because it would be confusing
38675                 setEffectiveTimeScale: function( timeScale ) {
38676
38677                         this.timeScale = timeScale;
38678                         this._effectiveTimeScale = this.paused ? 0 :timeScale;
38679
38680                         return this.stopWarping();
38681
38682                 },
38683
38684                 // return the time scale considering warping and .paused
38685                 getEffectiveTimeScale: function() {
38686
38687                         return this._effectiveTimeScale;
38688
38689                 },
38690
38691                 setDuration: function( duration ) {
38692
38693                         this.timeScale = this._clip.duration / duration;
38694
38695                         return this.stopWarping();
38696
38697                 },
38698
38699                 syncWith: function( action ) {
38700
38701                         this.time = action.time;
38702                         this.timeScale = action.timeScale;
38703
38704                         return this.stopWarping();
38705
38706                 },
38707
38708                 halt: function( duration ) {
38709
38710                         return this.warp( this._effectiveTimeScale, 0, duration );
38711
38712                 },
38713
38714                 warp: function( startTimeScale, endTimeScale, duration ) {
38715
38716                         var mixer = this._mixer, now = mixer.time,
38717                                 interpolant = this._timeScaleInterpolant,
38718
38719                                 timeScale = this.timeScale;
38720
38721                         if ( interpolant === null ) {
38722
38723                                 interpolant = mixer._lendControlInterpolant();
38724                                 this._timeScaleInterpolant = interpolant;
38725
38726                         }
38727
38728                         var times = interpolant.parameterPositions,
38729                                 values = interpolant.sampleValues;
38730
38731                         times[ 0 ] = now;
38732                         times[ 1 ] = now + duration;
38733
38734                         values[ 0 ] = startTimeScale / timeScale;
38735                         values[ 1 ] = endTimeScale / timeScale;
38736
38737                         return this;
38738
38739                 },
38740
38741                 stopWarping: function() {
38742
38743                         var timeScaleInterpolant = this._timeScaleInterpolant;
38744
38745                         if ( timeScaleInterpolant !== null ) {
38746
38747                                 this._timeScaleInterpolant = null;
38748                                 this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
38749
38750                         }
38751
38752                         return this;
38753
38754                 },
38755
38756                 // Object Accessors
38757
38758                 getMixer: function() {
38759
38760                         return this._mixer;
38761
38762                 },
38763
38764                 getClip: function() {
38765
38766                         return this._clip;
38767
38768                 },
38769
38770                 getRoot: function() {
38771
38772                         return this._localRoot || this._mixer._root;
38773
38774                 },
38775
38776                 // Interna
38777
38778                 _update: function( time, deltaTime, timeDirection, accuIndex ) {
38779
38780                         // called by the mixer
38781
38782                         if ( ! this.enabled ) {
38783
38784                                 // call ._updateWeight() to update ._effectiveWeight
38785
38786                                 this._updateWeight( time );
38787                                 return;
38788
38789                         }
38790
38791                         var startTime = this._startTime;
38792
38793                         if ( startTime !== null ) {
38794
38795                                 // check for scheduled start of action
38796
38797                                 var timeRunning = ( time - startTime ) * timeDirection;
38798                                 if ( timeRunning < 0 || timeDirection === 0 ) {
38799
38800                                         return; // yet to come / don't decide when delta = 0
38801
38802                                 }
38803
38804                                 // start
38805
38806                                 this._startTime = null; // unschedule
38807                                 deltaTime = timeDirection * timeRunning;
38808
38809                         }
38810
38811                         // apply time scale and advance time
38812
38813                         deltaTime *= this._updateTimeScale( time );
38814                         var clipTime = this._updateTime( deltaTime );
38815
38816                         // note: _updateTime may disable the action resulting in
38817                         // an effective weight of 0
38818
38819                         var weight = this._updateWeight( time );
38820
38821                         if ( weight > 0 ) {
38822
38823                                 var interpolants = this._interpolants;
38824                                 var propertyMixers = this._propertyBindings;
38825
38826                                 for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {
38827
38828                                         interpolants[ j ].evaluate( clipTime );
38829                                         propertyMixers[ j ].accumulate( accuIndex, weight );
38830
38831                                 }
38832
38833                         }
38834
38835                 },
38836
38837                 _updateWeight: function( time ) {
38838
38839                         var weight = 0;
38840
38841                         if ( this.enabled ) {
38842
38843                                 weight = this.weight;
38844                                 var interpolant = this._weightInterpolant;
38845
38846                                 if ( interpolant !== null ) {
38847
38848                                         var interpolantValue = interpolant.evaluate( time )[ 0 ];
38849
38850                                         weight *= interpolantValue;
38851
38852                                         if ( time > interpolant.parameterPositions[ 1 ] ) {
38853
38854                                                 this.stopFading();
38855
38856                                                 if ( interpolantValue === 0 ) {
38857
38858                                                         // faded out, disable
38859                                                         this.enabled = false;
38860
38861                                                 }
38862
38863                                         }
38864
38865                                 }
38866
38867                         }
38868
38869                         this._effectiveWeight = weight;
38870                         return weight;
38871
38872                 },
38873
38874                 _updateTimeScale: function( time ) {
38875
38876                         var timeScale = 0;
38877
38878                         if ( ! this.paused ) {
38879
38880                                 timeScale = this.timeScale;
38881
38882                                 var interpolant = this._timeScaleInterpolant;
38883
38884                                 if ( interpolant !== null ) {
38885
38886                                         var interpolantValue = interpolant.evaluate( time )[ 0 ];
38887
38888                                         timeScale *= interpolantValue;
38889
38890                                         if ( time > interpolant.parameterPositions[ 1 ] ) {
38891
38892                                                 this.stopWarping();
38893
38894                                                 if ( timeScale === 0 ) {
38895
38896                                                         // motion has halted, pause
38897                                                         this.paused = true;
38898
38899                                                 } else {
38900
38901                                                         // warp done - apply final time scale
38902                                                         this.timeScale = timeScale;
38903
38904                                                 }
38905
38906                                         }
38907
38908                                 }
38909
38910                         }
38911
38912                         this._effectiveTimeScale = timeScale;
38913                         return timeScale;
38914
38915                 },
38916
38917                 _updateTime: function( deltaTime ) {
38918
38919                         var time = this.time + deltaTime;
38920
38921                         if ( deltaTime === 0 ) return time;
38922
38923                         var duration = this._clip.duration,
38924
38925                                 loop = this.loop,
38926                                 loopCount = this._loopCount;
38927
38928                         if ( loop === LoopOnce ) {
38929
38930                                 if ( loopCount === -1 ) {
38931                                         // just started
38932
38933                                         this._loopCount = 0;
38934                                         this._setEndings( true, true, false );
38935
38936                                 }
38937
38938                                 handle_stop: {
38939
38940                                         if ( time >= duration ) {
38941
38942                                                 time = duration;
38943
38944                                         } else if ( time < 0 ) {
38945
38946                                                 time = 0;
38947
38948                                         } else break handle_stop;
38949
38950                                         if ( this.clampWhenFinished ) this.paused = true;
38951                                         else this.enabled = false;
38952
38953                                         this._mixer.dispatchEvent( {
38954                                                 type: 'finished', action: this,
38955                                                 direction: deltaTime < 0 ? -1 : 1
38956                                         } );
38957
38958                                 }
38959
38960                         } else { // repetitive Repeat or PingPong
38961
38962                                 var pingPong = ( loop === LoopPingPong );
38963
38964                                 if ( loopCount === -1 ) {
38965                                         // just started
38966
38967                                         if ( deltaTime >= 0 ) {
38968
38969                                                 loopCount = 0;
38970
38971                                                 this._setEndings(
38972                                                                 true, this.repetitions === 0, pingPong );
38973
38974                                         } else {
38975
38976                                                 // when looping in reverse direction, the initial
38977                                                 // transition through zero counts as a repetition,
38978                                                 // so leave loopCount at -1
38979
38980                                                 this._setEndings(
38981                                                                 this.repetitions === 0, true, pingPong );
38982
38983                                         }
38984
38985                                 }
38986
38987                                 if ( time >= duration || time < 0 ) {
38988                                         // wrap around
38989
38990                                         var loopDelta = Math.floor( time / duration ); // signed
38991                                         time -= duration * loopDelta;
38992
38993                                         loopCount += Math.abs( loopDelta );
38994
38995                                         var pending = this.repetitions - loopCount;
38996
38997                                         if ( pending < 0 ) {
38998                                                 // have to stop (switch state, clamp time, fire event)
38999
39000                                                 if ( this.clampWhenFinished ) this.paused = true;
39001                                                 else this.enabled = false;
39002
39003                                                 time = deltaTime > 0 ? duration : 0;
39004
39005                                                 this._mixer.dispatchEvent( {
39006                                                         type: 'finished', action: this,
39007                                                         direction: deltaTime > 0 ? 1 : -1
39008                                                 } );
39009
39010                                         } else {
39011                                                 // keep running
39012
39013                                                 if ( pending === 0 ) {
39014                                                         // entering the last round
39015
39016                                                         var atStart = deltaTime < 0;
39017                                                         this._setEndings( atStart, ! atStart, pingPong );
39018
39019                                                 } else {
39020
39021                                                         this._setEndings( false, false, pingPong );
39022
39023                                                 }
39024
39025                                                 this._loopCount = loopCount;
39026
39027                                                 this._mixer.dispatchEvent( {
39028                                                         type: 'loop', action: this, loopDelta: loopDelta
39029                                                 } );
39030
39031                                         }
39032
39033                                 }
39034
39035                                 if ( pingPong && ( loopCount & 1 ) === 1 ) {
39036                                         // invert time for the "pong round"
39037
39038                                         this.time = time;
39039                                         return duration - time;
39040
39041                                 }
39042
39043                         }
39044
39045                         this.time = time;
39046                         return time;
39047
39048                 },
39049
39050                 _setEndings: function( atStart, atEnd, pingPong ) {
39051
39052                         var settings = this._interpolantSettings;
39053
39054                         if ( pingPong ) {
39055
39056                                 settings.endingStart    = ZeroSlopeEnding;
39057                                 settings.endingEnd              = ZeroSlopeEnding;
39058
39059                         } else {
39060
39061                                 // assuming for LoopOnce atStart == atEnd == true
39062
39063                                 if ( atStart ) {
39064
39065                                         settings.endingStart = this.zeroSlopeAtStart ?
39066                                                         ZeroSlopeEnding : ZeroCurvatureEnding;
39067
39068                                 } else {
39069
39070                                         settings.endingStart = WrapAroundEnding;
39071
39072                                 }
39073
39074                                 if ( atEnd ) {
39075
39076                                         settings.endingEnd = this.zeroSlopeAtEnd ?
39077                                                         ZeroSlopeEnding : ZeroCurvatureEnding;
39078
39079                                 } else {
39080
39081                                         settings.endingEnd       = WrapAroundEnding;
39082
39083                                 }
39084
39085                         }
39086
39087                 },
39088
39089                 _scheduleFading: function( duration, weightNow, weightThen ) {
39090
39091                         var mixer = this._mixer, now = mixer.time,
39092                                 interpolant = this._weightInterpolant;
39093
39094                         if ( interpolant === null ) {
39095
39096                                 interpolant = mixer._lendControlInterpolant();
39097                                 this._weightInterpolant = interpolant;
39098
39099                         }
39100
39101                         var times = interpolant.parameterPositions,
39102                                 values = interpolant.sampleValues;
39103
39104                         times[ 0 ] = now;                               values[ 0 ] = weightNow;
39105                         times[ 1 ] = now + duration;    values[ 1 ] = weightThen;
39106
39107                         return this;
39108
39109                 }
39110
39111         } );
39112
39113         /**
39114          *
39115          * Player for AnimationClips.
39116          *
39117          *
39118          * @author Ben Houston / http://clara.io/
39119          * @author David Sarno / http://lighthaus.us/
39120          * @author tschw
39121          */
39122
39123         function AnimationMixer( root ) {
39124
39125                 this._root = root;
39126                 this._initMemoryManager();
39127                 this._accuIndex = 0;
39128
39129                 this.time = 0;
39130
39131                 this.timeScale = 1.0;
39132
39133         }
39134
39135         Object.assign( AnimationMixer.prototype, EventDispatcher.prototype, {
39136
39137                 _bindAction: function ( action, prototypeAction ) {
39138
39139                         var root = action._localRoot || this._root,
39140                                 tracks = action._clip.tracks,
39141                                 nTracks = tracks.length,
39142                                 bindings = action._propertyBindings,
39143                                 interpolants = action._interpolants,
39144                                 rootUuid = root.uuid,
39145                                 bindingsByRoot = this._bindingsByRootAndName,
39146                                 bindingsByName = bindingsByRoot[ rootUuid ];
39147
39148                         if ( bindingsByName === undefined ) {
39149
39150                                 bindingsByName = {};
39151                                 bindingsByRoot[ rootUuid ] = bindingsByName;
39152
39153                         }
39154
39155                         for ( var i = 0; i !== nTracks; ++ i ) {
39156
39157                                 var track = tracks[ i ],
39158                                         trackName = track.name,
39159                                         binding = bindingsByName[ trackName ];
39160
39161                                 if ( binding !== undefined ) {
39162
39163                                         bindings[ i ] = binding;
39164
39165                                 } else {
39166
39167                                         binding = bindings[ i ];
39168
39169                                         if ( binding !== undefined ) {
39170
39171                                                 // existing binding, make sure the cache knows
39172
39173                                                 if ( binding._cacheIndex === null ) {
39174
39175                                                         ++ binding.referenceCount;
39176                                                         this._addInactiveBinding( binding, rootUuid, trackName );
39177
39178                                                 }
39179
39180                                                 continue;
39181
39182                                         }
39183
39184                                         var path = prototypeAction && prototypeAction.
39185                                                         _propertyBindings[ i ].binding.parsedPath;
39186
39187                                         binding = new PropertyMixer(
39188                                                 PropertyBinding.create( root, trackName, path ),
39189                                                 track.ValueTypeName, track.getValueSize() );
39190
39191                                         ++ binding.referenceCount;
39192                                         this._addInactiveBinding( binding, rootUuid, trackName );
39193
39194                                         bindings[ i ] = binding;
39195
39196                                 }
39197
39198                                 interpolants[ i ].resultBuffer = binding.buffer;
39199
39200                         }
39201
39202                 },
39203
39204                 _activateAction: function ( action ) {
39205
39206                         if ( ! this._isActiveAction( action ) ) {
39207
39208                                 if ( action._cacheIndex === null ) {
39209
39210                                         // this action has been forgotten by the cache, but the user
39211                                         // appears to be still using it -> rebind
39212
39213                                         var rootUuid = ( action._localRoot || this._root ).uuid,
39214                                                 clipUuid = action._clip.uuid,
39215                                                 actionsForClip = this._actionsByClip[ clipUuid ];
39216
39217                                         this._bindAction( action,
39218                                                 actionsForClip && actionsForClip.knownActions[ 0 ] );
39219
39220                                         this._addInactiveAction( action, clipUuid, rootUuid );
39221
39222                                 }
39223
39224                                 var bindings = action._propertyBindings;
39225
39226                                 // increment reference counts / sort out state
39227                                 for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
39228
39229                                         var binding = bindings[ i ];
39230
39231                                         if ( binding.useCount ++ === 0 ) {
39232
39233                                                 this._lendBinding( binding );
39234                                                 binding.saveOriginalState();
39235
39236                                         }
39237
39238                                 }
39239
39240                                 this._lendAction( action );
39241
39242                         }
39243
39244                 },
39245
39246                 _deactivateAction: function ( action ) {
39247
39248                         if ( this._isActiveAction( action ) ) {
39249
39250                                 var bindings = action._propertyBindings;
39251
39252                                 // decrement reference counts / sort out state
39253                                 for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
39254
39255                                         var binding = bindings[ i ];
39256
39257                                         if ( -- binding.useCount === 0 ) {
39258
39259                                                 binding.restoreOriginalState();
39260                                                 this._takeBackBinding( binding );
39261
39262                                         }
39263
39264                                 }
39265
39266                                 this._takeBackAction( action );
39267
39268                         }
39269
39270                 },
39271
39272                 // Memory manager
39273
39274                 _initMemoryManager: function () {
39275
39276                         this._actions = []; // 'nActiveActions' followed by inactive ones
39277                         this._nActiveActions = 0;
39278
39279                         this._actionsByClip = {};
39280                         // inside:
39281                         // {
39282                         //              knownActions: Array< AnimationAction >  - used as prototypes
39283                         //              actionByRoot: AnimationAction                   - lookup
39284                         // }
39285
39286
39287                         this._bindings = []; // 'nActiveBindings' followed by inactive ones
39288                         this._nActiveBindings = 0;
39289
39290                         this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
39291
39292
39293                         this._controlInterpolants = []; // same game as above
39294                         this._nActiveControlInterpolants = 0;
39295
39296                         var scope = this;
39297
39298                         this.stats = {
39299
39300                                 actions: {
39301                                         get total() { return scope._actions.length; },
39302                                         get inUse() { return scope._nActiveActions; }
39303                                 },
39304                                 bindings: {
39305                                         get total() { return scope._bindings.length; },
39306                                         get inUse() { return scope._nActiveBindings; }
39307                                 },
39308                                 controlInterpolants: {
39309                                         get total() { return scope._controlInterpolants.length; },
39310                                         get inUse() { return scope._nActiveControlInterpolants; }
39311                                 }
39312
39313                         };
39314
39315                 },
39316
39317                 // Memory management for AnimationAction objects
39318
39319                 _isActiveAction: function ( action ) {
39320
39321                         var index = action._cacheIndex;
39322                         return index !== null && index < this._nActiveActions;
39323
39324                 },
39325
39326                 _addInactiveAction: function ( action, clipUuid, rootUuid ) {
39327
39328                         var actions = this._actions,
39329                                 actionsByClip = this._actionsByClip,
39330                                 actionsForClip = actionsByClip[ clipUuid ];
39331
39332                         if ( actionsForClip === undefined ) {
39333
39334                                 actionsForClip = {
39335
39336                                         knownActions: [ action ],
39337                                         actionByRoot: {}
39338
39339                                 };
39340
39341                                 action._byClipCacheIndex = 0;
39342
39343                                 actionsByClip[ clipUuid ] = actionsForClip;
39344
39345                         } else {
39346
39347                                 var knownActions = actionsForClip.knownActions;
39348
39349                                 action._byClipCacheIndex = knownActions.length;
39350                                 knownActions.push( action );
39351
39352                         }
39353
39354                         action._cacheIndex = actions.length;
39355                         actions.push( action );
39356
39357                         actionsForClip.actionByRoot[ rootUuid ] = action;
39358
39359                 },
39360
39361                 _removeInactiveAction: function ( action ) {
39362
39363                         var actions = this._actions,
39364                                 lastInactiveAction = actions[ actions.length - 1 ],
39365                                 cacheIndex = action._cacheIndex;
39366
39367                         lastInactiveAction._cacheIndex = cacheIndex;
39368                         actions[ cacheIndex ] = lastInactiveAction;
39369                         actions.pop();
39370
39371                         action._cacheIndex = null;
39372
39373
39374                         var clipUuid = action._clip.uuid,
39375                                 actionsByClip = this._actionsByClip,
39376                                 actionsForClip = actionsByClip[ clipUuid ],
39377                                 knownActionsForClip = actionsForClip.knownActions,
39378
39379                                 lastKnownAction =
39380                                         knownActionsForClip[ knownActionsForClip.length - 1 ],
39381
39382                                 byClipCacheIndex = action._byClipCacheIndex;
39383
39384                         lastKnownAction._byClipCacheIndex = byClipCacheIndex;
39385                         knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
39386                         knownActionsForClip.pop();
39387
39388                         action._byClipCacheIndex = null;
39389
39390
39391                         var actionByRoot = actionsForClip.actionByRoot,
39392                                 rootUuid = ( action._localRoot || this._root ).uuid;
39393
39394                         delete actionByRoot[ rootUuid ];
39395
39396                         if ( knownActionsForClip.length === 0 ) {
39397
39398                                 delete actionsByClip[ clipUuid ];
39399
39400                         }
39401
39402                         this._removeInactiveBindingsForAction( action );
39403
39404                 },
39405
39406                 _removeInactiveBindingsForAction: function ( action ) {
39407
39408                         var bindings = action._propertyBindings;
39409                         for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
39410
39411                                 var binding = bindings[ i ];
39412
39413                                 if ( -- binding.referenceCount === 0 ) {
39414
39415                                         this._removeInactiveBinding( binding );
39416
39417                                 }
39418
39419                         }
39420
39421                 },
39422
39423                 _lendAction: function ( action ) {
39424
39425                         // [ active actions |  inactive actions  ]
39426                         // [  active actions >| inactive actions ]
39427                         //                 s        a
39428                         //                  <-swap->
39429                         //                 a        s
39430
39431                         var actions = this._actions,
39432                                 prevIndex = action._cacheIndex,
39433
39434                                 lastActiveIndex = this._nActiveActions ++,
39435
39436                                 firstInactiveAction = actions[ lastActiveIndex ];
39437
39438                         action._cacheIndex = lastActiveIndex;
39439                         actions[ lastActiveIndex ] = action;
39440
39441                         firstInactiveAction._cacheIndex = prevIndex;
39442                         actions[ prevIndex ] = firstInactiveAction;
39443
39444                 },
39445
39446                 _takeBackAction: function ( action ) {
39447
39448                         // [  active actions  | inactive actions ]
39449                         // [ active actions |< inactive actions  ]
39450                         //        a        s
39451                         //         <-swap->
39452                         //        s        a
39453
39454                         var actions = this._actions,
39455                                 prevIndex = action._cacheIndex,
39456
39457                                 firstInactiveIndex = -- this._nActiveActions,
39458
39459                                 lastActiveAction = actions[ firstInactiveIndex ];
39460
39461                         action._cacheIndex = firstInactiveIndex;
39462                         actions[ firstInactiveIndex ] = action;
39463
39464                         lastActiveAction._cacheIndex = prevIndex;
39465                         actions[ prevIndex ] = lastActiveAction;
39466
39467                 },
39468
39469                 // Memory management for PropertyMixer objects
39470
39471                 _addInactiveBinding: function ( binding, rootUuid, trackName ) {
39472
39473                         var bindingsByRoot = this._bindingsByRootAndName,
39474                                 bindingByName = bindingsByRoot[ rootUuid ],
39475
39476                                 bindings = this._bindings;
39477
39478                         if ( bindingByName === undefined ) {
39479
39480                                 bindingByName = {};
39481                                 bindingsByRoot[ rootUuid ] = bindingByName;
39482
39483                         }
39484
39485                         bindingByName[ trackName ] = binding;
39486
39487                         binding._cacheIndex = bindings.length;
39488                         bindings.push( binding );
39489
39490                 },
39491
39492                 _removeInactiveBinding: function ( binding ) {
39493
39494                         var bindings = this._bindings,
39495                                 propBinding = binding.binding,
39496                                 rootUuid = propBinding.rootNode.uuid,
39497                                 trackName = propBinding.path,
39498                                 bindingsByRoot = this._bindingsByRootAndName,
39499                                 bindingByName = bindingsByRoot[ rootUuid ],
39500
39501                                 lastInactiveBinding = bindings[ bindings.length - 1 ],
39502                                 cacheIndex = binding._cacheIndex;
39503
39504                         lastInactiveBinding._cacheIndex = cacheIndex;
39505                         bindings[ cacheIndex ] = lastInactiveBinding;
39506                         bindings.pop();
39507
39508                         delete bindingByName[ trackName ];
39509
39510                         remove_empty_map: {
39511
39512                                 for ( var _ in bindingByName ) break remove_empty_map;
39513
39514                                 delete bindingsByRoot[ rootUuid ];
39515
39516                         }
39517
39518                 },
39519
39520                 _lendBinding: function ( binding ) {
39521
39522                         var bindings = this._bindings,
39523                                 prevIndex = binding._cacheIndex,
39524
39525                                 lastActiveIndex = this._nActiveBindings ++,
39526
39527                                 firstInactiveBinding = bindings[ lastActiveIndex ];
39528
39529                         binding._cacheIndex = lastActiveIndex;
39530                         bindings[ lastActiveIndex ] = binding;
39531
39532                         firstInactiveBinding._cacheIndex = prevIndex;
39533                         bindings[ prevIndex ] = firstInactiveBinding;
39534
39535                 },
39536
39537                 _takeBackBinding: function ( binding ) {
39538
39539                         var bindings = this._bindings,
39540                                 prevIndex = binding._cacheIndex,
39541
39542                                 firstInactiveIndex = -- this._nActiveBindings,
39543
39544                                 lastActiveBinding = bindings[ firstInactiveIndex ];
39545
39546                         binding._cacheIndex = firstInactiveIndex;
39547                         bindings[ firstInactiveIndex ] = binding;
39548
39549                         lastActiveBinding._cacheIndex = prevIndex;
39550                         bindings[ prevIndex ] = lastActiveBinding;
39551
39552                 },
39553
39554
39555                 // Memory management of Interpolants for weight and time scale
39556
39557                 _lendControlInterpolant: function () {
39558
39559                         var interpolants = this._controlInterpolants,
39560                                 lastActiveIndex = this._nActiveControlInterpolants ++,
39561                                 interpolant = interpolants[ lastActiveIndex ];
39562
39563                         if ( interpolant === undefined ) {
39564
39565                                 interpolant = new LinearInterpolant(
39566                                         new Float32Array( 2 ), new Float32Array( 2 ),
39567                                         1, this._controlInterpolantsResultBuffer );
39568
39569                                 interpolant.__cacheIndex = lastActiveIndex;
39570                                 interpolants[ lastActiveIndex ] = interpolant;
39571
39572                         }
39573
39574                         return interpolant;
39575
39576                 },
39577
39578                 _takeBackControlInterpolant: function ( interpolant ) {
39579
39580                         var interpolants = this._controlInterpolants,
39581                                 prevIndex = interpolant.__cacheIndex,
39582
39583                                 firstInactiveIndex = -- this._nActiveControlInterpolants,
39584
39585                                 lastActiveInterpolant = interpolants[ firstInactiveIndex ];
39586
39587                         interpolant.__cacheIndex = firstInactiveIndex;
39588                         interpolants[ firstInactiveIndex ] = interpolant;
39589
39590                         lastActiveInterpolant.__cacheIndex = prevIndex;
39591                         interpolants[ prevIndex ] = lastActiveInterpolant;
39592
39593                 },
39594
39595                 _controlInterpolantsResultBuffer: new Float32Array( 1 ),
39596
39597                 // return an action for a clip optionally using a custom root target
39598                 // object (this method allocates a lot of dynamic memory in case a
39599                 // previously unknown clip/root combination is specified)
39600                 clipAction: function ( clip, optionalRoot ) {
39601
39602                         var root = optionalRoot || this._root,
39603                                 rootUuid = root.uuid,
39604
39605                                 clipObject = typeof clip === 'string' ?
39606                                         AnimationClip.findByName( root, clip ) : clip,
39607
39608                                 clipUuid = clipObject !== null ? clipObject.uuid : clip,
39609
39610                                 actionsForClip = this._actionsByClip[ clipUuid ],
39611                                 prototypeAction = null;
39612
39613                         if ( actionsForClip !== undefined ) {
39614
39615                                 var existingAction =
39616                                                 actionsForClip.actionByRoot[ rootUuid ];
39617
39618                                 if ( existingAction !== undefined ) {
39619
39620                                         return existingAction;
39621
39622                                 }
39623
39624                                 // we know the clip, so we don't have to parse all
39625                                 // the bindings again but can just copy
39626                                 prototypeAction = actionsForClip.knownActions[ 0 ];
39627
39628                                 // also, take the clip from the prototype action
39629                                 if ( clipObject === null )
39630                                         clipObject = prototypeAction._clip;
39631
39632                         }
39633
39634                         // clip must be known when specified via string
39635                         if ( clipObject === null ) return null;
39636
39637                         // allocate all resources required to run it
39638                         var newAction = new AnimationAction( this, clipObject, optionalRoot );
39639
39640                         this._bindAction( newAction, prototypeAction );
39641
39642                         // and make the action known to the memory manager
39643                         this._addInactiveAction( newAction, clipUuid, rootUuid );
39644
39645                         return newAction;
39646
39647                 },
39648
39649                 // get an existing action
39650                 existingAction: function ( clip, optionalRoot ) {
39651
39652                         var root = optionalRoot || this._root,
39653                                 rootUuid = root.uuid,
39654
39655                                 clipObject = typeof clip === 'string' ?
39656                                         AnimationClip.findByName( root, clip ) : clip,
39657
39658                                 clipUuid = clipObject ? clipObject.uuid : clip,
39659
39660                                 actionsForClip = this._actionsByClip[ clipUuid ];
39661
39662                         if ( actionsForClip !== undefined ) {
39663
39664                                 return actionsForClip.actionByRoot[ rootUuid ] || null;
39665
39666                         }
39667
39668                         return null;
39669
39670                 },
39671
39672                 // deactivates all previously scheduled actions
39673                 stopAllAction: function () {
39674
39675                         var actions = this._actions,
39676                                 nActions = this._nActiveActions,
39677                                 bindings = this._bindings,
39678                                 nBindings = this._nActiveBindings;
39679
39680                         this._nActiveActions = 0;
39681                         this._nActiveBindings = 0;
39682
39683                         for ( var i = 0; i !== nActions; ++ i ) {
39684
39685                                 actions[ i ].reset();
39686
39687                         }
39688
39689                         for ( var i = 0; i !== nBindings; ++ i ) {
39690
39691                                 bindings[ i ].useCount = 0;
39692
39693                         }
39694
39695                         return this;
39696
39697                 },
39698
39699                 // advance the time and update apply the animation
39700                 update: function ( deltaTime ) {
39701
39702                         deltaTime *= this.timeScale;
39703
39704                         var actions = this._actions,
39705                                 nActions = this._nActiveActions,
39706
39707                                 time = this.time += deltaTime,
39708                                 timeDirection = Math.sign( deltaTime ),
39709
39710                                 accuIndex = this._accuIndex ^= 1;
39711
39712                         // run active actions
39713
39714                         for ( var i = 0; i !== nActions; ++ i ) {
39715
39716                                 var action = actions[ i ];
39717
39718                                 action._update( time, deltaTime, timeDirection, accuIndex );
39719
39720                         }
39721
39722                         // update scene graph
39723
39724                         var bindings = this._bindings,
39725                                 nBindings = this._nActiveBindings;
39726
39727                         for ( var i = 0; i !== nBindings; ++ i ) {
39728
39729                                 bindings[ i ].apply( accuIndex );
39730
39731                         }
39732
39733                         return this;
39734
39735                 },
39736
39737                 // return this mixer's root target object
39738                 getRoot: function () {
39739
39740                         return this._root;
39741
39742                 },
39743
39744                 // free all resources specific to a particular clip
39745                 uncacheClip: function ( clip ) {
39746
39747                         var actions = this._actions,
39748                                 clipUuid = clip.uuid,
39749                                 actionsByClip = this._actionsByClip,
39750                                 actionsForClip = actionsByClip[ clipUuid ];
39751
39752                         if ( actionsForClip !== undefined ) {
39753
39754                                 // note: just calling _removeInactiveAction would mess up the
39755                                 // iteration state and also require updating the state we can
39756                                 // just throw away
39757
39758                                 var actionsToRemove = actionsForClip.knownActions;
39759
39760                                 for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
39761
39762                                         var action = actionsToRemove[ i ];
39763
39764                                         this._deactivateAction( action );
39765
39766                                         var cacheIndex = action._cacheIndex,
39767                                                 lastInactiveAction = actions[ actions.length - 1 ];
39768
39769                                         action._cacheIndex = null;
39770                                         action._byClipCacheIndex = null;
39771
39772                                         lastInactiveAction._cacheIndex = cacheIndex;
39773                                         actions[ cacheIndex ] = lastInactiveAction;
39774                                         actions.pop();
39775
39776                                         this._removeInactiveBindingsForAction( action );
39777
39778                                 }
39779
39780                                 delete actionsByClip[ clipUuid ];
39781
39782                         }
39783
39784                 },
39785
39786                 // free all resources specific to a particular root target object
39787                 uncacheRoot: function ( root ) {
39788
39789                         var rootUuid = root.uuid,
39790                                 actionsByClip = this._actionsByClip;
39791
39792                         for ( var clipUuid in actionsByClip ) {
39793
39794                                 var actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
39795                                         action = actionByRoot[ rootUuid ];
39796
39797                                 if ( action !== undefined ) {
39798
39799                                         this._deactivateAction( action );
39800                                         this._removeInactiveAction( action );
39801
39802                                 }
39803
39804                         }
39805
39806                         var bindingsByRoot = this._bindingsByRootAndName,
39807                                 bindingByName = bindingsByRoot[ rootUuid ];
39808
39809                         if ( bindingByName !== undefined ) {
39810
39811                                 for ( var trackName in bindingByName ) {
39812
39813                                         var binding = bindingByName[ trackName ];
39814                                         binding.restoreOriginalState();
39815                                         this._removeInactiveBinding( binding );
39816
39817                                 }
39818
39819                         }
39820
39821                 },
39822
39823                 // remove a targeted clip from the cache
39824                 uncacheAction: function ( clip, optionalRoot ) {
39825
39826                         var action = this.existingAction( clip, optionalRoot );
39827
39828                         if ( action !== null ) {
39829
39830                                 this._deactivateAction( action );
39831                                 this._removeInactiveAction( action );
39832
39833                         }
39834
39835                 }
39836
39837         } );
39838
39839         /**
39840          * @author mrdoob / http://mrdoob.com/
39841          */
39842
39843         function Uniform( value ) {
39844
39845                 if ( typeof value === 'string' ) {
39846
39847                         console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
39848                         value = arguments[ 1 ];
39849
39850                 }
39851
39852                 this.value = value;
39853
39854         }
39855
39856         Uniform.prototype.clone = function () {
39857
39858                 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
39859
39860         };
39861
39862         /**
39863          * @author benaadams / https://twitter.com/ben_a_adams
39864          */
39865
39866         function InstancedBufferGeometry() {
39867
39868                 BufferGeometry.call( this );
39869
39870                 this.type = 'InstancedBufferGeometry';
39871                 this.maxInstancedCount = undefined;
39872
39873         }
39874
39875         InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
39876
39877                 constructor: InstancedBufferGeometry,
39878
39879                 isInstancedBufferGeometry: true,
39880
39881                 addGroup: function ( start, count, materialIndex ) {
39882
39883                         this.groups.push( {
39884
39885                                 start: start,
39886                                 count: count,
39887                                 materialIndex: materialIndex
39888
39889                         } );
39890
39891                 },
39892
39893                 copy: function ( source ) {
39894
39895                         var index = source.index;
39896
39897                         if ( index !== null ) {
39898
39899                                 this.setIndex( index.clone() );
39900
39901                         }
39902
39903                         var attributes = source.attributes;
39904
39905                         for ( var name in attributes ) {
39906
39907                                 var attribute = attributes[ name ];
39908                                 this.addAttribute( name, attribute.clone() );
39909
39910                         }
39911
39912                         var groups = source.groups;
39913
39914                         for ( var i = 0, l = groups.length; i < l; i ++ ) {
39915
39916                                 var group = groups[ i ];
39917                                 this.addGroup( group.start, group.count, group.materialIndex );
39918
39919                         }
39920
39921                         return this;
39922
39923                 }
39924
39925         } );
39926
39927         /**
39928          * @author benaadams / https://twitter.com/ben_a_adams
39929          */
39930
39931         function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
39932
39933                 this.uuid = _Math.generateUUID();
39934
39935                 this.data = interleavedBuffer;
39936                 this.itemSize = itemSize;
39937                 this.offset = offset;
39938
39939                 this.normalized = normalized === true;
39940
39941         }
39942
39943         Object.defineProperties( InterleavedBufferAttribute.prototype, {
39944
39945                 count: {
39946
39947                         get: function () {
39948
39949                                 return this.data.count;
39950
39951                         }
39952
39953                 },
39954
39955                 array: {
39956
39957                         get: function () {
39958
39959                                 return this.data.array;
39960
39961                         }
39962
39963                 }
39964
39965         } );
39966
39967         Object.assign( InterleavedBufferAttribute.prototype, {
39968
39969                 isInterleavedBufferAttribute: true,
39970
39971                 setX: function ( index, x ) {
39972
39973                         this.data.array[ index * this.data.stride + this.offset ] = x;
39974
39975                         return this;
39976
39977                 },
39978
39979                 setY: function ( index, y ) {
39980
39981                         this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
39982
39983                         return this;
39984
39985                 },
39986
39987                 setZ: function ( index, z ) {
39988
39989                         this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
39990
39991                         return this;
39992
39993                 },
39994
39995                 setW: function ( index, w ) {
39996
39997                         this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
39998
39999                         return this;
40000
40001                 },
40002
40003                 getX: function ( index ) {
40004
40005                         return this.data.array[ index * this.data.stride + this.offset ];
40006
40007                 },
40008
40009                 getY: function ( index ) {
40010
40011                         return this.data.array[ index * this.data.stride + this.offset + 1 ];
40012
40013                 },
40014
40015                 getZ: function ( index ) {
40016
40017                         return this.data.array[ index * this.data.stride + this.offset + 2 ];
40018
40019                 },
40020
40021                 getW: function ( index ) {
40022
40023                         return this.data.array[ index * this.data.stride + this.offset + 3 ];
40024
40025                 },
40026
40027                 setXY: function ( index, x, y ) {
40028
40029                         index = index * this.data.stride + this.offset;
40030
40031                         this.data.array[ index + 0 ] = x;
40032                         this.data.array[ index + 1 ] = y;
40033
40034                         return this;
40035
40036                 },
40037
40038                 setXYZ: function ( index, x, y, z ) {
40039
40040                         index = index * this.data.stride + this.offset;
40041
40042                         this.data.array[ index + 0 ] = x;
40043                         this.data.array[ index + 1 ] = y;
40044                         this.data.array[ index + 2 ] = z;
40045
40046                         return this;
40047
40048                 },
40049
40050                 setXYZW: function ( index, x, y, z, w ) {
40051
40052                         index = index * this.data.stride + this.offset;
40053
40054                         this.data.array[ index + 0 ] = x;
40055                         this.data.array[ index + 1 ] = y;
40056                         this.data.array[ index + 2 ] = z;
40057                         this.data.array[ index + 3 ] = w;
40058
40059                         return this;
40060
40061                 }
40062
40063         } );
40064
40065         /**
40066          * @author benaadams / https://twitter.com/ben_a_adams
40067          */
40068
40069         function InterleavedBuffer( array, stride ) {
40070
40071                 this.uuid = _Math.generateUUID();
40072
40073                 this.array = array;
40074                 this.stride = stride;
40075                 this.count = array !== undefined ? array.length / stride : 0;
40076
40077                 this.dynamic = false;
40078                 this.updateRange = { offset: 0, count: - 1 };
40079
40080                 this.onUploadCallback = function () {};
40081
40082                 this.version = 0;
40083
40084         }
40085
40086         Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
40087
40088                 set: function ( value ) {
40089
40090                         if ( value === true ) this.version ++;
40091
40092                 }
40093
40094         } );
40095
40096         Object.assign( InterleavedBuffer.prototype, {
40097
40098                 isInterleavedBuffer: true,
40099
40100                 setArray: function ( array ) {
40101
40102                         if ( Array.isArray( array ) ) {
40103
40104                                 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
40105
40106                         }
40107
40108                         this.count = array !== undefined ? array.length / this.stride : 0;
40109                         this.array = array;
40110
40111                 },
40112
40113                 setDynamic: function ( value ) {
40114
40115                         this.dynamic = value;
40116
40117                         return this;
40118
40119                 },
40120
40121                 copy: function ( source ) {
40122
40123                         this.array = new source.array.constructor( source.array );
40124                         this.count = source.count;
40125                         this.stride = source.stride;
40126                         this.dynamic = source.dynamic;
40127
40128                         return this;
40129
40130                 },
40131
40132                 copyAt: function ( index1, attribute, index2 ) {
40133
40134                         index1 *= this.stride;
40135                         index2 *= attribute.stride;
40136
40137                         for ( var i = 0, l = this.stride; i < l; i ++ ) {
40138
40139                                 this.array[ index1 + i ] = attribute.array[ index2 + i ];
40140
40141                         }
40142
40143                         return this;
40144
40145                 },
40146
40147                 set: function ( value, offset ) {
40148
40149                         if ( offset === undefined ) offset = 0;
40150
40151                         this.array.set( value, offset );
40152
40153                         return this;
40154
40155                 },
40156
40157                 clone: function () {
40158
40159                         return new this.constructor().copy( this );
40160
40161                 },
40162
40163                 onUpload: function ( callback ) {
40164
40165                         this.onUploadCallback = callback;
40166
40167                         return this;
40168
40169                 }
40170
40171         } );
40172
40173         /**
40174          * @author benaadams / https://twitter.com/ben_a_adams
40175          */
40176
40177         function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
40178
40179                 InterleavedBuffer.call( this, array, stride );
40180
40181                 this.meshPerAttribute = meshPerAttribute || 1;
40182
40183         }
40184
40185         InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
40186
40187                 constructor: InstancedInterleavedBuffer,
40188
40189                 isInstancedInterleavedBuffer: true,
40190
40191                 copy: function ( source ) {
40192
40193                         InterleavedBuffer.prototype.copy.call( this, source );
40194
40195                         this.meshPerAttribute = source.meshPerAttribute;
40196
40197                         return this;
40198
40199                 }
40200
40201         } );
40202
40203         /**
40204          * @author benaadams / https://twitter.com/ben_a_adams
40205          */
40206
40207         function InstancedBufferAttribute( array, itemSize, meshPerAttribute ) {
40208
40209                 BufferAttribute.call( this, array, itemSize );
40210
40211                 this.meshPerAttribute = meshPerAttribute || 1;
40212
40213         }
40214
40215         InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
40216
40217                 constructor: InstancedBufferAttribute,
40218
40219                 isInstancedBufferAttribute: true,
40220
40221                 copy: function ( source ) {
40222
40223                         BufferAttribute.prototype.copy.call( this, source );
40224
40225                         this.meshPerAttribute = source.meshPerAttribute;
40226
40227                         return this;
40228
40229                 }
40230
40231         } );
40232
40233         /**
40234          * @author mrdoob / http://mrdoob.com/
40235          * @author bhouston / http://clara.io/
40236          * @author stephomi / http://stephaneginier.com/
40237          */
40238
40239         function Raycaster( origin, direction, near, far ) {
40240
40241                 this.ray = new Ray( origin, direction );
40242                 // direction is assumed to be normalized (for accurate distance calculations)
40243
40244                 this.near = near || 0;
40245                 this.far = far || Infinity;
40246
40247                 this.params = {
40248                         Mesh: {},
40249                         Line: {},
40250                         LOD: {},
40251                         Points: { threshold: 1 },
40252                         Sprite: {}
40253                 };
40254
40255                 Object.defineProperties( this.params, {
40256                         PointCloud: {
40257                                 get: function () {
40258                                         console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
40259                                         return this.Points;
40260                                 }
40261                         }
40262                 } );
40263
40264         }
40265
40266         function ascSort( a, b ) {
40267
40268                 return a.distance - b.distance;
40269
40270         }
40271
40272         function intersectObject( object, raycaster, intersects, recursive ) {
40273
40274                 if ( object.visible === false ) return;
40275
40276                 object.raycast( raycaster, intersects );
40277
40278                 if ( recursive === true ) {
40279
40280                         var children = object.children;
40281
40282                         for ( var i = 0, l = children.length; i < l; i ++ ) {
40283
40284                                 intersectObject( children[ i ], raycaster, intersects, true );
40285
40286                         }
40287
40288                 }
40289
40290         }
40291
40292         Object.assign( Raycaster.prototype, {
40293
40294                 linePrecision: 1,
40295
40296                 set: function ( origin, direction ) {
40297
40298                         // direction is assumed to be normalized (for accurate distance calculations)
40299
40300                         this.ray.set( origin, direction );
40301
40302                 },
40303
40304                 setFromCamera: function ( coords, camera ) {
40305
40306                         if ( ( camera && camera.isPerspectiveCamera ) ) {
40307
40308                                 this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
40309                                 this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
40310
40311                         } else if ( ( camera && camera.isOrthographicCamera ) ) {
40312
40313                                 this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
40314                                 this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
40315
40316                         } else {
40317
40318                                 console.error( 'THREE.Raycaster: Unsupported camera type.' );
40319
40320                         }
40321
40322                 },
40323
40324                 intersectObject: function ( object, recursive ) {
40325
40326                         var intersects = [];
40327
40328                         intersectObject( object, this, intersects, recursive );
40329
40330                         intersects.sort( ascSort );
40331
40332                         return intersects;
40333
40334                 },
40335
40336                 intersectObjects: function ( objects, recursive ) {
40337
40338                         var intersects = [];
40339
40340                         if ( Array.isArray( objects ) === false ) {
40341
40342                                 console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
40343                                 return intersects;
40344
40345                         }
40346
40347                         for ( var i = 0, l = objects.length; i < l; i ++ ) {
40348
40349                                 intersectObject( objects[ i ], this, intersects, recursive );
40350
40351                         }
40352
40353                         intersects.sort( ascSort );
40354
40355                         return intersects;
40356
40357                 }
40358
40359         } );
40360
40361         /**
40362          * @author alteredq / http://alteredqualia.com/
40363          */
40364
40365         function Clock( autoStart ) {
40366
40367                 this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
40368
40369                 this.startTime = 0;
40370                 this.oldTime = 0;
40371                 this.elapsedTime = 0;
40372
40373                 this.running = false;
40374
40375         }
40376
40377         Object.assign( Clock.prototype, {
40378
40379                 start: function () {
40380
40381                         this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
40382
40383                         this.oldTime = this.startTime;
40384                         this.elapsedTime = 0;
40385                         this.running = true;
40386
40387                 },
40388
40389                 stop: function () {
40390
40391                         this.getElapsedTime();
40392                         this.running = false;
40393                         this.autoStart = false;
40394
40395                 },
40396
40397                 getElapsedTime: function () {
40398
40399                         this.getDelta();
40400                         return this.elapsedTime;
40401
40402                 },
40403
40404                 getDelta: function () {
40405
40406                         var diff = 0;
40407
40408                         if ( this.autoStart && ! this.running ) {
40409
40410                                 this.start();
40411                                 return 0;
40412
40413                         }
40414
40415                         if ( this.running ) {
40416
40417                                 var newTime = ( typeof performance === 'undefined' ? Date : performance ).now();
40418
40419                                 diff = ( newTime - this.oldTime ) / 1000;
40420                                 this.oldTime = newTime;
40421
40422                                 this.elapsedTime += diff;
40423
40424                         }
40425
40426                         return diff;
40427
40428                 }
40429
40430         } );
40431
40432         /**
40433          * @author bhouston / http://clara.io
40434          * @author WestLangley / http://github.com/WestLangley
40435          *
40436          * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
40437          *
40438          * The poles (phi) are at the positive and negative y axis.
40439          * The equator starts at positive z.
40440          */
40441
40442         function Spherical( radius, phi, theta ) {
40443
40444                 this.radius = ( radius !== undefined ) ? radius : 1.0;
40445                 this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole
40446                 this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere
40447
40448                 return this;
40449
40450         }
40451
40452         Object.assign( Spherical.prototype, {
40453
40454                 set: function ( radius, phi, theta ) {
40455
40456                         this.radius = radius;
40457                         this.phi = phi;
40458                         this.theta = theta;
40459
40460                         return this;
40461
40462                 },
40463
40464                 clone: function () {
40465
40466                         return new this.constructor().copy( this );
40467
40468                 },
40469
40470                 copy: function ( other ) {
40471
40472                         this.radius = other.radius;
40473                         this.phi = other.phi;
40474                         this.theta = other.theta;
40475
40476                         return this;
40477
40478                 },
40479
40480                 // restrict phi to be betwee EPS and PI-EPS
40481                 makeSafe: function() {
40482
40483                         var EPS = 0.000001;
40484                         this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
40485
40486                         return this;
40487
40488                 },
40489
40490                 setFromVector3: function( vec3 ) {
40491
40492                         this.radius = vec3.length();
40493
40494                         if ( this.radius === 0 ) {
40495
40496                                 this.theta = 0;
40497                                 this.phi = 0;
40498
40499                         } else {
40500
40501                                 this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis
40502                                 this.phi = Math.acos( _Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle
40503
40504                         }
40505
40506                         return this;
40507
40508                 }
40509
40510         } );
40511
40512         /**
40513          * @author Mugen87 / https://github.com/Mugen87
40514          *
40515          * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
40516          *
40517          */
40518
40519         function Cylindrical( radius, theta, y ) {
40520
40521                 this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane
40522                 this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
40523                 this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane
40524
40525                 return this;
40526
40527         }
40528
40529         Object.assign( Cylindrical.prototype, {
40530
40531                 set: function ( radius, theta, y ) {
40532
40533                         this.radius = radius;
40534                         this.theta = theta;
40535                         this.y = y;
40536
40537                         return this;
40538
40539                 },
40540
40541                 clone: function () {
40542
40543                         return new this.constructor().copy( this );
40544
40545                 },
40546
40547                 copy: function ( other ) {
40548
40549                         this.radius = other.radius;
40550                         this.theta = other.theta;
40551                         this.y = other.y;
40552
40553                         return this;
40554
40555                 },
40556
40557                 setFromVector3: function( vec3 ) {
40558
40559                         this.radius = Math.sqrt( vec3.x * vec3.x + vec3.z * vec3.z );
40560                         this.theta = Math.atan2( vec3.x, vec3.z );
40561                         this.y = vec3.y;
40562
40563                         return this;
40564
40565                 }
40566
40567         } );
40568
40569         /**
40570          * @author alteredq / http://alteredqualia.com/
40571          */
40572
40573         function ImmediateRenderObject( material ) {
40574
40575                 Object3D.call( this );
40576
40577                 this.material = material;
40578                 this.render = function ( renderCallback ) {};
40579
40580         }
40581
40582         ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
40583         ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
40584
40585         ImmediateRenderObject.prototype.isImmediateRenderObject = true;
40586
40587         /**
40588          * @author mrdoob / http://mrdoob.com/
40589          * @author WestLangley / http://github.com/WestLangley
40590          */
40591
40592         function VertexNormalsHelper( object, size, hex, linewidth ) {
40593
40594                 this.object = object;
40595
40596                 this.size = ( size !== undefined ) ? size : 1;
40597
40598                 var color = ( hex !== undefined ) ? hex : 0xff0000;
40599
40600                 var width = ( linewidth !== undefined ) ? linewidth : 1;
40601
40602                 //
40603
40604                 var nNormals = 0;
40605
40606                 var objGeometry = this.object.geometry;
40607
40608                 if ( objGeometry && objGeometry.isGeometry ) {
40609
40610                         nNormals = objGeometry.faces.length * 3;
40611
40612                 } else if ( objGeometry && objGeometry.isBufferGeometry ) {
40613
40614                         nNormals = objGeometry.attributes.normal.count;
40615
40616                 }
40617
40618                 //
40619
40620                 var geometry = new BufferGeometry();
40621
40622                 var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
40623
40624                 geometry.addAttribute( 'position', positions );
40625
40626                 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
40627
40628                 //
40629
40630                 this.matrixAutoUpdate = false;
40631
40632                 this.update();
40633
40634         }
40635
40636         VertexNormalsHelper.prototype = Object.create( LineSegments.prototype );
40637         VertexNormalsHelper.prototype.constructor = VertexNormalsHelper;
40638
40639         VertexNormalsHelper.prototype.update = ( function () {
40640
40641                 var v1 = new Vector3();
40642                 var v2 = new Vector3();
40643                 var normalMatrix = new Matrix3();
40644
40645                 return function update() {
40646
40647                         var keys = [ 'a', 'b', 'c' ];
40648
40649                         this.object.updateMatrixWorld( true );
40650
40651                         normalMatrix.getNormalMatrix( this.object.matrixWorld );
40652
40653                         var matrixWorld = this.object.matrixWorld;
40654
40655                         var position = this.geometry.attributes.position;
40656
40657                         //
40658
40659                         var objGeometry = this.object.geometry;
40660
40661                         if ( objGeometry && objGeometry.isGeometry ) {
40662
40663                                 var vertices = objGeometry.vertices;
40664
40665                                 var faces = objGeometry.faces;
40666
40667                                 var idx = 0;
40668
40669                                 for ( var i = 0, l = faces.length; i < l; i ++ ) {
40670
40671                                         var face = faces[ i ];
40672
40673                                         for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
40674
40675                                                 var vertex = vertices[ face[ keys[ j ] ] ];
40676
40677                                                 var normal = face.vertexNormals[ j ];
40678
40679                                                 v1.copy( vertex ).applyMatrix4( matrixWorld );
40680
40681                                                 v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
40682
40683                                                 position.setXYZ( idx, v1.x, v1.y, v1.z );
40684
40685                                                 idx = idx + 1;
40686
40687                                                 position.setXYZ( idx, v2.x, v2.y, v2.z );
40688
40689                                                 idx = idx + 1;
40690
40691                                         }
40692
40693                                 }
40694
40695                         } else if ( objGeometry && objGeometry.isBufferGeometry ) {
40696
40697                                 var objPos = objGeometry.attributes.position;
40698
40699                                 var objNorm = objGeometry.attributes.normal;
40700
40701                                 var idx = 0;
40702
40703                                 // for simplicity, ignore index and drawcalls, and render every normal
40704
40705                                 for ( var j = 0, jl = objPos.count; j < jl; j ++ ) {
40706
40707                                         v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );
40708
40709                                         v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );
40710
40711                                         v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
40712
40713                                         position.setXYZ( idx, v1.x, v1.y, v1.z );
40714
40715                                         idx = idx + 1;
40716
40717                                         position.setXYZ( idx, v2.x, v2.y, v2.z );
40718
40719                                         idx = idx + 1;
40720
40721                                 }
40722
40723                         }
40724
40725                         position.needsUpdate = true;
40726
40727                 };
40728
40729         }() );
40730
40731         /**
40732          * @author alteredq / http://alteredqualia.com/
40733          * @author mrdoob / http://mrdoob.com/
40734          * @author WestLangley / http://github.com/WestLangley
40735          */
40736
40737         function SpotLightHelper( light, color ) {
40738
40739                 Object3D.call( this );
40740
40741                 this.light = light;
40742                 this.light.updateMatrixWorld();
40743
40744                 this.matrix = light.matrixWorld;
40745                 this.matrixAutoUpdate = false;
40746
40747                 this.color = color;
40748
40749                 var geometry = new BufferGeometry();
40750
40751                 var positions = [
40752                         0, 0, 0,   0,   0,   1,
40753                         0, 0, 0,   1,   0,   1,
40754                         0, 0, 0, - 1,   0,   1,
40755                         0, 0, 0,   0,   1,   1,
40756                         0, 0, 0,   0, - 1,   1
40757                 ];
40758
40759                 for ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
40760
40761                         var p1 = ( i / l ) * Math.PI * 2;
40762                         var p2 = ( j / l ) * Math.PI * 2;
40763
40764                         positions.push(
40765                                 Math.cos( p1 ), Math.sin( p1 ), 1,
40766                                 Math.cos( p2 ), Math.sin( p2 ), 1
40767                         );
40768
40769                 }
40770
40771                 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
40772
40773                 var material = new LineBasicMaterial( { fog: false } );
40774
40775                 this.cone = new LineSegments( geometry, material );
40776                 this.add( this.cone );
40777
40778                 this.update();
40779
40780         }
40781
40782         SpotLightHelper.prototype = Object.create( Object3D.prototype );
40783         SpotLightHelper.prototype.constructor = SpotLightHelper;
40784
40785         SpotLightHelper.prototype.dispose = function () {
40786
40787                 this.cone.geometry.dispose();
40788                 this.cone.material.dispose();
40789
40790         };
40791
40792         SpotLightHelper.prototype.update = function () {
40793
40794                 var vector = new Vector3();
40795                 var vector2 = new Vector3();
40796
40797                 return function update() {
40798
40799                         this.light.updateMatrixWorld();
40800
40801                         var coneLength = this.light.distance ? this.light.distance : 1000;
40802                         var coneWidth = coneLength * Math.tan( this.light.angle );
40803
40804                         this.cone.scale.set( coneWidth, coneWidth, coneLength );
40805
40806                         vector.setFromMatrixPosition( this.light.matrixWorld );
40807                         vector2.setFromMatrixPosition( this.light.target.matrixWorld );
40808
40809                         this.cone.lookAt( vector2.sub( vector ) );
40810
40811                         if ( this.color !== undefined ) {
40812
40813                                 this.cone.material.color.set( this.color );
40814
40815                         } else {
40816
40817                                 this.cone.material.color.copy( this.light.color );
40818
40819                         }
40820
40821                 };
40822
40823         }();
40824
40825         /**
40826          * @author Sean Griffin / http://twitter.com/sgrif
40827          * @author Michael Guerrero / http://realitymeltdown.com
40828          * @author mrdoob / http://mrdoob.com/
40829          * @author ikerr / http://verold.com
40830          * @author Mugen87 / https://github.com/Mugen87
40831          */
40832
40833         function getBoneList( object ) {
40834
40835                 var boneList = [];
40836
40837                 if ( object && object.isBone ) {
40838
40839                         boneList.push( object );
40840
40841                 }
40842
40843                 for ( var i = 0; i < object.children.length; i ++ ) {
40844
40845                         boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
40846
40847                 }
40848
40849                 return boneList;
40850
40851         }
40852
40853         function SkeletonHelper( object ) {
40854
40855                 var bones = getBoneList( object );
40856
40857                 var geometry = new BufferGeometry();
40858
40859                 var vertices = [];
40860                 var colors = [];
40861
40862                 var color1 = new Color( 0, 0, 1 );
40863                 var color2 = new Color( 0, 1, 0 );
40864
40865                 for ( var i = 0; i < bones.length; i ++ ) {
40866
40867                         var bone = bones[ i ];
40868
40869                         if ( bone.parent && bone.parent.isBone ) {
40870
40871                                 vertices.push( 0, 0, 0 );
40872                                 vertices.push( 0, 0, 0 );
40873                                 colors.push( color1.r, color1.g, color1.b );
40874                                 colors.push( color2.r, color2.g, color2.b );
40875
40876                         }
40877
40878                 }
40879
40880                 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
40881                 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
40882
40883                 var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } );
40884
40885                 LineSegments.call( this, geometry, material );
40886
40887                 this.root = object;
40888                 this.bones = bones;
40889
40890                 this.matrix = object.matrixWorld;
40891                 this.matrixAutoUpdate = false;
40892
40893                 this.onBeforeRender();
40894
40895         }
40896
40897         SkeletonHelper.prototype = Object.create( LineSegments.prototype );
40898         SkeletonHelper.prototype.constructor = SkeletonHelper;
40899
40900         SkeletonHelper.prototype.onBeforeRender = function () {
40901
40902                 var vector = new Vector3();
40903
40904                 var boneMatrix = new Matrix4();
40905                 var matrixWorldInv = new Matrix4();
40906
40907                 return function onBeforeRender() {
40908
40909                         var bones = this.bones;
40910
40911                         var geometry = this.geometry;
40912                         var position = geometry.getAttribute( 'position' );
40913
40914                         matrixWorldInv.getInverse( this.root.matrixWorld );
40915
40916                         for ( var i = 0, j = 0; i < bones.length; i ++ ) {
40917
40918                                 var bone = bones[ i ];
40919
40920                                 if ( bone.parent && bone.parent.isBone ) {
40921
40922                                         boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );
40923                                         vector.setFromMatrixPosition( boneMatrix );
40924                                         position.setXYZ( j, vector.x, vector.y, vector.z );
40925
40926                                         boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );
40927                                         vector.setFromMatrixPosition( boneMatrix );
40928                                         position.setXYZ( j + 1, vector.x, vector.y, vector.z );
40929
40930                                         j += 2;
40931
40932                                 }
40933
40934                         }
40935
40936                         geometry.getAttribute( 'position' ).needsUpdate = true;
40937
40938                 };
40939
40940         }();
40941
40942         /**
40943          * @author alteredq / http://alteredqualia.com/
40944          * @author mrdoob / http://mrdoob.com/
40945          */
40946
40947         function PointLightHelper( light, sphereSize, color ) {
40948
40949                 this.light = light;
40950                 this.light.updateMatrixWorld();
40951
40952                 this.color = color;
40953
40954                 var geometry = new SphereBufferGeometry( sphereSize, 4, 2 );
40955                 var material = new MeshBasicMaterial( { wireframe: true, fog: false } );
40956
40957                 Mesh.call( this, geometry, material );
40958
40959                 this.matrix = this.light.matrixWorld;
40960                 this.matrixAutoUpdate = false;
40961
40962                 this.update();
40963
40964
40965                 /*
40966                 var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
40967                 var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
40968
40969                 this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
40970                 this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
40971
40972                 var d = light.distance;
40973
40974                 if ( d === 0.0 ) {
40975
40976                         this.lightDistance.visible = false;
40977
40978                 } else {
40979
40980                         this.lightDistance.scale.set( d, d, d );
40981
40982                 }
40983
40984                 this.add( this.lightDistance );
40985                 */
40986
40987         }
40988
40989         PointLightHelper.prototype = Object.create( Mesh.prototype );
40990         PointLightHelper.prototype.constructor = PointLightHelper;
40991
40992         PointLightHelper.prototype.dispose = function () {
40993
40994                 this.geometry.dispose();
40995                 this.material.dispose();
40996
40997         };
40998
40999         PointLightHelper.prototype.update = function () {
41000
41001                 if ( this.color !== undefined ) {
41002
41003                         this.material.color.set( this.color );
41004
41005                 } else {
41006
41007                         this.material.color.copy( this.light.color );
41008
41009                 }
41010
41011                 /*
41012                 var d = this.light.distance;
41013
41014                 if ( d === 0.0 ) {
41015
41016                         this.lightDistance.visible = false;
41017
41018                 } else {
41019
41020                         this.lightDistance.visible = true;
41021                         this.lightDistance.scale.set( d, d, d );
41022
41023                 }
41024                 */
41025
41026         };
41027
41028         /**
41029          * @author abelnation / http://github.com/abelnation
41030          * @author Mugen87 / http://github.com/Mugen87
41031          * @author WestLangley / http://github.com/WestLangley
41032          */
41033
41034         function RectAreaLightHelper( light, color ) {
41035
41036                 Object3D.call( this );
41037
41038                 this.light = light;
41039                 this.light.updateMatrixWorld();
41040
41041                 this.matrix = light.matrixWorld;
41042                 this.matrixAutoUpdate = false;
41043
41044                 this.color = color;
41045
41046                 var material = new LineBasicMaterial( { fog: false } );
41047
41048                 var geometry = new BufferGeometry();
41049
41050                 geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) );
41051
41052                 this.line = new Line( geometry, material );
41053                 this.add( this.line );
41054
41055
41056                 this.update();
41057
41058         }
41059
41060         RectAreaLightHelper.prototype = Object.create( Object3D.prototype );
41061         RectAreaLightHelper.prototype.constructor = RectAreaLightHelper;
41062
41063         RectAreaLightHelper.prototype.dispose = function () {
41064
41065                 this.children[ 0 ].geometry.dispose();
41066                 this.children[ 0 ].material.dispose();
41067
41068         };
41069
41070         RectAreaLightHelper.prototype.update = function () {
41071
41072                 // calculate new dimensions of the helper
41073
41074                 var hx = this.light.width * 0.5;
41075                 var hy = this.light.height * 0.5;
41076
41077                 var position = this.line.geometry.attributes.position;
41078                 var array = position.array;
41079
41080                 // update vertices
41081
41082                 array[  0 ] =   hx; array[  1 ] = - hy; array[  2 ] = 0;
41083                 array[  3 ] =   hx; array[  4 ] =   hy; array[  5 ] = 0;
41084                 array[  6 ] = - hx; array[  7 ] =   hy; array[  8 ] = 0;
41085                 array[  9 ] = - hx; array[ 10 ] = - hy; array[ 11 ] = 0;
41086                 array[ 12 ] =   hx; array[ 13 ] = - hy; array[ 14 ] = 0;
41087
41088                 position.needsUpdate = true;
41089
41090                 if ( this.color !== undefined ) {
41091
41092                         this.line.material.color.set( this.color );
41093
41094                 } else {
41095
41096                         this.line.material.color.copy( this.light.color );
41097
41098                 }
41099
41100         };
41101
41102         /**
41103          * @author alteredq / http://alteredqualia.com/
41104          * @author mrdoob / http://mrdoob.com/
41105          * @author Mugen87 / https://github.com/Mugen87
41106          */
41107
41108         function HemisphereLightHelper( light, size, color ) {
41109
41110                 Object3D.call( this );
41111
41112                 this.light = light;
41113                 this.light.updateMatrixWorld();
41114
41115                 this.matrix = light.matrixWorld;
41116                 this.matrixAutoUpdate = false;
41117
41118                 this.color = color;
41119
41120                 var geometry = new OctahedronBufferGeometry( size );
41121                 geometry.rotateY( Math.PI * 0.5 );
41122
41123                 this.material = new MeshBasicMaterial( { wireframe: true, fog: false } );
41124                 if ( this.color === undefined ) this.material.vertexColors = VertexColors;
41125
41126                 var position = geometry.getAttribute( 'position' );
41127                 var colors = new Float32Array( position.count * 3 );
41128
41129                 geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) );
41130
41131                 this.add( new Mesh( geometry, this.material ) );
41132
41133                 this.update();
41134
41135         }
41136
41137         HemisphereLightHelper.prototype = Object.create( Object3D.prototype );
41138         HemisphereLightHelper.prototype.constructor = HemisphereLightHelper;
41139
41140         HemisphereLightHelper.prototype.dispose = function () {
41141
41142                 this.children[ 0 ].geometry.dispose();
41143                 this.children[ 0 ].material.dispose();
41144
41145         };
41146
41147         HemisphereLightHelper.prototype.update = function () {
41148
41149                 var vector = new Vector3();
41150
41151                 var color1 = new Color();
41152                 var color2 = new Color();
41153
41154                 return function update() {
41155
41156                         var mesh = this.children[ 0 ];
41157
41158                         if ( this.color !== undefined ) {
41159
41160                                 this.material.color.set( this.color );
41161
41162                         } else {
41163
41164                                 var colors = mesh.geometry.getAttribute( 'color' );
41165
41166                                 color1.copy( this.light.color );
41167                                 color2.copy( this.light.groundColor );
41168
41169                                 for ( var i = 0, l = colors.count; i < l; i ++ ) {
41170
41171                                         var color = ( i < ( l / 2 ) ) ? color1 : color2;
41172
41173                                         colors.setXYZ( i, color.r, color.g, color.b );
41174
41175                                 }
41176
41177                                 colors.needsUpdate = true;
41178
41179                         }
41180
41181                         mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );
41182
41183                 };
41184
41185         }();
41186
41187         /**
41188          * @author mrdoob / http://mrdoob.com/
41189          */
41190
41191         function GridHelper( size, divisions, color1, color2 ) {
41192
41193                 size = size || 10;
41194                 divisions = divisions || 10;
41195                 color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
41196                 color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
41197
41198                 var center = divisions / 2;
41199                 var step = size / divisions;
41200                 var halfSize = size / 2;
41201
41202                 var vertices = [], colors = [];
41203
41204                 for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
41205
41206                         vertices.push( - halfSize, 0, k, halfSize, 0, k );
41207                         vertices.push( k, 0, - halfSize, k, 0, halfSize );
41208
41209                         var color = i === center ? color1 : color2;
41210
41211                         color.toArray( colors, j ); j += 3;
41212                         color.toArray( colors, j ); j += 3;
41213                         color.toArray( colors, j ); j += 3;
41214                         color.toArray( colors, j ); j += 3;
41215
41216                 }
41217
41218                 var geometry = new BufferGeometry();
41219                 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
41220                 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
41221
41222                 var material = new LineBasicMaterial( { vertexColors: VertexColors } );
41223
41224                 LineSegments.call( this, geometry, material );
41225
41226         }
41227
41228         GridHelper.prototype = Object.create( LineSegments.prototype );
41229         GridHelper.prototype.constructor = GridHelper;
41230
41231         /**
41232          * @author mrdoob / http://mrdoob.com/
41233          * @author Mugen87 / http://github.com/Mugen87
41234          * @author Hectate / http://www.github.com/Hectate
41235          */
41236
41237         function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) {
41238
41239                 radius = radius || 10;
41240                 radials = radials || 16;
41241                 circles = circles || 8;
41242                 divisions = divisions || 64;
41243                 color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
41244                 color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
41245
41246                 var vertices = [];
41247                 var colors = [];
41248
41249                 var x, z;
41250                 var v, i, j, r, color;
41251
41252                 // create the radials
41253
41254                 for ( i = 0; i <= radials; i ++ ) {
41255
41256                         v = ( i / radials ) * ( Math.PI * 2 );
41257
41258                         x = Math.sin( v ) * radius;
41259                         z = Math.cos( v ) * radius;
41260
41261                         vertices.push( 0, 0, 0 );
41262                         vertices.push( x, 0, z );
41263
41264                         color = ( i & 1 ) ? color1 : color2;
41265
41266                         colors.push( color.r, color.g, color.b );
41267                         colors.push( color.r, color.g, color.b );
41268
41269                 }
41270
41271                 // create the circles
41272
41273                 for ( i = 0; i <= circles; i ++ ) {
41274
41275                         color = ( i & 1 ) ? color1 : color2;
41276
41277                         r = radius - ( radius / circles * i );
41278
41279                         for ( j = 0; j < divisions; j ++ ) {
41280
41281                                 // first vertex
41282
41283                                 v = ( j / divisions ) * ( Math.PI * 2 );
41284
41285                                 x = Math.sin( v ) * r;
41286                                 z = Math.cos( v ) * r;
41287
41288                                 vertices.push( x, 0, z );
41289                                 colors.push( color.r, color.g, color.b );
41290
41291                                 // second vertex
41292
41293                                 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
41294
41295                                 x = Math.sin( v ) * r;
41296                                 z = Math.cos( v ) * r;
41297
41298                                 vertices.push( x, 0, z );
41299                                 colors.push( color.r, color.g, color.b );
41300
41301                         }
41302
41303                 }
41304
41305                 var geometry = new BufferGeometry();
41306                 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
41307                 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
41308
41309                 var material = new LineBasicMaterial( { vertexColors: VertexColors } );
41310
41311                 LineSegments.call( this, geometry, material );
41312
41313         }
41314
41315         PolarGridHelper.prototype = Object.create( LineSegments.prototype );
41316         PolarGridHelper.prototype.constructor = PolarGridHelper;
41317
41318         /**
41319          * @author mrdoob / http://mrdoob.com/
41320          * @author WestLangley / http://github.com/WestLangley
41321          */
41322
41323         function FaceNormalsHelper( object, size, hex, linewidth ) {
41324
41325                 // FaceNormalsHelper only supports THREE.Geometry
41326
41327                 this.object = object;
41328
41329                 this.size = ( size !== undefined ) ? size : 1;
41330
41331                 var color = ( hex !== undefined ) ? hex : 0xffff00;
41332
41333                 var width = ( linewidth !== undefined ) ? linewidth : 1;
41334
41335                 //
41336
41337                 var nNormals = 0;
41338
41339                 var objGeometry = this.object.geometry;
41340
41341                 if ( objGeometry && objGeometry.isGeometry ) {
41342
41343                         nNormals = objGeometry.faces.length;
41344
41345                 } else {
41346
41347                         console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );
41348
41349                 }
41350
41351                 //
41352
41353                 var geometry = new BufferGeometry();
41354
41355                 var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
41356
41357                 geometry.addAttribute( 'position', positions );
41358
41359                 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
41360
41361                 //
41362
41363                 this.matrixAutoUpdate = false;
41364                 this.update();
41365
41366         }
41367
41368         FaceNormalsHelper.prototype = Object.create( LineSegments.prototype );
41369         FaceNormalsHelper.prototype.constructor = FaceNormalsHelper;
41370
41371         FaceNormalsHelper.prototype.update = ( function () {
41372
41373                 var v1 = new Vector3();
41374                 var v2 = new Vector3();
41375                 var normalMatrix = new Matrix3();
41376
41377                 return function update() {
41378
41379                         this.object.updateMatrixWorld( true );
41380
41381                         normalMatrix.getNormalMatrix( this.object.matrixWorld );
41382
41383                         var matrixWorld = this.object.matrixWorld;
41384
41385                         var position = this.geometry.attributes.position;
41386
41387                         //
41388
41389                         var objGeometry = this.object.geometry;
41390
41391                         var vertices = objGeometry.vertices;
41392
41393                         var faces = objGeometry.faces;
41394
41395                         var idx = 0;
41396
41397                         for ( var i = 0, l = faces.length; i < l; i ++ ) {
41398
41399                                 var face = faces[ i ];
41400
41401                                 var normal = face.normal;
41402
41403                                 v1.copy( vertices[ face.a ] )
41404                                         .add( vertices[ face.b ] )
41405                                         .add( vertices[ face.c ] )
41406                                         .divideScalar( 3 )
41407                                         .applyMatrix4( matrixWorld );
41408
41409                                 v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
41410
41411                                 position.setXYZ( idx, v1.x, v1.y, v1.z );
41412
41413                                 idx = idx + 1;
41414
41415                                 position.setXYZ( idx, v2.x, v2.y, v2.z );
41416
41417                                 idx = idx + 1;
41418
41419                         }
41420
41421                         position.needsUpdate = true;
41422
41423                 };
41424
41425         }() );
41426
41427         /**
41428          * @author alteredq / http://alteredqualia.com/
41429          * @author mrdoob / http://mrdoob.com/
41430          * @author WestLangley / http://github.com/WestLangley
41431          */
41432
41433         function DirectionalLightHelper( light, size, color ) {
41434
41435                 Object3D.call( this );
41436
41437                 this.light = light;
41438                 this.light.updateMatrixWorld();
41439
41440                 this.matrix = light.matrixWorld;
41441                 this.matrixAutoUpdate = false;
41442
41443                 this.color = color;
41444
41445                 if ( size === undefined ) size = 1;
41446
41447                 var geometry = new BufferGeometry();
41448                 geometry.addAttribute( 'position', new Float32BufferAttribute( [
41449                         - size,   size, 0,
41450                           size,   size, 0,
41451                           size, - size, 0,
41452                         - size, - size, 0,
41453                         - size,   size, 0
41454                 ], 3 ) );
41455
41456                 var material = new LineBasicMaterial( { fog: false } );
41457
41458                 this.lightPlane = new Line( geometry, material );
41459                 this.add( this.lightPlane );
41460
41461                 geometry = new BufferGeometry();
41462                 geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
41463
41464                 this.targetLine = new Line( geometry, material );
41465                 this.add( this.targetLine );
41466
41467                 this.update();
41468
41469         }
41470
41471         DirectionalLightHelper.prototype = Object.create( Object3D.prototype );
41472         DirectionalLightHelper.prototype.constructor = DirectionalLightHelper;
41473
41474         DirectionalLightHelper.prototype.dispose = function () {
41475
41476                 this.lightPlane.geometry.dispose();
41477                 this.lightPlane.material.dispose();
41478                 this.targetLine.geometry.dispose();
41479                 this.targetLine.material.dispose();
41480
41481         };
41482
41483         DirectionalLightHelper.prototype.update = function () {
41484
41485                 var v1 = new Vector3();
41486                 var v2 = new Vector3();
41487                 var v3 = new Vector3();
41488
41489                 return function update() {
41490
41491                         v1.setFromMatrixPosition( this.light.matrixWorld );
41492                         v2.setFromMatrixPosition( this.light.target.matrixWorld );
41493                         v3.subVectors( v2, v1 );
41494
41495                         this.lightPlane.lookAt( v3 );
41496
41497                         if ( this.color !== undefined ) {
41498
41499                                 this.lightPlane.material.color.set( this.color );
41500                                 this.targetLine.material.color.set( this.color );
41501
41502                         } else {
41503
41504                                 this.lightPlane.material.color.copy( this.light.color );
41505                                 this.targetLine.material.color.copy( this.light.color );
41506
41507                         }
41508
41509                         this.targetLine.lookAt( v3 );
41510                         this.targetLine.scale.z = v3.length();
41511
41512                 };
41513
41514         }();
41515
41516         /**
41517          * @author alteredq / http://alteredqualia.com/
41518          * @author Mugen87 / https://github.com/Mugen87
41519          *
41520          *      - shows frustum, line of sight and up of the camera
41521          *      - suitable for fast updates
41522          *      - based on frustum visualization in lightgl.js shadowmap example
41523          *              http://evanw.github.com/lightgl.js/tests/shadowmap.html
41524          */
41525
41526         function CameraHelper( camera ) {
41527
41528                 var geometry = new BufferGeometry();
41529                 var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } );
41530
41531                 var vertices = [];
41532                 var colors = [];
41533
41534                 var pointMap = {};
41535
41536                 // colors
41537
41538                 var colorFrustum = new Color( 0xffaa00 );
41539                 var colorCone = new Color( 0xff0000 );
41540                 var colorUp = new Color( 0x00aaff );
41541                 var colorTarget = new Color( 0xffffff );
41542                 var colorCross = new Color( 0x333333 );
41543
41544                 // near
41545
41546                 addLine( "n1", "n2", colorFrustum );
41547                 addLine( "n2", "n4", colorFrustum );
41548                 addLine( "n4", "n3", colorFrustum );
41549                 addLine( "n3", "n1", colorFrustum );
41550
41551                 // far
41552
41553                 addLine( "f1", "f2", colorFrustum );
41554                 addLine( "f2", "f4", colorFrustum );
41555                 addLine( "f4", "f3", colorFrustum );
41556                 addLine( "f3", "f1", colorFrustum );
41557
41558                 // sides
41559
41560                 addLine( "n1", "f1", colorFrustum );
41561                 addLine( "n2", "f2", colorFrustum );
41562                 addLine( "n3", "f3", colorFrustum );
41563                 addLine( "n4", "f4", colorFrustum );
41564
41565                 // cone
41566
41567                 addLine( "p", "n1", colorCone );
41568                 addLine( "p", "n2", colorCone );
41569                 addLine( "p", "n3", colorCone );
41570                 addLine( "p", "n4", colorCone );
41571
41572                 // up
41573
41574                 addLine( "u1", "u2", colorUp );
41575                 addLine( "u2", "u3", colorUp );
41576                 addLine( "u3", "u1", colorUp );
41577
41578                 // target
41579
41580                 addLine( "c", "t", colorTarget );
41581                 addLine( "p", "c", colorCross );
41582
41583                 // cross
41584
41585                 addLine( "cn1", "cn2", colorCross );
41586                 addLine( "cn3", "cn4", colorCross );
41587
41588                 addLine( "cf1", "cf2", colorCross );
41589                 addLine( "cf3", "cf4", colorCross );
41590
41591                 function addLine( a, b, color ) {
41592
41593                         addPoint( a, color );
41594                         addPoint( b, color );
41595
41596                 }
41597
41598                 function addPoint( id, color ) {
41599
41600                         vertices.push( 0, 0, 0 );
41601                         colors.push( color.r, color.g, color.b );
41602
41603                         if ( pointMap[ id ] === undefined ) {
41604
41605                                 pointMap[ id ] = [];
41606
41607                         }
41608
41609                         pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
41610
41611                 }
41612
41613                 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
41614                 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
41615
41616                 LineSegments.call( this, geometry, material );
41617
41618                 this.camera = camera;
41619                 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
41620
41621                 this.matrix = camera.matrixWorld;
41622                 this.matrixAutoUpdate = false;
41623
41624                 this.pointMap = pointMap;
41625
41626                 this.update();
41627
41628         }
41629
41630         CameraHelper.prototype = Object.create( LineSegments.prototype );
41631         CameraHelper.prototype.constructor = CameraHelper;
41632
41633         CameraHelper.prototype.update = function () {
41634
41635                 var geometry, pointMap;
41636
41637                 var vector = new Vector3();
41638                 var camera = new Camera();
41639
41640                 function setPoint( point, x, y, z ) {
41641
41642                         vector.set( x, y, z ).unproject( camera );
41643
41644                         var points = pointMap[ point ];
41645
41646                         if ( points !== undefined ) {
41647
41648                                 var position = geometry.getAttribute( 'position' );
41649
41650                                 for ( var i = 0, l = points.length; i < l; i ++ ) {
41651
41652                                         position.setXYZ( points[ i ], vector.x, vector.y, vector.z );
41653
41654                                 }
41655
41656                         }
41657
41658                 }
41659
41660                 return function update() {
41661
41662                         geometry = this.geometry;
41663                         pointMap = this.pointMap;
41664
41665                         var w = 1, h = 1;
41666
41667                         // we need just camera projection matrix
41668                         // world matrix must be identity
41669
41670                         camera.projectionMatrix.copy( this.camera.projectionMatrix );
41671
41672                         // center / target
41673
41674                         setPoint( "c", 0, 0, - 1 );
41675                         setPoint( "t", 0, 0,  1 );
41676
41677                         // near
41678
41679                         setPoint( "n1", - w, - h, - 1 );
41680                         setPoint( "n2",   w, - h, - 1 );
41681                         setPoint( "n3", - w,   h, - 1 );
41682                         setPoint( "n4",   w,   h, - 1 );
41683
41684                         // far
41685
41686                         setPoint( "f1", - w, - h, 1 );
41687                         setPoint( "f2",   w, - h, 1 );
41688                         setPoint( "f3", - w,   h, 1 );
41689                         setPoint( "f4",   w,   h, 1 );
41690
41691                         // up
41692
41693                         setPoint( "u1",   w * 0.7, h * 1.1, - 1 );
41694                         setPoint( "u2", - w * 0.7, h * 1.1, - 1 );
41695                         setPoint( "u3",         0, h * 2,   - 1 );
41696
41697                         // cross
41698
41699                         setPoint( "cf1", - w,   0, 1 );
41700                         setPoint( "cf2",   w,   0, 1 );
41701                         setPoint( "cf3",   0, - h, 1 );
41702                         setPoint( "cf4",   0,   h, 1 );
41703
41704                         setPoint( "cn1", - w,   0, - 1 );
41705                         setPoint( "cn2",   w,   0, - 1 );
41706                         setPoint( "cn3",   0, - h, - 1 );
41707                         setPoint( "cn4",   0,   h, - 1 );
41708
41709                         geometry.getAttribute( 'position' ).needsUpdate = true;
41710
41711                 };
41712
41713         }();
41714
41715         /**
41716          * @author mrdoob / http://mrdoob.com/
41717          * @author Mugen87 / http://github.com/Mugen87
41718          */
41719
41720         function BoxHelper( object, color ) {
41721
41722                 this.object = object;
41723
41724                 if ( color === undefined ) color = 0xffff00;
41725
41726                 var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
41727                 var positions = new Float32Array( 8 * 3 );
41728
41729                 var geometry = new BufferGeometry();
41730                 geometry.setIndex( new BufferAttribute( indices, 1 ) );
41731                 geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );
41732
41733                 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
41734
41735                 this.matrixAutoUpdate = false;
41736
41737                 this.update();
41738
41739         }
41740
41741         BoxHelper.prototype = Object.create( LineSegments.prototype );
41742         BoxHelper.prototype.constructor = BoxHelper;
41743
41744         BoxHelper.prototype.update = ( function () {
41745
41746                 var box = new Box3();
41747
41748                 return function update( object ) {
41749
41750                         if ( object !== undefined ) {
41751
41752                                 console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
41753
41754                         }
41755
41756                         if ( this.object !== undefined ) {
41757
41758                                 box.setFromObject( this.object );
41759
41760                         }
41761
41762                         if ( box.isEmpty() ) return;
41763
41764                         var min = box.min;
41765                         var max = box.max;
41766
41767                         /*
41768                           5____4
41769                         1/___0/|
41770                         | 6__|_7
41771                         2/___3/
41772
41773                         0: max.x, max.y, max.z
41774                         1: min.x, max.y, max.z
41775                         2: min.x, min.y, max.z
41776                         3: max.x, min.y, max.z
41777                         4: max.x, max.y, min.z
41778                         5: min.x, max.y, min.z
41779                         6: min.x, min.y, min.z
41780                         7: max.x, min.y, min.z
41781                         */
41782
41783                         var position = this.geometry.attributes.position;
41784                         var array = position.array;
41785
41786                         array[  0 ] = max.x; array[  1 ] = max.y; array[  2 ] = max.z;
41787                         array[  3 ] = min.x; array[  4 ] = max.y; array[  5 ] = max.z;
41788                         array[  6 ] = min.x; array[  7 ] = min.y; array[  8 ] = max.z;
41789                         array[  9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
41790                         array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
41791                         array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
41792                         array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
41793                         array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
41794
41795                         position.needsUpdate = true;
41796
41797                         this.geometry.computeBoundingSphere();
41798
41799                 };
41800
41801         } )();
41802
41803         BoxHelper.prototype.setFromObject = function ( object ) {
41804
41805                 this.object = object;
41806                 this.update();
41807
41808                 return this;
41809
41810         };
41811
41812         /**
41813          * @author WestLangley / http://github.com/WestLangley
41814          */
41815
41816         function Box3Helper( box, hex ) {
41817
41818                 this.type = 'Box3Helper';
41819
41820                 this.box = box;
41821
41822                 var color = ( hex !== undefined ) ? hex : 0xffff00;
41823
41824                 var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
41825
41826                 var positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ];
41827
41828                 var geometry = new BufferGeometry();
41829
41830                 geometry.setIndex( new BufferAttribute( indices, 1 ) );
41831
41832                 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
41833
41834                 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
41835
41836                 this.geometry.computeBoundingSphere();
41837
41838                 this.onBeforeRender();
41839
41840         }
41841
41842         Box3Helper.prototype = Object.create( LineSegments.prototype );
41843         Box3Helper.prototype.constructor = Box3Helper;
41844
41845         Box3Helper.prototype.onBeforeRender = function () {
41846
41847                 var box = this.box;
41848
41849                 if ( box.isEmpty() ) return;
41850
41851                 box.getCenter( this.position );
41852
41853                 box.getSize( this.scale );
41854
41855                 this.scale.multiplyScalar( 0.5 );
41856
41857         };
41858
41859         /**
41860          * @author WestLangley / http://github.com/WestLangley
41861          */
41862
41863         function PlaneHelper( plane, size, hex ) {
41864
41865                 this.type = 'PlaneHelper';
41866
41867                 this.plane = plane;
41868
41869                 this.size = ( size === undefined ) ? 1 : size;
41870
41871                 var color = ( hex !== undefined ) ? hex : 0xffff00;
41872
41873                 var positions = [ 1, - 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 ];
41874
41875                 var geometry = new BufferGeometry();
41876                 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
41877                 geometry.computeBoundingSphere();
41878
41879                 Line.call( this, geometry, new LineBasicMaterial( { color: color } ) );
41880
41881                 //
41882
41883                 var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];
41884
41885                 var geometry2 = new BufferGeometry();
41886                 geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
41887                 geometry2.computeBoundingSphere();
41888
41889                 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) );
41890
41891                 //
41892
41893                 this.onBeforeRender();
41894
41895         }
41896
41897         PlaneHelper.prototype = Object.create( Line.prototype );
41898         PlaneHelper.prototype.constructor = PlaneHelper;
41899
41900         PlaneHelper.prototype.onBeforeRender = function () {
41901
41902                 var scale = - this.plane.constant;
41903
41904                 if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter
41905
41906                 this.scale.set( 0.5 * this.size, 0.5 * this.size, scale );
41907
41908                 this.lookAt( this.plane.normal );
41909
41910                 this.updateMatrixWorld();
41911
41912         };
41913
41914         /**
41915          * @author WestLangley / http://github.com/WestLangley
41916          * @author zz85 / http://github.com/zz85
41917          * @author bhouston / http://clara.io
41918          *
41919          * Creates an arrow for visualizing directions
41920          *
41921          * Parameters:
41922          *  dir - Vector3
41923          *  origin - Vector3
41924          *  length - Number
41925          *  color - color in hex value
41926          *  headLength - Number
41927          *  headWidth - Number
41928          */
41929
41930         var lineGeometry;
41931         var coneGeometry;
41932
41933         function ArrowHelper( dir, origin, length, color, headLength, headWidth ) {
41934
41935                 // dir is assumed to be normalized
41936
41937                 Object3D.call( this );
41938
41939                 if ( color === undefined ) color = 0xffff00;
41940                 if ( length === undefined ) length = 1;
41941                 if ( headLength === undefined ) headLength = 0.2 * length;
41942                 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
41943
41944                 if ( lineGeometry === undefined ) {
41945
41946                         lineGeometry = new BufferGeometry();
41947                         lineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
41948
41949                         coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );
41950                         coneGeometry.translate( 0, - 0.5, 0 );
41951
41952                 }
41953
41954                 this.position.copy( origin );
41955
41956                 this.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) );
41957                 this.line.matrixAutoUpdate = false;
41958                 this.add( this.line );
41959
41960                 this.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) );
41961                 this.cone.matrixAutoUpdate = false;
41962                 this.add( this.cone );
41963
41964                 this.setDirection( dir );
41965                 this.setLength( length, headLength, headWidth );
41966
41967         }
41968
41969         ArrowHelper.prototype = Object.create( Object3D.prototype );
41970         ArrowHelper.prototype.constructor = ArrowHelper;
41971
41972         ArrowHelper.prototype.setDirection = ( function () {
41973
41974                 var axis = new Vector3();
41975                 var radians;
41976
41977                 return function setDirection( dir ) {
41978
41979                         // dir is assumed to be normalized
41980
41981                         if ( dir.y > 0.99999 ) {
41982
41983                                 this.quaternion.set( 0, 0, 0, 1 );
41984
41985                         } else if ( dir.y < - 0.99999 ) {
41986
41987                                 this.quaternion.set( 1, 0, 0, 0 );
41988
41989                         } else {
41990
41991                                 axis.set( dir.z, 0, - dir.x ).normalize();
41992
41993                                 radians = Math.acos( dir.y );
41994
41995                                 this.quaternion.setFromAxisAngle( axis, radians );
41996
41997                         }
41998
41999                 };
42000
42001         }() );
42002
42003         ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
42004
42005                 if ( headLength === undefined ) headLength = 0.2 * length;
42006                 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
42007
42008                 this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 );
42009                 this.line.updateMatrix();
42010
42011                 this.cone.scale.set( headWidth, headLength, headWidth );
42012                 this.cone.position.y = length;
42013                 this.cone.updateMatrix();
42014
42015         };
42016
42017         ArrowHelper.prototype.setColor = function ( color ) {
42018
42019                 this.line.material.color.copy( color );
42020                 this.cone.material.color.copy( color );
42021
42022         };
42023
42024         /**
42025          * @author sroucheray / http://sroucheray.org/
42026          * @author mrdoob / http://mrdoob.com/
42027          */
42028
42029         function AxisHelper( size ) {
42030
42031                 size = size || 1;
42032
42033                 var vertices = [
42034                         0, 0, 0,  size, 0, 0,
42035                         0, 0, 0,  0, size, 0,
42036                         0, 0, 0,  0, 0, size
42037                 ];
42038
42039                 var colors = [
42040                         1, 0, 0,  1, 0.6, 0,
42041                         0, 1, 0,  0.6, 1, 0,
42042                         0, 0, 1,  0, 0.6, 1
42043                 ];
42044
42045                 var geometry = new BufferGeometry();
42046                 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
42047                 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
42048
42049                 var material = new LineBasicMaterial( { vertexColors: VertexColors } );
42050
42051                 LineSegments.call( this, geometry, material );
42052
42053         }
42054
42055         AxisHelper.prototype = Object.create( LineSegments.prototype );
42056         AxisHelper.prototype.constructor = AxisHelper;
42057
42058         /**
42059          * @author zz85 https://github.com/zz85
42060          *
42061          * Centripetal CatmullRom Curve - which is useful for avoiding
42062          * cusps and self-intersections in non-uniform catmull rom curves.
42063          * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
42064          *
42065          * curve.type accepts centripetal(default), chordal and catmullrom
42066          * curve.tension is used for catmullrom which defaults to 0.5
42067          */
42068
42069
42070         /*
42071         Based on an optimized c++ solution in
42072          - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
42073          - http://ideone.com/NoEbVM
42074
42075         This CubicPoly class could be used for reusing some variables and calculations,
42076         but for three.js curve use, it could be possible inlined and flatten into a single function call
42077         which can be placed in CurveUtils.
42078         */
42079
42080         function CubicPoly() {
42081
42082                 var c0 = 0, c1 = 0, c2 = 0, c3 = 0;
42083
42084                 /*
42085                  * Compute coefficients for a cubic polynomial
42086                  *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
42087                  * such that
42088                  *   p(0) = x0, p(1) = x1
42089                  *  and
42090                  *   p'(0) = t0, p'(1) = t1.
42091                  */
42092                 function init( x0, x1, t0, t1 ) {
42093
42094                         c0 = x0;
42095                         c1 = t0;
42096                         c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
42097                         c3 = 2 * x0 - 2 * x1 + t0 + t1;
42098
42099                 }
42100
42101                 return {
42102
42103                         initCatmullRom: function ( x0, x1, x2, x3, tension ) {
42104
42105                                 init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
42106
42107                         },
42108
42109                         initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
42110
42111                                 // compute tangents when parameterized in [t1,t2]
42112                                 var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
42113                                 var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
42114
42115                                 // rescale tangents for parametrization in [0,1]
42116                                 t1 *= dt1;
42117                                 t2 *= dt1;
42118
42119                                 init( x1, x2, t1, t2 );
42120
42121                         },
42122
42123                         calc: function ( t ) {
42124
42125                                 var t2 = t * t;
42126                                 var t3 = t2 * t;
42127                                 return c0 + c1 * t + c2 * t2 + c3 * t3;
42128
42129                         }
42130
42131                 };
42132
42133         }
42134
42135         //
42136
42137         var tmp = new Vector3();
42138         var px = new CubicPoly();
42139         var py = new CubicPoly();
42140         var pz = new CubicPoly();
42141
42142         function CatmullRomCurve3( points ) {
42143
42144                 Curve.call( this );
42145
42146                 if ( points.length < 2 ) console.warn( 'THREE.CatmullRomCurve3: Points array needs at least two entries.' );
42147
42148                 this.points = points || [];
42149                 this.closed = false;
42150
42151         }
42152
42153         CatmullRomCurve3.prototype = Object.create( Curve.prototype );
42154         CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
42155
42156         CatmullRomCurve3.prototype.getPoint = function ( t ) {
42157
42158                 var points = this.points;
42159                 var l = points.length;
42160
42161                 var point = ( l - ( this.closed ? 0 : 1 ) ) * t;
42162                 var intPoint = Math.floor( point );
42163                 var weight = point - intPoint;
42164
42165                 if ( this.closed ) {
42166
42167                         intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
42168
42169                 } else if ( weight === 0 && intPoint === l - 1 ) {
42170
42171                         intPoint = l - 2;
42172                         weight = 1;
42173
42174                 }
42175
42176                 var p0, p1, p2, p3; // 4 points
42177
42178                 if ( this.closed || intPoint > 0 ) {
42179
42180                         p0 = points[ ( intPoint - 1 ) % l ];
42181
42182                 } else {
42183
42184                         // extrapolate first point
42185                         tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
42186                         p0 = tmp;
42187
42188                 }
42189
42190                 p1 = points[ intPoint % l ];
42191                 p2 = points[ ( intPoint + 1 ) % l ];
42192
42193                 if ( this.closed || intPoint + 2 < l ) {
42194
42195                         p3 = points[ ( intPoint + 2 ) % l ];
42196
42197                 } else {
42198
42199                         // extrapolate last point
42200                         tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
42201                         p3 = tmp;
42202
42203                 }
42204
42205                 if ( this.type === undefined || this.type === 'centripetal' || this.type === 'chordal' ) {
42206
42207                         // init Centripetal / Chordal Catmull-Rom
42208                         var pow = this.type === 'chordal' ? 0.5 : 0.25;
42209                         var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
42210                         var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
42211                         var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
42212
42213                         // safety check for repeated points
42214                         if ( dt1 < 1e-4 ) dt1 = 1.0;
42215                         if ( dt0 < 1e-4 ) dt0 = dt1;
42216                         if ( dt2 < 1e-4 ) dt2 = dt1;
42217
42218                         px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
42219                         py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
42220                         pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
42221
42222                 } else if ( this.type === 'catmullrom' ) {
42223
42224                         var tension = this.tension !== undefined ? this.tension : 0.5;
42225                         px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, tension );
42226                         py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, tension );
42227                         pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, tension );
42228
42229                 }
42230
42231                 return new Vector3( px.calc( weight ), py.calc( weight ), pz.calc( weight ) );
42232
42233         };
42234
42235         function CubicBezierCurve3( v0, v1, v2, v3 ) {
42236
42237                 Curve.call( this );
42238
42239                 this.v0 = v0;
42240                 this.v1 = v1;
42241                 this.v2 = v2;
42242                 this.v3 = v3;
42243
42244         }
42245
42246         CubicBezierCurve3.prototype = Object.create( Curve.prototype );
42247         CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
42248
42249         CubicBezierCurve3.prototype.getPoint = function ( t ) {
42250
42251                 var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
42252
42253                 return new Vector3(
42254                         CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
42255                         CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
42256                         CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
42257                 );
42258
42259         };
42260
42261         function QuadraticBezierCurve3( v0, v1, v2 ) {
42262
42263                 Curve.call( this );
42264
42265                 this.v0 = v0;
42266                 this.v1 = v1;
42267                 this.v2 = v2;
42268
42269         }
42270
42271         QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
42272         QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
42273
42274         QuadraticBezierCurve3.prototype.getPoint = function ( t ) {
42275
42276                 var v0 = this.v0, v1 = this.v1, v2 = this.v2;
42277
42278                 return new Vector3(
42279                         QuadraticBezier( t, v0.x, v1.x, v2.x ),
42280                         QuadraticBezier( t, v0.y, v1.y, v2.y ),
42281                         QuadraticBezier( t, v0.z, v1.z, v2.z )
42282                 );
42283
42284         };
42285
42286         function LineCurve3( v1, v2 ) {
42287
42288                 Curve.call( this );
42289
42290                 this.v1 = v1;
42291                 this.v2 = v2;
42292
42293         }
42294
42295         LineCurve3.prototype = Object.create( Curve.prototype );
42296         LineCurve3.prototype.constructor = LineCurve3;
42297
42298         LineCurve3.prototype.getPoint = function ( t ) {
42299
42300                 if ( t === 1 ) {
42301
42302                         return this.v2.clone();
42303
42304                 }
42305
42306                 var vector = new Vector3();
42307
42308                 vector.subVectors( this.v2, this.v1 ); // diff
42309                 vector.multiplyScalar( t );
42310                 vector.add( this.v1 );
42311
42312                 return vector;
42313
42314         };
42315
42316         function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
42317
42318                 EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
42319
42320         }
42321
42322         ArcCurve.prototype = Object.create( EllipseCurve.prototype );
42323         ArcCurve.prototype.constructor = ArcCurve;
42324
42325         /**
42326          * @author alteredq / http://alteredqualia.com/
42327          */
42328
42329         var SceneUtils = {
42330
42331                 createMultiMaterialObject: function ( geometry, materials ) {
42332
42333                         var group = new Group();
42334
42335                         for ( var i = 0, l = materials.length; i < l; i ++ ) {
42336
42337                                 group.add( new Mesh( geometry, materials[ i ] ) );
42338
42339                         }
42340
42341                         return group;
42342
42343                 },
42344
42345                 detach: function ( child, parent, scene ) {
42346
42347                         child.applyMatrix( parent.matrixWorld );
42348                         parent.remove( child );
42349                         scene.add( child );
42350
42351                 },
42352
42353                 attach: function ( child, scene, parent ) {
42354
42355                         child.applyMatrix( new Matrix4().getInverse( parent.matrixWorld ) );
42356
42357                         scene.remove( child );
42358                         parent.add( child );
42359
42360                 }
42361
42362         };
42363
42364         /**
42365          * @author mrdoob / http://mrdoob.com/
42366          */
42367
42368         function Face4( a, b, c, d, normal, color, materialIndex ) {
42369
42370                 console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
42371                 return new Face3( a, b, c, normal, color, materialIndex );
42372
42373         }
42374
42375         var LineStrip = 0;
42376
42377         var LinePieces = 1;
42378
42379         function MeshFaceMaterial( materials ) {
42380
42381                 console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );
42382                 return materials;
42383
42384         }
42385
42386         function MultiMaterial( materials ) {
42387
42388                 if ( materials === undefined ) materials = [];
42389
42390                 console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );
42391                 materials.isMultiMaterial = true;
42392                 materials.materials = materials;
42393                 materials.clone = function () {
42394
42395                         return materials.slice();
42396
42397                 };
42398                 return materials;
42399
42400         }
42401
42402         function PointCloud( geometry, material ) {
42403
42404                 console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
42405                 return new Points( geometry, material );
42406
42407         }
42408
42409         function Particle( material ) {
42410
42411                 console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );
42412                 return new Sprite( material );
42413
42414         }
42415
42416         function ParticleSystem( geometry, material ) {
42417
42418                 console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
42419                 return new Points( geometry, material );
42420
42421         }
42422
42423         function PointCloudMaterial( parameters ) {
42424
42425                 console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
42426                 return new PointsMaterial( parameters );
42427
42428         }
42429
42430         function ParticleBasicMaterial( parameters ) {
42431
42432                 console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
42433                 return new PointsMaterial( parameters );
42434
42435         }
42436
42437         function ParticleSystemMaterial( parameters ) {
42438
42439                 console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
42440                 return new PointsMaterial( parameters );
42441
42442         }
42443
42444         function Vertex( x, y, z ) {
42445
42446                 console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );
42447                 return new Vector3( x, y, z );
42448
42449         }
42450
42451         //
42452
42453         function DynamicBufferAttribute( array, itemSize ) {
42454
42455                 console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' );
42456                 return new BufferAttribute( array, itemSize ).setDynamic( true );
42457
42458         }
42459
42460         function Int8Attribute( array, itemSize ) {
42461
42462                 console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );
42463                 return new Int8BufferAttribute( array, itemSize );
42464
42465         }
42466
42467         function Uint8Attribute( array, itemSize ) {
42468
42469                 console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );
42470                 return new Uint8BufferAttribute( array, itemSize );
42471
42472         }
42473
42474         function Uint8ClampedAttribute( array, itemSize ) {
42475
42476                 console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );
42477                 return new Uint8ClampedBufferAttribute( array, itemSize );
42478
42479         }
42480
42481         function Int16Attribute( array, itemSize ) {
42482
42483                 console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );
42484                 return new Int16BufferAttribute( array, itemSize );
42485
42486         }
42487
42488         function Uint16Attribute( array, itemSize ) {
42489
42490                 console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );
42491                 return new Uint16BufferAttribute( array, itemSize );
42492
42493         }
42494
42495         function Int32Attribute( array, itemSize ) {
42496
42497                 console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );
42498                 return new Int32BufferAttribute( array, itemSize );
42499
42500         }
42501
42502         function Uint32Attribute( array, itemSize ) {
42503
42504                 console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );
42505                 return new Uint32BufferAttribute( array, itemSize );
42506
42507         }
42508
42509         function Float32Attribute( array, itemSize ) {
42510
42511                 console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );
42512                 return new Float32BufferAttribute( array, itemSize );
42513
42514         }
42515
42516         function Float64Attribute( array, itemSize ) {
42517
42518                 console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );
42519                 return new Float64BufferAttribute( array, itemSize );
42520
42521         }
42522
42523         //
42524
42525         Curve.create = function ( construct, getPoint ) {
42526
42527                 console.log( 'THREE.Curve.create() has been deprecated' );
42528
42529                 construct.prototype = Object.create( Curve.prototype );
42530                 construct.prototype.constructor = construct;
42531                 construct.prototype.getPoint = getPoint;
42532
42533                 return construct;
42534
42535         };
42536
42537         //
42538
42539         function ClosedSplineCurve3( points ) {
42540
42541                 console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
42542
42543                 CatmullRomCurve3.call( this, points );
42544                 this.type = 'catmullrom';
42545                 this.closed = true;
42546
42547         }
42548
42549         ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
42550
42551         //
42552
42553         function SplineCurve3( points ) {
42554
42555                 console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
42556
42557                 CatmullRomCurve3.call( this, points );
42558                 this.type = 'catmullrom';
42559
42560         }
42561
42562         SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
42563
42564         //
42565
42566         function Spline( points ) {
42567
42568                 console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
42569
42570                 CatmullRomCurve3.call( this, points );
42571                 this.type = 'catmullrom';
42572
42573         }
42574
42575         Spline.prototype = Object.create( CatmullRomCurve3.prototype );
42576
42577         Object.assign( Spline.prototype, {
42578
42579                 initFromArray: function ( a ) {
42580
42581                         console.error( 'THREE.Spline: .initFromArray() has been removed.' );
42582
42583                 },
42584                 getControlPointsArray: function ( optionalTarget ) {
42585
42586                         console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
42587
42588                 },
42589                 reparametrizeByArcLength: function ( samplingCoef ) {
42590
42591                         console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
42592
42593                 }
42594
42595         } );
42596
42597         //
42598         function BoundingBoxHelper( object, color ) {
42599
42600                 console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );
42601                 return new BoxHelper( object, color );
42602
42603         }
42604
42605         function EdgesHelper( object, hex ) {
42606
42607                 console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );
42608                 return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
42609
42610         }
42611
42612         GridHelper.prototype.setColors = function () {
42613
42614                 console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
42615
42616         };
42617
42618         SkeletonHelper.prototype.update = function () {
42619
42620                 console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
42621
42622         };
42623
42624         function WireframeHelper( object, hex ) {
42625
42626                 console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );
42627                 return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
42628
42629         }
42630
42631         //
42632
42633         function XHRLoader( manager ) {
42634
42635                 console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );
42636                 return new FileLoader( manager );
42637
42638         }
42639
42640         function BinaryTextureLoader( manager ) {
42641
42642                 console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );
42643                 return new DataTextureLoader( manager );
42644
42645         }
42646
42647         //
42648
42649         Object.assign( Box2.prototype, {
42650
42651                 center: function ( optionalTarget ) {
42652
42653                         console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
42654                         return this.getCenter( optionalTarget );
42655
42656                 },
42657                 empty: function () {
42658
42659                         console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
42660                         return this.isEmpty();
42661
42662                 },
42663                 isIntersectionBox: function ( box ) {
42664
42665                         console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
42666                         return this.intersectsBox( box );
42667
42668                 },
42669                 size: function ( optionalTarget ) {
42670
42671                         console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
42672                         return this.getSize( optionalTarget );
42673
42674                 }
42675         } );
42676
42677         Object.assign( Box3.prototype, {
42678
42679                 center: function ( optionalTarget ) {
42680
42681                         console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
42682                         return this.getCenter( optionalTarget );
42683
42684                 },
42685                 empty: function () {
42686
42687                         console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
42688                         return this.isEmpty();
42689
42690                 },
42691                 isIntersectionBox: function ( box ) {
42692
42693                         console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
42694                         return this.intersectsBox( box );
42695
42696                 },
42697                 isIntersectionSphere: function ( sphere ) {
42698
42699                         console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
42700                         return this.intersectsSphere( sphere );
42701
42702                 },
42703                 size: function ( optionalTarget ) {
42704
42705                         console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
42706                         return this.getSize( optionalTarget );
42707
42708                 }
42709         } );
42710
42711         Line3.prototype.center = function ( optionalTarget ) {
42712
42713                 console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );
42714                 return this.getCenter( optionalTarget );
42715
42716         };
42717
42718         _Math.random16 = function () {
42719
42720                 console.warn( 'THREE.Math.random16() has been deprecated. Use Math.random() instead.' );
42721                 return Math.random();
42722
42723         };
42724
42725         Object.assign( Matrix3.prototype, {
42726
42727                 flattenToArrayOffset: function ( array, offset ) {
42728
42729                         console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
42730                         return this.toArray( array, offset );
42731
42732                 },
42733                 multiplyVector3: function ( vector ) {
42734
42735                         console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
42736                         return vector.applyMatrix3( this );
42737
42738                 },
42739                 multiplyVector3Array: function ( a ) {
42740
42741                         console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.'  );
42742
42743                 },
42744                 applyToBuffer: function( buffer, offset, length ) {
42745
42746                         console.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
42747                         return this.applyToBufferAttribute( buffer );
42748
42749                 },
42750                 applyToVector3Array: function( array, offset, length ) {
42751
42752                         console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
42753
42754                 }
42755
42756         } );
42757
42758         Object.assign( Matrix4.prototype, {
42759
42760                 extractPosition: function ( m ) {
42761
42762                         console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
42763                         return this.copyPosition( m );
42764
42765                 },
42766                 flattenToArrayOffset: function ( array, offset ) {
42767
42768                         console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
42769                         return this.toArray( array, offset );
42770
42771                 },
42772                 getPosition: function () {
42773
42774                         var v1;
42775
42776                         return function getPosition() {
42777
42778                                 if ( v1 === undefined ) v1 = new Vector3();
42779                                 console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
42780                                 return v1.setFromMatrixColumn( this, 3 );
42781
42782                         };
42783
42784                 }(),
42785                 setRotationFromQuaternion: function ( q ) {
42786
42787                         console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
42788                         return this.makeRotationFromQuaternion( q );
42789
42790                 },
42791                 multiplyToArray: function () {
42792
42793                         console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
42794
42795                 },
42796                 multiplyVector3: function ( vector ) {
42797
42798                         console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
42799                         return vector.applyMatrix4( this );
42800
42801                 },
42802                 multiplyVector4: function ( vector ) {
42803
42804                         console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
42805                         return vector.applyMatrix4( this );
42806
42807                 },
42808                 multiplyVector3Array: function ( a ) {
42809
42810                         console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.'  );
42811
42812                 },
42813                 rotateAxis: function ( v ) {
42814
42815                         console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
42816                         v.transformDirection( this );
42817
42818                 },
42819                 crossVector: function ( vector ) {
42820
42821                         console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
42822                         return vector.applyMatrix4( this );
42823
42824                 },
42825                 translate: function () {
42826
42827                         console.error( 'THREE.Matrix4: .translate() has been removed.' );
42828
42829                 },
42830                 rotateX: function () {
42831
42832                         console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
42833
42834                 },
42835                 rotateY: function () {
42836
42837                         console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
42838
42839                 },
42840                 rotateZ: function () {
42841
42842                         console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
42843
42844                 },
42845                 rotateByAxis: function () {
42846
42847                         console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
42848
42849                 },
42850                 applyToBuffer: function( buffer, offset, length ) {
42851
42852                         console.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
42853                         return this.applyToBufferAttribute( buffer );
42854
42855                 },
42856                 applyToVector3Array: function( array, offset, length ) {
42857
42858                         console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
42859
42860                 },
42861                 makeFrustum: function( left, right, bottom, top, near, far ) {
42862
42863                         console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
42864                         return this.makePerspective( left, right, top, bottom, near, far );
42865
42866                 }
42867
42868         } );
42869
42870         Plane.prototype.isIntersectionLine = function ( line ) {
42871
42872                 console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
42873                 return this.intersectsLine( line );
42874
42875         };
42876
42877         Quaternion.prototype.multiplyVector3 = function ( vector ) {
42878
42879                 console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
42880                 return vector.applyQuaternion( this );
42881
42882         };
42883
42884         Object.assign( Ray.prototype, {
42885
42886                 isIntersectionBox: function ( box ) {
42887
42888                         console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
42889                         return this.intersectsBox( box );
42890
42891                 },
42892                 isIntersectionPlane: function ( plane ) {
42893
42894                         console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
42895                         return this.intersectsPlane( plane );
42896
42897                 },
42898                 isIntersectionSphere: function ( sphere ) {
42899
42900                         console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
42901                         return this.intersectsSphere( sphere );
42902
42903                 }
42904
42905         } );
42906
42907         Object.assign( Shape.prototype, {
42908
42909                 extrude: function ( options ) {
42910
42911                         console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
42912                         return new ExtrudeGeometry( this, options );
42913
42914                 },
42915                 makeGeometry: function ( options ) {
42916
42917                         console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
42918                         return new ShapeGeometry( this, options );
42919
42920                 }
42921
42922         } );
42923
42924         Object.assign( Vector2.prototype, {
42925
42926                 fromAttribute: function ( attribute, index, offset ) {
42927
42928                         console.error( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
42929                         return this.fromBufferAttribute( attribute, index, offset );
42930
42931                 }
42932
42933         } );
42934
42935         Object.assign( Vector3.prototype, {
42936
42937                 setEulerFromRotationMatrix: function () {
42938
42939                         console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
42940
42941                 },
42942                 setEulerFromQuaternion: function () {
42943
42944                         console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
42945
42946                 },
42947                 getPositionFromMatrix: function ( m ) {
42948
42949                         console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
42950                         return this.setFromMatrixPosition( m );
42951
42952                 },
42953                 getScaleFromMatrix: function ( m ) {
42954
42955                         console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
42956                         return this.setFromMatrixScale( m );
42957
42958                 },
42959                 getColumnFromMatrix: function ( index, matrix ) {
42960
42961                         console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
42962                         return this.setFromMatrixColumn( matrix, index );
42963
42964                 },
42965                 applyProjection: function ( m ) {
42966
42967                         console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
42968                         return this.applyMatrix4( m );
42969
42970                 },
42971                 fromAttribute: function ( attribute, index, offset ) {
42972
42973                         console.error( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
42974                         return this.fromBufferAttribute( attribute, index, offset );
42975
42976                 }
42977
42978         } );
42979
42980         Object.assign( Vector4.prototype, {
42981
42982                 fromAttribute: function ( attribute, index, offset ) {
42983
42984                         console.error( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
42985                         return this.fromBufferAttribute( attribute, index, offset );
42986
42987                 }
42988
42989         } );
42990
42991         //
42992
42993         Geometry.prototype.computeTangents = function () {
42994
42995                 console.warn( 'THREE.Geometry: .computeTangents() has been removed.' );
42996
42997         };
42998
42999         Object.assign( Object3D.prototype, {
43000
43001                 getChildByName: function ( name ) {
43002
43003                         console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
43004                         return this.getObjectByName( name );
43005
43006                 },
43007                 renderDepth: function () {
43008
43009                         console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
43010
43011                 },
43012                 translate: function ( distance, axis ) {
43013
43014                         console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
43015                         return this.translateOnAxis( axis, distance );
43016
43017                 }
43018
43019         } );
43020
43021         Object.defineProperties( Object3D.prototype, {
43022
43023                 eulerOrder: {
43024                         get: function () {
43025
43026                                 console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
43027                                 return this.rotation.order;
43028
43029                         },
43030                         set: function ( value ) {
43031
43032                                 console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
43033                                 this.rotation.order = value;
43034
43035                         }
43036                 },
43037                 useQuaternion: {
43038                         get: function () {
43039
43040                                 console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
43041
43042                         },
43043                         set: function () {
43044
43045                                 console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
43046
43047                         }
43048                 }
43049
43050         } );
43051
43052         Object.defineProperties( LOD.prototype, {
43053
43054                 objects: {
43055                         get: function () {
43056
43057                                 console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
43058                                 return this.levels;
43059
43060                         }
43061                 }
43062
43063         } );
43064
43065         Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
43066
43067                 get: function () {
43068
43069                         console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
43070
43071                 },
43072                 set: function () {
43073
43074                         console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
43075
43076                 }
43077
43078         } );
43079
43080         Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
43081
43082                 get: function () {
43083
43084                         console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
43085                         return this.arcLengthDivisions;
43086
43087                 },
43088                 set: function ( value ) {
43089
43090                         console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
43091                         this.arcLengthDivisions = value;
43092
43093                 }
43094
43095         } );
43096
43097         //
43098
43099         PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
43100
43101                 console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
43102                                 "Use .setFocalLength and .filmGauge for a photographic setup." );
43103
43104                 if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
43105                 this.setFocalLength( focalLength );
43106
43107         };
43108
43109         //
43110
43111         Object.defineProperties( Light.prototype, {
43112                 onlyShadow: {
43113                         set: function () {
43114
43115                                 console.warn( 'THREE.Light: .onlyShadow has been removed.' );
43116
43117                         }
43118                 },
43119                 shadowCameraFov: {
43120                         set: function ( value ) {
43121
43122                                 console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
43123                                 this.shadow.camera.fov = value;
43124
43125                         }
43126                 },
43127                 shadowCameraLeft: {
43128                         set: function ( value ) {
43129
43130                                 console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
43131                                 this.shadow.camera.left = value;
43132
43133                         }
43134                 },
43135                 shadowCameraRight: {
43136                         set: function ( value ) {
43137
43138                                 console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
43139                                 this.shadow.camera.right = value;
43140
43141                         }
43142                 },
43143                 shadowCameraTop: {
43144                         set: function ( value ) {
43145
43146                                 console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
43147                                 this.shadow.camera.top = value;
43148
43149                         }
43150                 },
43151                 shadowCameraBottom: {
43152                         set: function ( value ) {
43153
43154                                 console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
43155                                 this.shadow.camera.bottom = value;
43156
43157                         }
43158                 },
43159                 shadowCameraNear: {
43160                         set: function ( value ) {
43161
43162                                 console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
43163                                 this.shadow.camera.near = value;
43164
43165                         }
43166                 },
43167                 shadowCameraFar: {
43168                         set: function ( value ) {
43169
43170                                 console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
43171                                 this.shadow.camera.far = value;
43172
43173                         }
43174                 },
43175                 shadowCameraVisible: {
43176                         set: function () {
43177
43178                                 console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
43179
43180                         }
43181                 },
43182                 shadowBias: {
43183                         set: function ( value ) {
43184
43185                                 console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
43186                                 this.shadow.bias = value;
43187
43188                         }
43189                 },
43190                 shadowDarkness: {
43191                         set: function () {
43192
43193                                 console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
43194
43195                         }
43196                 },
43197                 shadowMapWidth: {
43198                         set: function ( value ) {
43199
43200                                 console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
43201                                 this.shadow.mapSize.width = value;
43202
43203                         }
43204                 },
43205                 shadowMapHeight: {
43206                         set: function ( value ) {
43207
43208                                 console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
43209                                 this.shadow.mapSize.height = value;
43210
43211                         }
43212                 }
43213         } );
43214
43215         //
43216
43217         Object.defineProperties( BufferAttribute.prototype, {
43218
43219                 length: {
43220                         get: function () {
43221
43222                                 console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
43223                                 return this.array.length;
43224
43225                         }
43226                 }
43227
43228         } );
43229
43230         Object.assign( BufferGeometry.prototype, {
43231
43232                 addIndex: function ( index ) {
43233
43234                         console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
43235                         this.setIndex( index );
43236
43237                 },
43238                 addDrawCall: function ( start, count, indexOffset ) {
43239
43240                         if ( indexOffset !== undefined ) {
43241
43242                                 console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
43243
43244                         }
43245                         console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
43246                         this.addGroup( start, count );
43247
43248                 },
43249                 clearDrawCalls: function () {
43250
43251                         console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
43252                         this.clearGroups();
43253
43254                 },
43255                 computeTangents: function () {
43256
43257                         console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
43258
43259                 },
43260                 computeOffsets: function () {
43261
43262                         console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
43263
43264                 }
43265
43266         } );
43267
43268         Object.defineProperties( BufferGeometry.prototype, {
43269
43270                 drawcalls: {
43271                         get: function () {
43272
43273                                 console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
43274                                 return this.groups;
43275
43276                         }
43277                 },
43278                 offsets: {
43279                         get: function () {
43280
43281                                 console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
43282                                 return this.groups;
43283
43284                         }
43285                 }
43286
43287         } );
43288
43289         //
43290
43291         Object.defineProperties( Uniform.prototype, {
43292
43293                 dynamic: {
43294                         set: function () {
43295
43296                                 console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
43297
43298                         }
43299                 },
43300                 onUpdate: {
43301                         value: function () {
43302
43303                                 console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
43304                                 return this;
43305
43306                         }
43307                 }
43308
43309         } );
43310
43311         //
43312
43313         Object.defineProperties( Material.prototype, {
43314
43315                 wrapAround: {
43316                         get: function () {
43317
43318                                 console.warn( 'THREE.Material: .wrapAround has been removed.' );
43319
43320                         },
43321                         set: function () {
43322
43323                                 console.warn( 'THREE.Material: .wrapAround has been removed.' );
43324
43325                         }
43326                 },
43327                 wrapRGB: {
43328                         get: function () {
43329
43330                                 console.warn( 'THREE.Material: .wrapRGB has been removed.' );
43331                                 return new Color();
43332
43333                         }
43334                 },
43335
43336                 shading: {
43337                         get: function () {
43338
43339                                 console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
43340
43341                         },
43342                         set: function ( value ) {
43343
43344                                 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
43345                                 this.flatShading = ( value === FlatShading );
43346
43347                         }
43348                 }
43349
43350         } );
43351
43352         Object.defineProperties( MeshPhongMaterial.prototype, {
43353
43354                 metal: {
43355                         get: function () {
43356
43357                                 console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
43358                                 return false;
43359
43360                         },
43361                         set: function () {
43362
43363                                 console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
43364
43365                         }
43366                 }
43367
43368         } );
43369
43370         Object.defineProperties( ShaderMaterial.prototype, {
43371
43372                 derivatives: {
43373                         get: function () {
43374
43375                                 console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
43376                                 return this.extensions.derivatives;
43377
43378                         },
43379                         set: function ( value ) {
43380
43381                                 console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
43382                                 this.extensions.derivatives = value;
43383
43384                         }
43385                 }
43386
43387         } );
43388
43389         //
43390
43391         Object.assign( WebGLRenderer.prototype, {
43392
43393                 getCurrentRenderTarget: function () {
43394
43395                         console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
43396                         return this.getRenderTarget();
43397
43398                 },
43399
43400                 getMaxAnisotropy: function () {
43401
43402                         console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
43403                         return this.capabilities.getMaxAnisotropy();
43404
43405                 },
43406
43407                 getPrecision: function () {
43408
43409                         console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
43410                         return this.capabilities.precision;
43411
43412                 },
43413
43414                 supportsFloatTextures: function () {
43415
43416                         console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
43417                         return this.extensions.get( 'OES_texture_float' );
43418
43419                 },
43420                 supportsHalfFloatTextures: function () {
43421
43422                         console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
43423                         return this.extensions.get( 'OES_texture_half_float' );
43424
43425                 },
43426                 supportsStandardDerivatives: function () {
43427
43428                         console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
43429                         return this.extensions.get( 'OES_standard_derivatives' );
43430
43431                 },
43432                 supportsCompressedTextureS3TC: function () {
43433
43434                         console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
43435                         return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
43436
43437                 },
43438                 supportsCompressedTexturePVRTC: function () {
43439
43440                         console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
43441                         return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
43442
43443                 },
43444                 supportsBlendMinMax: function () {
43445
43446                         console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
43447                         return this.extensions.get( 'EXT_blend_minmax' );
43448
43449                 },
43450                 supportsVertexTextures: function () {
43451
43452                         console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
43453                         return this.capabilities.vertexTextures;
43454
43455                 },
43456                 supportsInstancedArrays: function () {
43457
43458                         console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
43459                         return this.extensions.get( 'ANGLE_instanced_arrays' );
43460
43461                 },
43462                 enableScissorTest: function ( boolean ) {
43463
43464                         console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
43465                         this.setScissorTest( boolean );
43466
43467                 },
43468                 initMaterial: function () {
43469
43470                         console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
43471
43472                 },
43473                 addPrePlugin: function () {
43474
43475                         console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
43476
43477                 },
43478                 addPostPlugin: function () {
43479
43480                         console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
43481
43482                 },
43483                 updateShadowMap: function () {
43484
43485                         console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
43486
43487                 }
43488
43489         } );
43490
43491         Object.defineProperties( WebGLRenderer.prototype, {
43492
43493                 shadowMapEnabled: {
43494                         get: function () {
43495
43496                                 return this.shadowMap.enabled;
43497
43498                         },
43499                         set: function ( value ) {
43500
43501                                 console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
43502                                 this.shadowMap.enabled = value;
43503
43504                         }
43505                 },
43506                 shadowMapType: {
43507                         get: function () {
43508
43509                                 return this.shadowMap.type;
43510
43511                         },
43512                         set: function ( value ) {
43513
43514                                 console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
43515                                 this.shadowMap.type = value;
43516
43517                         }
43518                 },
43519                 shadowMapCullFace: {
43520                         get: function () {
43521
43522                                 return this.shadowMap.cullFace;
43523
43524                         },
43525                         set: function ( value ) {
43526
43527                                 console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace.' );
43528                                 this.shadowMap.cullFace = value;
43529
43530                         }
43531                 }
43532         } );
43533
43534         Object.defineProperties( WebGLShadowMap.prototype, {
43535
43536                 cullFace: {
43537                         get: function () {
43538
43539                                 return this.renderReverseSided ? CullFaceFront : CullFaceBack;
43540
43541                         },
43542                         set: function ( cullFace ) {
43543
43544                                 var value = ( cullFace !== CullFaceBack );
43545                                 console.warn( "WebGLRenderer: .shadowMap.cullFace is deprecated. Set .shadowMap.renderReverseSided to " + value + "." );
43546                                 this.renderReverseSided = value;
43547
43548                         }
43549                 }
43550
43551         } );
43552
43553         //
43554
43555         Object.defineProperties( WebGLRenderTarget.prototype, {
43556
43557                 wrapS: {
43558                         get: function () {
43559
43560                                 console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
43561                                 return this.texture.wrapS;
43562
43563                         },
43564                         set: function ( value ) {
43565
43566                                 console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
43567                                 this.texture.wrapS = value;
43568
43569                         }
43570                 },
43571                 wrapT: {
43572                         get: function () {
43573
43574                                 console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
43575                                 return this.texture.wrapT;
43576
43577                         },
43578                         set: function ( value ) {
43579
43580                                 console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
43581                                 this.texture.wrapT = value;
43582
43583                         }
43584                 },
43585                 magFilter: {
43586                         get: function () {
43587
43588                                 console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
43589                                 return this.texture.magFilter;
43590
43591                         },
43592                         set: function ( value ) {
43593
43594                                 console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
43595                                 this.texture.magFilter = value;
43596
43597                         }
43598                 },
43599                 minFilter: {
43600                         get: function () {
43601
43602                                 console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
43603                                 return this.texture.minFilter;
43604
43605                         },
43606                         set: function ( value ) {
43607
43608                                 console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
43609                                 this.texture.minFilter = value;
43610
43611                         }
43612                 },
43613                 anisotropy: {
43614                         get: function () {
43615
43616                                 console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
43617                                 return this.texture.anisotropy;
43618
43619                         },
43620                         set: function ( value ) {
43621
43622                                 console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
43623                                 this.texture.anisotropy = value;
43624
43625                         }
43626                 },
43627                 offset: {
43628                         get: function () {
43629
43630                                 console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
43631                                 return this.texture.offset;
43632
43633                         },
43634                         set: function ( value ) {
43635
43636                                 console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
43637                                 this.texture.offset = value;
43638
43639                         }
43640                 },
43641                 repeat: {
43642                         get: function () {
43643
43644                                 console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
43645                                 return this.texture.repeat;
43646
43647                         },
43648                         set: function ( value ) {
43649
43650                                 console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
43651                                 this.texture.repeat = value;
43652
43653                         }
43654                 },
43655                 format: {
43656                         get: function () {
43657
43658                                 console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
43659                                 return this.texture.format;
43660
43661                         },
43662                         set: function ( value ) {
43663
43664                                 console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
43665                                 this.texture.format = value;
43666
43667                         }
43668                 },
43669                 type: {
43670                         get: function () {
43671
43672                                 console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
43673                                 return this.texture.type;
43674
43675                         },
43676                         set: function ( value ) {
43677
43678                                 console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
43679                                 this.texture.type = value;
43680
43681                         }
43682                 },
43683                 generateMipmaps: {
43684                         get: function () {
43685
43686                                 console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
43687                                 return this.texture.generateMipmaps;
43688
43689                         },
43690                         set: function ( value ) {
43691
43692                                 console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
43693                                 this.texture.generateMipmaps = value;
43694
43695                         }
43696                 }
43697
43698         } );
43699
43700         //
43701
43702         Audio.prototype.load = function ( file ) {
43703
43704                 console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
43705                 var scope = this;
43706                 var audioLoader = new AudioLoader();
43707                 audioLoader.load( file, function ( buffer ) {
43708
43709                         scope.setBuffer( buffer );
43710
43711                 } );
43712                 return this;
43713
43714         };
43715
43716         AudioAnalyser.prototype.getData = function () {
43717
43718                 console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );
43719                 return this.getFrequencyData();
43720
43721         };
43722
43723         //
43724
43725         CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
43726
43727                 console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
43728                 return this.update( renderer, scene );
43729
43730         };
43731
43732         //
43733
43734         var GeometryUtils = {
43735
43736                 merge: function ( geometry1, geometry2, materialIndexOffset ) {
43737
43738                         console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
43739                         var matrix;
43740
43741                         if ( geometry2.isMesh ) {
43742
43743                                 geometry2.matrixAutoUpdate && geometry2.updateMatrix();
43744
43745                                 matrix = geometry2.matrix;
43746                                 geometry2 = geometry2.geometry;
43747
43748                         }
43749
43750                         geometry1.merge( geometry2, matrix, materialIndexOffset );
43751
43752                 },
43753
43754                 center: function ( geometry ) {
43755
43756                         console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
43757                         return geometry.center();
43758
43759                 }
43760
43761         };
43762
43763         var ImageUtils = {
43764
43765                 crossOrigin: undefined,
43766
43767                 loadTexture: function ( url, mapping, onLoad, onError ) {
43768
43769                         console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
43770
43771                         var loader = new TextureLoader();
43772                         loader.setCrossOrigin( this.crossOrigin );
43773
43774                         var texture = loader.load( url, onLoad, undefined, onError );
43775
43776                         if ( mapping ) texture.mapping = mapping;
43777
43778                         return texture;
43779
43780                 },
43781
43782                 loadTextureCube: function ( urls, mapping, onLoad, onError ) {
43783
43784                         console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
43785
43786                         var loader = new CubeTextureLoader();
43787                         loader.setCrossOrigin( this.crossOrigin );
43788
43789                         var texture = loader.load( urls, onLoad, undefined, onError );
43790
43791                         if ( mapping ) texture.mapping = mapping;
43792
43793                         return texture;
43794
43795                 },
43796
43797                 loadCompressedTexture: function () {
43798
43799                         console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
43800
43801                 },
43802
43803                 loadCompressedTextureCube: function () {
43804
43805                         console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
43806
43807                 }
43808
43809         };
43810
43811         //
43812
43813         function Projector() {
43814
43815                 console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' );
43816
43817                 this.projectVector = function ( vector, camera ) {
43818
43819                         console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
43820                         vector.project( camera );
43821
43822                 };
43823
43824                 this.unprojectVector = function ( vector, camera ) {
43825
43826                         console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
43827                         vector.unproject( camera );
43828
43829                 };
43830
43831                 this.pickingRay = function () {
43832
43833                         console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
43834
43835                 };
43836
43837         }
43838
43839         //
43840
43841         function CanvasRenderer() {
43842
43843                 console.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' );
43844
43845                 this.domElement = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
43846                 this.clear = function () {};
43847                 this.render = function () {};
43848                 this.setClearColor = function () {};
43849                 this.setSize = function () {};
43850
43851         }
43852
43853         exports.WebGLRenderTargetCube = WebGLRenderTargetCube;
43854         exports.WebGLRenderTarget = WebGLRenderTarget;
43855         exports.WebGLRenderer = WebGLRenderer;
43856         exports.ShaderLib = ShaderLib;
43857         exports.UniformsLib = UniformsLib;
43858         exports.UniformsUtils = UniformsUtils;
43859         exports.ShaderChunk = ShaderChunk;
43860         exports.FogExp2 = FogExp2;
43861         exports.Fog = Fog;
43862         exports.Scene = Scene;
43863         exports.LensFlare = LensFlare;
43864         exports.Sprite = Sprite;
43865         exports.LOD = LOD;
43866         exports.SkinnedMesh = SkinnedMesh;
43867         exports.Skeleton = Skeleton;
43868         exports.Bone = Bone;
43869         exports.Mesh = Mesh;
43870         exports.LineSegments = LineSegments;
43871         exports.LineLoop = LineLoop;
43872         exports.Line = Line;
43873         exports.Points = Points;
43874         exports.Group = Group;
43875         exports.VideoTexture = VideoTexture;
43876         exports.DataTexture = DataTexture;
43877         exports.CompressedTexture = CompressedTexture;
43878         exports.CubeTexture = CubeTexture;
43879         exports.CanvasTexture = CanvasTexture;
43880         exports.DepthTexture = DepthTexture;
43881         exports.Texture = Texture;
43882         exports.CompressedTextureLoader = CompressedTextureLoader;
43883         exports.DataTextureLoader = DataTextureLoader;
43884         exports.CubeTextureLoader = CubeTextureLoader;
43885         exports.TextureLoader = TextureLoader;
43886         exports.ObjectLoader = ObjectLoader;
43887         exports.MaterialLoader = MaterialLoader;
43888         exports.BufferGeometryLoader = BufferGeometryLoader;
43889         exports.DefaultLoadingManager = DefaultLoadingManager;
43890         exports.LoadingManager = LoadingManager;
43891         exports.JSONLoader = JSONLoader;
43892         exports.ImageLoader = ImageLoader;
43893         exports.FontLoader = FontLoader;
43894         exports.FileLoader = FileLoader;
43895         exports.Loader = Loader;
43896         exports.Cache = Cache;
43897         exports.AudioLoader = AudioLoader;
43898         exports.SpotLightShadow = SpotLightShadow;
43899         exports.SpotLight = SpotLight;
43900         exports.PointLight = PointLight;
43901         exports.RectAreaLight = RectAreaLight;
43902         exports.HemisphereLight = HemisphereLight;
43903         exports.DirectionalLightShadow = DirectionalLightShadow;
43904         exports.DirectionalLight = DirectionalLight;
43905         exports.AmbientLight = AmbientLight;
43906         exports.LightShadow = LightShadow;
43907         exports.Light = Light;
43908         exports.StereoCamera = StereoCamera;
43909         exports.PerspectiveCamera = PerspectiveCamera;
43910         exports.OrthographicCamera = OrthographicCamera;
43911         exports.CubeCamera = CubeCamera;
43912         exports.ArrayCamera = ArrayCamera;
43913         exports.Camera = Camera;
43914         exports.AudioListener = AudioListener;
43915         exports.PositionalAudio = PositionalAudio;
43916         exports.AudioContext = AudioContext;
43917         exports.AudioAnalyser = AudioAnalyser;
43918         exports.Audio = Audio;
43919         exports.VectorKeyframeTrack = VectorKeyframeTrack;
43920         exports.StringKeyframeTrack = StringKeyframeTrack;
43921         exports.QuaternionKeyframeTrack = QuaternionKeyframeTrack;
43922         exports.NumberKeyframeTrack = NumberKeyframeTrack;
43923         exports.ColorKeyframeTrack = ColorKeyframeTrack;
43924         exports.BooleanKeyframeTrack = BooleanKeyframeTrack;
43925         exports.PropertyMixer = PropertyMixer;
43926         exports.PropertyBinding = PropertyBinding;
43927         exports.KeyframeTrack = KeyframeTrack;
43928         exports.AnimationUtils = AnimationUtils;
43929         exports.AnimationObjectGroup = AnimationObjectGroup;
43930         exports.AnimationMixer = AnimationMixer;
43931         exports.AnimationClip = AnimationClip;
43932         exports.Uniform = Uniform;
43933         exports.InstancedBufferGeometry = InstancedBufferGeometry;
43934         exports.BufferGeometry = BufferGeometry;
43935         exports.GeometryIdCount = GeometryIdCount;
43936         exports.Geometry = Geometry;
43937         exports.InterleavedBufferAttribute = InterleavedBufferAttribute;
43938         exports.InstancedInterleavedBuffer = InstancedInterleavedBuffer;
43939         exports.InterleavedBuffer = InterleavedBuffer;
43940         exports.InstancedBufferAttribute = InstancedBufferAttribute;
43941         exports.Face3 = Face3;
43942         exports.Object3D = Object3D;
43943         exports.Raycaster = Raycaster;
43944         exports.Layers = Layers;
43945         exports.EventDispatcher = EventDispatcher;
43946         exports.Clock = Clock;
43947         exports.QuaternionLinearInterpolant = QuaternionLinearInterpolant;
43948         exports.LinearInterpolant = LinearInterpolant;
43949         exports.DiscreteInterpolant = DiscreteInterpolant;
43950         exports.CubicInterpolant = CubicInterpolant;
43951         exports.Interpolant = Interpolant;
43952         exports.Triangle = Triangle;
43953         exports.Math = _Math;
43954         exports.Spherical = Spherical;
43955         exports.Cylindrical = Cylindrical;
43956         exports.Plane = Plane;
43957         exports.Frustum = Frustum;
43958         exports.Sphere = Sphere;
43959         exports.Ray = Ray;
43960         exports.Matrix4 = Matrix4;
43961         exports.Matrix3 = Matrix3;
43962         exports.Box3 = Box3;
43963         exports.Box2 = Box2;
43964         exports.Line3 = Line3;
43965         exports.Euler = Euler;
43966         exports.Vector4 = Vector4;
43967         exports.Vector3 = Vector3;
43968         exports.Vector2 = Vector2;
43969         exports.Quaternion = Quaternion;
43970         exports.Color = Color;
43971         exports.ImmediateRenderObject = ImmediateRenderObject;
43972         exports.VertexNormalsHelper = VertexNormalsHelper;
43973         exports.SpotLightHelper = SpotLightHelper;
43974         exports.SkeletonHelper = SkeletonHelper;
43975         exports.PointLightHelper = PointLightHelper;
43976         exports.RectAreaLightHelper = RectAreaLightHelper;
43977         exports.HemisphereLightHelper = HemisphereLightHelper;
43978         exports.GridHelper = GridHelper;
43979         exports.PolarGridHelper = PolarGridHelper;
43980         exports.FaceNormalsHelper = FaceNormalsHelper;
43981         exports.DirectionalLightHelper = DirectionalLightHelper;
43982         exports.CameraHelper = CameraHelper;
43983         exports.BoxHelper = BoxHelper;
43984         exports.Box3Helper = Box3Helper;
43985         exports.PlaneHelper = PlaneHelper;
43986         exports.ArrowHelper = ArrowHelper;
43987         exports.AxisHelper = AxisHelper;
43988         exports.CatmullRomCurve3 = CatmullRomCurve3;
43989         exports.CubicBezierCurve3 = CubicBezierCurve3;
43990         exports.QuadraticBezierCurve3 = QuadraticBezierCurve3;
43991         exports.LineCurve3 = LineCurve3;
43992         exports.ArcCurve = ArcCurve;
43993         exports.EllipseCurve = EllipseCurve;
43994         exports.SplineCurve = SplineCurve;
43995         exports.CubicBezierCurve = CubicBezierCurve;
43996         exports.QuadraticBezierCurve = QuadraticBezierCurve;
43997         exports.LineCurve = LineCurve;
43998         exports.Shape = Shape;
43999         exports.Path = Path;
44000         exports.ShapePath = ShapePath;
44001         exports.Font = Font;
44002         exports.CurvePath = CurvePath;
44003         exports.Curve = Curve;
44004         exports.ShapeUtils = ShapeUtils;
44005         exports.SceneUtils = SceneUtils;
44006         exports.WebGLUtils = WebGLUtils;
44007         exports.WireframeGeometry = WireframeGeometry;
44008         exports.ParametricGeometry = ParametricGeometry;
44009         exports.ParametricBufferGeometry = ParametricBufferGeometry;
44010         exports.TetrahedronGeometry = TetrahedronGeometry;
44011         exports.TetrahedronBufferGeometry = TetrahedronBufferGeometry;
44012         exports.OctahedronGeometry = OctahedronGeometry;
44013         exports.OctahedronBufferGeometry = OctahedronBufferGeometry;
44014         exports.IcosahedronGeometry = IcosahedronGeometry;
44015         exports.IcosahedronBufferGeometry = IcosahedronBufferGeometry;
44016         exports.DodecahedronGeometry = DodecahedronGeometry;
44017         exports.DodecahedronBufferGeometry = DodecahedronBufferGeometry;
44018         exports.PolyhedronGeometry = PolyhedronGeometry;
44019         exports.PolyhedronBufferGeometry = PolyhedronBufferGeometry;
44020         exports.TubeGeometry = TubeGeometry;
44021         exports.TubeBufferGeometry = TubeBufferGeometry;
44022         exports.TorusKnotGeometry = TorusKnotGeometry;
44023         exports.TorusKnotBufferGeometry = TorusKnotBufferGeometry;
44024         exports.TorusGeometry = TorusGeometry;
44025         exports.TorusBufferGeometry = TorusBufferGeometry;
44026         exports.TextGeometry = TextGeometry;
44027         exports.TextBufferGeometry = TextBufferGeometry;
44028         exports.SphereGeometry = SphereGeometry;
44029         exports.SphereBufferGeometry = SphereBufferGeometry;
44030         exports.RingGeometry = RingGeometry;
44031         exports.RingBufferGeometry = RingBufferGeometry;
44032         exports.PlaneGeometry = PlaneGeometry;
44033         exports.PlaneBufferGeometry = PlaneBufferGeometry;
44034         exports.LatheGeometry = LatheGeometry;
44035         exports.LatheBufferGeometry = LatheBufferGeometry;
44036         exports.ShapeGeometry = ShapeGeometry;
44037         exports.ShapeBufferGeometry = ShapeBufferGeometry;
44038         exports.ExtrudeGeometry = ExtrudeGeometry;
44039         exports.ExtrudeBufferGeometry = ExtrudeBufferGeometry;
44040         exports.EdgesGeometry = EdgesGeometry;
44041         exports.ConeGeometry = ConeGeometry;
44042         exports.ConeBufferGeometry = ConeBufferGeometry;
44043         exports.CylinderGeometry = CylinderGeometry;
44044         exports.CylinderBufferGeometry = CylinderBufferGeometry;
44045         exports.CircleGeometry = CircleGeometry;
44046         exports.CircleBufferGeometry = CircleBufferGeometry;
44047         exports.BoxGeometry = BoxGeometry;
44048         exports.BoxBufferGeometry = BoxBufferGeometry;
44049         exports.ShadowMaterial = ShadowMaterial;
44050         exports.SpriteMaterial = SpriteMaterial;
44051         exports.RawShaderMaterial = RawShaderMaterial;
44052         exports.ShaderMaterial = ShaderMaterial;
44053         exports.PointsMaterial = PointsMaterial;
44054         exports.MeshPhysicalMaterial = MeshPhysicalMaterial;
44055         exports.MeshStandardMaterial = MeshStandardMaterial;
44056         exports.MeshPhongMaterial = MeshPhongMaterial;
44057         exports.MeshToonMaterial = MeshToonMaterial;
44058         exports.MeshNormalMaterial = MeshNormalMaterial;
44059         exports.MeshLambertMaterial = MeshLambertMaterial;
44060         exports.MeshDepthMaterial = MeshDepthMaterial;
44061         exports.MeshDistanceMaterial = MeshDistanceMaterial;
44062         exports.MeshBasicMaterial = MeshBasicMaterial;
44063         exports.LineDashedMaterial = LineDashedMaterial;
44064         exports.LineBasicMaterial = LineBasicMaterial;
44065         exports.Material = Material;
44066         exports.Float64BufferAttribute = Float64BufferAttribute;
44067         exports.Float32BufferAttribute = Float32BufferAttribute;
44068         exports.Uint32BufferAttribute = Uint32BufferAttribute;
44069         exports.Int32BufferAttribute = Int32BufferAttribute;
44070         exports.Uint16BufferAttribute = Uint16BufferAttribute;
44071         exports.Int16BufferAttribute = Int16BufferAttribute;
44072         exports.Uint8ClampedBufferAttribute = Uint8ClampedBufferAttribute;
44073         exports.Uint8BufferAttribute = Uint8BufferAttribute;
44074         exports.Int8BufferAttribute = Int8BufferAttribute;
44075         exports.BufferAttribute = BufferAttribute;
44076         exports.REVISION = REVISION;
44077         exports.MOUSE = MOUSE;
44078         exports.CullFaceNone = CullFaceNone;
44079         exports.CullFaceBack = CullFaceBack;
44080         exports.CullFaceFront = CullFaceFront;
44081         exports.CullFaceFrontBack = CullFaceFrontBack;
44082         exports.FrontFaceDirectionCW = FrontFaceDirectionCW;
44083         exports.FrontFaceDirectionCCW = FrontFaceDirectionCCW;
44084         exports.BasicShadowMap = BasicShadowMap;
44085         exports.PCFShadowMap = PCFShadowMap;
44086         exports.PCFSoftShadowMap = PCFSoftShadowMap;
44087         exports.FrontSide = FrontSide;
44088         exports.BackSide = BackSide;
44089         exports.DoubleSide = DoubleSide;
44090         exports.FlatShading = FlatShading;
44091         exports.SmoothShading = SmoothShading;
44092         exports.NoColors = NoColors;
44093         exports.FaceColors = FaceColors;
44094         exports.VertexColors = VertexColors;
44095         exports.NoBlending = NoBlending;
44096         exports.NormalBlending = NormalBlending;
44097         exports.AdditiveBlending = AdditiveBlending;
44098         exports.SubtractiveBlending = SubtractiveBlending;
44099         exports.MultiplyBlending = MultiplyBlending;
44100         exports.CustomBlending = CustomBlending;
44101         exports.AddEquation = AddEquation;
44102         exports.SubtractEquation = SubtractEquation;
44103         exports.ReverseSubtractEquation = ReverseSubtractEquation;
44104         exports.MinEquation = MinEquation;
44105         exports.MaxEquation = MaxEquation;
44106         exports.ZeroFactor = ZeroFactor;
44107         exports.OneFactor = OneFactor;
44108         exports.SrcColorFactor = SrcColorFactor;
44109         exports.OneMinusSrcColorFactor = OneMinusSrcColorFactor;
44110         exports.SrcAlphaFactor = SrcAlphaFactor;
44111         exports.OneMinusSrcAlphaFactor = OneMinusSrcAlphaFactor;
44112         exports.DstAlphaFactor = DstAlphaFactor;
44113         exports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor;
44114         exports.DstColorFactor = DstColorFactor;
44115         exports.OneMinusDstColorFactor = OneMinusDstColorFactor;
44116         exports.SrcAlphaSaturateFactor = SrcAlphaSaturateFactor;
44117         exports.NeverDepth = NeverDepth;
44118         exports.AlwaysDepth = AlwaysDepth;
44119         exports.LessDepth = LessDepth;
44120         exports.LessEqualDepth = LessEqualDepth;
44121         exports.EqualDepth = EqualDepth;
44122         exports.GreaterEqualDepth = GreaterEqualDepth;
44123         exports.GreaterDepth = GreaterDepth;
44124         exports.NotEqualDepth = NotEqualDepth;
44125         exports.MultiplyOperation = MultiplyOperation;
44126         exports.MixOperation = MixOperation;
44127         exports.AddOperation = AddOperation;
44128         exports.NoToneMapping = NoToneMapping;
44129         exports.LinearToneMapping = LinearToneMapping;
44130         exports.ReinhardToneMapping = ReinhardToneMapping;
44131         exports.Uncharted2ToneMapping = Uncharted2ToneMapping;
44132         exports.CineonToneMapping = CineonToneMapping;
44133         exports.UVMapping = UVMapping;
44134         exports.CubeReflectionMapping = CubeReflectionMapping;
44135         exports.CubeRefractionMapping = CubeRefractionMapping;
44136         exports.EquirectangularReflectionMapping = EquirectangularReflectionMapping;
44137         exports.EquirectangularRefractionMapping = EquirectangularRefractionMapping;
44138         exports.SphericalReflectionMapping = SphericalReflectionMapping;
44139         exports.CubeUVReflectionMapping = CubeUVReflectionMapping;
44140         exports.CubeUVRefractionMapping = CubeUVRefractionMapping;
44141         exports.RepeatWrapping = RepeatWrapping;
44142         exports.ClampToEdgeWrapping = ClampToEdgeWrapping;
44143         exports.MirroredRepeatWrapping = MirroredRepeatWrapping;
44144         exports.NearestFilter = NearestFilter;
44145         exports.NearestMipMapNearestFilter = NearestMipMapNearestFilter;
44146         exports.NearestMipMapLinearFilter = NearestMipMapLinearFilter;
44147         exports.LinearFilter = LinearFilter;
44148         exports.LinearMipMapNearestFilter = LinearMipMapNearestFilter;
44149         exports.LinearMipMapLinearFilter = LinearMipMapLinearFilter;
44150         exports.UnsignedByteType = UnsignedByteType;
44151         exports.ByteType = ByteType;
44152         exports.ShortType = ShortType;
44153         exports.UnsignedShortType = UnsignedShortType;
44154         exports.IntType = IntType;
44155         exports.UnsignedIntType = UnsignedIntType;
44156         exports.FloatType = FloatType;
44157         exports.HalfFloatType = HalfFloatType;
44158         exports.UnsignedShort4444Type = UnsignedShort4444Type;
44159         exports.UnsignedShort5551Type = UnsignedShort5551Type;
44160         exports.UnsignedShort565Type = UnsignedShort565Type;
44161         exports.UnsignedInt248Type = UnsignedInt248Type;
44162         exports.AlphaFormat = AlphaFormat;
44163         exports.RGBFormat = RGBFormat;
44164         exports.RGBAFormat = RGBAFormat;
44165         exports.LuminanceFormat = LuminanceFormat;
44166         exports.LuminanceAlphaFormat = LuminanceAlphaFormat;
44167         exports.RGBEFormat = RGBEFormat;
44168         exports.DepthFormat = DepthFormat;
44169         exports.DepthStencilFormat = DepthStencilFormat;
44170         exports.RGB_S3TC_DXT1_Format = RGB_S3TC_DXT1_Format;
44171         exports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format;
44172         exports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format;
44173         exports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format;
44174         exports.RGB_PVRTC_4BPPV1_Format = RGB_PVRTC_4BPPV1_Format;
44175         exports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format;
44176         exports.RGBA_PVRTC_4BPPV1_Format = RGBA_PVRTC_4BPPV1_Format;
44177         exports.RGBA_PVRTC_2BPPV1_Format = RGBA_PVRTC_2BPPV1_Format;
44178         exports.RGB_ETC1_Format = RGB_ETC1_Format;
44179         exports.LoopOnce = LoopOnce;
44180         exports.LoopRepeat = LoopRepeat;
44181         exports.LoopPingPong = LoopPingPong;
44182         exports.InterpolateDiscrete = InterpolateDiscrete;
44183         exports.InterpolateLinear = InterpolateLinear;
44184         exports.InterpolateSmooth = InterpolateSmooth;
44185         exports.ZeroCurvatureEnding = ZeroCurvatureEnding;
44186         exports.ZeroSlopeEnding = ZeroSlopeEnding;
44187         exports.WrapAroundEnding = WrapAroundEnding;
44188         exports.TrianglesDrawMode = TrianglesDrawMode;
44189         exports.TriangleStripDrawMode = TriangleStripDrawMode;
44190         exports.TriangleFanDrawMode = TriangleFanDrawMode;
44191         exports.LinearEncoding = LinearEncoding;
44192         exports.sRGBEncoding = sRGBEncoding;
44193         exports.GammaEncoding = GammaEncoding;
44194         exports.RGBEEncoding = RGBEEncoding;
44195         exports.LogLuvEncoding = LogLuvEncoding;
44196         exports.RGBM7Encoding = RGBM7Encoding;
44197         exports.RGBM16Encoding = RGBM16Encoding;
44198         exports.RGBDEncoding = RGBDEncoding;
44199         exports.BasicDepthPacking = BasicDepthPacking;
44200         exports.RGBADepthPacking = RGBADepthPacking;
44201         exports.CubeGeometry = BoxGeometry;
44202         exports.Face4 = Face4;
44203         exports.LineStrip = LineStrip;
44204         exports.LinePieces = LinePieces;
44205         exports.MeshFaceMaterial = MeshFaceMaterial;
44206         exports.MultiMaterial = MultiMaterial;
44207         exports.PointCloud = PointCloud;
44208         exports.Particle = Particle;
44209         exports.ParticleSystem = ParticleSystem;
44210         exports.PointCloudMaterial = PointCloudMaterial;
44211         exports.ParticleBasicMaterial = ParticleBasicMaterial;
44212         exports.ParticleSystemMaterial = ParticleSystemMaterial;
44213         exports.Vertex = Vertex;
44214         exports.DynamicBufferAttribute = DynamicBufferAttribute;
44215         exports.Int8Attribute = Int8Attribute;
44216         exports.Uint8Attribute = Uint8Attribute;
44217         exports.Uint8ClampedAttribute = Uint8ClampedAttribute;
44218         exports.Int16Attribute = Int16Attribute;
44219         exports.Uint16Attribute = Uint16Attribute;
44220         exports.Int32Attribute = Int32Attribute;
44221         exports.Uint32Attribute = Uint32Attribute;
44222         exports.Float32Attribute = Float32Attribute;
44223         exports.Float64Attribute = Float64Attribute;
44224         exports.ClosedSplineCurve3 = ClosedSplineCurve3;
44225         exports.SplineCurve3 = SplineCurve3;
44226         exports.Spline = Spline;
44227         exports.BoundingBoxHelper = BoundingBoxHelper;
44228         exports.EdgesHelper = EdgesHelper;
44229         exports.WireframeHelper = WireframeHelper;
44230         exports.XHRLoader = XHRLoader;
44231         exports.BinaryTextureLoader = BinaryTextureLoader;
44232         exports.GeometryUtils = GeometryUtils;
44233         exports.ImageUtils = ImageUtils;
44234         exports.Projector = Projector;
44235         exports.CanvasRenderer = CanvasRenderer;
44236
44237         Object.defineProperty(exports, '__esModule', { value: true });
44238
44239 })));